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

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 8223559e536b 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 }
303
304 if(n->op == OCONVNOP) {
305 n->op = OEMPTY;
306 n->type = T;
307 } 307 }
308 308
309 if(n->op == ONAME) 309 if(n->op == ONAME)
310 fatal("walkstmt ended up with name: %+N", n); 310 fatal("walkstmt ended up with name: %+N", n);
311 ········ 311 ········
312 *np = n; 312 *np = n;
313 } 313 }
314 314
315 315
316 /* 316 /*
(...skipping 19 matching lines...) Expand all
336 walkexpr(&l->n, init); 336 walkexpr(&l->n, init);
337 } 337 }
338 } 338 }
339 339
340 void 340 void
341 walkexpr(Node **np, NodeList **init) 341 walkexpr(Node **np, NodeList **init)
342 { 342 {
343 Node *r, *l, *var, *a; 343 Node *r, *l, *var, *a;
344 NodeList *ll, *lr, *lpost; 344 NodeList *ll, *lr, *lpost;
345 Type *t; 345 Type *t;
346 » int et; 346 » int et, old_safemode;
347 int64 v; 347 int64 v;
348 int32 lno; 348 int32 lno;
349 Node *n, *fn, *n1, *n2; 349 Node *n, *fn, *n1, *n2;
350 Sym *sym; 350 Sym *sym;
351 char buf[100], *p; 351 char buf[100], *p;
352 352
353 n = *np; 353 n = *np;
354 354
355 if(n == N) 355 if(n == N)
356 return; 356 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 case OCOM: 401 case OCOM:
402 case OREAL: 402 case OREAL:
403 case OIMAG: 403 case OIMAG:
404 case ODOTMETH: 404 case ODOTMETH:
405 case ODOTINTER: 405 case ODOTINTER:
406 walkexpr(&n->left, init); 406 walkexpr(&n->left, init);
407 goto ret; 407 goto ret;
408 408
409 case OIND: 409 case OIND:
410 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.
411 n->left = cheapexpr(n->left, init); 412 n->left = cheapexpr(n->left, init);
412 » » » checknotnil(n->left, init); 413 » » » checknil(n->left, init);
413 } 414 }
414 walkexpr(&n->left, init); 415 walkexpr(&n->left, init);
415 goto ret; 416 goto ret;
416 417
417 case ODOT: 418 case ODOT:
418 usefield(n); 419 usefield(n);
419 walkexpr(&n->left, init); 420 walkexpr(&n->left, init);
420 goto ret; 421 goto ret;
421 422
422 case ODOTPTR: 423 case ODOTPTR:
423 usefield(n); 424 usefield(n);
424 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.
425 n->left = cheapexpr(n->left, init); 427 n->left = cheapexpr(n->left, init);
426 » » » checknotnil(n->left, init); 428 » » » checknil(n->left, init);
427 } 429 }
428 walkexpr(&n->left, init); 430 walkexpr(&n->left, init);
429 goto ret; 431 goto ret;
430 432
431 case OEFACE: 433 case OEFACE:
432 walkexpr(&n->left, init); 434 walkexpr(&n->left, init);
433 walkexpr(&n->right, init); 435 walkexpr(&n->right, init);
434 goto ret; 436 goto ret;
435 437
436 case OSPTR: 438 case OSPTR:
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 case OXOR: 485 case OXOR:
484 walkexpr(&n->left, init); 486 walkexpr(&n->left, init);
485 walkexpr(&n->right, init); 487 walkexpr(&n->right, init);
486 walkrotate(&n); 488 walkrotate(&n);
487 goto ret; 489 goto ret;
488 490
489 case OEQ: 491 case OEQ:
490 case ONE: 492 case ONE:
491 walkexpr(&n->left, init); 493 walkexpr(&n->left, init);
492 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;
493 walkcompare(&n, init); 502 walkcompare(&n, init);
503 safemode = old_safemode;
494 goto ret; 504 goto ret;
495 505
496 case OANDAND: 506 case OANDAND:
497 case OOROR: 507 case OOROR:
498 walkexpr(&n->left, init); 508 walkexpr(&n->left, init);
499 // cannot put side effects from n->right on init, 509 // cannot put side effects from n->right on init,
500 // because they cannot run before n->left is checked. 510 // because they cannot run before n->left is checked.
501 // save elsewhere and store on the eventual n->right. 511 // save elsewhere and store on the eventual n->right.
502 ll = nil; 512 ll = nil;
503 walkexpr(&n->right, &ll); 513 walkexpr(&n->right, &ll);
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 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))
1114 n->left = copyexpr(n->left, n->left->type, init); 1124 n->left = copyexpr(n->left, n->left->type, init);
1115 else 1125 else
1116 n->left = safeexpr(n->left, init); 1126 n->left = safeexpr(n->left, init);
1117 walkexpr(&n->right->left, init); 1127 walkexpr(&n->right->left, init);
1118 n->right->left = safeexpr(n->right->left, init); 1128 n->right->left = safeexpr(n->right->left, init);
1119 walkexpr(&n->right->right, init); 1129 walkexpr(&n->right->right, init);
1120 n->right->right = safeexpr(n->right->right, init); 1130 n->right->right = safeexpr(n->right->right, init);
1121 n = sliceany(n, init); // chops n->right, sets n->list 1131 n = sliceany(n, init); // chops n->right, sets n->list
1122 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;
1123 1154
1124 case OADDR: 1155 case OADDR:
1125 walkexpr(&n->left, init); 1156 walkexpr(&n->left, init);
1126 goto ret; 1157 goto ret;
1127 1158
1128 case ONEW: 1159 case ONEW:
1129 if(n->esc == EscNone && n->type->type->width < (1<<16)) { 1160 if(n->esc == EscNone && n->type->type->width < (1<<16)) {
1130 r = temp(n->type->type); 1161 r = temp(n->type->type);
1131 r = nod(OAS, r, N); // zero temp 1162 r = nod(OAS, r, N); // zero temp
1132 typecheck(&r, Etop); 1163 typecheck(&r, Etop);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 fn = syslook("makemap", 1); 1281 fn = syslook("makemap", 1);
1251 argtype(fn, t->down); // any-1 1282 argtype(fn, t->down); // any-1
1252 argtype(fn, t->type); // any-2 1283 argtype(fn, t->type); // any-2
1253 1284
1254 n = mkcall1(fn, n->type, init, 1285 n = mkcall1(fn, n->type, init,
1255 typename(n->type), 1286 typename(n->type),
1256 conv(n->left, types[TINT64])); 1287 conv(n->left, types[TINT64]));
1257 goto ret; 1288 goto ret;
1258 1289
1259 case OMAKESLICE: 1290 case OMAKESLICE:
1260 // makeslice(t *Type, nel int64, max int64) (ary []any)
1261 l = n->left; 1291 l = n->left;
1262 r = n->right; 1292 r = n->right;
1263 if(r == nil) 1293 if(r == nil)
1264 l = r = safeexpr(l, init); 1294 l = r = safeexpr(l, init);
1265 t = n->type; 1295 t = n->type;
1266 » » fn = syslook("makeslice", 1); 1296 » » if(n->esc == EscNone
1267 » » argtype(fn, t->type);» » » // any-1 1297 » » » && smallintconst(l) && smallintconst(r)
1268 » » n = mkcall1(fn, n->type, init, 1298 » » » && mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width ) {
1269 » » » typename(n->type), 1299 » » » // var arr [r]T
1270 » » » conv(l, types[TINT64]), 1300 » » » // n = arr[:l]
1271 » » » 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 » » }
1272 goto ret; 1320 goto ret;
1273 1321
1274 case ORUNESTR: 1322 case ORUNESTR:
1275 // sys_intstring(v) 1323 // sys_intstring(v)
1276 n = mkcall("intstring", n->type, init, 1324 n = mkcall("intstring", n->type, init,
1277 conv(n->left, types[TINT64])); 1325 conv(n->left, types[TINT64]));
1278 goto ret; 1326 goto ret;
1279 1327
1280 case OARRAYBYTESTR: 1328 case OARRAYBYTESTR:
1281 // slicebytetostring([]byte) string; 1329 // slicebytetostring([]byte) string;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 n = walkclosure(n, init); 1390 n = walkclosure(n, init);
1343 goto ret; 1391 goto ret;
1344 ········ 1392 ········
1345 case OCALLPART: 1393 case OCALLPART:
1346 n = walkpartialcall(n, init); 1394 n = walkpartialcall(n, init);
1347 goto ret; 1395 goto ret;
1348 } 1396 }
1349 fatal("missing switch %O", n->op); 1397 fatal("missing switch %O", n->op);
1350 1398
1351 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
1352 ullmancalc(n); 1411 ullmancalc(n);
1353 1412
1354 if(debug['w'] && n != N) 1413 if(debug['w'] && n != N)
1355 dump("walk", n); 1414 dump("walk", n);
1356 1415
1357 lineno = lno; 1416 lineno = lno;
1358 *np = n; 1417 *np = n;
1359 } 1418 }
1360 1419
1361 static Node* 1420 static Node*
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after
2265 Type *t; 2324 Type *t;
2266 Iter savet; 2325 Iter savet;
2267 Node *v; 2326 Node *v;
2268 NodeList *nn; 2327 NodeList *nn;
2269 2328
2270 nn = nil; 2329 nn = nil;
2271 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) { 2330 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
2272 v = t->nname; 2331 v = t->nname;
2273 if(v && v->sym && v->sym->name[0] == '~') 2332 if(v && v->sym && v->sym->name[0] == '~')
2274 v = N; 2333 v = N;
2275 » » 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))) {
2276 // Defer might stop a panic and show the 2337 // Defer might stop a panic and show the
2277 // return values as they exist at the time of panic. 2338 // return values as they exist at the time of panic.
2278 // Make sure to zero them on entry to the function. 2339 // Make sure to zero them on entry to the function.
2279 nn = list(nn, nod(OAS, nodarg(t, 1), N)); 2340 nn = list(nn, nod(OAS, nodarg(t, 1), N));
2280 } 2341 }
2281 if(v == N || !(v->class & PHEAP)) 2342 if(v == N || !(v->class & PHEAP))
2282 continue; 2343 continue;
2283 2344
2284 // generate allocation & copying code 2345 // generate allocation & copying code
2285 if(v->alloc == nil) 2346 if(v->alloc == nil)
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
2541 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,
2542 typename(ns->type), 2603 typename(ns->type),
2543 ns, 2604 ns,
2544 conv(na, types[TINT64])))); 2605 conv(na, types[TINT64]))));
2545 l = list(l, nx); 2606 l = list(l, nx);
2546 2607
2547 nn = temp(types[TINT]); 2608 nn = temp(types[TINT]);
2548 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)
2549 2610
2550 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 ]
2551 » nx->bounded = 1; 2612 » nx->etype = 1;
2552 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc] 2613 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
2553 2614
2554 for (a = n->list->next; a != nil; a = a->next) { 2615 for (a = n->list->next; a != nil; a = a->next) {
2555 nx = nod(OINDEX, ns, nn); // s[n] ... 2616 nx = nod(OINDEX, ns, nn); // s[n] ...
2556 nx->bounded = 1; 2617 nx->bounded = 1;
2557 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg 2618 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
2558 if (a->next != nil) 2619 if (a->next != nil)
2559 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
2560 } 2621 }
2561 2622
2562 typechecklist(l, Etop); 2623 typechecklist(l, Etop);
2563 walkstmtlist(l); 2624 walkstmtlist(l);
2564 *init = concat(*init, l); 2625 *init = concat(*init, l);
2565 return ns; 2626 return ns;
2566 } 2627 }
2567 2628
2568 // Lower copy(a, b) to a memmove call. 2629 // Lower copy(a, b) to a memmove call.
2569 // 2630 //
2570 // init { 2631 // init {
2571 // n := len(a) 2632 // n := len(a)
2572 // if n > len(b) { n = len(b) } 2633 // if n > len(b) { n = len(b) }
2573 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) 2634 // memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
2574 // } 2635 // }
2575 // l; 2636 // n;
2576 // 2637 //
2577 // Also works if b is a string. 2638 // Also works if b is a string.
2578 // 2639 //
2579 static Node* 2640 static Node*
2580 copyany(Node *n, NodeList **init) 2641 copyany(Node *n, NodeList **init)
2581 { 2642 {
2582 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; 2643 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
2583 NodeList *l; 2644 NodeList *l;
2584 2645
2585 walkexpr(&n->left, init); 2646 walkexpr(&n->left, init);
(...skipping 12 matching lines...) Expand all
2598 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N))); 2659 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N)));
2599 // if n > len(frm) { n = len(frm) } 2660 // if n > len(frm) { n = len(frm) }
2600 nif = nod(OIF, N, N); 2661 nif = nod(OIF, N, N);
2601 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N)); 2662 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N));
2602 nif->nbody = list(nif->nbody, 2663 nif->nbody = list(nif->nbody,
2603 nod(OAS, nlen, nod(OLEN, nr, N))); 2664 nod(OAS, nlen, nod(OLEN, nr, N)));
2604 l = list(l, nif); 2665 l = list(l, nif);
2605 2666
2606 // Call memmove. 2667 // Call memmove.
2607 fn = syslook("memmove", 1); 2668 fn = syslook("memmove", 1);
2669 argtype(fn, nl->type->type);
2670 argtype(fn, nl->type->type);
2608 nwid = temp(types[TUINTPTR]); 2671 nwid = temp(types[TUINTPTR]);
2609 l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR]))); 2672 l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR])));
2610 nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width)); 2673 nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width));
2611 l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid)); 2674 l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid));
2612 2675
2613 typechecklist(l, Etop); 2676 typechecklist(l, Etop);
2614 walkstmtlist(l); 2677 walkstmtlist(l);
2615 *init = concat(*init, l); 2678 *init = concat(*init, l);
2616 return nlen; 2679 return nlen;
2617 } 2680 }
2618 2681
2619 // Generate frontend part for OSLICE[ARR|STR] 2682 // Generate frontend part for OSLICE[3][ARR|STR]
2620 //· 2683 //·
2621 static Node* 2684 static Node*
2622 sliceany(Node* n, NodeList **init) 2685 sliceany(Node* n, NodeList **init)
2623 { 2686 {
2624 » int bounded; 2687 » int bounded, slice3;
2625 » Node *src, *lb, *hb, *bound, *chk, *chk1, *chk2; 2688 » Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
2626 » int64 lbv, hbv, bv, w; 2689 » int64 lbv, hbv, cbv, bv, w;
2627 Type *bt; 2690 Type *bt;
2628 2691
2629 // print("before sliceany: %+N\n", n); 2692 // print("before sliceany: %+N\n", n);
2630 2693
2631 src = n->left; 2694 src = n->left;
2632 lb = n->right->left; 2695 lb = n->right->left;
2633 » 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 » }
2634 2704
2635 bounded = n->etype; 2705 bounded = n->etype;
2636 ········ 2706 ········
2637 if(n->op == OSLICESTR) 2707 if(n->op == OSLICESTR)
2638 bound = nod(OLEN, src, N); 2708 bound = nod(OLEN, src, N);
2639 else 2709 else
2640 bound = nod(OCAP, src, N); 2710 bound = nod(OCAP, src, N);
2641 2711
2642 typecheck(&bound, Erv); 2712 typecheck(&bound, Erv);
2643 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.
2644 2714
2645 // static checks if possible 2715 // static checks if possible
2646 bv = 1LL<<50; 2716 bv = 1LL<<50;
2647 if(isconst(bound, CTINT)) { 2717 if(isconst(bound, CTINT)) {
2648 if(!smallintconst(bound)) 2718 if(!smallintconst(bound))
2649 yyerror("array len too large"); 2719 yyerror("array len too large");
2650 else 2720 else
2651 bv = mpgetfix(bound->val.u.xval); 2721 bv = mpgetfix(bound->val.u.xval);
2652 } 2722 }
2653 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 }
2654 if(isconst(hb, CTINT)) { 2731 if(isconst(hb, CTINT)) {
2655 hbv = mpgetfix(hb->val.u.xval); 2732 hbv = mpgetfix(hb->val.u.xval);
2656 if(hbv < 0 || hbv > bv) { 2733 if(hbv < 0 || hbv > bv) {
2657 yyerror("slice index out of bounds"); 2734 yyerror("slice index out of bounds");
2658 hbv = -1; 2735 hbv = -1;
2659 } 2736 }
2660 } 2737 }
2661 if(isconst(lb, CTINT)) { 2738 if(isconst(lb, CTINT)) {
2662 lbv = mpgetfix(lb->val.u.xval); 2739 lbv = mpgetfix(lb->val.u.xval);
2663 if(lbv < 0 || lbv > bv) { 2740 if(lbv < 0 || lbv > bv) {
2664 yyerror("slice index out of bounds"); 2741 yyerror("slice index out of bounds");
2665 lbv = -1; 2742 lbv = -1;
2666 } 2743 }
2667 if(lbv == 0) 2744 if(lbv == 0)
2668 lb = N; 2745 lb = N;
2669 } 2746 }
2670 2747
2671 // 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
2672 // generate 2749 // generate
2673 // if hb > bound || lb > hb { panicslice() } 2750 // if hb > bound || lb > hb { panicslice() }
2674 chk = N; 2751 chk = N;
2752 chk0 = N;
2675 chk1 = N; 2753 chk1 = N;
2676 chk2 = N; 2754 chk2 = N;
2677 2755
2678 bt = types[simtype[TUINT]]; 2756 bt = types[simtype[TUINT]];
2757 if(cb != N && cb->type->width > 4)
2758 bt = types[TUINT64];
2679 if(hb != N && hb->type->width > 4) 2759 if(hb != N && hb->type->width > 4)
2680 bt = types[TUINT64]; 2760 bt = types[TUINT64];
2681 if(lb != N && lb->type->width > 4) 2761 if(lb != N && lb->type->width > 4)
2682 bt = types[TUINT64]; 2762 bt = types[TUINT64];
2683 2763
2684 bound = cheapexpr(conv(bound, bt), init); 2764 bound = cheapexpr(conv(bound, bt), init);
2685 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 ················
2686 if(hb != N) { 2775 if(hb != N) {
2687 hb = cheapexpr(conv(hb, bt), init); 2776 hb = cheapexpr(conv(hb, bt), init);
2688 » » if(!bounded) 2777 » » if(!bounded) {
2689 » » » 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
2690 } else if(n->op == OSLICEARR) { 2786 } else if(n->op == OSLICEARR) {
2691 hb = bound; 2787 hb = bound;
2692 } else { 2788 } else {
2693 hb = nod(OLEN, src, N); 2789 hb = nod(OLEN, src, N);
2694 typecheck(&hb, Erv); 2790 typecheck(&hb, Erv);
2695 walkexpr(&hb, init); 2791 walkexpr(&hb, init);
2696 hb = cheapexpr(conv(hb, bt), init); 2792 hb = cheapexpr(conv(hb, bt), init);
2697 } 2793 }
2698 2794
2699 if(lb != N) { 2795 if(lb != N) {
2700 lb = cheapexpr(conv(lb, bt), init); 2796 lb = cheapexpr(conv(lb, bt), init);
2701 if(!bounded) 2797 if(!bounded)
2702 chk2 = nod(OLT, hb, lb);·· 2798 chk2 = nod(OLT, hb, lb);··
2703 } 2799 }
2704 2800
2705 » if(chk1 != N || chk2 != N) { 2801 » if(chk0 != N || chk1 != N || chk2 != N) {
2706 chk = nod(OIF, N, N); 2802 chk = nod(OIF, N, N);
2707 chk->nbody = list1(mkcall("panicslice", T, init)); 2803 chk->nbody = list1(mkcall("panicslice", T, init));
2708 » » if(chk1 != N) 2804 » » chk->likely = -1;
2709 » » » 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 » » }
2710 if(chk2 != N) { 2813 if(chk2 != N) {
2711 if(chk->ntest == N) 2814 if(chk->ntest == N)
2712 chk->ntest = chk2; 2815 chk->ntest = chk2;
2713 else 2816 else
2714 chk->ntest = nod(OOROR, chk->ntest, chk2); 2817 chk->ntest = nod(OOROR, chk->ntest, chk2);
2715 } 2818 }
2716 typecheck(&chk, Etop); 2819 typecheck(&chk, Etop);
2717 walkstmt(&chk); 2820 walkstmt(&chk);
2718 *init = concat(*init, chk->ninit); 2821 *init = concat(*init, chk->ninit);
2719 chk->ninit = nil; 2822 chk->ninit = nil;
2720 *init = list(*init, chk); 2823 *init = list(*init, chk);
2721 } 2824 }
2722 ········ 2825 ········
2723 // prepare new cap, len and offs for backend cgen_slice 2826 // prepare new cap, len and offs for backend cgen_slice
2724 // cap = bound [ - lo ] 2827 // cap = bound [ - lo ]
2725 n->right = N; 2828 n->right = N;
2726 n->list = nil; 2829 n->list = nil;
2830 if(!slice3)
2831 cb = bound;
2727 if(lb == N) 2832 if(lb == N)
2728 » » bound = conv(bound, types[simtype[TUINT]]); 2833 » » bound = conv(cb, types[simtype[TUINT]]);
2729 else 2834 else
2730 » » 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]]));
2731 typecheck(&bound, Erv); 2836 typecheck(&bound, Erv);
2732 walkexpr(&bound, init); 2837 walkexpr(&bound, init);
2733 n->list = list(n->list, bound); 2838 n->list = list(n->list, bound);
2734 2839
2735 // len = hi [ - lo] 2840 // len = hi [ - lo]
2736 if(lb == N) 2841 if(lb == N)
2737 hb = conv(hb, types[simtype[TUINT]]); 2842 hb = conv(hb, types[simtype[TUINT]]);
2738 else 2843 else
2739 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]]));
2740 typecheck(&hb, Erv); 2845 typecheck(&hb, Erv);
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
3550 !candiscardlist(n->ninit) || 3655 !candiscardlist(n->ninit) ||
3551 !candiscardlist(n->nbody) || 3656 !candiscardlist(n->nbody) ||
3552 !candiscardlist(n->nelse) || 3657 !candiscardlist(n->nelse) ||
3553 !candiscardlist(n->list) || 3658 !candiscardlist(n->list) ||
3554 !candiscardlist(n->rlist)) { 3659 !candiscardlist(n->rlist)) {
3555 return 0; 3660 return 0;
3556 } 3661 }
3557 ········ 3662 ········
3558 return 1; 3663 return 1;
3559 } 3664 }
LEFTRIGHT

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