Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1482)

Delta Between Two Patch Sets: src/cmd/gc/walk.c

Issue 9101048: code review 9101048: cmd/gc: inline copy in frontend to call memmove directly. (Closed)
Left Patch Set: diff -r 0d28fd55e721 https://go.googlecode.com/hg/ Created 11 years, 10 months ago
Right Patch Set: diff -r c47375e68297 https://go.googlecode.com/hg/ Created 11 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/gc/typecheck.c ('k') | src/pkg/runtime/append_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 #include <u.h> 5 #include <u.h>
6 #include <libc.h> 6 #include <libc.h>
7 #include "go.h" 7 #include "go.h"
8 8
9 static Node* walkprint(Node*, NodeList**, int); 9 static Node* walkprint(Node*, NodeList**, int);
10 static Node* mapfn(char*, Type*); 10 static Node* mapfn(char*, Type*);
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 case OPRINTN: 168 case OPRINTN:
169 case OPANIC: 169 case OPANIC:
170 case OEMPTY: 170 case OEMPTY:
171 case ORECOVER: 171 case ORECOVER:
172 if(n->typecheck == 0) 172 if(n->typecheck == 0)
173 fatal("missing typecheck: %+N", n); 173 fatal("missing typecheck: %+N", n);
174 init = n->ninit; 174 init = n->ninit;
175 n->ninit = nil; 175 n->ninit = nil;
176 walkexpr(&n, &init); 176 walkexpr(&n, &init);
177 addinit(&n, init); 177 addinit(&n, init);
178 if((*np)->op == OCOPY && n->op == OCONVNOP)
179 n->op = OEMPTY; // don't leave plain values as statement s.
178 break; 180 break;
179 181
180 case OBREAK: 182 case OBREAK:
181 case ODCL: 183 case ODCL:
182 case OCONTINUE: 184 case OCONTINUE:
183 case OFALL: 185 case OFALL:
184 case OGOTO: 186 case OGOTO:
185 case OLABEL: 187 case OLABEL:
186 case ODCLCONST: 188 case ODCLCONST:
187 case ODCLTYPE: 189 case ODCLTYPE:
188 » case OCHECKNOTNIL: 190 » case OCHECKNIL:
189 break; 191 break;
190 192
191 case OBLOCK: 193 case OBLOCK:
192 walkstmtlist(n->list); 194 walkstmtlist(n->list);
193 break; 195 break;
194 196
195 case OXCASE: 197 case OXCASE:
196 yyerror("case statement out of place"); 198 yyerror("case statement out of place");
197 n->op = OCASE; 199 n->op = OCASE;
198 case OCASE: 200 case OCASE:
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 // move function calls out, to make reorder3's job easie r. 278 // move function calls out, to make reorder3's job easie r.
277 walkexprlistsafe(n->list, &n->ninit); 279 walkexprlistsafe(n->list, &n->ninit);
278 ll = ascompatee(n->op, rl, n->list, &n->ninit); 280 ll = ascompatee(n->op, rl, n->list, &n->ninit);
279 n->list = reorder3(ll); 281 n->list = reorder3(ll);
280 break; 282 break;
281 } 283 }
282 ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit); 284 ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
283 n->list = ll; 285 n->list = ll;
284 break; 286 break;
285 287
288 case ORETJMP:
289 break;
290
286 case OSELECT: 291 case OSELECT:
287 walkselect(n); 292 walkselect(n);
288 break; 293 break;
289 294
290 case OSWITCH: 295 case OSWITCH:
291 walkswitch(n); 296 walkswitch(n);
292 break; 297 break;
293 298
294 case ORANGE: 299 case ORANGE:
295 walkrange(n); 300 walkrange(n);
296 break; 301 break;
297 302
298 case OXFALL: 303 case OXFALL:
299 yyerror("fallthrough statement out of place"); 304 yyerror("fallthrough statement out of place");
300 n->op = OFALL; 305 n->op = OFALL;
301 break; 306 break;
302 } 307 }
303 308
304 if(n->op == ONAME) 309 if(n->op == ONAME)
305 fatal("walkstmt ended up with name: %+N", n); 310 fatal("walkstmt ended up with name: %+N", n);
306 311 »
307 *np = n; 312 *np = n;
308 } 313 }
309 314
310 315
311 /* 316 /*
312 * walk the whole tree of the body of an 317 * walk the whole tree of the body of an
313 * expression or simple statement. 318 * expression or simple statement.
314 * the types expressions are calculated. 319 * the types expressions are calculated.
315 * compile-time constants are evaluated. 320 * compile-time constants are evaluated.
316 * complex side effects like statements are appended to init 321 * complex side effects like statements are appended to init
(...skipping 14 matching lines...) Expand all
331 walkexpr(&l->n, init); 336 walkexpr(&l->n, init);
332 } 337 }
333 } 338 }
334 339
335 void 340 void
336 walkexpr(Node **np, NodeList **init) 341 walkexpr(Node **np, NodeList **init)
337 { 342 {
338 Node *r, *l, *var, *a; 343 Node *r, *l, *var, *a;
339 NodeList *ll, *lr, *lpost; 344 NodeList *ll, *lr, *lpost;
340 Type *t; 345 Type *t;
341 » int et; 346 » int et, old_safemode;
342 int64 v; 347 int64 v;
343 int32 lno; 348 int32 lno;
344 Node *n, *fn, *n1, *n2; 349 Node *n, *fn, *n1, *n2;
345 Sym *sym; 350 Sym *sym;
346 char buf[100], *p; 351 char buf[100], *p;
347 352
348 n = *np; 353 n = *np;
349 354
350 if(n == N) 355 if(n == N)
351 return; 356 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 case OCOM: 401 case OCOM:
397 case OREAL: 402 case OREAL:
398 case OIMAG: 403 case OIMAG:
399 case ODOTMETH: 404 case ODOTMETH:
400 case ODOTINTER: 405 case ODOTINTER:
401 walkexpr(&n->left, init); 406 walkexpr(&n->left, init);
402 goto ret; 407 goto ret;
403 408
404 case OIND: 409 case OIND:
405 if(n->left->type->type->width == 0) { 410 if(n->left->type->type->width == 0) {
411 // No actual copy will be generated, so emit an explicit nil check.
406 n->left = cheapexpr(n->left, init); 412 n->left = cheapexpr(n->left, init);
407 » » » checknotnil(n->left, init); 413 » » » checknil(n->left, init);
408 } 414 }
409 walkexpr(&n->left, init); 415 walkexpr(&n->left, init);
410 goto ret; 416 goto ret;
411 417
412 case ODOT: 418 case ODOT:
413 usefield(n); 419 usefield(n);
414 walkexpr(&n->left, init); 420 walkexpr(&n->left, init);
415 goto ret; 421 goto ret;
416 422
417 case ODOTPTR: 423 case ODOTPTR:
418 usefield(n); 424 usefield(n);
419 if(n->op == ODOTPTR && n->left->type->type->width == 0) { 425 if(n->op == ODOTPTR && n->left->type->type->width == 0) {
426 // No actual copy will be generated, so emit an explicit nil check.
420 n->left = cheapexpr(n->left, init); 427 n->left = cheapexpr(n->left, init);
421 » » » checknotnil(n->left, init); 428 » » » checknil(n->left, init);
422 } 429 }
423 walkexpr(&n->left, init); 430 walkexpr(&n->left, init);
424 goto ret; 431 goto ret;
425 432
426 case OEFACE: 433 case OEFACE:
427 walkexpr(&n->left, init); 434 walkexpr(&n->left, init);
428 walkexpr(&n->right, init); 435 walkexpr(&n->right, init);
429 goto ret; 436 goto ret;
430 437
431 case OSPTR: 438 case OSPTR:
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 case OXOR: 485 case OXOR:
479 walkexpr(&n->left, init); 486 walkexpr(&n->left, init);
480 walkexpr(&n->right, init); 487 walkexpr(&n->right, init);
481 walkrotate(&n); 488 walkrotate(&n);
482 goto ret; 489 goto ret;
483 490
484 case OEQ: 491 case OEQ:
485 case ONE: 492 case ONE:
486 walkexpr(&n->left, init); 493 walkexpr(&n->left, init);
487 walkexpr(&n->right, init); 494 walkexpr(&n->right, init);
495 // Disable safemode while compiling this code: the code we
496 // generate internally can refer to unsafe.Pointer.
497 // In this case it can happen if we need to generate an ==
498 // for a struct containing a reflect.Value, which itself has
499 // an unexported field of type unsafe.Pointer.
500 old_safemode = safemode;
501 safemode = 0;
488 walkcompare(&n, init); 502 walkcompare(&n, init);
503 safemode = old_safemode;
489 goto ret; 504 goto ret;
490 505
491 case OANDAND: 506 case OANDAND:
492 case OOROR: 507 case OOROR:
493 walkexpr(&n->left, init); 508 walkexpr(&n->left, init);
494 // cannot put side effects from n->right on init, 509 // cannot put side effects from n->right on init,
495 // because they cannot run before n->left is checked. 510 // because they cannot run before n->left is checked.
496 // save elsewhere and store on the eventual n->right. 511 // save elsewhere and store on the eventual n->right.
497 ll = nil; 512 ll = nil;
498 walkexpr(&n->right, &ll); 513 walkexpr(&n->right, &ll);
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left-> op == OINDEX)) 1123 if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left-> op == OINDEX))
1109 n->left = copyexpr(n->left, n->left->type, init); 1124 n->left = copyexpr(n->left, n->left->type, init);
1110 else 1125 else
1111 n->left = safeexpr(n->left, init); 1126 n->left = safeexpr(n->left, init);
1112 walkexpr(&n->right->left, init); 1127 walkexpr(&n->right->left, init);
1113 n->right->left = safeexpr(n->right->left, init); 1128 n->right->left = safeexpr(n->right->left, init);
1114 walkexpr(&n->right->right, init); 1129 walkexpr(&n->right->right, init);
1115 n->right->right = safeexpr(n->right->right, init); 1130 n->right->right = safeexpr(n->right->right, init);
1116 n = sliceany(n, init); // chops n->right, sets n->list 1131 n = sliceany(n, init); // chops n->right, sets n->list
1117 goto ret; 1132 goto ret;
1133 ········
1134 case OSLICE3:
1135 case OSLICE3ARR:
1136 if(n->right == N) // already processed
1137 goto ret;
1138
1139 walkexpr(&n->left, init);
1140 // TODO the OINDEX case is a bug elsewhere that needs to be trac ed. it causes a crash on ([2][]int{ ... })[1][lo:hi]
1141 // TODO the comment on the previous line was copied from case OS LICE. it might not even be true.
1142 if(n->left->op == OINDEX)
1143 n->left = copyexpr(n->left, n->left->type, init);
1144 else
1145 n->left = safeexpr(n->left, init);
1146 walkexpr(&n->right->left, init);
1147 n->right->left = safeexpr(n->right->left, init);
1148 walkexpr(&n->right->right->left, init);
1149 n->right->right->left = safeexpr(n->right->right->left, init);
1150 walkexpr(&n->right->right->right, init);
1151 n->right->right->right = safeexpr(n->right->right->right, init);
1152 n = sliceany(n, init); // chops n->right, sets n->list
1153 goto ret;
1118 1154
1119 case OADDR: 1155 case OADDR:
1120 walkexpr(&n->left, init); 1156 walkexpr(&n->left, init);
1121 goto ret; 1157 goto ret;
1122 1158
1123 case ONEW: 1159 case ONEW:
1124 if(n->esc == EscNone && n->type->type->width < (1<<16)) { 1160 if(n->esc == EscNone && n->type->type->width < (1<<16)) {
1125 r = temp(n->type->type); 1161 r = temp(n->type->type);
1126 r = nod(OAS, r, N); // zero temp 1162 r = nod(OAS, r, N); // zero temp
1127 typecheck(&r, Etop); 1163 typecheck(&r, Etop);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1245 fn = syslook("makemap", 1); 1281 fn = syslook("makemap", 1);
1246 argtype(fn, t->down); // any-1 1282 argtype(fn, t->down); // any-1
1247 argtype(fn, t->type); // any-2 1283 argtype(fn, t->type); // any-2
1248 1284
1249 n = mkcall1(fn, n->type, init, 1285 n = mkcall1(fn, n->type, init,
1250 typename(n->type), 1286 typename(n->type),
1251 conv(n->left, types[TINT64])); 1287 conv(n->left, types[TINT64]));
1252 goto ret; 1288 goto ret;
1253 1289
1254 case OMAKESLICE: 1290 case OMAKESLICE:
1255 // makeslice(t *Type, nel int64, max int64) (ary []any)
1256 l = n->left; 1291 l = n->left;
1257 r = n->right; 1292 r = n->right;
1258 if(r == nil) 1293 if(r == nil)
1259 l = r = safeexpr(l, init); 1294 l = r = safeexpr(l, init);
1260 t = n->type; 1295 t = n->type;
1261 » » fn = syslook("makeslice", 1); 1296 » » if(n->esc == EscNone
1262 » » argtype(fn, t->type);» » » // any-1 1297 » » » && smallintconst(l) && smallintconst(r)
1263 » » n = mkcall1(fn, n->type, init, 1298 » » » && mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width ) {
1264 » » » typename(n->type), 1299 » » » // var arr [r]T
1265 » » » conv(l, types[TINT64]), 1300 » » » // n = arr[:l]
1266 » » » conv(r, types[TINT64])); 1301 » » » t = aindex(r, t->type); // [r]T
1302 » » » var = temp(t);
1303 » » » a = nod(OAS, var, N); // zero temp
1304 » » » typecheck(&a, Etop);
1305 » » » *init = list(*init, a);
1306 » » » r = nod(OSLICE, var, nod(OKEY, N, l)); // arr[:l]
1307 » » » r = conv(r, n->type); // in case n->type is named.
1308 » » » typecheck(&r, Erv);
1309 » » » walkexpr(&r, init);
1310 » » » n = r;
1311 » » } else {
1312 » » » // makeslice(t *Type, nel int64, max int64) (ary []any)
1313 » » » fn = syslook("makeslice", 1);
1314 » » » argtype(fn, t->type);» » » // any-1
1315 » » » n = mkcall1(fn, n->type, init,
1316 » » » » typename(n->type),
1317 » » » » conv(l, types[TINT64]),
1318 » » » » conv(r, types[TINT64]));
1319 » » }
1267 goto ret; 1320 goto ret;
1268 1321
1269 case ORUNESTR: 1322 case ORUNESTR:
1270 // sys_intstring(v) 1323 // sys_intstring(v)
1271 n = mkcall("intstring", n->type, init, 1324 n = mkcall("intstring", n->type, init,
1272 conv(n->left, types[TINT64])); 1325 conv(n->left, types[TINT64]));
1273 goto ret; 1326 goto ret;
1274 1327
1275 case OARRAYBYTESTR: 1328 case OARRAYBYTESTR:
1276 // slicebytetostring([]byte) string; 1329 // slicebytetostring([]byte) string;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 n = walkclosure(n, init); 1390 n = walkclosure(n, init);
1338 goto ret; 1391 goto ret;
1339 ········ 1392 ········
1340 case OCALLPART: 1393 case OCALLPART:
1341 n = walkpartialcall(n, init); 1394 n = walkpartialcall(n, init);
1342 goto ret; 1395 goto ret;
1343 } 1396 }
1344 fatal("missing switch %O", n->op); 1397 fatal("missing switch %O", n->op);
1345 1398
1346 ret: 1399 ret:
1400 // Expressions that are constant at run time but not
1401 // considered const by the language spec are not turned into
1402 // constants until walk. For example, if n is y%1 == 0, the
1403 // walk of y%1 may have replaced it by 0.
1404 // Check whether n with its updated args is itself now a constant.
1405 t = n->type;
1406 evconst(n);
1407 n->type = t;
1408 if(n->op == OLITERAL)
1409 typecheck(&n, Erv);
1410
1347 ullmancalc(n); 1411 ullmancalc(n);
1348 1412
1349 if(debug['w'] && n != N) 1413 if(debug['w'] && n != N)
1350 dump("walk", n); 1414 dump("walk", n);
1351 1415
1352 lineno = lno; 1416 lineno = lno;
1353 *np = n; 1417 *np = n;
1354 } 1418 }
1355 1419
1356 static Node* 1420 static Node*
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after
2260 Type *t; 2324 Type *t;
2261 Iter savet; 2325 Iter savet;
2262 Node *v; 2326 Node *v;
2263 NodeList *nn; 2327 NodeList *nn;
2264 2328
2265 nn = nil; 2329 nn = nil;
2266 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) { 2330 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
2267 v = t->nname; 2331 v = t->nname;
2268 if(v && v->sym && v->sym->name[0] == '~') 2332 if(v && v->sym && v->sym->name[0] == '~')
2269 v = N; 2333 v = N;
2270 » » if(v == N && out && hasdefer) { 2334 » » // The garbage collector assumes results are always live,
2335 » » // so zero them always (1 ||).
2336 » » if(out && (1 || (v == N && hasdefer))) {
2271 // Defer might stop a panic and show the 2337 // Defer might stop a panic and show the
2272 // return values as they exist at the time of panic. 2338 // return values as they exist at the time of panic.
2273 // Make sure to zero them on entry to the function. 2339 // Make sure to zero them on entry to the function.
2274 nn = list(nn, nod(OAS, nodarg(t, 1), N)); 2340 nn = list(nn, nod(OAS, nodarg(t, 1), N));
2275 } 2341 }
2276 if(v == N || !(v->class & PHEAP)) 2342 if(v == N || !(v->class & PHEAP))
2277 continue; 2343 continue;
2278 2344
2279 // generate allocation & copying code 2345 // generate allocation & copying code
2280 if(v->alloc == nil) 2346 if(v->alloc == nil)
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
2536 nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit, 2602 nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit,
2537 typename(ns->type), 2603 typename(ns->type),
2538 ns, 2604 ns,
2539 conv(na, types[TINT64])))); 2605 conv(na, types[TINT64]))));
2540 l = list(l, nx); 2606 l = list(l, nx);
2541 2607
2542 nn = temp(types[TINT]); 2608 nn = temp(types[TINT]);
2543 l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s) 2609 l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s)
2544 2610
2545 nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc ] 2611 nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc ]
2546 » nx->bounded = 1; 2612 » nx->etype = 1;
2547 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc] 2613 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
2548 2614
2549 for (a = n->list->next; a != nil; a = a->next) { 2615 for (a = n->list->next; a != nil; a = a->next) {
2550 nx = nod(OINDEX, ns, nn); // s[n] ... 2616 nx = nod(OINDEX, ns, nn); // s[n] ...
2551 nx->bounded = 1; 2617 nx->bounded = 1;
2552 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg 2618 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
2553 if (a->next != nil) 2619 if (a->next != nil)
2554 l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))) ; // n = n + 1 2620 l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))) ; // n = n + 1
2555 } 2621 }
2556 2622
2557 typechecklist(l, Etop); 2623 typechecklist(l, Etop);
2558 walkstmtlist(l); 2624 walkstmtlist(l);
2559 *init = concat(*init, l); 2625 *init = concat(*init, l);
2560 return ns; 2626 return ns;
2561 } 2627 }
2562 2628
2563 // Lower copy(a, b) to a memmove call. 2629 // Lower copy(a, b) to a memmove call.
2564 // 2630 //
2565 // init { 2631 // init {
2566 // n := len(a) 2632 // n := len(a)
2567 // if n > len(b) { n = len(b) } 2633 // if n > len(b) { n = len(b) }
2568 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) 2634 // memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
2569 // } 2635 // }
2570 // l; 2636 // n;
2571 // 2637 //
2572 // Also works if b is a string. 2638 // Also works if b is a string.
2573 // 2639 //
2574 static Node* 2640 static Node*
2575 copyany(Node *n, NodeList **init) 2641 copyany(Node *n, NodeList **init)
2576 { 2642 {
2577 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; 2643 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
2578 NodeList *l; 2644 NodeList *l;
2579 Type *tp;
2580 2645
2581 walkexpr(&n->left, init); 2646 walkexpr(&n->left, init);
2582 walkexpr(&n->right, init); 2647 walkexpr(&n->right, init);
2583 nl = temp(n->left->type); 2648 nl = temp(n->left->type);
2584 nr = temp(n->right->type); 2649 nr = temp(n->right->type);
2585 l = nil; 2650 l = nil;
2586 l = list(l, nod(OAS, nl, n->left)); 2651 l = list(l, nod(OAS, nl, n->left));
2587 l = list(l, nod(OAS, nr, n->right)); 2652 l = list(l, nod(OAS, nr, n->right));
2588 2653
2589 » tp = ptrto(bytetype); 2654 » nfrm = nod(OSPTR, nr, N);
2590 » nfrm = conv(nod(OSPTR, nr, N), tp); 2655 » nto = nod(OSPTR, nl, N);
2591 » nto = conv(nod(OSPTR, nl, N), tp);
2592 2656
2593 nlen = temp(types[TINT]); 2657 nlen = temp(types[TINT]);
2594 // n = len(to) 2658 // n = len(to)
2595 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N))); 2659 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N)));
2596 // if n > len(frm) { n = len(frm) } 2660 // if n > len(frm) { n = len(frm) }
2597 nif = nod(OIF, N, N); 2661 nif = nod(OIF, N, N);
2598 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N)); 2662 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N));
2599 nif->nbody = list(nif->nbody, 2663 nif->nbody = list(nif->nbody,
2600 nod(OAS, nlen, nod(OLEN, nr, N))); 2664 nod(OAS, nlen, nod(OLEN, nr, N)));
2601 l = list(l, nif); 2665 l = list(l, nif);
2602 2666
2603 // Call memmove. 2667 // Call memmove.
2604 fn = syslook("memmove", 1); 2668 fn = syslook("memmove", 1);
2669 argtype(fn, nl->type->type);
2670 argtype(fn, nl->type->type);
2605 nwid = temp(types[TUINTPTR]); 2671 nwid = temp(types[TUINTPTR]);
2606 l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR]))); 2672 l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR])));
2607 nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width)); 2673 nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width));
2608 l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid)); 2674 l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid));
2609 2675
2610 typechecklist(l, Etop); 2676 typechecklist(l, Etop);
2611 walkstmtlist(l); 2677 walkstmtlist(l);
2612 *init = concat(*init, l); 2678 *init = concat(*init, l);
2613 return nlen; 2679 return nlen;
2614 } 2680 }
2615 2681
2616 // Generate frontend part for OSLICE[ARR|STR] 2682 // Generate frontend part for OSLICE[3][ARR|STR]
2617 //· 2683 //·
2618 static Node* 2684 static Node*
2619 sliceany(Node* n, NodeList **init) 2685 sliceany(Node* n, NodeList **init)
2620 { 2686 {
2621 » int bounded; 2687 » int bounded, slice3;
2622 » Node *src, *lb, *hb, *bound, *chk, *chk1, *chk2; 2688 » Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
2623 » int64 lbv, hbv, bv, w; 2689 » int64 lbv, hbv, cbv, bv, w;
2624 Type *bt; 2690 Type *bt;
2625 2691
2626 // print("before sliceany: %+N\n", n); 2692 // print("before sliceany: %+N\n", n);
2627 2693
2628 src = n->left; 2694 src = n->left;
2629 lb = n->right->left; 2695 lb = n->right->left;
2630 » hb = n->right->right; 2696 » slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR;
2697 » if(slice3) {
2698 » » hb = n->right->right->left;
2699 » » cb = n->right->right->right;
2700 » } else {
2701 » » hb = n->right->right;
2702 » » cb = N;
2703 » }
2631 2704
2632 bounded = n->etype; 2705 bounded = n->etype;
2633 ········ 2706 ········
2634 if(n->op == OSLICESTR) 2707 if(n->op == OSLICESTR)
2635 bound = nod(OLEN, src, N); 2708 bound = nod(OLEN, src, N);
2636 else 2709 else
2637 bound = nod(OCAP, src, N); 2710 bound = nod(OCAP, src, N);
2638 2711
2639 typecheck(&bound, Erv); 2712 typecheck(&bound, Erv);
2640 walkexpr(&bound, init); // if src is an array, bound will be a const no w. 2713 walkexpr(&bound, init); // if src is an array, bound will be a const no w.
2641 2714
2642 // static checks if possible 2715 // static checks if possible
2643 bv = 1LL<<50; 2716 bv = 1LL<<50;
2644 if(isconst(bound, CTINT)) { 2717 if(isconst(bound, CTINT)) {
2645 if(!smallintconst(bound)) 2718 if(!smallintconst(bound))
2646 yyerror("array len too large"); 2719 yyerror("array len too large");
2647 else 2720 else
2648 bv = mpgetfix(bound->val.u.xval); 2721 bv = mpgetfix(bound->val.u.xval);
2649 } 2722 }
2650 2723
2724 if(isconst(cb, CTINT)) {
2725 cbv = mpgetfix(cb->val.u.xval);
2726 if(cbv < 0 || cbv > bv) {
2727 yyerror("slice index out of bounds");
2728 cbv = -1;
2729 }
2730 }
2651 if(isconst(hb, CTINT)) { 2731 if(isconst(hb, CTINT)) {
2652 hbv = mpgetfix(hb->val.u.xval); 2732 hbv = mpgetfix(hb->val.u.xval);
2653 if(hbv < 0 || hbv > bv) { 2733 if(hbv < 0 || hbv > bv) {
2654 yyerror("slice index out of bounds"); 2734 yyerror("slice index out of bounds");
2655 hbv = -1; 2735 hbv = -1;
2656 } 2736 }
2657 } 2737 }
2658 if(isconst(lb, CTINT)) { 2738 if(isconst(lb, CTINT)) {
2659 lbv = mpgetfix(lb->val.u.xval); 2739 lbv = mpgetfix(lb->val.u.xval);
2660 if(lbv < 0 || lbv > bv) { 2740 if(lbv < 0 || lbv > bv) {
2661 yyerror("slice index out of bounds"); 2741 yyerror("slice index out of bounds");
2662 lbv = -1; 2742 lbv = -1;
2663 } 2743 }
2664 if(lbv == 0) 2744 if(lbv == 0)
2665 lb = N; 2745 lb = N;
2666 } 2746 }
2667 2747
2668 // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison 2748 // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison
2669 // generate 2749 // generate
2670 // if hb > bound || lb > hb { panicslice() } 2750 // if hb > bound || lb > hb { panicslice() }
2671 chk = N; 2751 chk = N;
2752 chk0 = N;
2672 chk1 = N; 2753 chk1 = N;
2673 chk2 = N; 2754 chk2 = N;
2674 2755
2675 bt = types[simtype[TUINT]]; 2756 bt = types[simtype[TUINT]];
2757 if(cb != N && cb->type->width > 4)
2758 bt = types[TUINT64];
2676 if(hb != N && hb->type->width > 4) 2759 if(hb != N && hb->type->width > 4)
2677 bt = types[TUINT64]; 2760 bt = types[TUINT64];
2678 if(lb != N && lb->type->width > 4) 2761 if(lb != N && lb->type->width > 4)
2679 bt = types[TUINT64]; 2762 bt = types[TUINT64];
2680 2763
2681 bound = cheapexpr(conv(bound, bt), init); 2764 bound = cheapexpr(conv(bound, bt), init);
2682 2765
2766 if(cb != N) {
2767 cb = cheapexpr(conv(cb, bt), init);
2768 if(!bounded)
2769 chk0 = nod(OLT, bound, cb);
2770 } else if(slice3) {
2771 // When we figure out what this means, implement it.
2772 fatal("slice3 with cb == N"); // rejected by parser
2773 }
2774 ················
2683 if(hb != N) { 2775 if(hb != N) {
2684 hb = cheapexpr(conv(hb, bt), init); 2776 hb = cheapexpr(conv(hb, bt), init);
2685 » » if(!bounded) 2777 » » if(!bounded) {
2686 » » » chk1 = nod(OLT, bound, hb);·· 2778 » » » if(cb != N)
2779 » » » » chk1 = nod(OLT, cb, hb);
2780 » » » else
2781 » » » » chk1 = nod(OLT, bound, hb);
2782 » » }
2783 » } else if(slice3) {
2784 » » // When we figure out what this means, implement it.
2785 » » fatal("slice3 with hb == N"); // rejected by parser
2687 } else if(n->op == OSLICEARR) { 2786 } else if(n->op == OSLICEARR) {
2688 hb = bound; 2787 hb = bound;
2689 } else { 2788 } else {
2690 hb = nod(OLEN, src, N); 2789 hb = nod(OLEN, src, N);
2691 typecheck(&hb, Erv); 2790 typecheck(&hb, Erv);
2692 walkexpr(&hb, init); 2791 walkexpr(&hb, init);
2693 hb = cheapexpr(conv(hb, bt), init); 2792 hb = cheapexpr(conv(hb, bt), init);
2694 } 2793 }
2695 2794
2696 if(lb != N) { 2795 if(lb != N) {
2697 lb = cheapexpr(conv(lb, bt), init); 2796 lb = cheapexpr(conv(lb, bt), init);
2698 if(!bounded) 2797 if(!bounded)
2699 chk2 = nod(OLT, hb, lb);·· 2798 chk2 = nod(OLT, hb, lb);··
2700 } 2799 }
2701 2800
2702 » if(chk1 != N || chk2 != N) { 2801 » if(chk0 != N || chk1 != N || chk2 != N) {
2703 chk = nod(OIF, N, N); 2802 chk = nod(OIF, N, N);
2704 chk->nbody = list1(mkcall("panicslice", T, init)); 2803 chk->nbody = list1(mkcall("panicslice", T, init));
2705 » » if(chk1 != N) 2804 » » chk->likely = -1;
2706 » » » chk->ntest = chk1; 2805 » » if(chk0 != N)
2806 » » » chk->ntest = chk0;
2807 » » if(chk1 != N) {
2808 » » » if(chk->ntest == N)
2809 » » » » chk->ntest = chk1;
2810 » » » else
2811 » » » » chk->ntest = nod(OOROR, chk->ntest, chk1);
2812 » » }
2707 if(chk2 != N) { 2813 if(chk2 != N) {
2708 if(chk->ntest == N) 2814 if(chk->ntest == N)
2709 chk->ntest = chk2; 2815 chk->ntest = chk2;
2710 else 2816 else
2711 chk->ntest = nod(OOROR, chk->ntest, chk2); 2817 chk->ntest = nod(OOROR, chk->ntest, chk2);
2712 } 2818 }
2713 typecheck(&chk, Etop); 2819 typecheck(&chk, Etop);
2714 walkstmt(&chk); 2820 walkstmt(&chk);
2715 *init = concat(*init, chk->ninit); 2821 *init = concat(*init, chk->ninit);
2716 chk->ninit = nil; 2822 chk->ninit = nil;
2717 *init = list(*init, chk); 2823 *init = list(*init, chk);
2718 } 2824 }
2719 ········ 2825 ········
2720 // prepare new cap, len and offs for backend cgen_slice 2826 // prepare new cap, len and offs for backend cgen_slice
2721 // cap = bound [ - lo ] 2827 // cap = bound [ - lo ]
2722 n->right = N; 2828 n->right = N;
2723 n->list = nil; 2829 n->list = nil;
2830 if(!slice3)
2831 cb = bound;
2724 if(lb == N) 2832 if(lb == N)
2725 » » bound = conv(bound, types[simtype[TUINT]]); 2833 » » bound = conv(cb, types[simtype[TUINT]]);
2726 else 2834 else
2727 » » bound = nod(OSUB, conv(bound, types[simtype[TUINT]]), conv(lb, t ypes[simtype[TUINT]])); 2835 » » bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, type s[simtype[TUINT]]));
2728 typecheck(&bound, Erv); 2836 typecheck(&bound, Erv);
2729 walkexpr(&bound, init); 2837 walkexpr(&bound, init);
2730 n->list = list(n->list, bound); 2838 n->list = list(n->list, bound);
2731 2839
2732 // len = hi [ - lo] 2840 // len = hi [ - lo]
2733 if(lb == N) 2841 if(lb == N)
2734 hb = conv(hb, types[simtype[TUINT]]); 2842 hb = conv(hb, types[simtype[TUINT]]);
2735 else 2843 else
2736 hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[s imtype[TUINT]])); 2844 hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[s imtype[TUINT]]));
2737 typecheck(&hb, Erv); 2845 typecheck(&hb, Erv);
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
3547 !candiscardlist(n->ninit) || 3655 !candiscardlist(n->ninit) ||
3548 !candiscardlist(n->nbody) || 3656 !candiscardlist(n->nbody) ||
3549 !candiscardlist(n->nelse) || 3657 !candiscardlist(n->nelse) ||
3550 !candiscardlist(n->list) || 3658 !candiscardlist(n->list) ||
3551 !candiscardlist(n->rlist)) { 3659 !candiscardlist(n->rlist)) {
3552 return 0; 3660 return 0;
3553 } 3661 }
3554 ········ 3662 ········
3555 return 1; 3663 return 1;
3556 } 3664 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b