1
2
3
4
5 package walk
6
7 import (
8 "fmt"
9 "go/constant"
10
11 "cmd/compile/internal/base"
12 "cmd/compile/internal/ir"
13 "cmd/compile/internal/reflectdata"
14 "cmd/compile/internal/ssa"
15 "cmd/compile/internal/staticinit"
16 "cmd/compile/internal/typecheck"
17 "cmd/compile/internal/types"
18 "cmd/internal/objabi"
19 "cmd/internal/src"
20 )
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 type orderState struct {
42 out []ir.Node
43 temp []*ir.Name
44 free map[string][]*ir.Name
45 edit func(ir.Node) ir.Node
46 }
47
48
49
50 func order(fn *ir.Func) {
51 if base.Flag.W > 1 {
52 s := fmt.Sprintf("\nbefore order %v", fn.Sym())
53 ir.DumpList(s, fn.Body)
54 }
55 ir.SetPos(fn)
56 orderBlock(&fn.Body, map[string][]*ir.Name{})
57 }
58
59
60 func (o *orderState) append(stmt ir.Node) {
61 o.out = append(o.out, typecheck.Stmt(stmt))
62 }
63
64
65
66
67 func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name {
68 var v *ir.Name
69 key := t.LinkString()
70 if a := o.free[key]; len(a) > 0 {
71 v = a[len(a)-1]
72 if !types.Identical(t, v.Type()) {
73 base.Fatalf("expected %L to have type %v", v, t)
74 }
75 o.free[key] = a[:len(a)-1]
76 } else {
77 v = typecheck.TempAt(base.Pos, ir.CurFunc, t)
78 }
79 if clear {
80 o.append(ir.NewAssignStmt(base.Pos, v, nil))
81 }
82
83 o.temp = append(o.temp, v)
84 return v
85 }
86
87
88
89 func (o *orderState) copyExpr(n ir.Node) *ir.Name {
90 return o.copyExpr1(n, false)
91 }
92
93
94
95
96
97
98
99
100
101
102
103 func (o *orderState) copyExprClear(n ir.Node) *ir.Name {
104 return o.copyExpr1(n, true)
105 }
106
107 func (o *orderState) copyExpr1(n ir.Node, clear bool) *ir.Name {
108 t := n.Type()
109 v := o.newTemp(t, clear)
110 o.append(ir.NewAssignStmt(base.Pos, v, n))
111 return v
112 }
113
114
115
116
117
118 func (o *orderState) cheapExpr(n ir.Node) ir.Node {
119 if n == nil {
120 return nil
121 }
122
123 switch n.Op() {
124 case ir.ONAME, ir.OLITERAL, ir.ONIL:
125 return n
126 case ir.OLEN, ir.OCAP:
127 n := n.(*ir.UnaryExpr)
128 l := o.cheapExpr(n.X)
129 if l == n.X {
130 return n
131 }
132 a := ir.Copy(n).(*ir.UnaryExpr)
133 a.X = l
134 return typecheck.Expr(a)
135 }
136
137 return o.copyExpr(n)
138 }
139
140
141
142
143
144
145
146
147 func (o *orderState) safeExpr(n ir.Node) ir.Node {
148 switch n.Op() {
149 case ir.ONAME, ir.OLITERAL, ir.ONIL:
150 return n
151
152 case ir.OLEN, ir.OCAP:
153 n := n.(*ir.UnaryExpr)
154 l := o.safeExpr(n.X)
155 if l == n.X {
156 return n
157 }
158 a := ir.Copy(n).(*ir.UnaryExpr)
159 a.X = l
160 return typecheck.Expr(a)
161
162 case ir.ODOT:
163 n := n.(*ir.SelectorExpr)
164 l := o.safeExpr(n.X)
165 if l == n.X {
166 return n
167 }
168 a := ir.Copy(n).(*ir.SelectorExpr)
169 a.X = l
170 return typecheck.Expr(a)
171
172 case ir.ODOTPTR:
173 n := n.(*ir.SelectorExpr)
174 l := o.cheapExpr(n.X)
175 if l == n.X {
176 return n
177 }
178 a := ir.Copy(n).(*ir.SelectorExpr)
179 a.X = l
180 return typecheck.Expr(a)
181
182 case ir.ODEREF:
183 n := n.(*ir.StarExpr)
184 l := o.cheapExpr(n.X)
185 if l == n.X {
186 return n
187 }
188 a := ir.Copy(n).(*ir.StarExpr)
189 a.X = l
190 return typecheck.Expr(a)
191
192 case ir.OINDEX, ir.OINDEXMAP:
193 n := n.(*ir.IndexExpr)
194 var l ir.Node
195 if n.X.Type().IsArray() {
196 l = o.safeExpr(n.X)
197 } else {
198 l = o.cheapExpr(n.X)
199 }
200 r := o.cheapExpr(n.Index)
201 if l == n.X && r == n.Index {
202 return n
203 }
204 a := ir.Copy(n).(*ir.IndexExpr)
205 a.X = l
206 a.Index = r
207 return typecheck.Expr(a)
208
209 default:
210 base.Fatalf("order.safeExpr %v", n.Op())
211 return nil
212 }
213 }
214
215
216
217
218
219
220
221 func (o *orderState) addrTemp(n ir.Node) ir.Node {
222 if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL {
223
224 n = typecheck.DefaultLit(n, nil)
225 types.CalcSize(n.Type())
226 vstat := readonlystaticname(n.Type())
227 var s staticinit.Schedule
228 s.StaticAssign(vstat, 0, n, n.Type())
229 if s.Out != nil {
230 base.Fatalf("staticassign of const generated code: %+v", n)
231 }
232 vstat = typecheck.Expr(vstat).(*ir.Name)
233 return vstat
234 }
235
236
237
238
239
240
241
242
243 if ir.IsAddressable(n) {
244 if name, ok := ir.OuterValue(n).(*ir.Name); ok && name.Op() == ir.ONAME {
245 if name.Class == ir.PAUTO && !name.Addrtaken() && ssa.CanSSA(name.Type()) {
246 goto Copy
247 }
248 }
249
250 return n
251 }
252
253 Copy:
254 return o.copyExpr(n)
255 }
256
257
258
259
260 func (o *orderState) mapKeyTemp(outerPos src.XPos, t *types.Type, n ir.Node) ir.Node {
261 pos := outerPos
262 if ir.HasUniquePos(n) {
263 pos = n.Pos()
264 }
265
266
267 alg := mapfast(t)
268 if alg == mapslow {
269 return o.addrTemp(n)
270 }
271 var kt *types.Type
272 switch alg {
273 case mapfast32:
274 kt = types.Types[types.TUINT32]
275 case mapfast64:
276 kt = types.Types[types.TUINT64]
277 case mapfast32ptr, mapfast64ptr:
278 kt = types.Types[types.TUNSAFEPTR]
279 case mapfaststr:
280 kt = types.Types[types.TSTRING]
281 }
282 nt := n.Type()
283 switch {
284 case nt == kt:
285 return n
286 case nt.Kind() == kt.Kind(), nt.IsPtrShaped() && kt.IsPtrShaped():
287
288 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, kt, n))
289 case nt.IsInteger() && kt.IsInteger():
290
291 if n.Op() == ir.OLITERAL && nt.IsSigned() {
292
293 n = ir.NewConstExpr(constant.MakeUint64(uint64(ir.Int64Val(n))), n)
294 n.SetType(kt)
295 return n
296 }
297 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, kt, n))
298 default:
299
300
301
302 if uint8(kt.Alignment()) < uint8(nt.Alignment()) {
303 base.Fatalf("mapKeyTemp: key type is not sufficiently aligned, kt=%v nt=%v", kt, nt)
304 }
305 tmp := o.newTemp(kt, true)
306
307 var e ir.Node = typecheck.NodAddr(tmp)
308 e = ir.NewConvExpr(pos, ir.OCONVNOP, nt.PtrTo(), e)
309 e = ir.NewStarExpr(pos, e)
310 o.append(ir.NewAssignStmt(pos, e, n))
311 return tmp
312 }
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 func mapKeyReplaceStrConv(n ir.Node) bool {
332 var replaced bool
333 switch n.Op() {
334 case ir.OBYTES2STR:
335 n := n.(*ir.ConvExpr)
336 n.SetOp(ir.OBYTES2STRTMP)
337 replaced = true
338 case ir.OSTRUCTLIT:
339 n := n.(*ir.CompLitExpr)
340 for _, elem := range n.List {
341 elem := elem.(*ir.StructKeyExpr)
342 if mapKeyReplaceStrConv(elem.Value) {
343 replaced = true
344 }
345 }
346 case ir.OARRAYLIT:
347 n := n.(*ir.CompLitExpr)
348 for _, elem := range n.List {
349 if elem.Op() == ir.OKEY {
350 elem = elem.(*ir.KeyExpr).Value
351 }
352 if mapKeyReplaceStrConv(elem) {
353 replaced = true
354 }
355 }
356 }
357 return replaced
358 }
359
360 type ordermarker int
361
362
363 func (o *orderState) markTemp() ordermarker {
364 return ordermarker(len(o.temp))
365 }
366
367
368
369 func (o *orderState) popTemp(mark ordermarker) {
370 for _, n := range o.temp[mark:] {
371 key := n.Type().LinkString()
372 o.free[key] = append(o.free[key], n)
373 }
374 o.temp = o.temp[:mark]
375 }
376
377
378 func (o *orderState) stmtList(l ir.Nodes) {
379 s := l
380 for i := range s {
381 orderMakeSliceCopy(s[i:])
382 o.stmt(s[i])
383 }
384 }
385
386
387
388
389
390
391
392
393 func orderMakeSliceCopy(s []ir.Node) {
394 if base.Flag.N != 0 || base.Flag.Cfg.Instrumenting {
395 return
396 }
397 if len(s) < 2 || s[0] == nil || s[0].Op() != ir.OAS || s[1] == nil || s[1].Op() != ir.OCOPY {
398 return
399 }
400
401 as := s[0].(*ir.AssignStmt)
402 cp := s[1].(*ir.BinaryExpr)
403 if as.Y == nil || as.Y.Op() != ir.OMAKESLICE || ir.IsBlank(as.X) ||
404 as.X.Op() != ir.ONAME || cp.X.Op() != ir.ONAME || cp.Y.Op() != ir.ONAME ||
405 as.X.Name() != cp.X.Name() || cp.X.Name() == cp.Y.Name() {
406
407
408
409 return
410 }
411
412 mk := as.Y.(*ir.MakeExpr)
413 if mk.Esc() == ir.EscNone || mk.Len == nil || mk.Cap != nil {
414 return
415 }
416 mk.SetOp(ir.OMAKESLICECOPY)
417 mk.Cap = cp.Y
418
419 mk.SetBounded(mk.Len.Op() == ir.OLEN && ir.SameSafeExpr(mk.Len.(*ir.UnaryExpr).X, cp.Y))
420 as.Y = typecheck.Expr(mk)
421 s[1] = nil
422 }
423
424
425 func (o *orderState) edge() {
426 if base.Debug.Libfuzzer == 0 {
427 return
428 }
429
430
431 counter := staticinit.StaticName(types.Types[types.TUINT8])
432 counter.SetLibfuzzer8BitCounter(true)
433
434
435
436
437
438
439 counter.Linksym().Type = objabi.SLIBFUZZER_8BIT_COUNTER
440
441
442
443
444
445
446
447
448
449
450
451 o.append(ir.NewIfStmt(base.Pos,
452 ir.NewBinaryExpr(base.Pos, ir.OEQ, counter, ir.NewInt(base.Pos, 0xff)),
453 []ir.Node{ir.NewAssignStmt(base.Pos, counter, ir.NewInt(base.Pos, 1))},
454 []ir.Node{ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(base.Pos, 1))}))
455 }
456
457
458
459
460 func orderBlock(n *ir.Nodes, free map[string][]*ir.Name) {
461 if len(*n) != 0 {
462
463
464
465 ir.SetPos((*n)[0])
466 }
467 var order orderState
468 order.free = free
469 mark := order.markTemp()
470 order.edge()
471 order.stmtList(*n)
472 order.popTemp(mark)
473 *n = order.out
474 }
475
476
477
478
479
480
481 func (o *orderState) exprInPlace(n ir.Node) ir.Node {
482 var order orderState
483 order.free = o.free
484 n = order.expr(n, nil)
485 n = ir.InitExpr(order.out, n)
486
487
488
489 o.temp = append(o.temp, order.temp...)
490 return n
491 }
492
493
494
495
496
497
498
499
500 func orderStmtInPlace(n ir.Node, free map[string][]*ir.Name) ir.Node {
501 var order orderState
502 order.free = free
503 mark := order.markTemp()
504 order.stmt(n)
505 order.popTemp(mark)
506 return ir.NewBlockStmt(src.NoXPos, order.out)
507 }
508
509
510 func (o *orderState) init(n ir.Node) {
511 if ir.MayBeShared(n) {
512
513
514 if len(n.Init()) > 0 {
515 base.Fatalf("order.init shared node with ninit")
516 }
517 return
518 }
519 o.stmtList(ir.TakeInit(n))
520 }
521
522
523
524 func (o *orderState) call(nn ir.Node) {
525 if len(nn.Init()) > 0 {
526
527 base.Fatalf("%v with unexpected ninit", nn.Op())
528 }
529 if nn.Op() == ir.OCALLMETH {
530 base.FatalfAt(nn.Pos(), "OCALLMETH missed by typecheck")
531 }
532
533
534 if nn.Op() != ir.OCALLFUNC && nn.Op() != ir.OCALLINTER {
535 switch n := nn.(type) {
536 default:
537 base.Fatalf("unexpected call: %+v", n)
538 case *ir.UnaryExpr:
539 n.X = o.expr(n.X, nil)
540 case *ir.ConvExpr:
541 n.X = o.expr(n.X, nil)
542 case *ir.BinaryExpr:
543 n.X = o.expr(n.X, nil)
544 n.Y = o.expr(n.Y, nil)
545 case *ir.MakeExpr:
546 n.Len = o.expr(n.Len, nil)
547 n.Cap = o.expr(n.Cap, nil)
548 case *ir.CallExpr:
549 o.exprList(n.Args)
550 }
551 return
552 }
553
554 n := nn.(*ir.CallExpr)
555 typecheck.AssertFixedCall(n)
556
557 if ir.IsFuncPCIntrinsic(n) && ir.IsIfaceOfFunc(n.Args[0]) != nil {
558
559
560
561 return
562 }
563
564 n.Fun = o.expr(n.Fun, nil)
565 o.exprList(n.Args)
566 }
567
568
569 func (o *orderState) mapAssign(n ir.Node) {
570 switch n.Op() {
571 default:
572 base.Fatalf("order.mapAssign %v", n.Op())
573
574 case ir.OAS:
575 n := n.(*ir.AssignStmt)
576 if n.X.Op() == ir.OINDEXMAP {
577 n.Y = o.safeMapRHS(n.Y)
578 }
579 o.out = append(o.out, n)
580 case ir.OASOP:
581 n := n.(*ir.AssignOpStmt)
582 if n.X.Op() == ir.OINDEXMAP {
583 n.Y = o.safeMapRHS(n.Y)
584 }
585 o.out = append(o.out, n)
586 }
587 }
588
589 func (o *orderState) safeMapRHS(r ir.Node) ir.Node {
590
591
592 if r.Op() == ir.OAPPEND {
593 r := r.(*ir.CallExpr)
594 s := r.Args[1:]
595 for i, n := range s {
596 s[i] = o.cheapExpr(n)
597 }
598 return r
599 }
600 return o.cheapExpr(r)
601 }
602
603
604 func (o *orderState) stmt(n ir.Node) {
605 if n == nil {
606 return
607 }
608
609 lno := ir.SetPos(n)
610 o.init(n)
611
612 switch n.Op() {
613 default:
614 base.Fatalf("order.stmt %v", n.Op())
615
616 case ir.OINLMARK:
617 o.out = append(o.out, n)
618
619 case ir.OAS:
620 n := n.(*ir.AssignStmt)
621 t := o.markTemp()
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636 mapAppend := n.X.Op() == ir.OINDEXMAP && n.Y.Op() == ir.OAPPEND &&
637 ir.SameSafeExpr(n.X, n.Y.(*ir.CallExpr).Args[0])
638
639 n.X = o.expr(n.X, nil)
640 if mapAppend {
641 indexLHS := n.X.(*ir.IndexExpr)
642 indexLHS.X = o.cheapExpr(indexLHS.X)
643 indexLHS.Index = o.cheapExpr(indexLHS.Index)
644
645 call := n.Y.(*ir.CallExpr)
646 arg0 := call.Args[0]
647
648 for arg0.Op() == ir.OCONVNOP {
649 arg0 = arg0.(*ir.ConvExpr).X
650 }
651 indexRHS := arg0.(*ir.IndexExpr)
652 indexRHS.X = indexLHS.X
653 indexRHS.Index = indexLHS.Index
654
655 o.exprList(call.Args[1:])
656 } else {
657 n.Y = o.expr(n.Y, n.X)
658 }
659 o.mapAssign(n)
660 o.popTemp(t)
661
662 case ir.OASOP:
663 n := n.(*ir.AssignOpStmt)
664 t := o.markTemp()
665 n.X = o.expr(n.X, nil)
666 n.Y = o.expr(n.Y, nil)
667
668 if base.Flag.Cfg.Instrumenting || n.X.Op() == ir.OINDEXMAP && (n.AsOp == ir.ODIV || n.AsOp == ir.OMOD) {
669
670
671
672
673
674
675 l1 := o.safeExpr(n.X)
676 l2 := ir.DeepCopy(src.NoXPos, l1)
677 if l2.Op() == ir.OINDEXMAP {
678 l2 := l2.(*ir.IndexExpr)
679 l2.Assigned = false
680 }
681 l2 = o.copyExpr(l2)
682 r := o.expr(typecheck.Expr(ir.NewBinaryExpr(n.Pos(), n.AsOp, l2, n.Y)), nil)
683 as := typecheck.Stmt(ir.NewAssignStmt(n.Pos(), l1, r))
684 o.mapAssign(as)
685 o.popTemp(t)
686 return
687 }
688
689 o.mapAssign(n)
690 o.popTemp(t)
691
692 case ir.OAS2:
693 n := n.(*ir.AssignListStmt)
694 t := o.markTemp()
695 o.exprList(n.Lhs)
696 o.exprList(n.Rhs)
697 o.out = append(o.out, n)
698 o.popTemp(t)
699
700
701 case ir.OAS2FUNC:
702 n := n.(*ir.AssignListStmt)
703 t := o.markTemp()
704 o.exprList(n.Lhs)
705 call := n.Rhs[0]
706 o.init(call)
707 if ic, ok := call.(*ir.InlinedCallExpr); ok {
708 o.stmtList(ic.Body)
709
710 n.SetOp(ir.OAS2)
711 n.Rhs = ic.ReturnVars
712
713 o.exprList(n.Rhs)
714 o.out = append(o.out, n)
715 } else {
716 o.call(call)
717 o.as2func(n)
718 }
719 o.popTemp(t)
720
721
722
723
724
725
726
727 case ir.OAS2DOTTYPE, ir.OAS2RECV, ir.OAS2MAPR:
728 n := n.(*ir.AssignListStmt)
729 t := o.markTemp()
730 o.exprList(n.Lhs)
731
732 switch r := n.Rhs[0]; r.Op() {
733 case ir.ODOTTYPE2:
734 r := r.(*ir.TypeAssertExpr)
735 r.X = o.expr(r.X, nil)
736 case ir.ODYNAMICDOTTYPE2:
737 r := r.(*ir.DynamicTypeAssertExpr)
738 r.X = o.expr(r.X, nil)
739 r.RType = o.expr(r.RType, nil)
740 r.ITab = o.expr(r.ITab, nil)
741 case ir.ORECV:
742 r := r.(*ir.UnaryExpr)
743 r.X = o.expr(r.X, nil)
744 case ir.OINDEXMAP:
745 r := r.(*ir.IndexExpr)
746 r.X = o.expr(r.X, nil)
747 r.Index = o.expr(r.Index, nil)
748
749 _ = mapKeyReplaceStrConv(r.Index)
750 r.Index = o.mapKeyTemp(r.Pos(), r.X.Type(), r.Index)
751 default:
752 base.Fatalf("order.stmt: %v", r.Op())
753 }
754
755 o.as2ok(n)
756 o.popTemp(t)
757
758
759 case ir.OBLOCK:
760 n := n.(*ir.BlockStmt)
761 o.stmtList(n.List)
762
763
764 case ir.OBREAK,
765 ir.OCONTINUE,
766 ir.ODCL,
767 ir.OFALL,
768 ir.OGOTO,
769 ir.OLABEL,
770 ir.OTAILCALL:
771 o.out = append(o.out, n)
772
773
774 case ir.OCALLFUNC, ir.OCALLINTER:
775 n := n.(*ir.CallExpr)
776 t := o.markTemp()
777 o.call(n)
778 o.out = append(o.out, n)
779 o.popTemp(t)
780
781 case ir.OINLCALL:
782 n := n.(*ir.InlinedCallExpr)
783 o.stmtList(n.Body)
784
785
786 for _, result := range n.ReturnVars {
787 if staticinit.AnySideEffects(result) {
788 base.FatalfAt(result.Pos(), "inlined call result has side effects: %v", result)
789 }
790 }
791
792 case ir.OCHECKNIL, ir.OCLEAR, ir.OCLOSE, ir.OPANIC, ir.ORECV:
793 n := n.(*ir.UnaryExpr)
794 t := o.markTemp()
795 n.X = o.expr(n.X, nil)
796 o.out = append(o.out, n)
797 o.popTemp(t)
798
799 case ir.OCOPY:
800 n := n.(*ir.BinaryExpr)
801 t := o.markTemp()
802 n.X = o.expr(n.X, nil)
803 n.Y = o.expr(n.Y, nil)
804 o.out = append(o.out, n)
805 o.popTemp(t)
806
807 case ir.OPRINT, ir.OPRINTLN, ir.ORECOVERFP:
808 n := n.(*ir.CallExpr)
809 t := o.markTemp()
810 o.call(n)
811 o.out = append(o.out, n)
812 o.popTemp(t)
813
814
815 case ir.ODEFER, ir.OGO:
816 n := n.(*ir.GoDeferStmt)
817 t := o.markTemp()
818 o.init(n.Call)
819 o.call(n.Call)
820 o.out = append(o.out, n)
821 o.popTemp(t)
822
823 case ir.ODELETE:
824 n := n.(*ir.CallExpr)
825 t := o.markTemp()
826 n.Args[0] = o.expr(n.Args[0], nil)
827 n.Args[1] = o.expr(n.Args[1], nil)
828 n.Args[1] = o.mapKeyTemp(n.Pos(), n.Args[0].Type(), n.Args[1])
829 o.out = append(o.out, n)
830 o.popTemp(t)
831
832
833
834 case ir.OFOR:
835 n := n.(*ir.ForStmt)
836 t := o.markTemp()
837 n.Cond = o.exprInPlace(n.Cond)
838 orderBlock(&n.Body, o.free)
839 n.Post = orderStmtInPlace(n.Post, o.free)
840 o.out = append(o.out, n)
841 o.popTemp(t)
842
843
844
845 case ir.OIF:
846 n := n.(*ir.IfStmt)
847 t := o.markTemp()
848 n.Cond = o.exprInPlace(n.Cond)
849 o.popTemp(t)
850 orderBlock(&n.Body, o.free)
851 orderBlock(&n.Else, o.free)
852 o.out = append(o.out, n)
853
854 case ir.ORANGE:
855
856
857
858
859
860
861
862
863
864
865
866
867
868 n := n.(*ir.RangeStmt)
869 if x, ok := n.X.(*ir.ConvExpr); ok {
870 switch x.Op() {
871 case ir.OSTR2BYTES:
872 x.SetOp(ir.OSTR2BYTESTMP)
873 fallthrough
874 case ir.OSTR2BYTESTMP:
875 x.MarkNonNil()
876 }
877 }
878
879 t := o.markTemp()
880 n.X = o.expr(n.X, nil)
881
882 orderBody := true
883 xt := typecheck.RangeExprType(n.X.Type())
884 switch k := xt.Kind(); {
885 default:
886 base.Fatalf("order.stmt range %v", n.Type())
887
888 case types.IsInt[k]:
889
890
891 case k == types.TARRAY, k == types.TSLICE:
892 if n.Value == nil || ir.IsBlank(n.Value) {
893
894
895 break
896 }
897 fallthrough
898
899 case k == types.TCHAN, k == types.TSTRING:
900
901
902 r := n.X
903
904 if r.Type().IsString() && r.Type() != types.Types[types.TSTRING] {
905 r = ir.NewConvExpr(base.Pos, ir.OCONV, nil, r)
906 r.SetType(types.Types[types.TSTRING])
907 r = typecheck.Expr(r)
908 }
909
910 n.X = o.copyExpr(r)
911
912 case k == types.TMAP:
913 if isMapClear(n) {
914
915
916
917 orderBody = false
918 break
919 }
920
921
922
923
924 r := n.X
925 n.X = o.copyExpr(r)
926
927
928
929 n.Prealloc = o.newTemp(reflectdata.MapIterType(), true)
930 }
931 n.Key = o.exprInPlace(n.Key)
932 n.Value = o.exprInPlace(n.Value)
933 if orderBody {
934 orderBlock(&n.Body, o.free)
935 }
936 o.out = append(o.out, n)
937 o.popTemp(t)
938
939 case ir.ORETURN:
940 n := n.(*ir.ReturnStmt)
941 o.exprList(n.Results)
942 o.out = append(o.out, n)
943
944
945
946
947
948
949
950
951
952
953 case ir.OSELECT:
954 n := n.(*ir.SelectStmt)
955 t := o.markTemp()
956 for _, ncas := range n.Cases {
957 r := ncas.Comm
958 ir.SetPos(ncas)
959
960
961
962 if len(ncas.Init()) != 0 {
963 base.Fatalf("order select ninit")
964 }
965 if r == nil {
966 continue
967 }
968 switch r.Op() {
969 default:
970 ir.Dump("select case", r)
971 base.Fatalf("unknown op in select %v", r.Op())
972
973 case ir.OSELRECV2:
974
975 r := r.(*ir.AssignListStmt)
976 recv := r.Rhs[0].(*ir.UnaryExpr)
977 recv.X = o.expr(recv.X, nil)
978 if !ir.IsAutoTmp(recv.X) {
979 recv.X = o.copyExpr(recv.X)
980 }
981 init := ir.TakeInit(r)
982
983 colas := r.Def
984 do := func(i int, t *types.Type) {
985 n := r.Lhs[i]
986 if ir.IsBlank(n) {
987 return
988 }
989
990
991
992
993 if colas {
994 if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).X == n {
995 init = init[1:]
996
997
998
999 if len(init) > 0 && init[0].Op() == ir.OAS && init[0].(*ir.AssignStmt).X == n {
1000 init = init[1:]
1001 }
1002 }
1003 dcl := typecheck.Stmt(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name)))
1004 ncas.PtrInit().Append(dcl)
1005 }
1006 tmp := o.newTemp(t, t.HasPointers())
1007 as := typecheck.Stmt(ir.NewAssignStmt(base.Pos, n, typecheck.Conv(tmp, n.Type())))
1008 ncas.PtrInit().Append(as)
1009 r.Lhs[i] = tmp
1010 }
1011 do(0, recv.X.Type().Elem())
1012 do(1, types.Types[types.TBOOL])
1013 if len(init) != 0 {
1014 ir.DumpList("ninit", init)
1015 base.Fatalf("ninit on select recv")
1016 }
1017 orderBlock(ncas.PtrInit(), o.free)
1018
1019 case ir.OSEND:
1020 r := r.(*ir.SendStmt)
1021 if len(r.Init()) != 0 {
1022 ir.DumpList("ninit", r.Init())
1023 base.Fatalf("ninit on select send")
1024 }
1025
1026
1027
1028 r.Chan = o.expr(r.Chan, nil)
1029
1030 if !ir.IsAutoTmp(r.Chan) {
1031 r.Chan = o.copyExpr(r.Chan)
1032 }
1033 r.Value = o.expr(r.Value, nil)
1034 if !ir.IsAutoTmp(r.Value) {
1035 r.Value = o.copyExpr(r.Value)
1036 }
1037 }
1038 }
1039
1040
1041
1042 for _, cas := range n.Cases {
1043 orderBlock(&cas.Body, o.free)
1044
1045
1046
1047 cas.Body.Prepend(ir.TakeInit(cas)...)
1048 }
1049
1050 o.out = append(o.out, n)
1051 o.popTemp(t)
1052
1053
1054 case ir.OSEND:
1055 n := n.(*ir.SendStmt)
1056 t := o.markTemp()
1057 n.Chan = o.expr(n.Chan, nil)
1058 n.Value = o.expr(n.Value, nil)
1059 if base.Flag.Cfg.Instrumenting {
1060
1061
1062 n.Value = o.copyExpr(n.Value)
1063 } else {
1064 n.Value = o.addrTemp(n.Value)
1065 }
1066 o.out = append(o.out, n)
1067 o.popTemp(t)
1068
1069
1070
1071
1072
1073
1074
1075
1076 case ir.OSWITCH:
1077 n := n.(*ir.SwitchStmt)
1078 if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) {
1079
1080 n.Cases = append(n.Cases, ir.NewCaseStmt(base.Pos, nil, nil))
1081 }
1082
1083 t := o.markTemp()
1084 n.Tag = o.expr(n.Tag, nil)
1085 for _, ncas := range n.Cases {
1086 o.exprListInPlace(ncas.List)
1087 orderBlock(&ncas.Body, o.free)
1088 }
1089
1090 o.out = append(o.out, n)
1091 o.popTemp(t)
1092 }
1093
1094 base.Pos = lno
1095 }
1096
1097 func hasDefaultCase(n *ir.SwitchStmt) bool {
1098 for _, ncas := range n.Cases {
1099 if len(ncas.List) == 0 {
1100 return true
1101 }
1102 }
1103 return false
1104 }
1105
1106
1107 func (o *orderState) exprList(l ir.Nodes) {
1108 s := l
1109 for i := range s {
1110 s[i] = o.expr(s[i], nil)
1111 }
1112 }
1113
1114
1115
1116 func (o *orderState) exprListInPlace(l ir.Nodes) {
1117 s := l
1118 for i := range s {
1119 s[i] = o.exprInPlace(s[i])
1120 }
1121 }
1122
1123 func (o *orderState) exprNoLHS(n ir.Node) ir.Node {
1124 return o.expr(n, nil)
1125 }
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 func (o *orderState) expr(n, lhs ir.Node) ir.Node {
1136 if n == nil {
1137 return n
1138 }
1139 lno := ir.SetPos(n)
1140 n = o.expr1(n, lhs)
1141 base.Pos = lno
1142 return n
1143 }
1144
1145 func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
1146 o.init(n)
1147
1148 switch n.Op() {
1149 default:
1150 if o.edit == nil {
1151 o.edit = o.exprNoLHS
1152 }
1153 ir.EditChildren(n, o.edit)
1154 return n
1155
1156
1157
1158
1159 case ir.OADDSTR:
1160 n := n.(*ir.AddStringExpr)
1161 o.exprList(n.List)
1162
1163 if len(n.List) > 5 {
1164 t := types.NewArray(types.Types[types.TSTRING], int64(len(n.List)))
1165 n.Prealloc = o.newTemp(t, false)
1166 }
1167
1168
1169
1170
1171
1172
1173
1174
1175 hasbyte := false
1176
1177 haslit := false
1178 for _, n1 := range n.List {
1179 hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
1180 haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0
1181 }
1182
1183 if haslit && hasbyte {
1184 for _, n2 := range n.List {
1185 if n2.Op() == ir.OBYTES2STR {
1186 n2 := n2.(*ir.ConvExpr)
1187 n2.SetOp(ir.OBYTES2STRTMP)
1188 }
1189 }
1190 }
1191 return n
1192
1193 case ir.OINDEXMAP:
1194 n := n.(*ir.IndexExpr)
1195 n.X = o.expr(n.X, nil)
1196 n.Index = o.expr(n.Index, nil)
1197 needCopy := false
1198
1199 if !n.Assigned {
1200
1201
1202
1203
1204 needCopy = mapKeyReplaceStrConv(n.Index)
1205
1206 if base.Flag.Cfg.Instrumenting {
1207
1208 needCopy = true
1209 }
1210 }
1211
1212
1213 n.Index = o.mapKeyTemp(n.Pos(), n.X.Type(), n.Index)
1214 if needCopy {
1215 return o.copyExpr(n)
1216 }
1217 return n
1218
1219
1220
1221 case ir.OCONVIFACE:
1222 n := n.(*ir.ConvExpr)
1223 n.X = o.expr(n.X, nil)
1224 if n.X.Type().IsInterface() {
1225 return n
1226 }
1227 if _, _, needsaddr := dataWordFuncName(n.X.Type()); needsaddr || isStaticCompositeLiteral(n.X) {
1228
1229
1230
1231 n.X = o.addrTemp(n.X)
1232 }
1233 return n
1234
1235 case ir.OCONVNOP:
1236 n := n.(*ir.ConvExpr)
1237 if n.X.Op() == ir.OCALLMETH {
1238 base.FatalfAt(n.X.Pos(), "OCALLMETH missed by typecheck")
1239 }
1240 if n.Type().IsKind(types.TUNSAFEPTR) && n.X.Type().IsKind(types.TUINTPTR) && (n.X.Op() == ir.OCALLFUNC || n.X.Op() == ir.OCALLINTER) {
1241 call := n.X.(*ir.CallExpr)
1242
1243
1244
1245 o.init(call)
1246 o.call(call)
1247 if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1248 return o.copyExpr(n)
1249 }
1250 } else {
1251 n.X = o.expr(n.X, nil)
1252 }
1253 return n
1254
1255 case ir.OANDAND, ir.OOROR:
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265 n := n.(*ir.LogicalExpr)
1266 r := o.newTemp(n.Type(), false)
1267
1268
1269 lhs := o.expr(n.X, nil)
1270 o.out = append(o.out, typecheck.Stmt(ir.NewAssignStmt(base.Pos, r, lhs)))
1271
1272
1273 saveout := o.out
1274 o.out = nil
1275 t := o.markTemp()
1276 o.edge()
1277 rhs := o.expr(n.Y, nil)
1278 o.out = append(o.out, typecheck.Stmt(ir.NewAssignStmt(base.Pos, r, rhs)))
1279 o.popTemp(t)
1280 gen := o.out
1281 o.out = saveout
1282
1283
1284 nif := ir.NewIfStmt(base.Pos, r, nil, nil)
1285 if n.Op() == ir.OANDAND {
1286 nif.Body = gen
1287 } else {
1288 nif.Else = gen
1289 }
1290 o.out = append(o.out, nif)
1291 return r
1292
1293 case ir.OCALLMETH:
1294 base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
1295 panic("unreachable")
1296
1297 case ir.OCALLFUNC,
1298 ir.OCALLINTER,
1299 ir.OCAP,
1300 ir.OCOMPLEX,
1301 ir.OCOPY,
1302 ir.OIMAG,
1303 ir.OLEN,
1304 ir.OMAKECHAN,
1305 ir.OMAKEMAP,
1306 ir.OMAKESLICE,
1307 ir.OMAKESLICECOPY,
1308 ir.OMAX,
1309 ir.OMIN,
1310 ir.ONEW,
1311 ir.OREAL,
1312 ir.ORECOVERFP,
1313 ir.OSTR2BYTES,
1314 ir.OSTR2BYTESTMP,
1315 ir.OSTR2RUNES:
1316
1317 if isRuneCount(n) {
1318
1319 conv := n.(*ir.UnaryExpr).X.(*ir.ConvExpr)
1320 conv.X = o.expr(conv.X, nil)
1321 } else {
1322 o.call(n)
1323 }
1324
1325 if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1326 return o.copyExpr(n)
1327 }
1328 return n
1329
1330 case ir.OINLCALL:
1331 n := n.(*ir.InlinedCallExpr)
1332 o.stmtList(n.Body)
1333 return n.SingleResult()
1334
1335 case ir.OAPPEND:
1336
1337 n := n.(*ir.CallExpr)
1338 if isAppendOfMake(n) {
1339 n.Args[0] = o.expr(n.Args[0], nil)
1340 mk := n.Args[1].(*ir.MakeExpr)
1341 mk.Len = o.expr(mk.Len, nil)
1342 } else {
1343 o.exprList(n.Args)
1344 }
1345
1346 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.Args[0]) {
1347 return o.copyExpr(n)
1348 }
1349 return n
1350
1351 case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
1352 n := n.(*ir.SliceExpr)
1353 n.X = o.expr(n.X, nil)
1354 n.Low = o.cheapExpr(o.expr(n.Low, nil))
1355 n.High = o.cheapExpr(o.expr(n.High, nil))
1356 n.Max = o.cheapExpr(o.expr(n.Max, nil))
1357 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.X) {
1358 return o.copyExpr(n)
1359 }
1360 return n
1361
1362 case ir.OCLOSURE:
1363 n := n.(*ir.ClosureExpr)
1364 if n.Transient() && len(n.Func.ClosureVars) > 0 {
1365 n.Prealloc = o.newTemp(typecheck.ClosureType(n), false)
1366 }
1367 return n
1368
1369 case ir.OMETHVALUE:
1370 n := n.(*ir.SelectorExpr)
1371 n.X = o.expr(n.X, nil)
1372 if n.Transient() {
1373 t := typecheck.MethodValueType(n)
1374 n.Prealloc = o.newTemp(t, false)
1375 }
1376 return n
1377
1378 case ir.OSLICELIT:
1379 n := n.(*ir.CompLitExpr)
1380 o.exprList(n.List)
1381 if n.Transient() {
1382 t := types.NewArray(n.Type().Elem(), n.Len)
1383 n.Prealloc = o.newTemp(t, false)
1384 }
1385 return n
1386
1387 case ir.ODOTTYPE, ir.ODOTTYPE2:
1388 n := n.(*ir.TypeAssertExpr)
1389 n.X = o.expr(n.X, nil)
1390 if !types.IsDirectIface(n.Type()) || base.Flag.Cfg.Instrumenting {
1391 return o.copyExprClear(n)
1392 }
1393 return n
1394
1395 case ir.ORECV:
1396 n := n.(*ir.UnaryExpr)
1397 n.X = o.expr(n.X, nil)
1398 return o.copyExprClear(n)
1399
1400 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
1401 n := n.(*ir.BinaryExpr)
1402 n.X = o.expr(n.X, nil)
1403 n.Y = o.expr(n.Y, nil)
1404
1405 t := n.X.Type()
1406 switch {
1407 case t.IsString():
1408
1409
1410
1411 if n.X.Op() == ir.OBYTES2STR {
1412 n.X.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1413 }
1414 if n.Y.Op() == ir.OBYTES2STR {
1415 n.Y.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1416 }
1417
1418 case t.IsStruct() || t.IsArray():
1419
1420
1421 n.X = o.addrTemp(n.X)
1422 n.Y = o.addrTemp(n.Y)
1423 }
1424 return n
1425
1426 case ir.OMAPLIT:
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442 n := n.(*ir.CompLitExpr)
1443 entries := n.List
1444 statics := entries[:0]
1445 var dynamics []*ir.KeyExpr
1446 for _, r := range entries {
1447 r := r.(*ir.KeyExpr)
1448
1449 if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1450 dynamics = append(dynamics, r)
1451 continue
1452 }
1453
1454
1455
1456 r = o.expr(r, nil).(*ir.KeyExpr)
1457 if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1458 dynamics = append(dynamics, r)
1459 continue
1460 }
1461
1462 statics = append(statics, r)
1463 }
1464 n.List = statics
1465
1466 if len(dynamics) == 0 {
1467 return n
1468 }
1469
1470
1471 m := o.newTemp(n.Type(), false)
1472 as := ir.NewAssignStmt(base.Pos, m, n)
1473 typecheck.Stmt(as)
1474 o.stmt(as)
1475
1476
1477 for _, r := range dynamics {
1478 lhs := typecheck.AssignExpr(ir.NewIndexExpr(base.Pos, m, r.Key)).(*ir.IndexExpr)
1479 base.AssertfAt(lhs.Op() == ir.OINDEXMAP, lhs.Pos(), "want OINDEXMAP, have %+v", lhs)
1480 lhs.RType = n.RType
1481
1482 as := ir.NewAssignStmt(base.Pos, lhs, r.Value)
1483 typecheck.Stmt(as)
1484 o.stmt(as)
1485 }
1486
1487
1488
1489
1490
1491
1492
1493 n.Len += int64(len(dynamics))
1494
1495 return m
1496 }
1497
1498
1499 }
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513 func (o *orderState) as2func(n *ir.AssignListStmt) {
1514 results := n.Rhs[0].Type()
1515 as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1516 for i, nl := range n.Lhs {
1517 if !ir.IsBlank(nl) {
1518 typ := results.Field(i).Type
1519 tmp := o.newTemp(typ, typ.HasPointers())
1520 n.Lhs[i] = tmp
1521 as.Lhs = append(as.Lhs, nl)
1522 as.Rhs = append(as.Rhs, tmp)
1523 }
1524 }
1525
1526 o.out = append(o.out, n)
1527 o.stmt(typecheck.Stmt(as))
1528 }
1529
1530
1531
1532 func (o *orderState) as2ok(n *ir.AssignListStmt) {
1533 as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1534
1535 do := func(i int, typ *types.Type) {
1536 if nl := n.Lhs[i]; !ir.IsBlank(nl) {
1537 var tmp ir.Node = o.newTemp(typ, typ.HasPointers())
1538 n.Lhs[i] = tmp
1539 as.Lhs = append(as.Lhs, nl)
1540 if i == 1 {
1541
1542
1543
1544 tmp = typecheck.Conv(tmp, nl.Type())
1545 }
1546 as.Rhs = append(as.Rhs, tmp)
1547 }
1548 }
1549
1550 do(0, n.Rhs[0].Type())
1551 do(1, types.Types[types.TBOOL])
1552
1553 o.out = append(o.out, n)
1554 o.stmt(typecheck.Stmt(as))
1555 }
1556
View as plain text