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