LEFT | RIGHT |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
LEFT | RIGHT |