LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 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 // Rewrite tree to use separate statements to enforce | 5 // Rewrite tree to use separate statements to enforce |
6 // order of evaluation. Makes walk easier, because it | 6 // order of evaluation. Makes walk easier, because it |
7 // can (after this runs) reorder at will within an expression. | 7 // can (after this runs) reorder at will within an expression. |
8 // | 8 // |
9 // Rewrite x op= y into x = x op y. | 9 // Rewrite x op= y into x = x op y. |
10 // | 10 // |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 | 586 |
587 case OAS2RECV: | 587 case OAS2RECV: |
588 // Special: avoid copy of receive. | 588 // Special: avoid copy of receive. |
589 // Use temporary variables to hold result, | 589 // Use temporary variables to hold result, |
590 // so that chanrecv can take address of temporary. | 590 // so that chanrecv can take address of temporary. |
591 t = marktemp(order); | 591 t = marktemp(order); |
592 orderexprlist(n->list, order); | 592 orderexprlist(n->list, order); |
593 orderexpr(&n->rlist->n->left, order); // arg to recv | 593 orderexpr(&n->rlist->n->left, order); // arg to recv |
594 ch = n->rlist->n->left->type; | 594 ch = n->rlist->n->left->type; |
595 tmp1 = ordertemp(ch->type, order, haspointers(ch->type)); | 595 tmp1 = ordertemp(ch->type, order, haspointers(ch->type)); |
596 » » tmp2 = ordertemp(types[TBOOL], order, 0); | 596 » » if(!isblank(n->list->next->n)) |
| 597 » » » tmp2 = ordertemp(n->list->next->n->type, order, 0); |
| 598 » » else |
| 599 » » » tmp2 = ordertemp(types[TBOOL], order, 0); |
597 order->out = list(order->out, n); | 600 order->out = list(order->out, n); |
598 r = nod(OAS, n->list->n, tmp1); | 601 r = nod(OAS, n->list->n, tmp1); |
599 typecheck(&r, Etop); | 602 typecheck(&r, Etop); |
600 ordermapassign(r, order); | 603 ordermapassign(r, order); |
601 r = nod(OAS, n->list->next->n, tmp2); | 604 r = nod(OAS, n->list->next->n, tmp2); |
602 typecheck(&r, Etop); | 605 typecheck(&r, Etop); |
603 ordermapassign(r, order); | 606 ordermapassign(r, order); |
604 n->list = list(list1(tmp1), tmp2); | 607 n->list = list(list1(tmp1), tmp2); |
605 cleantemp(t, order); | 608 cleantemp(t, order); |
606 break; | 609 break; |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 | 764 |
762 case ORETURN: | 765 case ORETURN: |
763 ordercallargs(&n->list, order); | 766 ordercallargs(&n->list, order); |
764 order->out = list(order->out, n); | 767 order->out = list(order->out, n); |
765 break; | 768 break; |
766 ········ | 769 ········ |
767 case OSELECT: | 770 case OSELECT: |
768 // Special: clean case temporaries in each block entry. | 771 // Special: clean case temporaries in each block entry. |
769 // Select must enter one of its blocks, so there is no | 772 // Select must enter one of its blocks, so there is no |
770 // need for a cleaning at the end. | 773 // need for a cleaning at the end. |
| 774 // Doubly special: evaluation order for select is stricter |
| 775 // than ordinary expressions. Even something like p.c |
| 776 // has to be hoisted into a temporary, so that it cannot be |
| 777 // reordered after the channel evaluation for a different |
| 778 // case (if p were nil, then the timing of the fault would |
| 779 // give this away). |
771 t = marktemp(order); | 780 t = marktemp(order); |
772 for(l=n->list; l; l=l->next) { | 781 for(l=n->list; l; l=l->next) { |
773 if(l->n->op != OXCASE) | 782 if(l->n->op != OXCASE) |
774 fatal("order select case %O", l->n->op); | 783 fatal("order select case %O", l->n->op); |
775 r = l->n->left; | 784 r = l->n->left; |
776 setlineno(l->n); | 785 setlineno(l->n); |
777 // Append any new body prologue to ninit. | 786 // Append any new body prologue to ninit. |
778 // The next loop will insert ninit into nbody. | 787 // The next loop will insert ninit into nbody. |
779 if(l->n->ninit != nil) | 788 if(l->n->ninit != nil) |
780 fatal("order select ninit"); | 789 fatal("order select ninit"); |
(...skipping 22 matching lines...) Expand all Loading... |
803 if(r->ninit != nil) { | 812 if(r->ninit != nil) { |
804 yyerror("ninit on select recv"); | 813 yyerror("ninit on select recv"); |
805 dumplist("ninit", r->ninit); | 814 dumplist("ninit", r->ninit); |
806 } | 815 } |
807 // case x = <-c | 816 // case x = <-c |
808 // case x, ok = <-c | 817 // case x, ok = <-c |
809 // r->left is x, r->ntest is ok, r->righ
t is ORECV, r->right->left is c. | 818 // r->left is x, r->ntest is ok, r->righ
t is ORECV, r->right->left is c. |
810 // r->left == N means 'case <-c'. | 819 // r->left == N means 'case <-c'. |
811 // c is always evaluated; x and ok are o
nly evaluated when assigned. | 820 // c is always evaluated; x and ok are o
nly evaluated when assigned. |
812 orderexpr(&r->right->left, order); | 821 orderexpr(&r->right->left, order); |
| 822 if(r->right->left->op != ONAME) |
| 823 r->right->left = ordercopyexpr(r
->right->left, r->right->left->type, order, 0); |
813 | 824 |
814 // Introduce temporary for receive and m
ove actual copy into case body. | 825 // Introduce temporary for receive and m
ove actual copy into case body. |
815 // avoids problems with target being add
ressed, as usual. | 826 // avoids problems with target being add
ressed, as usual. |
816 // NOTE: If we wanted to be clever, we c
ould arrange for just one | 827 // NOTE: If we wanted to be clever, we c
ould arrange for just one |
817 // temporary per distinct type, sharing
the temp among all receives | 828 // temporary per distinct type, sharing
the temp among all receives |
818 // with that temp. Similarly one ok bool
could be shared among all | 829 // with that temp. Similarly one ok bool
could be shared among all |
819 // the x,ok receives. Not worth doing un
til there's a clear need. | 830 // the x,ok receives. Not worth doing un
til there's a clear need. |
820 if(r->left != N && isblank(r->left)) | 831 if(r->left != N && isblank(r->left)) |
821 r->left = N; | 832 r->left = N; |
822 if(r->left != N) { | 833 if(r->left != N) { |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 // completes. We could be more aggressive and try to arr
ange for it | 1059 // completes. We could be more aggressive and try to arr
ange for it |
1049 // to be cleaned up when the call completes. | 1060 // to be cleaned up when the call completes. |
1050 n->alloc = ordertemp(n->type->type, order, 0); | 1061 n->alloc = ordertemp(n->type->type, order, 0); |
1051 } | 1062 } |
1052 break; | 1063 break; |
1053 | 1064 |
1054 case ORECV: | 1065 case ORECV: |
1055 orderexpr(&n->left, order); | 1066 orderexpr(&n->left, order); |
1056 n = ordercopyexpr(n, n->type, order, 1); | 1067 n = ordercopyexpr(n, n->type, order, 1); |
1057 break; | 1068 break; |
| 1069 |
| 1070 case OEQ: |
| 1071 case ONE: |
| 1072 orderexpr(&n->left, order); |
| 1073 orderexpr(&n->right, order); |
| 1074 t = n->left->type; |
| 1075 if(t->etype == TSTRUCT || isfixedarray(t)) { |
| 1076 // for complex comparisons, we need both args to be |
| 1077 // addressable so we can pass them to the runtime. |
| 1078 orderaddrtemp(&n->left, order); |
| 1079 orderaddrtemp(&n->right, order); |
| 1080 } |
| 1081 break; |
1058 } | 1082 } |
1059 ········ | 1083 ········ |
1060 lineno = lno; | 1084 lineno = lno; |
1061 | 1085 |
1062 *np = n; | 1086 *np = n; |
1063 } | 1087 } |
LEFT | RIGHT |