1
2
3
4
5 package walk
6
7 import (
8 "fmt"
9 "go/constant"
10 "internal/abi"
11
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/reflectdata"
15 "cmd/compile/internal/ssa"
16 "cmd/compile/internal/staticinit"
17 "cmd/compile/internal/typecheck"
18 "cmd/compile/internal/types"
19 "cmd/internal/objabi"
20 "cmd/internal/src"
21 )
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 type orderState struct {
43 out []ir.Node
44 temp []*ir.Name
45 free map[string][]*ir.Name
46 edit func(ir.Node) ir.Node
47 walkstate *walkState
48 }
49
50
51
52 func (w *walkState) 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 w.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(o.walkstate.curfunc, stmt))
64 }
65
66
67
68
69 func (o *orderState) newTemp(walkstate *walkState, 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, walkstate.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(walkstate *walkState, n ir.Node) *ir.Name {
92 return o.copyExpr1(walkstate, n, false)
93 }
94
95
96
97
98
99
100
101
102
103
104
105 func (o *orderState) copyExprClear(walkstate *walkState, n ir.Node) *ir.Name {
106 return o.copyExpr1(walkstate, n, true)
107 }
108
109 func (o *orderState) copyExpr1(walkstate *walkState, n ir.Node, clear bool) *ir.Name {
110 t := n.Type()
111 v := o.newTemp(walkstate, 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(walkstate *walkState, 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(walkstate, 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(o.walkstate.curfunc, a)
137 }
138
139 return o.copyExpr(walkstate, n)
140 }
141
142
143
144
145
146
147
148
149 func (o *orderState) safeExpr(walkstate *walkState, 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(walkstate, 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(o.walkstate.curfunc, a)
163
164 case ir.ODOT:
165 n := n.(*ir.SelectorExpr)
166 l := o.safeExpr(walkstate, 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(o.walkstate.curfunc, a)
173
174 case ir.ODOTPTR:
175 n := n.(*ir.SelectorExpr)
176 l := o.cheapExpr(walkstate, 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(o.walkstate.curfunc, a)
183
184 case ir.ODEREF:
185 n := n.(*ir.StarExpr)
186 l := o.cheapExpr(walkstate, 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(o.walkstate.curfunc, 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(walkstate, n.X)
199 } else {
200 l = o.cheapExpr(walkstate, n.X)
201 }
202 r := o.cheapExpr(walkstate, 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(o.walkstate.curfunc, 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(walkstate *walkState, 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(o.walkstate.curfunc, 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(o.walkstate.curfunc, vstat).(*ir.Name)
241 return vstat
242 }
243
244
245 v := walkstate.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(o.walkstate.curfunc, 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 walkstate.fixedlit(initKindStatic, lit, vstat, nil)
265 vstat = typecheck.Expr(o.walkstate.curfunc, 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(walkstate, n)
289 }
290
291
292
293
294 func (o *orderState) mapKeyTemp(walkstate *walkState, 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(walkstate, 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(o.walkstate.curfunc, 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(o.walkstate.curfunc, 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(walkstate, kt, true)
340
341 var e ir.Node = typecheck.NodAddr(o.walkstate.curfunc, 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(walkstate *walkState, l ir.Nodes) {
421 s := l
422 for i := range s {
423 orderMakeSliceCopy(o.walkstate.curfunc, s[i:])
424 o.stmt(walkstate, s[i])
425 }
426 }
427
428
429
430 func nonAddrTakenName(n ir.Node) *ir.Name {
431 if n.Op() == ir.ONAME {
432 if v := n.(*ir.Name); !v.Addrtaken() {
433 return v
434 }
435 }
436
437 return nil
438 }
439
440
441 func containsName(root ir.Node, target *ir.Name) bool {
442 return ir.Any(root, func(n ir.Node) bool {
443 return n.Op() == ir.ONAME && n.(*ir.Name) == target
444 })
445 }
446
447
448
449
450
451
452
453
454 func orderMakeSliceCopy(curfunc *ir.Func, s []ir.Node) {
455 if base.Flag.N != 0 || base.Flag.Cfg.Instrumenting {
456 return
457 }
458 if len(s) < 2 || s[0] == nil || s[0].Op() != ir.OAS || s[1] == nil || s[1].Op() != ir.OCOPY {
459 return
460 }
461
462 as := s[0].(*ir.AssignStmt)
463 cp := s[1].(*ir.BinaryExpr)
464 if as.Y == nil || as.Y.Op() != ir.OMAKESLICE || ir.IsBlank(as.X) ||
465 !ir.SameSafeExpr(as.X, cp.X) || ir.SameSafeExpr(cp.X, cp.Y) {
466
467
468
469 return
470 }
471
472 safe := false
473 if dst := nonAddrTakenName(as.X); dst != nil {
474 safe = !containsName(cp.Y, dst)
475 }
476 if !safe {
477 if src := nonAddrTakenName(cp.Y); src != nil {
478 safe = !containsName(as.X, src)
479 }
480 }
481 if !safe {
482
483
484
485
486 return
487 }
488
489 mk := as.Y.(*ir.MakeExpr)
490 if mk.Esc() == ir.EscNone || mk.Len == nil || mk.Cap != nil {
491 return
492 }
493 mk.SetOp(ir.OMAKESLICECOPY)
494 mk.Cap = cp.Y
495
496 mk.SetBounded(mk.Len.Op() == ir.OLEN && ir.SameSafeExpr(mk.Len.(*ir.UnaryExpr).X, cp.Y))
497 as.Y = typecheck.Expr(curfunc, mk)
498 s[1] = nil
499 }
500
501
502 func (o *orderState) edge() {
503 if base.Debug.Libfuzzer == 0 {
504 return
505 }
506
507
508 counter := staticinit.StaticName(types.Types[types.TUINT8])
509 counter.SetLibfuzzer8BitCounter(true)
510
511
512
513
514
515
516 counter.Linksym().Type = objabi.SLIBFUZZER_8BIT_COUNTER
517
518
519
520
521
522
523
524
525
526
527
528 o.append(ir.NewIfStmt(base.Pos,
529 ir.NewBinaryExpr(base.Pos, ir.OEQ, counter, ir.NewInt(base.Pos, 0xff)),
530 []ir.Node{ir.NewAssignStmt(base.Pos, counter, ir.NewInt(base.Pos, 1))},
531 []ir.Node{ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(base.Pos, 1))}))
532 }
533
534
535
536
537 func (w *walkState) orderBlock(n *ir.Nodes, free map[string][]*ir.Name) {
538 if len(*n) != 0 {
539
540
541
542 ir.SetPos((*n)[0])
543 }
544 var order orderState
545 order.walkstate = w
546 order.free = free
547 mark := order.markTemp()
548 order.edge()
549 order.stmtList(w, *n)
550 order.popTemp(mark)
551 *n = order.out
552 }
553
554
555
556
557
558
559 func (o *orderState) exprInPlace(walkstate *walkState, n ir.Node) ir.Node {
560 var order orderState
561 order.walkstate = walkstate
562 order.free = o.free
563 n = order.expr(walkstate, n, nil)
564 n = ir.InitExpr(order.out, n)
565
566
567
568 o.temp = append(o.temp, order.temp...)
569 return n
570 }
571
572
573
574
575
576
577
578
579 func (w *walkState) orderStmtInPlace(n ir.Node, free map[string][]*ir.Name) ir.Node {
580 var order orderState
581 order.walkstate = w
582 order.free = free
583 mark := order.markTemp()
584 order.stmt(w, n)
585 order.popTemp(mark)
586 return ir.NewBlockStmt(src.NoXPos, order.out)
587 }
588
589
590 func (o *orderState) init(walkstate *walkState, n ir.Node) {
591 if ir.MayBeShared(n) {
592
593
594 if len(n.Init()) > 0 {
595 base.Fatalf("order.init shared node with ninit")
596 }
597 return
598 }
599 o.stmtList(walkstate, ir.TakeInit(n))
600 }
601
602
603
604 func (o *orderState) call(walkstate *walkState, nn ir.Node) {
605 if len(nn.Init()) > 0 {
606
607 base.Fatalf("%v with unexpected ninit", nn.Op())
608 }
609 if nn.Op() == ir.OCALLMETH {
610 base.FatalfAt(nn.Pos(), "OCALLMETH missed by typecheck")
611 }
612
613
614 if nn.Op() != ir.OCALLFUNC && nn.Op() != ir.OCALLINTER {
615 switch n := nn.(type) {
616 default:
617 base.Fatalf("unexpected call: %+v", n)
618 case *ir.UnaryExpr:
619 n.X = o.expr(walkstate, n.X, nil)
620 case *ir.ConvExpr:
621 n.X = o.expr(walkstate, n.X, nil)
622 case *ir.BinaryExpr:
623 n.X = o.expr(walkstate, n.X, nil)
624 n.Y = o.expr(walkstate, n.Y, nil)
625 case *ir.MakeExpr:
626 n.Len = o.expr(walkstate, n.Len, nil)
627 n.Cap = o.expr(walkstate, n.Cap, nil)
628 case *ir.CallExpr:
629 o.exprList(walkstate, n.Args)
630 }
631 return
632 }
633
634 n := nn.(*ir.CallExpr)
635 typecheck.AssertFixedCall(n)
636
637 if ir.IsFuncPCIntrinsic(n) && ir.IsIfaceOfFunc(n.Args[0]) != nil {
638
639
640
641 return
642 }
643
644 n.Fun = o.expr(walkstate, n.Fun, nil)
645 o.exprList(walkstate, n.Args)
646 }
647
648
649 func (o *orderState) mapAssign(walkstate *walkState, n ir.Node) {
650 switch n.Op() {
651 default:
652 base.Fatalf("order.mapAssign %v", n.Op())
653
654 case ir.OAS:
655 n := n.(*ir.AssignStmt)
656 if n.X.Op() == ir.OINDEXMAP {
657 n.Y = o.safeMapRHS(walkstate, n.Y)
658 }
659 o.out = append(o.out, n)
660 case ir.OASOP:
661 n := n.(*ir.AssignOpStmt)
662 if n.X.Op() == ir.OINDEXMAP {
663 n.Y = o.safeMapRHS(walkstate, n.Y)
664 }
665 o.out = append(o.out, n)
666 }
667 }
668
669 func (o *orderState) safeMapRHS(walkstate *walkState, r ir.Node) ir.Node {
670
671
672 if r.Op() == ir.OAPPEND {
673 r := r.(*ir.CallExpr)
674 s := r.Args[1:]
675 for i, n := range s {
676 s[i] = o.cheapExpr(walkstate, n)
677 }
678 return r
679 }
680 return o.cheapExpr(walkstate, r)
681 }
682
683
684 func (o *orderState) stmt(walkstate *walkState, n ir.Node) {
685 if n == nil {
686 return
687 }
688
689 lno := ir.SetPos(n)
690 o.init(walkstate, n)
691
692 switch n.Op() {
693 default:
694 base.Fatalf("order.stmt %v", n.Op())
695
696 case ir.OINLMARK:
697 o.out = append(o.out, n)
698
699 case ir.OAS:
700 n := n.(*ir.AssignStmt)
701 t := o.markTemp()
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716 mapAppend := n.X.Op() == ir.OINDEXMAP && n.Y.Op() == ir.OAPPEND &&
717 ir.SameSafeExpr(n.X, n.Y.(*ir.CallExpr).Args[0])
718
719 n.X = o.expr(walkstate, n.X, nil)
720 if mapAppend {
721 indexLHS := n.X.(*ir.IndexExpr)
722 indexLHS.X = o.cheapExpr(walkstate, indexLHS.X)
723 indexLHS.Index = o.cheapExpr(walkstate, indexLHS.Index)
724
725 call := n.Y.(*ir.CallExpr)
726 arg0 := call.Args[0]
727
728 for arg0.Op() == ir.OCONVNOP {
729 arg0 = arg0.(*ir.ConvExpr).X
730 }
731 indexRHS := arg0.(*ir.IndexExpr)
732 indexRHS.X = indexLHS.X
733 indexRHS.Index = indexLHS.Index
734
735 o.exprList(walkstate, call.Args[1:])
736 } else {
737 n.Y = o.expr(walkstate, n.Y, n.X)
738 }
739 o.mapAssign(walkstate, n)
740 o.popTemp(t)
741
742 case ir.OASOP:
743 n := n.(*ir.AssignOpStmt)
744 t := o.markTemp()
745 n.X = o.expr(walkstate, n.X, nil)
746 n.Y = o.expr(walkstate, n.Y, nil)
747
748 if base.Flag.Cfg.Instrumenting || n.X.Op() == ir.OINDEXMAP && (n.AsOp == ir.ODIV || n.AsOp == ir.OMOD) {
749
750
751
752
753
754
755 l1 := o.safeExpr(walkstate, n.X)
756 l2 := ir.DeepCopy(src.NoXPos, l1)
757 if l2.Op() == ir.OINDEXMAP {
758 l2 := l2.(*ir.IndexExpr)
759 l2.Assigned = false
760 }
761 l2 = o.copyExpr(walkstate, l2)
762 r := o.expr(walkstate, typecheck.Expr(o.walkstate.curfunc, ir.NewBinaryExpr(n.Pos(), n.AsOp, l2, n.Y)), nil)
763 as := typecheck.Stmt(o.walkstate.curfunc, ir.NewAssignStmt(n.Pos(), l1, r))
764 o.mapAssign(walkstate, as)
765 o.popTemp(t)
766 return
767 }
768
769 o.mapAssign(walkstate, n)
770 o.popTemp(t)
771
772 case ir.OAS2:
773 n := n.(*ir.AssignListStmt)
774 t := o.markTemp()
775 o.exprList(walkstate, n.Lhs)
776 o.exprList(walkstate, n.Rhs)
777 o.out = append(o.out, n)
778 o.popTemp(t)
779
780
781 case ir.OAS2FUNC:
782 n := n.(*ir.AssignListStmt)
783 t := o.markTemp()
784 o.exprList(walkstate, n.Lhs)
785 call := n.Rhs[0]
786 o.init(walkstate, call)
787 if ic, ok := call.(*ir.InlinedCallExpr); ok {
788 o.stmtList(walkstate, ic.Body)
789
790 n.SetOp(ir.OAS2)
791 n.Rhs = ic.ReturnVars
792
793 o.exprList(walkstate, n.Rhs)
794 o.out = append(o.out, n)
795 } else {
796 o.call(walkstate, call)
797 o.as2func(walkstate, n)
798 }
799 o.popTemp(t)
800
801
802
803
804
805
806
807 case ir.OAS2DOTTYPE, ir.OAS2RECV, ir.OAS2MAPR:
808 n := n.(*ir.AssignListStmt)
809 t := o.markTemp()
810 o.exprList(walkstate, n.Lhs)
811
812 switch r := n.Rhs[0]; r.Op() {
813 case ir.ODOTTYPE2:
814 r := r.(*ir.TypeAssertExpr)
815 r.X = o.expr(walkstate, r.X, nil)
816 case ir.ODYNAMICDOTTYPE2:
817 r := r.(*ir.DynamicTypeAssertExpr)
818 r.X = o.expr(walkstate, r.X, nil)
819 r.RType = o.expr(walkstate, r.RType, nil)
820 r.ITab = o.expr(walkstate, r.ITab, nil)
821 case ir.ORECV:
822 r := r.(*ir.UnaryExpr)
823 r.X = o.expr(walkstate, r.X, nil)
824 case ir.OINDEXMAP:
825 r := r.(*ir.IndexExpr)
826 r.X = o.expr(walkstate, r.X, nil)
827 r.Index = o.expr(walkstate, r.Index, nil)
828
829 _ = mapKeyReplaceStrConv(r.Index)
830 r.Index = o.mapKeyTemp(walkstate, r.Pos(), r.X.Type(), r.Index)
831 default:
832 base.Fatalf("order.stmt: %v", r.Op())
833 }
834
835 o.as2ok(walkstate, n)
836 o.popTemp(t)
837
838
839 case ir.OBLOCK:
840 n := n.(*ir.BlockStmt)
841 o.stmtList(walkstate, n.List)
842
843
844 case ir.OBREAK,
845 ir.OCONTINUE,
846 ir.ODCL,
847 ir.OFALL,
848 ir.OGOTO,
849 ir.OLABEL,
850 ir.OTAILCALL:
851 o.out = append(o.out, n)
852
853
854 case ir.OCALLFUNC, ir.OCALLINTER:
855 n := n.(*ir.CallExpr)
856 t := o.markTemp()
857 o.call(walkstate, n)
858 o.out = append(o.out, n)
859 o.popTemp(t)
860
861 case ir.OINLCALL:
862 n := n.(*ir.InlinedCallExpr)
863 o.stmtList(walkstate, n.Body)
864
865
866 for _, result := range n.ReturnVars {
867 if ir.AnySideEffects(result) {
868 base.FatalfAt(result.Pos(), "inlined call result has side effects: %v", result)
869 }
870 }
871
872 case ir.OCHECKNIL, ir.OCLEAR, ir.OCLOSE, ir.OPANIC, ir.ORECV:
873 n := n.(*ir.UnaryExpr)
874 t := o.markTemp()
875 n.X = o.expr(walkstate, n.X, nil)
876 o.out = append(o.out, n)
877 o.popTemp(t)
878
879 case ir.OCOPY:
880 n := n.(*ir.BinaryExpr)
881 t := o.markTemp()
882 n.X = o.expr(walkstate, n.X, nil)
883 n.Y = o.expr(walkstate, n.Y, nil)
884 o.out = append(o.out, n)
885 o.popTemp(t)
886
887 case ir.OPRINT, ir.OPRINTLN, ir.ORECOVER:
888 n := n.(*ir.CallExpr)
889 t := o.markTemp()
890 o.call(walkstate, n)
891 o.out = append(o.out, n)
892 o.popTemp(t)
893
894
895 case ir.ODEFER, ir.OGO:
896 n := n.(*ir.GoDeferStmt)
897 t := o.markTemp()
898 o.init(walkstate, n.Call)
899 o.call(walkstate, n.Call)
900 o.out = append(o.out, n)
901 o.popTemp(t)
902
903 case ir.ODELETE:
904 n := n.(*ir.CallExpr)
905 t := o.markTemp()
906 n.Args[0] = o.expr(walkstate, n.Args[0], nil)
907 n.Args[1] = o.expr(walkstate, n.Args[1], nil)
908 n.Args[1] = o.mapKeyTemp(walkstate, n.Pos(), n.Args[0].Type(), n.Args[1])
909 o.out = append(o.out, n)
910 o.popTemp(t)
911
912
913
914 case ir.OFOR:
915 n := n.(*ir.ForStmt)
916 t := o.markTemp()
917 n.Cond = o.exprInPlace(walkstate, n.Cond)
918 walkstate.orderBlock(&n.Body, o.free)
919 n.Post = walkstate.orderStmtInPlace(n.Post, o.free)
920 o.out = append(o.out, n)
921 o.popTemp(t)
922
923
924
925 case ir.OIF:
926 n := n.(*ir.IfStmt)
927 t := o.markTemp()
928 n.Cond = o.exprInPlace(walkstate, n.Cond)
929 o.popTemp(t)
930 walkstate.orderBlock(&n.Body, o.free)
931 walkstate.orderBlock(&n.Else, o.free)
932 o.out = append(o.out, n)
933
934 case ir.ORANGE:
935
936
937
938
939
940
941
942
943
944
945
946
947
948 n := n.(*ir.RangeStmt)
949 if x, ok := n.X.(*ir.ConvExpr); ok {
950 switch x.Op() {
951 case ir.OSTR2BYTES:
952 x.SetOp(ir.OSTR2BYTESTMP)
953 fallthrough
954 case ir.OSTR2BYTESTMP:
955 x.MarkNonNil()
956 }
957 }
958
959 t := o.markTemp()
960 n.X = o.expr(walkstate, n.X, nil)
961
962 orderBody := true
963 xt := typecheck.RangeExprType(n.X.Type())
964 switch k := xt.Kind(); {
965 default:
966 base.Fatalf("order.stmt range %v", n.Type())
967
968 case types.IsInt[k]:
969
970
971 case k == types.TARRAY, k == types.TSLICE:
972 if n.Value == nil || ir.IsBlank(n.Value) {
973
974
975 break
976 }
977 fallthrough
978
979 case k == types.TCHAN, k == types.TSTRING:
980
981
982 r := n.X
983
984 if r.Type().IsString() && r.Type() != types.Types[types.TSTRING] {
985 r = ir.NewConvExpr(base.Pos, ir.OCONV, nil, r)
986 r.SetType(types.Types[types.TSTRING])
987 r = typecheck.Expr(o.walkstate.curfunc, r)
988 }
989
990 n.X = o.copyExpr(walkstate, r)
991
992 case k == types.TMAP:
993 if isMapClear(n) {
994
995
996
997 orderBody = false
998 break
999 }
1000
1001
1002
1003
1004 r := n.X
1005 n.X = o.copyExpr(walkstate, r)
1006
1007
1008
1009 n.Prealloc = o.newTemp(walkstate, reflectdata.MapIterType(), true)
1010 }
1011 n.Key = o.exprInPlace(walkstate, n.Key)
1012 n.Value = o.exprInPlace(walkstate, n.Value)
1013 if orderBody {
1014 walkstate.orderBlock(&n.Body, o.free)
1015 }
1016 o.out = append(o.out, n)
1017 o.popTemp(t)
1018
1019 case ir.ORETURN:
1020 n := n.(*ir.ReturnStmt)
1021 o.exprList(walkstate, n.Results)
1022 o.out = append(o.out, n)
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 case ir.OSELECT:
1034 n := n.(*ir.SelectStmt)
1035 t := o.markTemp()
1036 for _, ncas := range n.Cases {
1037 r := ncas.Comm
1038 ir.SetPos(ncas)
1039
1040
1041
1042 if len(ncas.Init()) != 0 {
1043 base.Fatalf("order select ninit")
1044 }
1045 if r == nil {
1046 continue
1047 }
1048 switch r.Op() {
1049 default:
1050 ir.Dump("select case", r)
1051 base.Fatalf("unknown op in select %v", r.Op())
1052
1053 case ir.OSELRECV2:
1054
1055 r := r.(*ir.AssignListStmt)
1056 recv := r.Rhs[0].(*ir.UnaryExpr)
1057 recv.X = o.expr(walkstate, recv.X, nil)
1058 if !ir.IsAutoTmp(recv.X) {
1059 recv.X = o.copyExpr(walkstate, recv.X)
1060 }
1061 init := ir.TakeInit(r)
1062
1063 colas := r.Def
1064 do := func(i int, t *types.Type) {
1065 n := r.Lhs[i]
1066 if ir.IsBlank(n) {
1067 return
1068 }
1069
1070
1071
1072
1073 if colas {
1074 if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).X == n {
1075 init = init[1:]
1076
1077
1078
1079 if len(init) > 0 && init[0].Op() == ir.OAS && init[0].(*ir.AssignStmt).X == n {
1080 init = init[1:]
1081 }
1082 }
1083 dcl := typecheck.Stmt(o.walkstate.curfunc, ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name)))
1084 ncas.PtrInit().Append(dcl)
1085 }
1086 tmp := o.newTemp(walkstate, t, t.HasPointers())
1087 as := typecheck.Stmt(o.walkstate.curfunc, ir.NewAssignStmt(base.Pos, n, typecheck.Conv(o.walkstate.curfunc, tmp, n.Type())))
1088 ncas.PtrInit().Append(as)
1089 r.Lhs[i] = tmp
1090 }
1091 do(0, recv.X.Type().Elem())
1092 do(1, types.Types[types.TBOOL])
1093 if len(init) != 0 {
1094 ir.DumpList("ninit", init)
1095 base.Fatalf("ninit on select recv")
1096 }
1097 walkstate.orderBlock(ncas.PtrInit(), o.free)
1098
1099 case ir.OSEND:
1100 r := r.(*ir.SendStmt)
1101 if len(r.Init()) != 0 {
1102 ir.DumpList("ninit", r.Init())
1103 base.Fatalf("ninit on select send")
1104 }
1105
1106
1107
1108 r.Chan = o.expr(walkstate, r.Chan, nil)
1109
1110 if !ir.IsAutoTmp(r.Chan) {
1111 r.Chan = o.copyExpr(walkstate, r.Chan)
1112 }
1113 r.Value = o.expr(walkstate, r.Value, nil)
1114 if !ir.IsAutoTmp(r.Value) {
1115 r.Value = o.copyExpr(walkstate, r.Value)
1116 }
1117 }
1118 }
1119
1120
1121
1122 for _, cas := range n.Cases {
1123 walkstate.orderBlock(&cas.Body, o.free)
1124
1125
1126
1127 cas.Body.Prepend(ir.TakeInit(cas)...)
1128 }
1129
1130 o.out = append(o.out, n)
1131 o.popTemp(t)
1132
1133
1134 case ir.OSEND:
1135 n := n.(*ir.SendStmt)
1136 t := o.markTemp()
1137 n.Chan = o.expr(walkstate, n.Chan, nil)
1138 n.Value = o.expr(walkstate, n.Value, nil)
1139 if base.Flag.Cfg.Instrumenting {
1140
1141
1142 n.Value = o.copyExpr(walkstate, n.Value)
1143 } else {
1144 n.Value = o.addrTemp(walkstate, n.Value)
1145 }
1146 o.out = append(o.out, n)
1147 o.popTemp(t)
1148
1149
1150
1151
1152
1153
1154
1155
1156 case ir.OSWITCH:
1157 n := n.(*ir.SwitchStmt)
1158 if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) {
1159
1160 n.Cases = append(n.Cases, ir.NewCaseStmt(base.Pos, nil, nil))
1161 }
1162
1163 t := o.markTemp()
1164 n.Tag = o.expr(walkstate, n.Tag, nil)
1165 for _, ncas := range n.Cases {
1166 o.exprListInPlace(walkstate, ncas.List)
1167 walkstate.orderBlock(&ncas.Body, o.free)
1168 }
1169
1170 o.out = append(o.out, n)
1171 o.popTemp(t)
1172 }
1173
1174 base.Pos = lno
1175 }
1176
1177 func hasDefaultCase(n *ir.SwitchStmt) bool {
1178 for _, ncas := range n.Cases {
1179 if len(ncas.List) == 0 {
1180 return true
1181 }
1182 }
1183 return false
1184 }
1185
1186
1187 func (o *orderState) exprList(walkstate *walkState, l ir.Nodes) {
1188 s := l
1189 for i := range s {
1190 s[i] = o.expr(walkstate, s[i], nil)
1191 }
1192 }
1193
1194
1195
1196 func (o *orderState) exprListInPlace(walkstate *walkState, l ir.Nodes) {
1197 s := l
1198 for i := range s {
1199 s[i] = o.exprInPlace(walkstate, s[i])
1200 }
1201 }
1202
1203 func (o *orderState) exprNoLHS(n ir.Node) ir.Node {
1204 return o.expr(o.walkstate, n, nil)
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215 func (o *orderState) expr(walkstate *walkState, n, lhs ir.Node) ir.Node {
1216 if n == nil {
1217 return n
1218 }
1219 lno := ir.SetPos(n)
1220 n = o.expr1(walkstate, n, lhs)
1221 base.Pos = lno
1222 return n
1223 }
1224
1225 func (o *orderState) expr1(walkstate *walkState, n, lhs ir.Node) ir.Node {
1226 o.init(walkstate, n)
1227
1228 switch n.Op() {
1229 default:
1230 if o.edit == nil {
1231 o.edit = o.exprNoLHS
1232 }
1233 ir.EditChildren(n, o.edit)
1234 return n
1235
1236
1237
1238
1239 case ir.OADDSTR:
1240 n := n.(*ir.AddStringExpr)
1241 o.exprList(walkstate, n.List)
1242
1243 if len(n.List) > 5 {
1244 t := types.NewArray(types.Types[types.TSTRING], int64(len(n.List)))
1245 n.Prealloc = o.newTemp(walkstate, t, false)
1246 }
1247
1248
1249
1250
1251
1252
1253
1254
1255 hasbyte := false
1256
1257 haslit := false
1258 for _, n1 := range n.List {
1259 hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
1260 haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0
1261 }
1262
1263 if haslit && hasbyte {
1264 for _, n2 := range n.List {
1265 if n2.Op() == ir.OBYTES2STR {
1266 n2 := n2.(*ir.ConvExpr)
1267 n2.SetOp(ir.OBYTES2STRTMP)
1268 }
1269 }
1270 }
1271 return n
1272
1273 case ir.OINDEXMAP:
1274 n := n.(*ir.IndexExpr)
1275 n.X = o.expr(walkstate, n.X, nil)
1276 n.Index = o.expr(walkstate, n.Index, nil)
1277 needCopy := false
1278
1279 if !n.Assigned {
1280
1281
1282
1283
1284 needCopy = mapKeyReplaceStrConv(n.Index)
1285
1286 if base.Flag.Cfg.Instrumenting {
1287
1288 needCopy = true
1289 }
1290 }
1291
1292
1293 n.Index = o.mapKeyTemp(walkstate, n.Pos(), n.X.Type(), n.Index)
1294 if needCopy {
1295 return o.copyExpr(walkstate, n)
1296 }
1297 return n
1298
1299
1300
1301 case ir.OCONVIFACE:
1302 n := n.(*ir.ConvExpr)
1303 n.X = o.expr(walkstate, n.X, nil)
1304 if n.X.Type().IsInterface() {
1305 return n
1306 }
1307 if _, _, needsaddr := dataWordFuncName(n.X.Type()); needsaddr || isStaticCompositeLiteral(n.X) {
1308
1309
1310
1311 n.X = o.addrTemp(walkstate, n.X)
1312 }
1313 return n
1314
1315 case ir.OCONVNOP:
1316 n := n.(*ir.ConvExpr)
1317 if n.X.Op() == ir.OCALLMETH {
1318 base.FatalfAt(n.X.Pos(), "OCALLMETH missed by typecheck")
1319 }
1320 if n.Type().IsKind(types.TUNSAFEPTR) && n.X.Type().IsKind(types.TUINTPTR) && (n.X.Op() == ir.OCALLFUNC || n.X.Op() == ir.OCALLINTER) {
1321 call := n.X.(*ir.CallExpr)
1322
1323
1324
1325 o.init(walkstate, call)
1326 o.call(walkstate, call)
1327 if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1328 return o.copyExpr(walkstate, n)
1329 }
1330 } else {
1331 n.X = o.expr(walkstate, n.X, nil)
1332 }
1333 return n
1334
1335 case ir.OANDAND, ir.OOROR:
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345 n := n.(*ir.LogicalExpr)
1346 r := o.newTemp(walkstate, n.Type(), false)
1347
1348
1349 lhs := o.expr(walkstate, n.X, nil)
1350 o.out = append(o.out, typecheck.Stmt(o.walkstate.curfunc, ir.NewAssignStmt(base.Pos, r, lhs)))
1351
1352
1353 saveout := o.out
1354 o.out = nil
1355 t := o.markTemp()
1356 o.edge()
1357 rhs := o.expr(walkstate, n.Y, nil)
1358 o.out = append(o.out, typecheck.Stmt(o.walkstate.curfunc, ir.NewAssignStmt(base.Pos, r, rhs)))
1359 o.popTemp(t)
1360 gen := o.out
1361 o.out = saveout
1362
1363
1364 nif := ir.NewIfStmt(base.Pos, r, nil, nil)
1365 if n.Op() == ir.OANDAND {
1366 nif.Body = gen
1367 } else {
1368 nif.Else = gen
1369 }
1370 o.out = append(o.out, nif)
1371 return r
1372
1373 case ir.OCALLMETH:
1374 base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
1375 panic("unreachable")
1376
1377 case ir.OCALLFUNC,
1378 ir.OCALLINTER,
1379 ir.OCAP,
1380 ir.OCOMPLEX,
1381 ir.OCOPY,
1382 ir.OIMAG,
1383 ir.OLEN,
1384 ir.OMAKECHAN,
1385 ir.OMAKEMAP,
1386 ir.OMAKESLICE,
1387 ir.OMAKESLICECOPY,
1388 ir.OMAX,
1389 ir.OMIN,
1390 ir.ONEW,
1391 ir.OREAL,
1392 ir.ORECOVER,
1393 ir.OSTR2BYTES,
1394 ir.OSTR2BYTESTMP,
1395 ir.OSTR2RUNES:
1396
1397 if isRuneCount(n) {
1398
1399 conv := n.(*ir.UnaryExpr).X.(*ir.ConvExpr)
1400 conv.X = o.expr(walkstate, conv.X, nil)
1401 } else {
1402 o.call(walkstate, n)
1403 }
1404
1405 if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1406 return o.copyExpr(walkstate, n)
1407 }
1408 return n
1409
1410 case ir.OINLCALL:
1411 n := n.(*ir.InlinedCallExpr)
1412 o.stmtList(walkstate, n.Body)
1413 return n.SingleResult()
1414
1415 case ir.OAPPEND:
1416
1417 n := n.(*ir.CallExpr)
1418 if isAppendOfMake(n) {
1419 n.Args[0] = o.expr(walkstate, n.Args[0], nil)
1420 mk := n.Args[1].(*ir.MakeExpr)
1421 mk.Len = o.expr(walkstate, mk.Len, nil)
1422 } else {
1423 o.exprList(walkstate, n.Args)
1424 }
1425
1426 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.Args[0]) {
1427 return o.copyExpr(walkstate, n)
1428 }
1429 return n
1430
1431 case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
1432 n := n.(*ir.SliceExpr)
1433 n.X = o.expr(walkstate, n.X, nil)
1434 n.Low = o.cheapExpr(walkstate, o.expr(walkstate, n.Low, nil))
1435 n.High = o.cheapExpr(walkstate, o.expr(walkstate, n.High, nil))
1436 n.Max = o.cheapExpr(walkstate, o.expr(walkstate, n.Max, nil))
1437 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.X) {
1438 return o.copyExpr(walkstate, n)
1439 }
1440 return n
1441
1442 case ir.OCLOSURE:
1443 n := n.(*ir.ClosureExpr)
1444 if n.Transient() && len(n.Func.ClosureVars) > 0 {
1445 n.Prealloc = o.newTemp(walkstate, typecheck.ClosureType(n), false)
1446 }
1447 return n
1448
1449 case ir.OMETHVALUE:
1450 n := n.(*ir.SelectorExpr)
1451 n.X = o.expr(walkstate, n.X, nil)
1452 if n.Transient() {
1453 t := typecheck.MethodValueType(n)
1454 n.Prealloc = o.newTemp(walkstate, t, false)
1455 }
1456 return n
1457
1458 case ir.OSLICELIT:
1459 n := n.(*ir.CompLitExpr)
1460 o.exprList(walkstate, n.List)
1461 if n.Transient() {
1462 t := types.NewArray(n.Type().Elem(), n.Len)
1463 n.Prealloc = o.newTemp(walkstate, t, false)
1464 }
1465 return n
1466
1467 case ir.ODOTTYPE, ir.ODOTTYPE2:
1468 n := n.(*ir.TypeAssertExpr)
1469 n.X = o.expr(walkstate, n.X, nil)
1470 if !types.IsDirectIface(n.Type()) || base.Flag.Cfg.Instrumenting {
1471 return o.copyExprClear(walkstate, n)
1472 }
1473 return n
1474
1475 case ir.ORECV:
1476 n := n.(*ir.UnaryExpr)
1477 n.X = o.expr(walkstate, n.X, nil)
1478 return o.copyExprClear(walkstate, n)
1479
1480 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
1481 n := n.(*ir.BinaryExpr)
1482 n.X = o.expr(walkstate, n.X, nil)
1483 n.Y = o.expr(walkstate, n.Y, nil)
1484
1485 t := n.X.Type()
1486 switch {
1487 case t.IsString():
1488
1489
1490
1491 if n.X.Op() == ir.OBYTES2STR {
1492 n.X.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1493 }
1494 if n.Y.Op() == ir.OBYTES2STR {
1495 n.Y.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1496 }
1497
1498 case t.IsStruct() || t.IsArray():
1499
1500
1501 n.X = o.addrTemp(walkstate, n.X)
1502 n.Y = o.addrTemp(walkstate, n.Y)
1503 }
1504 return n
1505
1506 case ir.OMAPLIT:
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522 n := n.(*ir.CompLitExpr)
1523 entries := n.List
1524 statics := entries[:0]
1525 var dynamics []*ir.KeyExpr
1526 for _, r := range entries {
1527 r := r.(*ir.KeyExpr)
1528
1529 if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1530 dynamics = append(dynamics, r)
1531 continue
1532 }
1533
1534
1535
1536 r = o.expr(walkstate, r, nil).(*ir.KeyExpr)
1537 if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1538 dynamics = append(dynamics, r)
1539 continue
1540 }
1541
1542 statics = append(statics, r)
1543 }
1544 n.List = statics
1545
1546 if len(dynamics) == 0 {
1547 return n
1548 }
1549
1550
1551 m := o.newTemp(walkstate, n.Type(), false)
1552 as := ir.NewAssignStmt(base.Pos, m, n)
1553 typecheck.Stmt(o.walkstate.curfunc, as)
1554 o.stmt(walkstate, as)
1555
1556
1557 for _, r := range dynamics {
1558 lhs := typecheck.AssignExpr(o.walkstate.curfunc, ir.NewIndexExpr(base.Pos, m, r.Key)).(*ir.IndexExpr)
1559 base.AssertfAt(lhs.Op() == ir.OINDEXMAP, lhs.Pos(), "want OINDEXMAP, have %+v", lhs)
1560 lhs.RType = n.RType
1561
1562 as := ir.NewAssignStmt(base.Pos, lhs, r.Value)
1563 typecheck.Stmt(o.walkstate.curfunc, as)
1564 o.stmt(walkstate, as)
1565 }
1566
1567
1568
1569
1570
1571
1572
1573 n.Len += int64(len(dynamics))
1574
1575 return m
1576 }
1577
1578
1579 }
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593 func (o *orderState) as2func(walkstate *walkState, n *ir.AssignListStmt) {
1594 results := n.Rhs[0].Type()
1595 as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1596 for i, nl := range n.Lhs {
1597 if !ir.IsBlank(nl) {
1598 typ := results.Field(i).Type
1599 tmp := o.newTemp(walkstate, typ, typ.HasPointers())
1600 n.Lhs[i] = tmp
1601 as.Lhs = append(as.Lhs, nl)
1602 as.Rhs = append(as.Rhs, tmp)
1603 }
1604 }
1605
1606 o.out = append(o.out, n)
1607 o.stmt(walkstate, typecheck.Stmt(o.walkstate.curfunc, as))
1608 }
1609
1610
1611
1612 func (o *orderState) as2ok(walkstate *walkState, n *ir.AssignListStmt) {
1613 as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1614
1615 do := func(i int, typ *types.Type) {
1616 if nl := n.Lhs[i]; !ir.IsBlank(nl) {
1617 var tmp ir.Node = o.newTemp(walkstate, typ, typ.HasPointers())
1618 n.Lhs[i] = tmp
1619 as.Lhs = append(as.Lhs, nl)
1620 if i == 1 {
1621
1622
1623
1624 tmp = typecheck.Conv(o.walkstate.curfunc, tmp, nl.Type())
1625 }
1626 as.Rhs = append(as.Rhs, tmp)
1627 }
1628 }
1629
1630 do(0, n.Rhs[0].Type())
1631 do(1, types.Types[types.TBOOL])
1632
1633 o.out = append(o.out, n)
1634 o.stmt(walkstate, typecheck.Stmt(o.walkstate.curfunc, as))
1635 }
1636
View as plain text