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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 case OXOR: | 485 case OXOR: |
486 walkexpr(&n->left, init); | 486 walkexpr(&n->left, init); |
487 walkexpr(&n->right, init); | 487 walkexpr(&n->right, init); |
488 walkrotate(&n); | 488 walkrotate(&n); |
489 goto ret; | 489 goto ret; |
490 | 490 |
491 case OEQ: | 491 case OEQ: |
492 case ONE: | 492 case ONE: |
493 walkexpr(&n->left, init); | 493 walkexpr(&n->left, init); |
494 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; |
495 walkcompare(&n, init); | 502 walkcompare(&n, init); |
| 503 safemode = old_safemode; |
496 goto ret; | 504 goto ret; |
497 | 505 |
498 case OANDAND: | 506 case OANDAND: |
499 case OOROR: | 507 case OOROR: |
500 walkexpr(&n->left, init); | 508 walkexpr(&n->left, init); |
501 // cannot put side effects from n->right on init, | 509 // cannot put side effects from n->right on init, |
502 // because they cannot run before n->left is checked. | 510 // because they cannot run before n->left is checked. |
503 // save elsewhere and store on the eventual n->right. | 511 // save elsewhere and store on the eventual n->right. |
504 ll = nil; | 512 ll = nil; |
505 walkexpr(&n->right, &ll); | 513 walkexpr(&n->right, &ll); |
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 goto ret; | 1391 goto ret; |
1384 } | 1392 } |
1385 fatal("missing switch %O", n->op); | 1393 fatal("missing switch %O", n->op); |
1386 | 1394 |
1387 ret: | 1395 ret: |
1388 // Expressions that are constant at run time but not | 1396 // Expressions that are constant at run time but not |
1389 // considered const by the language spec are not turned into | 1397 // considered const by the language spec are not turned into |
1390 // constants until walk. For example, if n is y%1 == 0, the | 1398 // constants until walk. For example, if n is y%1 == 0, the |
1391 // walk of y%1 may have replaced it by 0. | 1399 // walk of y%1 may have replaced it by 0. |
1392 // Check whether n with its updated args is itself now a constant. | 1400 // Check whether n with its updated args is itself now a constant. |
| 1401 t = n->type; |
1393 evconst(n); | 1402 evconst(n); |
| 1403 n->type = t; |
| 1404 if(n->op == OLITERAL) |
| 1405 typecheck(&n, Erv); |
1394 | 1406 |
1395 ullmancalc(n); | 1407 ullmancalc(n); |
1396 | 1408 |
1397 if(debug['w'] && n != N) | 1409 if(debug['w'] && n != N) |
1398 dump("walk", n); | 1410 dump("walk", n); |
1399 | 1411 |
1400 lineno = lno; | 1412 lineno = lno; |
1401 *np = n; | 1413 *np = n; |
1402 } | 1414 } |
1403 | 1415 |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2518 typecheck(&r, Erv); | 2530 typecheck(&r, Erv); |
2519 walkexpr(&r, init); | 2531 walkexpr(&r, init); |
2520 r->type = n->type; | 2532 r->type = n->type; |
2521 | 2533 |
2522 return r; | 2534 return r; |
2523 } | 2535 } |
2524 | 2536 |
2525 // expand append(l1, l2...) to | 2537 // expand append(l1, l2...) to |
2526 // init { | 2538 // init { |
2527 // s := l1 | 2539 // s := l1 |
2528 // if cap(s) < len(l1) + len(l2) { | 2540 // if n := len(l1) + len(l2) - cap(s); n > 0 { |
2529 // s = growslice(s, len(l2) | 2541 // s = growslice(s, n) |
2530 // } | 2542 // } |
2531 // s = s[:len(l1)+len(l2)] | 2543 // s = s[:len(l1)+len(l2)] |
2532 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) | 2544 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) |
2533 // } | 2545 // } |
2534 // s | 2546 // s |
2535 // | 2547 // |
2536 // l2 is allowed to be a string. | 2548 // l2 is allowed to be a string. |
2537 static Node* | 2549 static Node* |
2538 appendslice(Node *n, NodeList **init) | 2550 appendslice(Node *n, NodeList **init) |
2539 { | 2551 { |
(...skipping 10 matching lines...) Expand all Loading... |
2550 for(l=n->list; l; l=l->next) | 2562 for(l=n->list; l; l=l->next) |
2551 l->n = cheapexpr(l->n, init); | 2563 l->n = cheapexpr(l->n, init); |
2552 | 2564 |
2553 l1 = n->list->n; | 2565 l1 = n->list->n; |
2554 l2 = n->list->next->n; | 2566 l2 = n->list->next->n; |
2555 | 2567 |
2556 s = temp(l1->type); // var s []T | 2568 s = temp(l1->type); // var s []T |
2557 l = nil; | 2569 l = nil; |
2558 l = list(l, nod(OAS, s, l1)); // s = l1 | 2570 l = list(l, nod(OAS, s, l1)); // s = l1 |
2559 | 2571 |
| 2572 nt = temp(types[TINT]); |
2560 nif = nod(OIF, N, N); | 2573 nif = nod(OIF, N, N); |
2561 » nif->ntest = nod(OLT, | 2574 » // n := len(s) + len(l2) - cap(s) |
2562 » » nod(OSUB, nod(OCAP, s, N), nod(OLEN, s, N)), | 2575 » nif->ninit = list1(nod(OAS, nt, |
2563 » » nod(OLEN, l2, N)); // if cap(s) - len(s) < len(l2)... | 2576 » » nod(OSUB, nod(OADD, nod(OLEN, s, N), nod(OLEN, l2, N)), nod(OCAP
, s, N)))); |
2564 | 2577 » nif->ntest = nod(OGT, nt, nodintconst(0)); |
2565 // instantiate growslice(Type*, []any, int64) []any | 2578 // instantiate growslice(Type*, []any, int64) []any |
2566 fn = syslook("growslice", 1); | 2579 fn = syslook("growslice", 1); |
2567 argtype(fn, s->type->type); | 2580 argtype(fn, s->type->type); |
2568 argtype(fn, s->type->type); | 2581 argtype(fn, s->type->type); |
2569 | 2582 |
2570 » // s = growslice(T, s, len(l2)) | 2583 » // s = growslice(T, s, n) |
2571 nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit, | 2584 nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit, |
2572 typename(s->type), | 2585 typename(s->type), |
2573 s, | 2586 s, |
2574 » » » » » conv(nod(OLEN, l2, N), types[TINT
64])))); | 2587 » » » » » conv(nt, types[TINT64])))); |
2575 | 2588 |
2576 l = list(l, nif); | 2589 l = list(l, nif); |
2577 | 2590 |
2578 if(flag_race) { | 2591 if(flag_race) { |
2579 // rely on runtime to instrument copy. | 2592 // rely on runtime to instrument copy. |
2580 // copy(s[len(l1):len(l1)+len(l2)], l2) | 2593 // copy(s[len(l1):len(l1)+len(l2)], l2) |
2581 nptr1 = nod(OSLICE, s, nod(OKEY, | 2594 nptr1 = nod(OSLICE, s, nod(OKEY, |
2582 nod(OLEN, l1, N), | 2595 nod(OLEN, l1, N), |
2583 nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N)))); | 2596 nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N)))); |
2584 nptr1->etype = 1; | 2597 nptr1->etype = 1; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2695 walkstmtlist(l); | 2708 walkstmtlist(l); |
2696 *init = concat(*init, l); | 2709 *init = concat(*init, l); |
2697 return ns; | 2710 return ns; |
2698 } | 2711 } |
2699 | 2712 |
2700 // Lower copy(a, b) to a memmove call. | 2713 // Lower copy(a, b) to a memmove call. |
2701 // | 2714 // |
2702 // init { | 2715 // init { |
2703 // n := len(a) | 2716 // n := len(a) |
2704 // if n > len(b) { n = len(b) } | 2717 // if n > len(b) { n = len(b) } |
2705 // if sizeof(a[0]) == 1 && n == 1 { | 2718 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) |
2706 // a[0] = b[0] | |
2707 // } else { | |
2708 // memmove(a.ptr, b.ptr, n*sizeof(elem(a))) | |
2709 // } | |
2710 // } | 2719 // } |
2711 // l; | 2720 // n; |
2712 // | 2721 // |
2713 // Also works if b is a string. | 2722 // Also works if b is a string. |
2714 // | 2723 // |
2715 static Node* | 2724 static Node* |
2716 copyany(Node *n, NodeList **init) | 2725 copyany(Node *n, NodeList **init) |
2717 { | 2726 { |
2718 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; | 2727 Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; |
2719 NodeList *l; | 2728 NodeList *l; |
2720 | 2729 |
2721 walkexpr(&n->left, init); | 2730 walkexpr(&n->left, init); |
(...skipping 11 matching lines...) Expand all Loading... |
2733 // n = len(to) | 2742 // n = len(to) |
2734 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N))); | 2743 l = list(l, nod(OAS, nlen, nod(OLEN, nl, N))); |
2735 // if n > len(frm) { n = len(frm) } | 2744 // if n > len(frm) { n = len(frm) } |
2736 nif = nod(OIF, N, N); | 2745 nif = nod(OIF, N, N); |
2737 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N)); | 2746 nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N)); |
2738 nif->nbody = list(nif->nbody, | 2747 nif->nbody = list(nif->nbody, |
2739 nod(OAS, nlen, nod(OLEN, nr, N))); | 2748 nod(OAS, nlen, nod(OLEN, nr, N))); |
2740 l = list(l, nif); | 2749 l = list(l, nif); |
2741 | 2750 |
2742 // Call memmove. | 2751 // Call memmove. |
2743 » if(nl->type->type->width == 1) { | 2752 » fn = syslook("memmove", 1); |
2744 » » nif = nod(OIF, N, N); | 2753 » argtype(fn, nl->type->type); |
2745 » » nif->ntest = nod(OEQ, nlen, nodintconst(1)); | 2754 » argtype(fn, nl->type->type); |
2746 » » // a[0] = b[0] | 2755 » nwid = temp(types[TUINTPTR]); |
2747 » » nif->nbody = list(nif->nbody, nod(OAS, | 2756 » l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR]))); |
2748 » » » » » nod(OINDEX, nl, nodintconst(0)), | 2757 » nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width)); |
2749 » » » » » nod(OINDEX, nr, nodintconst(0)))); | 2758 » l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid)); |
2750 » » nif->nbody->n->left->bounded = 1; | |
2751 » » nif->nbody->n->right->bounded = 1; | |
2752 | |
2753 » » fn = syslook("memmove", 1); | |
2754 » » argtype(fn, nl->type->type); | |
2755 » » argtype(fn, nl->type->type); | |
2756 » » nif->nelse = list(nif->nelse, mkcall1(fn, T, init, nto, nfrm, co
nv(nlen, types[TUINTPTR]))); | |
2757 » » l = list(l, nif); | |
2758 » } else { | |
2759 » » fn = syslook("memmove", 1); | |
2760 » » argtype(fn, nl->type->type); | |
2761 » » argtype(fn, nl->type->type); | |
2762 » » nwid = temp(types[TUINTPTR]); | |
2763 » » l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR]))); | |
2764 » » nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width)); | |
2765 » » l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid)); | |
2766 » } | |
2767 | 2759 |
2768 typechecklist(l, Etop); | 2760 typechecklist(l, Etop); |
2769 walkstmtlist(l); | 2761 walkstmtlist(l); |
2770 *init = concat(*init, l); | 2762 *init = concat(*init, l); |
2771 return nlen; | 2763 return nlen; |
2772 } | 2764 } |
2773 | 2765 |
2774 // Generate frontend part for OSLICE[3][ARR|STR] | 2766 // Generate frontend part for OSLICE[3][ARR|STR] |
2775 //· | 2767 //· |
2776 static Node* | 2768 static Node* |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2886 | 2878 |
2887 if(lb != N) { | 2879 if(lb != N) { |
2888 lb = cheapexpr(conv(lb, bt), init); | 2880 lb = cheapexpr(conv(lb, bt), init); |
2889 if(!bounded) | 2881 if(!bounded) |
2890 chk2 = nod(OLT, hb, lb);·· | 2882 chk2 = nod(OLT, hb, lb);·· |
2891 } | 2883 } |
2892 | 2884 |
2893 if(chk0 != N || chk1 != N || chk2 != N) { | 2885 if(chk0 != N || chk1 != N || chk2 != N) { |
2894 chk = nod(OIF, N, N); | 2886 chk = nod(OIF, N, N); |
2895 chk->nbody = list1(mkcall("panicslice", T, init)); | 2887 chk->nbody = list1(mkcall("panicslice", T, init)); |
| 2888 chk->likely = -1; |
2896 if(chk0 != N) | 2889 if(chk0 != N) |
2897 chk->ntest = chk0; | 2890 chk->ntest = chk0; |
2898 if(chk1 != N) { | 2891 if(chk1 != N) { |
2899 if(chk->ntest == N) | 2892 if(chk->ntest == N) |
2900 chk->ntest = chk1; | 2893 chk->ntest = chk1; |
2901 else | 2894 else |
2902 chk->ntest = nod(OOROR, chk->ntest, chk1); | 2895 chk->ntest = nod(OOROR, chk->ntest, chk1); |
2903 } | 2896 } |
2904 if(chk2 != N) { | 2897 if(chk2 != N) { |
2905 if(chk->ntest == N) | 2898 if(chk->ntest == N) |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3746 !candiscardlist(n->ninit) || | 3739 !candiscardlist(n->ninit) || |
3747 !candiscardlist(n->nbody) || | 3740 !candiscardlist(n->nbody) || |
3748 !candiscardlist(n->nelse) || | 3741 !candiscardlist(n->nelse) || |
3749 !candiscardlist(n->list) || | 3742 !candiscardlist(n->list) || |
3750 !candiscardlist(n->rlist)) { | 3743 !candiscardlist(n->rlist)) { |
3751 return 0; | 3744 return 0; |
3752 } | 3745 } |
3753 ········ | 3746 ········ |
3754 return 1; | 3747 return 1; |
3755 } | 3748 } |
LEFT | RIGHT |