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