Source file src/pkg/cmd/compile/internal/gc/order.go
1
2
3
4
5 package gc
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/src"
10 "fmt"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 type Order struct {
45 out []*Node
46 temp []*Node
47 free map[string][]*Node
48 }
49
50
51
52 func order(fn *Node) {
53 if Debug['W'] > 1 {
54 s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
55 dumplist(s, fn.Nbody)
56 }
57
58 orderBlock(&fn.Nbody, map[string][]*Node{})
59 }
60
61
62
63
64 func (o *Order) newTemp(t *types.Type, clear bool) *Node {
65 var v *Node
66
67
68 key := t.LongString()
69 a := o.free[key]
70 for i, n := range a {
71 if types.Identical(t, n.Type) {
72 v = a[i]
73 a[i] = a[len(a)-1]
74 a = a[:len(a)-1]
75 o.free[key] = a
76 break
77 }
78 }
79 if v == nil {
80 v = temp(t)
81 }
82 if clear {
83 a := nod(OAS, v, nil)
84 a = typecheck(a, ctxStmt)
85 o.out = append(o.out, a)
86 }
87
88 o.temp = append(o.temp, v)
89 return v
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104 func (o *Order) copyExpr(n *Node, t *types.Type, clear bool) *Node {
105 v := o.newTemp(t, clear)
106 a := nod(OAS, v, n)
107 a = typecheck(a, ctxStmt)
108 o.out = append(o.out, a)
109 return v
110 }
111
112
113
114
115
116 func (o *Order) cheapExpr(n *Node) *Node {
117 if n == nil {
118 return nil
119 }
120
121 switch n.Op {
122 case ONAME, OLITERAL:
123 return n
124 case OLEN, OCAP:
125 l := o.cheapExpr(n.Left)
126 if l == n.Left {
127 return n
128 }
129 a := n.sepcopy()
130 a.Left = l
131 return typecheck(a, ctxExpr)
132 }
133
134 return o.copyExpr(n, n.Type, false)
135 }
136
137
138
139
140
141
142
143
144 func (o *Order) safeExpr(n *Node) *Node {
145 switch n.Op {
146 case ONAME, OLITERAL:
147 return n
148
149 case ODOT, OLEN, OCAP:
150 l := o.safeExpr(n.Left)
151 if l == n.Left {
152 return n
153 }
154 a := n.sepcopy()
155 a.Left = l
156 return typecheck(a, ctxExpr)
157
158 case ODOTPTR, ODEREF:
159 l := o.cheapExpr(n.Left)
160 if l == n.Left {
161 return n
162 }
163 a := n.sepcopy()
164 a.Left = l
165 return typecheck(a, ctxExpr)
166
167 case OINDEX, OINDEXMAP:
168 var l *Node
169 if n.Left.Type.IsArray() {
170 l = o.safeExpr(n.Left)
171 } else {
172 l = o.cheapExpr(n.Left)
173 }
174 r := o.cheapExpr(n.Right)
175 if l == n.Left && r == n.Right {
176 return n
177 }
178 a := n.sepcopy()
179 a.Left = l
180 a.Right = r
181 return typecheck(a, ctxExpr)
182
183 default:
184 Fatalf("ordersafeexpr %v", n.Op)
185 return nil
186 }
187 }
188
189
190
191
192
193
194
195 func isaddrokay(n *Node) bool {
196 return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp())
197 }
198
199
200
201
202
203
204 func (o *Order) addrTemp(n *Node) *Node {
205 if consttype(n) > 0 {
206
207 n = defaultlit(n, nil)
208 dowidth(n.Type)
209 vstat := staticname(n.Type)
210 vstat.Name.SetReadonly(true)
211 var s InitSchedule
212 s.staticassign(vstat, n)
213 if s.out != nil {
214 Fatalf("staticassign of const generated code: %+v", n)
215 }
216 vstat = typecheck(vstat, ctxExpr)
217 return vstat
218 }
219 if isaddrokay(n) {
220 return n
221 }
222 return o.copyExpr(n, n.Type, false)
223 }
224
225
226
227 func (o *Order) mapKeyTemp(t *types.Type, n *Node) *Node {
228
229
230 if mapfast(t) == mapslow {
231 return o.addrTemp(n)
232 }
233 return n
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 func mapKeyReplaceStrConv(n *Node) bool {
251 var replaced bool
252 switch n.Op {
253 case OBYTES2STR:
254 n.Op = OBYTES2STRTMP
255 replaced = true
256 case OSTRUCTLIT:
257 for _, elem := range n.List.Slice() {
258 if mapKeyReplaceStrConv(elem.Left) {
259 replaced = true
260 }
261 }
262 case OARRAYLIT:
263 for _, elem := range n.List.Slice() {
264 if elem.Op == OKEY {
265 elem = elem.Right
266 }
267 if mapKeyReplaceStrConv(elem) {
268 replaced = true
269 }
270 }
271 }
272 return replaced
273 }
274
275 type ordermarker int
276
277
278 func (o *Order) markTemp() ordermarker {
279 return ordermarker(len(o.temp))
280 }
281
282
283
284 func (o *Order) popTemp(mark ordermarker) {
285 for _, n := range o.temp[mark:] {
286 key := n.Type.LongString()
287 o.free[key] = append(o.free[key], n)
288 }
289 o.temp = o.temp[:mark]
290 }
291
292
293
294
295 func (o *Order) cleanTempNoPop(mark ordermarker) []*Node {
296 var out []*Node
297 for i := len(o.temp) - 1; i >= int(mark); i-- {
298 n := o.temp[i]
299 if n.Name.Keepalive() {
300 n.Name.SetKeepalive(false)
301 n.SetAddrtaken(true)
302 live := nod(OVARLIVE, n, nil)
303 live = typecheck(live, ctxStmt)
304 out = append(out, live)
305 }
306 kill := nod(OVARKILL, n, nil)
307 kill = typecheck(kill, ctxStmt)
308 out = append(out, kill)
309 }
310 return out
311 }
312
313
314
315 func (o *Order) cleanTemp(top ordermarker) {
316 o.out = append(o.out, o.cleanTempNoPop(top)...)
317 o.popTemp(top)
318 }
319
320
321 func (o *Order) stmtList(l Nodes) {
322 for _, n := range l.Slice() {
323 o.stmt(n)
324 }
325 }
326
327
328
329
330 func orderBlock(n *Nodes, free map[string][]*Node) {
331 var order Order
332 order.free = free
333 mark := order.markTemp()
334 order.stmtList(*n)
335 order.cleanTemp(mark)
336 n.Set(order.out)
337 }
338
339
340
341
342
343 func (o *Order) exprInPlace(n *Node) *Node {
344 var order Order
345 order.free = o.free
346 n = order.expr(n, nil)
347 n = addinit(n, order.out)
348
349
350
351 o.temp = append(o.temp, order.temp...)
352 return n
353 }
354
355
356
357
358
359
360 func orderStmtInPlace(n *Node, free map[string][]*Node) *Node {
361 var order Order
362 order.free = free
363 mark := order.markTemp()
364 order.stmt(n)
365 order.cleanTemp(mark)
366 return liststmt(order.out)
367 }
368
369
370 func (o *Order) init(n *Node) {
371 if n.mayBeShared() {
372
373
374 if n.Ninit.Len() > 0 {
375 Fatalf("orderinit shared node with ninit")
376 }
377 return
378 }
379 o.stmtList(n.Ninit)
380 n.Ninit.Set(nil)
381 }
382
383
384
385 func (o *Order) call(n *Node) {
386 if n.Ninit.Len() > 0 {
387
388 Fatalf("%v with unexpected ninit", n.Op)
389 }
390 n.Left = o.expr(n.Left, nil)
391 n.Right = o.expr(n.Right, nil)
392 o.exprList(n.List)
393
394 if n.Op != OCALLFUNC {
395 return
396 }
397 keepAlive := func(i int) {
398
399
400
401
402 xp := n.List.Addr(i)
403 for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() {
404 xp = &(*xp).Left
405 }
406 x := *xp
407 if x.Type.IsUnsafePtr() {
408 x = o.copyExpr(x, x.Type, false)
409 x.Name.SetKeepalive(true)
410 *xp = x
411 }
412 }
413
414 for i, t := range n.Left.Type.Params().FieldSlice() {
415
416 if t.IsDDD() && !n.IsDDD() {
417 if t.Note == uintptrEscapesTag {
418 for ; i < n.List.Len(); i++ {
419 keepAlive(i)
420 }
421 }
422 } else {
423 if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
424 keepAlive(i)
425 }
426 }
427 }
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 func (o *Order) mapAssign(n *Node) {
446 switch n.Op {
447 default:
448 Fatalf("ordermapassign %v", n.Op)
449
450 case OAS, OASOP:
451 if n.Left.Op == OINDEXMAP {
452
453
454 if n.Right.Op == OAPPEND {
455 s := n.Right.List.Slice()[1:]
456 for i, n := range s {
457 s[i] = o.cheapExpr(n)
458 }
459 } else {
460 n.Right = o.cheapExpr(n.Right)
461 }
462 }
463 o.out = append(o.out, n)
464
465 case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
466 var post []*Node
467 for i, m := range n.List.Slice() {
468 switch {
469 case m.Op == OINDEXMAP:
470 if !m.Left.IsAutoTmp() {
471 m.Left = o.copyExpr(m.Left, m.Left.Type, false)
472 }
473 if !m.Right.IsAutoTmp() {
474 m.Right = o.copyExpr(m.Right, m.Right.Type, false)
475 }
476 fallthrough
477 case instrumenting && n.Op == OAS2FUNC && !m.isBlank():
478 t := o.newTemp(m.Type, false)
479 n.List.SetIndex(i, t)
480 a := nod(OAS, m, t)
481 a = typecheck(a, ctxStmt)
482 post = append(post, a)
483 }
484 }
485
486 o.out = append(o.out, n)
487 o.out = append(o.out, post...)
488 }
489 }
490
491
492
493
494 func (o *Order) stmt(n *Node) {
495 if n == nil {
496 return
497 }
498
499 lno := setlineno(n)
500 o.init(n)
501
502 switch n.Op {
503 default:
504 Fatalf("orderstmt %v", n.Op)
505
506 case OVARKILL, OVARLIVE, OINLMARK:
507 o.out = append(o.out, n)
508
509 case OAS:
510 t := o.markTemp()
511 n.Left = o.expr(n.Left, nil)
512 n.Right = o.expr(n.Right, n.Left)
513 o.mapAssign(n)
514 o.cleanTemp(t)
515
516 case OAS2,
517 OCLOSE,
518 OCOPY,
519 OPRINT,
520 OPRINTN,
521 ORECOVER,
522 ORECV:
523 t := o.markTemp()
524 n.Left = o.expr(n.Left, nil)
525 n.Right = o.expr(n.Right, nil)
526 o.exprList(n.List)
527 o.exprList(n.Rlist)
528 switch n.Op {
529 case OAS2:
530 o.mapAssign(n)
531 default:
532 o.out = append(o.out, n)
533 }
534 o.cleanTemp(t)
535
536 case OASOP:
537 t := o.markTemp()
538 n.Left = o.expr(n.Left, nil)
539 n.Right = o.expr(n.Right, nil)
540
541 if instrumenting || n.Left.Op == OINDEXMAP && (n.SubOp() == ODIV || n.SubOp() == OMOD) {
542
543
544
545
546
547 n.Left = o.safeExpr(n.Left)
548
549 l := treecopy(n.Left, src.NoXPos)
550 if l.Op == OINDEXMAP {
551 l.SetIndexMapLValue(false)
552 }
553 l = o.copyExpr(l, n.Left.Type, false)
554 n.Right = nod(n.SubOp(), l, n.Right)
555 n.Right = typecheck(n.Right, ctxExpr)
556 n.Right = o.expr(n.Right, nil)
557
558 n.Op = OAS
559 n.ResetAux()
560 }
561
562 o.mapAssign(n)
563 o.cleanTemp(t)
564
565
566
567 case OAS2MAPR:
568 t := o.markTemp()
569 o.exprList(n.List)
570 r := n.Rlist.First()
571 r.Left = o.expr(r.Left, nil)
572 r.Right = o.expr(r.Right, nil)
573
574
575 _ = mapKeyReplaceStrConv(r.Right)
576
577 r.Right = o.mapKeyTemp(r.Left.Type, r.Right)
578 o.okAs2(n)
579 o.cleanTemp(t)
580
581
582 case OAS2FUNC:
583 t := o.markTemp()
584 o.exprList(n.List)
585 o.init(n.Rlist.First())
586 o.call(n.Rlist.First())
587 o.as2(n)
588 o.cleanTemp(t)
589
590
591
592
593 case OAS2DOTTYPE:
594 t := o.markTemp()
595 o.exprList(n.List)
596 n.Rlist.First().Left = o.expr(n.Rlist.First().Left, nil)
597 o.okAs2(n)
598 o.cleanTemp(t)
599
600
601
602 case OAS2RECV:
603 t := o.markTemp()
604 o.exprList(n.List)
605 n.Rlist.First().Left = o.expr(n.Rlist.First().Left, nil)
606 ch := n.Rlist.First().Left.Type
607 tmp1 := o.newTemp(ch.Elem(), types.Haspointers(ch.Elem()))
608 tmp2 := o.newTemp(types.Types[TBOOL], false)
609 o.out = append(o.out, n)
610 r := nod(OAS, n.List.First(), tmp1)
611 r = typecheck(r, ctxStmt)
612 o.mapAssign(r)
613 r = okas(n.List.Second(), tmp2)
614 r = typecheck(r, ctxStmt)
615 o.mapAssign(r)
616 n.List.Set2(tmp1, tmp2)
617 o.cleanTemp(t)
618
619
620 case OBLOCK, OEMPTY:
621 o.stmtList(n.List)
622
623
624 case OBREAK,
625 OCONTINUE,
626 ODCL,
627 ODCLCONST,
628 ODCLTYPE,
629 OFALL,
630 OGOTO,
631 OLABEL,
632 ORETJMP:
633 o.out = append(o.out, n)
634
635
636 case OCALLFUNC, OCALLINTER, OCALLMETH:
637 t := o.markTemp()
638 o.call(n)
639 o.out = append(o.out, n)
640 o.cleanTemp(t)
641
642
643 case ODEFER, OGO:
644 t := o.markTemp()
645 o.init(n.Left)
646 o.call(n.Left)
647 o.out = append(o.out, n)
648 o.cleanTemp(t)
649
650 case ODELETE:
651 t := o.markTemp()
652 n.List.SetFirst(o.expr(n.List.First(), nil))
653 n.List.SetSecond(o.expr(n.List.Second(), nil))
654 n.List.SetSecond(o.mapKeyTemp(n.List.First().Type, n.List.Second()))
655 o.out = append(o.out, n)
656 o.cleanTemp(t)
657
658
659
660 case OFOR:
661 t := o.markTemp()
662 n.Left = o.exprInPlace(n.Left)
663 n.Nbody.Prepend(o.cleanTempNoPop(t)...)
664 orderBlock(&n.Nbody, o.free)
665 n.Right = orderStmtInPlace(n.Right, o.free)
666 o.out = append(o.out, n)
667 o.cleanTemp(t)
668
669
670
671 case OIF:
672 t := o.markTemp()
673 n.Left = o.exprInPlace(n.Left)
674 n.Nbody.Prepend(o.cleanTempNoPop(t)...)
675 n.Rlist.Prepend(o.cleanTempNoPop(t)...)
676 o.popTemp(t)
677 orderBlock(&n.Nbody, o.free)
678 orderBlock(&n.Rlist, o.free)
679 o.out = append(o.out, n)
680
681
682
683 case OPANIC:
684 t := o.markTemp()
685 n.Left = o.expr(n.Left, nil)
686 if !n.Left.Type.IsInterface() {
687 n.Left = o.addrTemp(n.Left)
688 }
689 o.out = append(o.out, n)
690 o.cleanTemp(t)
691
692 case ORANGE:
693
694
695
696
697
698
699
700
701
702
703
704
705
706 if n.Right.Op == OSTR2BYTES {
707 n.Right.Op = OSTR2BYTESTMP
708 }
709
710 t := o.markTemp()
711 n.Right = o.expr(n.Right, nil)
712
713 orderBody := true
714 switch n.Type.Etype {
715 default:
716 Fatalf("orderstmt range %v", n.Type)
717
718 case TARRAY, TSLICE:
719 if n.List.Len() < 2 || n.List.Second().isBlank() {
720
721
722 break
723 }
724 fallthrough
725
726 case TCHAN, TSTRING:
727
728
729 r := n.Right
730
731 if r.Type.IsString() && r.Type != types.Types[TSTRING] {
732 r = nod(OCONV, r, nil)
733 r.Type = types.Types[TSTRING]
734 r = typecheck(r, ctxExpr)
735 }
736
737 n.Right = o.copyExpr(r, r.Type, false)
738
739 case TMAP:
740 if isMapClear(n) {
741
742
743
744 orderBody = false
745 break
746 }
747
748
749
750
751 r := n.Right
752 n.Right = o.copyExpr(r, r.Type, false)
753
754
755
756 prealloc[n] = o.newTemp(hiter(n.Type), true)
757 }
758 o.exprListInPlace(n.List)
759 if orderBody {
760 orderBlock(&n.Nbody, o.free)
761 }
762 o.out = append(o.out, n)
763 o.cleanTemp(t)
764
765 case ORETURN:
766 o.exprList(n.List)
767 o.out = append(o.out, n)
768
769
770
771
772
773
774
775
776
777
778 case OSELECT:
779 t := o.markTemp()
780
781 for _, n2 := range n.List.Slice() {
782 if n2.Op != OXCASE {
783 Fatalf("order select case %v", n2.Op)
784 }
785 r := n2.Left
786 setlineno(n2)
787
788
789
790 if n2.Ninit.Len() != 0 {
791 Fatalf("order select ninit")
792 }
793 if r == nil {
794 continue
795 }
796 switch r.Op {
797 default:
798 Dump("select case", r)
799 Fatalf("unknown op in select %v", r.Op)
800
801
802
803
804
805 case OSELRECV, OSELRECV2:
806 if r.Colas() {
807 i := 0
808 if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
809 i++
810 }
811 if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
812 i++
813 }
814 if i >= r.Ninit.Len() {
815 r.Ninit.Set(nil)
816 }
817 }
818
819 if r.Ninit.Len() != 0 {
820 dumplist("ninit", r.Ninit)
821 Fatalf("ninit on select recv")
822 }
823
824
825
826
827
828
829 r.Right.Left = o.expr(r.Right.Left, nil)
830
831 if r.Right.Left.Op != ONAME {
832 r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false)
833 }
834
835
836
837
838
839
840
841 if r.Left != nil && r.Left.isBlank() {
842 r.Left = nil
843 }
844 if r.Left != nil {
845
846
847
848 tmp1 := r.Left
849
850 if r.Colas() {
851 tmp2 := nod(ODCL, tmp1, nil)
852 tmp2 = typecheck(tmp2, ctxStmt)
853 n2.Ninit.Append(tmp2)
854 }
855
856 r.Left = o.newTemp(r.Right.Left.Type.Elem(), types.Haspointers(r.Right.Left.Type.Elem()))
857 tmp2 := nod(OAS, tmp1, r.Left)
858 tmp2 = typecheck(tmp2, ctxStmt)
859 n2.Ninit.Append(tmp2)
860 }
861
862 if r.List.Len() != 0 && r.List.First().isBlank() {
863 r.List.Set(nil)
864 }
865 if r.List.Len() != 0 {
866 tmp1 := r.List.First()
867 if r.Colas() {
868 tmp2 := nod(ODCL, tmp1, nil)
869 tmp2 = typecheck(tmp2, ctxStmt)
870 n2.Ninit.Append(tmp2)
871 }
872
873 r.List.Set1(o.newTemp(types.Types[TBOOL], false))
874 tmp2 := okas(tmp1, r.List.First())
875 tmp2 = typecheck(tmp2, ctxStmt)
876 n2.Ninit.Append(tmp2)
877 }
878 orderBlock(&n2.Ninit, o.free)
879
880 case OSEND:
881 if r.Ninit.Len() != 0 {
882 dumplist("ninit", r.Ninit)
883 Fatalf("ninit on select send")
884 }
885
886
887
888 r.Left = o.expr(r.Left, nil)
889
890 if !r.Left.IsAutoTmp() {
891 r.Left = o.copyExpr(r.Left, r.Left.Type, false)
892 }
893 r.Right = o.expr(r.Right, nil)
894 if !r.Right.IsAutoTmp() {
895 r.Right = o.copyExpr(r.Right, r.Right.Type, false)
896 }
897 }
898 }
899
900
901
902 for _, n3 := range n.List.Slice() {
903 orderBlock(&n3.Nbody, o.free)
904 n3.Nbody.Prepend(o.cleanTempNoPop(t)...)
905
906
907
908 n3.Nbody.Prepend(n3.Ninit.Slice()...)
909 n3.Ninit.Set(nil)
910 }
911
912 o.out = append(o.out, n)
913 o.popTemp(t)
914
915
916 case OSEND:
917 t := o.markTemp()
918 n.Left = o.expr(n.Left, nil)
919 n.Right = o.expr(n.Right, nil)
920 if instrumenting {
921
922
923 n.Right = o.copyExpr(n.Right, n.Right.Type, false)
924 } else {
925 n.Right = o.addrTemp(n.Right)
926 }
927 o.out = append(o.out, n)
928 o.cleanTemp(t)
929
930
931
932
933
934
935
936
937 case OSWITCH:
938 t := o.markTemp()
939 n.Left = o.expr(n.Left, nil)
940 for _, ncas := range n.List.Slice() {
941 if ncas.Op != OXCASE {
942 Fatalf("order switch case %v", ncas.Op)
943 }
944 o.exprListInPlace(ncas.List)
945 orderBlock(&ncas.Nbody, o.free)
946 }
947
948 o.out = append(o.out, n)
949 o.cleanTemp(t)
950 }
951
952 lineno = lno
953 }
954
955
956 func (o *Order) exprList(l Nodes) {
957 s := l.Slice()
958 for i := range s {
959 s[i] = o.expr(s[i], nil)
960 }
961 }
962
963
964
965 func (o *Order) exprListInPlace(l Nodes) {
966 s := l.Slice()
967 for i := range s {
968 s[i] = o.exprInPlace(s[i])
969 }
970 }
971
972
973 var prealloc = map[*Node]*Node{}
974
975
976
977
978
979
980
981
982 func (o *Order) expr(n, lhs *Node) *Node {
983 if n == nil {
984 return n
985 }
986
987 lno := setlineno(n)
988 o.init(n)
989
990 switch n.Op {
991 default:
992 n.Left = o.expr(n.Left, nil)
993 n.Right = o.expr(n.Right, nil)
994 o.exprList(n.List)
995 o.exprList(n.Rlist)
996
997
998
999
1000 case OADDSTR:
1001 o.exprList(n.List)
1002
1003 if n.List.Len() > 5 {
1004 t := types.NewArray(types.Types[TSTRING], int64(n.List.Len()))
1005 prealloc[n] = o.newTemp(t, false)
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015 hasbyte := false
1016
1017 haslit := false
1018 for _, n1 := range n.List.Slice() {
1019 hasbyte = hasbyte || n1.Op == OBYTES2STR
1020 haslit = haslit || n1.Op == OLITERAL && len(n1.Val().U.(string)) != 0
1021 }
1022
1023 if haslit && hasbyte {
1024 for _, n2 := range n.List.Slice() {
1025 if n2.Op == OBYTES2STR {
1026 n2.Op = OBYTES2STRTMP
1027 }
1028 }
1029 }
1030
1031
1032 case OINDEXMAP:
1033 n.Left = o.expr(n.Left, nil)
1034 n.Right = o.expr(n.Right, nil)
1035 needCopy := false
1036
1037 if !n.IndexMapLValue() {
1038
1039
1040
1041
1042 needCopy = mapKeyReplaceStrConv(n.Right)
1043
1044 if instrumenting {
1045
1046
1047 needCopy = true
1048 }
1049 }
1050
1051 n.Right = o.mapKeyTemp(n.Left.Type, n.Right)
1052 if needCopy {
1053 n = o.copyExpr(n, n.Type, false)
1054 }
1055
1056
1057
1058 case OCONVIFACE:
1059 n.Left = o.expr(n.Left, nil)
1060 if n.Left.Type.IsInterface() {
1061 break
1062 }
1063 if _, needsaddr := convFuncName(n.Left.Type, n.Type); needsaddr || isStaticCompositeLiteral(n.Left) {
1064
1065
1066
1067 n.Left = o.addrTemp(n.Left)
1068 }
1069
1070 case OCONVNOP:
1071 if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) {
1072
1073
1074
1075 o.init(n.Left)
1076 o.call(n.Left)
1077 if lhs == nil || lhs.Op != ONAME || instrumenting {
1078 n = o.copyExpr(n, n.Type, false)
1079 }
1080 } else {
1081 n.Left = o.expr(n.Left, nil)
1082 }
1083
1084 case OANDAND, OOROR:
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 r := o.newTemp(n.Type, false)
1095
1096
1097 lhs := o.expr(n.Left, nil)
1098 o.out = append(o.out, typecheck(nod(OAS, r, lhs), ctxStmt))
1099
1100
1101 saveout := o.out
1102 o.out = nil
1103 t := o.markTemp()
1104 rhs := o.expr(n.Right, nil)
1105 o.out = append(o.out, typecheck(nod(OAS, r, rhs), ctxStmt))
1106 o.cleanTemp(t)
1107 gen := o.out
1108 o.out = saveout
1109
1110
1111 nif := nod(OIF, r, nil)
1112 if n.Op == OANDAND {
1113 nif.Nbody.Set(gen)
1114 } else {
1115 nif.Rlist.Set(gen)
1116 }
1117 o.out = append(o.out, nif)
1118 n = r
1119
1120 case OCALLFUNC,
1121 OCALLINTER,
1122 OCALLMETH,
1123 OCAP,
1124 OCOMPLEX,
1125 OCOPY,
1126 OIMAG,
1127 OLEN,
1128 OMAKECHAN,
1129 OMAKEMAP,
1130 OMAKESLICE,
1131 ONEW,
1132 OREAL,
1133 ORECOVER,
1134 OSTR2BYTES,
1135 OSTR2BYTESTMP,
1136 OSTR2RUNES:
1137
1138 if isRuneCount(n) {
1139
1140 n.Left.Left = o.expr(n.Left.Left, nil)
1141 } else {
1142 o.call(n)
1143 }
1144
1145 if lhs == nil || lhs.Op != ONAME || instrumenting {
1146 n = o.copyExpr(n, n.Type, false)
1147 }
1148
1149 case OAPPEND:
1150
1151 if isAppendOfMake(n) {
1152 n.List.SetFirst(o.expr(n.List.First(), nil))
1153 n.List.Second().Left = o.expr(n.List.Second().Left, nil)
1154 } else {
1155 o.exprList(n.List)
1156 }
1157
1158 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) {
1159 n = o.copyExpr(n, n.Type, false)
1160 }
1161
1162 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
1163 n.Left = o.expr(n.Left, nil)
1164 low, high, max := n.SliceBounds()
1165 low = o.expr(low, nil)
1166 low = o.cheapExpr(low)
1167 high = o.expr(high, nil)
1168 high = o.cheapExpr(high)
1169 max = o.expr(max, nil)
1170 max = o.cheapExpr(max)
1171 n.SetSliceBounds(low, high, max)
1172 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
1173 n = o.copyExpr(n, n.Type, false)
1174 }
1175
1176 case OCLOSURE:
1177 if n.Noescape() && n.Func.Closure.Func.Cvars.Len() > 0 {
1178 prealloc[n] = o.newTemp(closureType(n), false)
1179 }
1180
1181 case OSLICELIT, OCALLPART:
1182 n.Left = o.expr(n.Left, nil)
1183 n.Right = o.expr(n.Right, nil)
1184 o.exprList(n.List)
1185 o.exprList(n.Rlist)
1186 if n.Noescape() {
1187 var t *types.Type
1188 switch n.Op {
1189 case OSLICELIT:
1190 t = types.NewArray(n.Type.Elem(), n.Right.Int64())
1191 case OCALLPART:
1192 t = partialCallType(n)
1193 }
1194 prealloc[n] = o.newTemp(t, false)
1195 }
1196
1197 case ODDDARG:
1198 if n.Noescape() {
1199
1200
1201
1202
1203 prealloc[n] = o.newTemp(n.Type.Elem(), false)
1204 }
1205
1206 case ODOTTYPE, ODOTTYPE2:
1207 n.Left = o.expr(n.Left, nil)
1208
1209
1210
1211 if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting {
1212 n = o.copyExpr(n, n.Type, true)
1213 }
1214
1215 case ORECV:
1216 n.Left = o.expr(n.Left, nil)
1217 n = o.copyExpr(n, n.Type, true)
1218
1219 case OEQ, ONE, OLT, OLE, OGT, OGE:
1220 n.Left = o.expr(n.Left, nil)
1221 n.Right = o.expr(n.Right, nil)
1222
1223 t := n.Left.Type
1224 switch {
1225 case t.IsString():
1226
1227
1228
1229 if n.Left.Op == OBYTES2STR {
1230 n.Left.Op = OBYTES2STRTMP
1231 }
1232 if n.Right.Op == OBYTES2STR {
1233 n.Right.Op = OBYTES2STRTMP
1234 }
1235
1236 case t.IsStruct() || t.IsArray():
1237
1238
1239 n.Left = o.addrTemp(n.Left)
1240 n.Right = o.addrTemp(n.Right)
1241 }
1242 case OMAPLIT:
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258 entries := n.List.Slice()
1259 statics := entries[:0]
1260 var dynamics []*Node
1261 for _, r := range entries {
1262 if r.Op != OKEY {
1263 Fatalf("OMAPLIT entry not OKEY: %v\n", r)
1264 }
1265
1266 if !isStaticCompositeLiteral(r.Left) || !isStaticCompositeLiteral(r.Right) {
1267 dynamics = append(dynamics, r)
1268 continue
1269 }
1270
1271
1272
1273 r = o.expr(r, nil)
1274 if !isStaticCompositeLiteral(r.Left) || !isStaticCompositeLiteral(r.Right) {
1275 dynamics = append(dynamics, r)
1276 continue
1277 }
1278
1279 statics = append(statics, r)
1280 }
1281 n.List.Set(statics)
1282
1283 if len(dynamics) == 0 {
1284 break
1285 }
1286
1287
1288 m := o.newTemp(n.Type, false)
1289 as := nod(OAS, m, n)
1290 typecheck(as, ctxStmt)
1291 o.stmt(as)
1292 n = m
1293
1294
1295 for _, r := range dynamics {
1296 as := nod(OAS, nod(OINDEX, n, r.Left), r.Right)
1297 typecheck(as, ctxStmt)
1298 o.stmt(as)
1299 }
1300 }
1301
1302 lineno = lno
1303 return n
1304 }
1305
1306
1307
1308 func okas(ok, val *Node) *Node {
1309 if !ok.isBlank() {
1310 val = conv(val, ok.Type)
1311 }
1312 return nod(OAS, ok, val)
1313 }
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323 func (o *Order) as2(n *Node) {
1324 tmplist := []*Node{}
1325 left := []*Node{}
1326 for ni, l := range n.List.Slice() {
1327 if !l.isBlank() {
1328 tmp := o.newTemp(l.Type, types.Haspointers(l.Type))
1329 n.List.SetIndex(ni, tmp)
1330 tmplist = append(tmplist, tmp)
1331 left = append(left, l)
1332 }
1333 }
1334
1335 o.out = append(o.out, n)
1336
1337 as := nod(OAS2, nil, nil)
1338 as.List.Set(left)
1339 as.Rlist.Set(tmplist)
1340 as = typecheck(as, ctxStmt)
1341 o.stmt(as)
1342 }
1343
1344
1345
1346 func (o *Order) okAs2(n *Node) {
1347 var tmp1, tmp2 *Node
1348 if !n.List.First().isBlank() {
1349 typ := n.Rlist.First().Type
1350 tmp1 = o.newTemp(typ, types.Haspointers(typ))
1351 }
1352
1353 if !n.List.Second().isBlank() {
1354 tmp2 = o.newTemp(types.Types[TBOOL], false)
1355 }
1356
1357 o.out = append(o.out, n)
1358
1359 if tmp1 != nil {
1360 r := nod(OAS, n.List.First(), tmp1)
1361 r = typecheck(r, ctxStmt)
1362 o.mapAssign(r)
1363 n.List.SetFirst(tmp1)
1364 }
1365 if tmp2 != nil {
1366 r := okas(n.List.Second(), tmp2)
1367 r = typecheck(r, ctxStmt)
1368 o.mapAssign(r)
1369 n.List.SetSecond(tmp2)
1370 }
1371 }
1372
View as plain text