]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/walk/order.go
cmd/compile: move FuncPC intrinsic handling to common helper
[gostls13.git] / src / cmd / compile / internal / walk / order.go
1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
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/staticinit"
15         "cmd/compile/internal/typecheck"
16         "cmd/compile/internal/types"
17         "cmd/internal/objabi"
18         "cmd/internal/src"
19 )
20
21 // Rewrite tree to use separate statements to enforce
22 // order of evaluation. Makes walk easier, because it
23 // can (after this runs) reorder at will within an expression.
24 //
25 // Rewrite m[k] op= r into m[k] = m[k] op r if op is / or %.
26 //
27 // Introduce temporaries as needed by runtime routines.
28 // For example, the map runtime routines take the map key
29 // by reference, so make sure all map keys are addressable
30 // by copying them to temporaries as needed.
31 // The same is true for channel operations.
32 //
33 // Arrange that map index expressions only appear in direct
34 // assignments x = m[k] or m[k] = x, never in larger expressions.
35 //
36 // Arrange that receive expressions only appear in direct assignments
37 // x = <-c or as standalone statements <-c, never in larger expressions.
38
39 // orderState holds state during the ordering process.
40 type orderState struct {
41         out  []ir.Node             // list of generated statements
42         temp []*ir.Name            // stack of temporary variables
43         free map[string][]*ir.Name // free list of unused temporaries, by type.LinkString().
44         edit func(ir.Node) ir.Node // cached closure of o.exprNoLHS
45 }
46
47 // order rewrites fn.Nbody to apply the ordering constraints
48 // described in the comment at the top of the file.
49 func order(fn *ir.Func) {
50         if base.Flag.W > 1 {
51                 s := fmt.Sprintf("\nbefore order %v", fn.Sym())
52                 ir.DumpList(s, fn.Body)
53         }
54         ir.SetPos(fn) // Set reasonable position for instrumenting code. See issue 53688.
55         orderBlock(&fn.Body, map[string][]*ir.Name{})
56 }
57
58 // append typechecks stmt and appends it to out.
59 func (o *orderState) append(stmt ir.Node) {
60         o.out = append(o.out, typecheck.Stmt(stmt))
61 }
62
63 // newTemp allocates a new temporary with the given type,
64 // pushes it onto the temp stack, and returns it.
65 // If clear is true, newTemp emits code to zero the temporary.
66 func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name {
67         var v *ir.Name
68         key := t.LinkString()
69         if a := o.free[key]; len(a) > 0 {
70                 v = a[len(a)-1]
71                 if !types.Identical(t, v.Type()) {
72                         base.Fatalf("expected %L to have type %v", v, t)
73                 }
74                 o.free[key] = a[:len(a)-1]
75         } else {
76                 v = typecheck.TempAt(base.Pos, ir.CurFunc, t)
77         }
78         if clear {
79                 o.append(ir.NewAssignStmt(base.Pos, v, nil))
80         }
81
82         o.temp = append(o.temp, v)
83         return v
84 }
85
86 // copyExpr behaves like newTemp but also emits
87 // code to initialize the temporary to the value n.
88 func (o *orderState) copyExpr(n ir.Node) *ir.Name {
89         return o.copyExpr1(n, false)
90 }
91
92 // copyExprClear is like copyExpr but clears the temp before assignment.
93 // It is provided for use when the evaluation of tmp = n turns into
94 // a function call that is passed a pointer to the temporary as the output space.
95 // If the call blocks before tmp has been written,
96 // the garbage collector will still treat the temporary as live,
97 // so we must zero it before entering that call.
98 // Today, this only happens for channel receive operations.
99 // (The other candidate would be map access, but map access
100 // returns a pointer to the result data instead of taking a pointer
101 // to be filled in.)
102 func (o *orderState) copyExprClear(n ir.Node) *ir.Name {
103         return o.copyExpr1(n, true)
104 }
105
106 func (o *orderState) copyExpr1(n ir.Node, clear bool) *ir.Name {
107         t := n.Type()
108         v := o.newTemp(t, clear)
109         o.append(ir.NewAssignStmt(base.Pos, v, n))
110         return v
111 }
112
113 // cheapExpr returns a cheap version of n.
114 // The definition of cheap is that n is a variable or constant.
115 // If not, cheapExpr allocates a new tmp, emits tmp = n,
116 // and then returns tmp.
117 func (o *orderState) cheapExpr(n ir.Node) ir.Node {
118         if n == nil {
119                 return nil
120         }
121
122         switch n.Op() {
123         case ir.ONAME, ir.OLITERAL, ir.ONIL:
124                 return n
125         case ir.OLEN, ir.OCAP:
126                 n := n.(*ir.UnaryExpr)
127                 l := o.cheapExpr(n.X)
128                 if l == n.X {
129                         return n
130                 }
131                 a := ir.Copy(n).(*ir.UnaryExpr)
132                 a.X = l
133                 return typecheck.Expr(a)
134         }
135
136         return o.copyExpr(n)
137 }
138
139 // safeExpr returns a safe version of n.
140 // The definition of safe is that n can appear multiple times
141 // without violating the semantics of the original program,
142 // and that assigning to the safe version has the same effect
143 // as assigning to the original n.
144 //
145 // The intended use is to apply to x when rewriting x += y into x = x + y.
146 func (o *orderState) safeExpr(n ir.Node) ir.Node {
147         switch n.Op() {
148         case ir.ONAME, ir.OLITERAL, ir.ONIL:
149                 return n
150
151         case ir.OLEN, ir.OCAP:
152                 n := n.(*ir.UnaryExpr)
153                 l := o.safeExpr(n.X)
154                 if l == n.X {
155                         return n
156                 }
157                 a := ir.Copy(n).(*ir.UnaryExpr)
158                 a.X = l
159                 return typecheck.Expr(a)
160
161         case ir.ODOT:
162                 n := n.(*ir.SelectorExpr)
163                 l := o.safeExpr(n.X)
164                 if l == n.X {
165                         return n
166                 }
167                 a := ir.Copy(n).(*ir.SelectorExpr)
168                 a.X = l
169                 return typecheck.Expr(a)
170
171         case ir.ODOTPTR:
172                 n := n.(*ir.SelectorExpr)
173                 l := o.cheapExpr(n.X)
174                 if l == n.X {
175                         return n
176                 }
177                 a := ir.Copy(n).(*ir.SelectorExpr)
178                 a.X = l
179                 return typecheck.Expr(a)
180
181         case ir.ODEREF:
182                 n := n.(*ir.StarExpr)
183                 l := o.cheapExpr(n.X)
184                 if l == n.X {
185                         return n
186                 }
187                 a := ir.Copy(n).(*ir.StarExpr)
188                 a.X = l
189                 return typecheck.Expr(a)
190
191         case ir.OINDEX, ir.OINDEXMAP:
192                 n := n.(*ir.IndexExpr)
193                 var l ir.Node
194                 if n.X.Type().IsArray() {
195                         l = o.safeExpr(n.X)
196                 } else {
197                         l = o.cheapExpr(n.X)
198                 }
199                 r := o.cheapExpr(n.Index)
200                 if l == n.X && r == n.Index {
201                         return n
202                 }
203                 a := ir.Copy(n).(*ir.IndexExpr)
204                 a.X = l
205                 a.Index = r
206                 return typecheck.Expr(a)
207
208         default:
209                 base.Fatalf("order.safeExpr %v", n.Op())
210                 return nil // not reached
211         }
212 }
213
214 // addrTemp ensures that n is okay to pass by address to runtime routines.
215 // If the original argument n is not okay, addrTemp creates a tmp, emits
216 // tmp = n, and then returns tmp.
217 // The result of addrTemp MUST be assigned back to n, e.g.
218 //
219 //      n.Left = o.addrTemp(n.Left)
220 func (o *orderState) addrTemp(n ir.Node) ir.Node {
221         if n.Op() == ir.OLITERAL || n.Op() == ir.ONIL {
222                 // TODO: expand this to all static composite literal nodes?
223                 n = typecheck.DefaultLit(n, nil)
224                 types.CalcSize(n.Type())
225                 vstat := readonlystaticname(n.Type())
226                 var s staticinit.Schedule
227                 s.StaticAssign(vstat, 0, n, n.Type())
228                 if s.Out != nil {
229                         base.Fatalf("staticassign of const generated code: %+v", n)
230                 }
231                 vstat = typecheck.Expr(vstat).(*ir.Name)
232                 return vstat
233         }
234         if ir.IsAddressable(n) {
235                 return n
236         }
237         return o.copyExpr(n)
238 }
239
240 // mapKeyTemp prepares n to be a key in a map runtime call and returns n.
241 // It should only be used for map runtime calls which have *_fast* versions.
242 // The first parameter is the position of n's containing node, for use in case
243 // that n's position is not unique (e.g., if n is an ONAME).
244 func (o *orderState) mapKeyTemp(outerPos src.XPos, t *types.Type, n ir.Node) ir.Node {
245         pos := outerPos
246         if ir.HasUniquePos(n) {
247                 pos = n.Pos()
248         }
249         // Most map calls need to take the address of the key.
250         // Exception: map*_fast* calls. See golang.org/issue/19015.
251         alg := mapfast(t)
252         if alg == mapslow {
253                 return o.addrTemp(n)
254         }
255         var kt *types.Type
256         switch alg {
257         case mapfast32:
258                 kt = types.Types[types.TUINT32]
259         case mapfast64:
260                 kt = types.Types[types.TUINT64]
261         case mapfast32ptr, mapfast64ptr:
262                 kt = types.Types[types.TUNSAFEPTR]
263         case mapfaststr:
264                 kt = types.Types[types.TSTRING]
265         }
266         nt := n.Type()
267         switch {
268         case nt == kt:
269                 return n
270         case nt.Kind() == kt.Kind(), nt.IsPtrShaped() && kt.IsPtrShaped():
271                 // can directly convert (e.g. named type to underlying type, or one pointer to another)
272                 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, kt, n))
273         case nt.IsInteger() && kt.IsInteger():
274                 // can directly convert (e.g. int32 to uint32)
275                 if n.Op() == ir.OLITERAL && nt.IsSigned() {
276                         // avoid constant overflow error
277                         n = ir.NewConstExpr(constant.MakeUint64(uint64(ir.Int64Val(n))), n)
278                         n.SetType(kt)
279                         return n
280                 }
281                 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONV, kt, n))
282         default:
283                 // Unsafe cast through memory.
284                 // We'll need to do a load with type kt. Create a temporary of type kt to
285                 // ensure sufficient alignment. nt may be under-aligned.
286                 if uint8(kt.Alignment()) < uint8(nt.Alignment()) {
287                         base.Fatalf("mapKeyTemp: key type is not sufficiently aligned, kt=%v nt=%v", kt, nt)
288                 }
289                 tmp := o.newTemp(kt, true)
290                 // *(*nt)(&tmp) = n
291                 var e ir.Node = typecheck.NodAddr(tmp)
292                 e = ir.NewConvExpr(pos, ir.OCONVNOP, nt.PtrTo(), e)
293                 e = ir.NewStarExpr(pos, e)
294                 o.append(ir.NewAssignStmt(pos, e, n))
295                 return tmp
296         }
297 }
298
299 // mapKeyReplaceStrConv replaces OBYTES2STR by OBYTES2STRTMP
300 // in n to avoid string allocations for keys in map lookups.
301 // Returns a bool that signals if a modification was made.
302 //
303 // For:
304 //
305 //      x = m[string(k)]
306 //      x = m[T1{... Tn{..., string(k), ...}}]
307 //
308 // where k is []byte, T1 to Tn is a nesting of struct and array literals,
309 // the allocation of backing bytes for the string can be avoided
310 // by reusing the []byte backing array. These are special cases
311 // for avoiding allocations when converting byte slices to strings.
312 // It would be nice to handle these generally, but because
313 // []byte keys are not allowed in maps, the use of string(k)
314 // comes up in important cases in practice. See issue 3512.
315 func mapKeyReplaceStrConv(n ir.Node) bool {
316         var replaced bool
317         switch n.Op() {
318         case ir.OBYTES2STR:
319                 n := n.(*ir.ConvExpr)
320                 n.SetOp(ir.OBYTES2STRTMP)
321                 replaced = true
322         case ir.OSTRUCTLIT:
323                 n := n.(*ir.CompLitExpr)
324                 for _, elem := range n.List {
325                         elem := elem.(*ir.StructKeyExpr)
326                         if mapKeyReplaceStrConv(elem.Value) {
327                                 replaced = true
328                         }
329                 }
330         case ir.OARRAYLIT:
331                 n := n.(*ir.CompLitExpr)
332                 for _, elem := range n.List {
333                         if elem.Op() == ir.OKEY {
334                                 elem = elem.(*ir.KeyExpr).Value
335                         }
336                         if mapKeyReplaceStrConv(elem) {
337                                 replaced = true
338                         }
339                 }
340         }
341         return replaced
342 }
343
344 type ordermarker int
345
346 // markTemp returns the top of the temporary variable stack.
347 func (o *orderState) markTemp() ordermarker {
348         return ordermarker(len(o.temp))
349 }
350
351 // popTemp pops temporaries off the stack until reaching the mark,
352 // which must have been returned by markTemp.
353 func (o *orderState) popTemp(mark ordermarker) {
354         for _, n := range o.temp[mark:] {
355                 key := n.Type().LinkString()
356                 o.free[key] = append(o.free[key], n)
357         }
358         o.temp = o.temp[:mark]
359 }
360
361 // stmtList orders each of the statements in the list.
362 func (o *orderState) stmtList(l ir.Nodes) {
363         s := l
364         for i := range s {
365                 orderMakeSliceCopy(s[i:])
366                 o.stmt(s[i])
367         }
368 }
369
370 // orderMakeSliceCopy matches the pattern:
371 //
372 //      m = OMAKESLICE([]T, x); OCOPY(m, s)
373 //
374 // and rewrites it to:
375 //
376 //      m = OMAKESLICECOPY([]T, x, s); nil
377 func orderMakeSliceCopy(s []ir.Node) {
378         if base.Flag.N != 0 || base.Flag.Cfg.Instrumenting {
379                 return
380         }
381         if len(s) < 2 || s[0] == nil || s[0].Op() != ir.OAS || s[1] == nil || s[1].Op() != ir.OCOPY {
382                 return
383         }
384
385         as := s[0].(*ir.AssignStmt)
386         cp := s[1].(*ir.BinaryExpr)
387         if as.Y == nil || as.Y.Op() != ir.OMAKESLICE || ir.IsBlank(as.X) ||
388                 as.X.Op() != ir.ONAME || cp.X.Op() != ir.ONAME || cp.Y.Op() != ir.ONAME ||
389                 as.X.Name() != cp.X.Name() || cp.X.Name() == cp.Y.Name() {
390                 // The line above this one is correct with the differing equality operators:
391                 // we want as.X and cp.X to be the same name,
392                 // but we want the initial data to be coming from a different name.
393                 return
394         }
395
396         mk := as.Y.(*ir.MakeExpr)
397         if mk.Esc() == ir.EscNone || mk.Len == nil || mk.Cap != nil {
398                 return
399         }
400         mk.SetOp(ir.OMAKESLICECOPY)
401         mk.Cap = cp.Y
402         // Set bounded when m = OMAKESLICE([]T, len(s)); OCOPY(m, s)
403         mk.SetBounded(mk.Len.Op() == ir.OLEN && ir.SameSafeExpr(mk.Len.(*ir.UnaryExpr).X, cp.Y))
404         as.Y = typecheck.Expr(mk)
405         s[1] = nil // remove separate copy call
406 }
407
408 // edge inserts coverage instrumentation for libfuzzer.
409 func (o *orderState) edge() {
410         if base.Debug.Libfuzzer == 0 {
411                 return
412         }
413
414         // Create a new uint8 counter to be allocated in section __sancov_cntrs
415         counter := staticinit.StaticName(types.Types[types.TUINT8])
416         counter.SetLibfuzzer8BitCounter(true)
417         // As well as setting SetLibfuzzer8BitCounter, we preemptively set the
418         // symbol type to SLIBFUZZER_8BIT_COUNTER so that the race detector
419         // instrumentation pass (which does not have access to the flags set by
420         // SetLibfuzzer8BitCounter) knows to ignore them. This information is
421         // lost by the time it reaches the compile step, so SetLibfuzzer8BitCounter
422         // is still necessary.
423         counter.Linksym().Type = objabi.SLIBFUZZER_8BIT_COUNTER
424
425         // We guarantee that the counter never becomes zero again once it has been
426         // incremented once. This implementation follows the NeverZero optimization
427         // presented by the paper:
428         // "AFL++: Combining Incremental Steps of Fuzzing Research"
429         // The NeverZero policy avoids the overflow to 0 by setting the counter to one
430         // after it reaches 255 and so, if an edge is executed at least one time, the entry is
431         // never 0.
432         // Another policy presented in the paper is the Saturated Counters policy which
433         // freezes the counter when it reaches the value of 255. However, a range
434         // of experiments showed that that decreases overall performance.
435         o.append(ir.NewIfStmt(base.Pos,
436                 ir.NewBinaryExpr(base.Pos, ir.OEQ, counter, ir.NewInt(base.Pos, 0xff)),
437                 []ir.Node{ir.NewAssignStmt(base.Pos, counter, ir.NewInt(base.Pos, 1))},
438                 []ir.Node{ir.NewAssignOpStmt(base.Pos, ir.OADD, counter, ir.NewInt(base.Pos, 1))}))
439 }
440
441 // orderBlock orders the block of statements in n into a new slice,
442 // and then replaces the old slice in n with the new slice.
443 // free is a map that can be used to obtain temporary variables by type.
444 func orderBlock(n *ir.Nodes, free map[string][]*ir.Name) {
445         if len(*n) != 0 {
446                 // Set reasonable position for instrumenting code. See issue 53688.
447                 // It would be nice if ir.Nodes had a position (the opening {, probably),
448                 // but it doesn't. So we use the first statement's position instead.
449                 ir.SetPos((*n)[0])
450         }
451         var order orderState
452         order.free = free
453         mark := order.markTemp()
454         order.edge()
455         order.stmtList(*n)
456         order.popTemp(mark)
457         *n = order.out
458 }
459
460 // exprInPlace orders the side effects in *np and
461 // leaves them as the init list of the final *np.
462 // The result of exprInPlace MUST be assigned back to n, e.g.
463 //
464 //      n.Left = o.exprInPlace(n.Left)
465 func (o *orderState) exprInPlace(n ir.Node) ir.Node {
466         var order orderState
467         order.free = o.free
468         n = order.expr(n, nil)
469         n = ir.InitExpr(order.out, n)
470
471         // insert new temporaries from order
472         // at head of outer list.
473         o.temp = append(o.temp, order.temp...)
474         return n
475 }
476
477 // orderStmtInPlace orders the side effects of the single statement *np
478 // and replaces it with the resulting statement list.
479 // The result of orderStmtInPlace MUST be assigned back to n, e.g.
480 //
481 //      n.Left = orderStmtInPlace(n.Left)
482 //
483 // free is a map that can be used to obtain temporary variables by type.
484 func orderStmtInPlace(n ir.Node, free map[string][]*ir.Name) ir.Node {
485         var order orderState
486         order.free = free
487         mark := order.markTemp()
488         order.stmt(n)
489         order.popTemp(mark)
490         return ir.NewBlockStmt(src.NoXPos, order.out)
491 }
492
493 // init moves n's init list to o.out.
494 func (o *orderState) init(n ir.Node) {
495         if ir.MayBeShared(n) {
496                 // For concurrency safety, don't mutate potentially shared nodes.
497                 // First, ensure that no work is required here.
498                 if len(n.Init()) > 0 {
499                         base.Fatalf("order.init shared node with ninit")
500                 }
501                 return
502         }
503         o.stmtList(ir.TakeInit(n))
504 }
505
506 // call orders the call expression n.
507 // n.Op is OCALLFUNC/OCALLINTER or a builtin like OCOPY.
508 func (o *orderState) call(nn ir.Node) {
509         if len(nn.Init()) > 0 {
510                 // Caller should have already called o.init(nn).
511                 base.Fatalf("%v with unexpected ninit", nn.Op())
512         }
513         if nn.Op() == ir.OCALLMETH {
514                 base.FatalfAt(nn.Pos(), "OCALLMETH missed by typecheck")
515         }
516
517         // Builtin functions.
518         if nn.Op() != ir.OCALLFUNC && nn.Op() != ir.OCALLINTER {
519                 switch n := nn.(type) {
520                 default:
521                         base.Fatalf("unexpected call: %+v", n)
522                 case *ir.UnaryExpr:
523                         n.X = o.expr(n.X, nil)
524                 case *ir.ConvExpr:
525                         n.X = o.expr(n.X, nil)
526                 case *ir.BinaryExpr:
527                         n.X = o.expr(n.X, nil)
528                         n.Y = o.expr(n.Y, nil)
529                 case *ir.MakeExpr:
530                         n.Len = o.expr(n.Len, nil)
531                         n.Cap = o.expr(n.Cap, nil)
532                 case *ir.CallExpr:
533                         o.exprList(n.Args)
534                 }
535                 return
536         }
537
538         n := nn.(*ir.CallExpr)
539         typecheck.AssertFixedCall(n)
540
541         if ir.IsFuncPCIntrinsic(n) && ir.IsIfaceOfFunc(n.Args[0]) != nil {
542                 // For internal/abi.FuncPCABIxxx(fn), if fn is a defined function,
543                 // do not introduce temporaries here, so it is easier to rewrite it
544                 // to symbol address reference later in walk.
545                 return
546         }
547
548         n.Fun = o.expr(n.Fun, nil)
549         o.exprList(n.Args)
550 }
551
552 // mapAssign appends n to o.out.
553 func (o *orderState) mapAssign(n ir.Node) {
554         switch n.Op() {
555         default:
556                 base.Fatalf("order.mapAssign %v", n.Op())
557
558         case ir.OAS:
559                 n := n.(*ir.AssignStmt)
560                 if n.X.Op() == ir.OINDEXMAP {
561                         n.Y = o.safeMapRHS(n.Y)
562                 }
563                 o.out = append(o.out, n)
564         case ir.OASOP:
565                 n := n.(*ir.AssignOpStmt)
566                 if n.X.Op() == ir.OINDEXMAP {
567                         n.Y = o.safeMapRHS(n.Y)
568                 }
569                 o.out = append(o.out, n)
570         }
571 }
572
573 func (o *orderState) safeMapRHS(r ir.Node) ir.Node {
574         // Make sure we evaluate the RHS before starting the map insert.
575         // We need to make sure the RHS won't panic.  See issue 22881.
576         if r.Op() == ir.OAPPEND {
577                 r := r.(*ir.CallExpr)
578                 s := r.Args[1:]
579                 for i, n := range s {
580                         s[i] = o.cheapExpr(n)
581                 }
582                 return r
583         }
584         return o.cheapExpr(r)
585 }
586
587 // stmt orders the statement n, appending to o.out.
588 func (o *orderState) stmt(n ir.Node) {
589         if n == nil {
590                 return
591         }
592
593         lno := ir.SetPos(n)
594         o.init(n)
595
596         switch n.Op() {
597         default:
598                 base.Fatalf("order.stmt %v", n.Op())
599
600         case ir.OINLMARK:
601                 o.out = append(o.out, n)
602
603         case ir.OAS:
604                 n := n.(*ir.AssignStmt)
605                 t := o.markTemp()
606                 n.X = o.expr(n.X, nil)
607                 n.Y = o.expr(n.Y, n.X)
608                 o.mapAssign(n)
609                 o.popTemp(t)
610
611         case ir.OASOP:
612                 n := n.(*ir.AssignOpStmt)
613                 t := o.markTemp()
614                 n.X = o.expr(n.X, nil)
615                 n.Y = o.expr(n.Y, nil)
616
617                 if base.Flag.Cfg.Instrumenting || n.X.Op() == ir.OINDEXMAP && (n.AsOp == ir.ODIV || n.AsOp == ir.OMOD) {
618                         // Rewrite m[k] op= r into m[k] = m[k] op r so
619                         // that we can ensure that if op panics
620                         // because r is zero, the panic happens before
621                         // the map assignment.
622                         // DeepCopy is a big hammer here, but safeExpr
623                         // makes sure there is nothing too deep being copied.
624                         l1 := o.safeExpr(n.X)
625                         l2 := ir.DeepCopy(src.NoXPos, l1)
626                         if l2.Op() == ir.OINDEXMAP {
627                                 l2 := l2.(*ir.IndexExpr)
628                                 l2.Assigned = false
629                         }
630                         l2 = o.copyExpr(l2)
631                         r := o.expr(typecheck.Expr(ir.NewBinaryExpr(n.Pos(), n.AsOp, l2, n.Y)), nil)
632                         as := typecheck.Stmt(ir.NewAssignStmt(n.Pos(), l1, r))
633                         o.mapAssign(as)
634                         o.popTemp(t)
635                         return
636                 }
637
638                 o.mapAssign(n)
639                 o.popTemp(t)
640
641         case ir.OAS2:
642                 n := n.(*ir.AssignListStmt)
643                 t := o.markTemp()
644                 o.exprList(n.Lhs)
645                 o.exprList(n.Rhs)
646                 o.out = append(o.out, n)
647                 o.popTemp(t)
648
649         // Special: avoid copy of func call n.Right
650         case ir.OAS2FUNC:
651                 n := n.(*ir.AssignListStmt)
652                 t := o.markTemp()
653                 o.exprList(n.Lhs)
654                 call := n.Rhs[0]
655                 o.init(call)
656                 if ic, ok := call.(*ir.InlinedCallExpr); ok {
657                         o.stmtList(ic.Body)
658
659                         n.SetOp(ir.OAS2)
660                         n.Rhs = ic.ReturnVars
661
662                         o.exprList(n.Rhs)
663                         o.out = append(o.out, n)
664                 } else {
665                         o.call(call)
666                         o.as2func(n)
667                 }
668                 o.popTemp(t)
669
670         // Special: use temporary variables to hold result,
671         // so that runtime can take address of temporary.
672         // No temporary for blank assignment.
673         //
674         // OAS2MAPR: make sure key is addressable if needed,
675         //           and make sure OINDEXMAP is not copied out.
676         case ir.OAS2DOTTYPE, ir.OAS2RECV, ir.OAS2MAPR:
677                 n := n.(*ir.AssignListStmt)
678                 t := o.markTemp()
679                 o.exprList(n.Lhs)
680
681                 switch r := n.Rhs[0]; r.Op() {
682                 case ir.ODOTTYPE2:
683                         r := r.(*ir.TypeAssertExpr)
684                         r.X = o.expr(r.X, nil)
685                 case ir.ODYNAMICDOTTYPE2:
686                         r := r.(*ir.DynamicTypeAssertExpr)
687                         r.X = o.expr(r.X, nil)
688                         r.RType = o.expr(r.RType, nil)
689                         r.ITab = o.expr(r.ITab, nil)
690                 case ir.ORECV:
691                         r := r.(*ir.UnaryExpr)
692                         r.X = o.expr(r.X, nil)
693                 case ir.OINDEXMAP:
694                         r := r.(*ir.IndexExpr)
695                         r.X = o.expr(r.X, nil)
696                         r.Index = o.expr(r.Index, nil)
697                         // See similar conversion for OINDEXMAP below.
698                         _ = mapKeyReplaceStrConv(r.Index)
699                         r.Index = o.mapKeyTemp(r.Pos(), r.X.Type(), r.Index)
700                 default:
701                         base.Fatalf("order.stmt: %v", r.Op())
702                 }
703
704                 o.as2ok(n)
705                 o.popTemp(t)
706
707         // Special: does not save n onto out.
708         case ir.OBLOCK:
709                 n := n.(*ir.BlockStmt)
710                 o.stmtList(n.List)
711
712         // Special: n->left is not an expression; save as is.
713         case ir.OBREAK,
714                 ir.OCONTINUE,
715                 ir.ODCL,
716                 ir.OFALL,
717                 ir.OGOTO,
718                 ir.OLABEL,
719                 ir.OTAILCALL:
720                 o.out = append(o.out, n)
721
722         // Special: handle call arguments.
723         case ir.OCALLFUNC, ir.OCALLINTER:
724                 n := n.(*ir.CallExpr)
725                 t := o.markTemp()
726                 o.call(n)
727                 o.out = append(o.out, n)
728                 o.popTemp(t)
729
730         case ir.OINLCALL:
731                 n := n.(*ir.InlinedCallExpr)
732                 o.stmtList(n.Body)
733
734                 // discard results; double-check for no side effects
735                 for _, result := range n.ReturnVars {
736                         if staticinit.AnySideEffects(result) {
737                                 base.FatalfAt(result.Pos(), "inlined call result has side effects: %v", result)
738                         }
739                 }
740
741         case ir.OCHECKNIL, ir.OCLEAR, ir.OCLOSE, ir.OPANIC, ir.ORECV:
742                 n := n.(*ir.UnaryExpr)
743                 t := o.markTemp()
744                 n.X = o.expr(n.X, nil)
745                 o.out = append(o.out, n)
746                 o.popTemp(t)
747
748         case ir.OCOPY:
749                 n := n.(*ir.BinaryExpr)
750                 t := o.markTemp()
751                 n.X = o.expr(n.X, nil)
752                 n.Y = o.expr(n.Y, nil)
753                 o.out = append(o.out, n)
754                 o.popTemp(t)
755
756         case ir.OPRINT, ir.OPRINTLN, ir.ORECOVERFP:
757                 n := n.(*ir.CallExpr)
758                 t := o.markTemp()
759                 o.call(n)
760                 o.out = append(o.out, n)
761                 o.popTemp(t)
762
763         // Special: order arguments to inner call but not call itself.
764         case ir.ODEFER, ir.OGO:
765                 n := n.(*ir.GoDeferStmt)
766                 t := o.markTemp()
767                 o.init(n.Call)
768                 o.call(n.Call)
769                 o.out = append(o.out, n)
770                 o.popTemp(t)
771
772         case ir.ODELETE:
773                 n := n.(*ir.CallExpr)
774                 t := o.markTemp()
775                 n.Args[0] = o.expr(n.Args[0], nil)
776                 n.Args[1] = o.expr(n.Args[1], nil)
777                 n.Args[1] = o.mapKeyTemp(n.Pos(), n.Args[0].Type(), n.Args[1])
778                 o.out = append(o.out, n)
779                 o.popTemp(t)
780
781         // Clean temporaries from condition evaluation at
782         // beginning of loop body and after for statement.
783         case ir.OFOR:
784                 n := n.(*ir.ForStmt)
785                 t := o.markTemp()
786                 n.Cond = o.exprInPlace(n.Cond)
787                 orderBlock(&n.Body, o.free)
788                 n.Post = orderStmtInPlace(n.Post, o.free)
789                 o.out = append(o.out, n)
790                 o.popTemp(t)
791
792         // Clean temporaries from condition at
793         // beginning of both branches.
794         case ir.OIF:
795                 n := n.(*ir.IfStmt)
796                 t := o.markTemp()
797                 n.Cond = o.exprInPlace(n.Cond)
798                 o.popTemp(t)
799                 orderBlock(&n.Body, o.free)
800                 orderBlock(&n.Else, o.free)
801                 o.out = append(o.out, n)
802
803         case ir.ORANGE:
804                 // n.Right is the expression being ranged over.
805                 // order it, and then make a copy if we need one.
806                 // We almost always do, to ensure that we don't
807                 // see any value changes made during the loop.
808                 // Usually the copy is cheap (e.g., array pointer,
809                 // chan, slice, string are all tiny).
810                 // The exception is ranging over an array value
811                 // (not a slice, not a pointer to array),
812                 // which must make a copy to avoid seeing updates made during
813                 // the range body. Ranging over an array value is uncommon though.
814
815                 // Mark []byte(str) range expression to reuse string backing storage.
816                 // It is safe because the storage cannot be mutated.
817                 n := n.(*ir.RangeStmt)
818                 if x, ok := n.X.(*ir.ConvExpr); ok {
819                         switch x.Op() {
820                         case ir.OSTR2BYTES:
821                                 x.SetOp(ir.OSTR2BYTESTMP)
822                                 fallthrough
823                         case ir.OSTR2BYTESTMP:
824                                 x.MarkNonNil() // "range []byte(nil)" is fine
825                         }
826                 }
827
828                 t := o.markTemp()
829                 n.X = o.expr(n.X, nil)
830
831                 orderBody := true
832                 xt := typecheck.RangeExprType(n.X.Type())
833                 switch k := xt.Kind(); {
834                 default:
835                         base.Fatalf("order.stmt range %v", n.Type())
836
837                 case types.IsInt[k]:
838                         // Used only once, no need to copy.
839
840                 case k == types.TARRAY, k == types.TSLICE:
841                         if n.Value == nil || ir.IsBlank(n.Value) {
842                                 // for i := range x will only use x once, to compute len(x).
843                                 // No need to copy it.
844                                 break
845                         }
846                         fallthrough
847
848                 case k == types.TCHAN, k == types.TSTRING:
849                         // chan, string, slice, array ranges use value multiple times.
850                         // make copy.
851                         r := n.X
852
853                         if r.Type().IsString() && r.Type() != types.Types[types.TSTRING] {
854                                 r = ir.NewConvExpr(base.Pos, ir.OCONV, nil, r)
855                                 r.SetType(types.Types[types.TSTRING])
856                                 r = typecheck.Expr(r)
857                         }
858
859                         n.X = o.copyExpr(r)
860
861                 case k == types.TMAP:
862                         if isMapClear(n) {
863                                 // Preserve the body of the map clear pattern so it can
864                                 // be detected during walk. The loop body will not be used
865                                 // when optimizing away the range loop to a runtime call.
866                                 orderBody = false
867                                 break
868                         }
869
870                         // copy the map value in case it is a map literal.
871                         // TODO(rsc): Make tmp = literal expressions reuse tmp.
872                         // For maps tmp is just one word so it hardly matters.
873                         r := n.X
874                         n.X = o.copyExpr(r)
875
876                         // n.Prealloc is the temp for the iterator.
877                         // MapIterType contains pointers and needs to be zeroed.
878                         n.Prealloc = o.newTemp(reflectdata.MapIterType(), true)
879                 }
880                 n.Key = o.exprInPlace(n.Key)
881                 n.Value = o.exprInPlace(n.Value)
882                 if orderBody {
883                         orderBlock(&n.Body, o.free)
884                 }
885                 o.out = append(o.out, n)
886                 o.popTemp(t)
887
888         case ir.ORETURN:
889                 n := n.(*ir.ReturnStmt)
890                 o.exprList(n.Results)
891                 o.out = append(o.out, n)
892
893         // Special: clean case temporaries in each block entry.
894         // Select must enter one of its blocks, so there is no
895         // need for a cleaning at the end.
896         // Doubly special: evaluation order for select is stricter
897         // than ordinary expressions. Even something like p.c
898         // has to be hoisted into a temporary, so that it cannot be
899         // reordered after the channel evaluation for a different
900         // case (if p were nil, then the timing of the fault would
901         // give this away).
902         case ir.OSELECT:
903                 n := n.(*ir.SelectStmt)
904                 t := o.markTemp()
905                 for _, ncas := range n.Cases {
906                         r := ncas.Comm
907                         ir.SetPos(ncas)
908
909                         // Append any new body prologue to ninit.
910                         // The next loop will insert ninit into nbody.
911                         if len(ncas.Init()) != 0 {
912                                 base.Fatalf("order select ninit")
913                         }
914                         if r == nil {
915                                 continue
916                         }
917                         switch r.Op() {
918                         default:
919                                 ir.Dump("select case", r)
920                                 base.Fatalf("unknown op in select %v", r.Op())
921
922                         case ir.OSELRECV2:
923                                 // case x, ok = <-c
924                                 r := r.(*ir.AssignListStmt)
925                                 recv := r.Rhs[0].(*ir.UnaryExpr)
926                                 recv.X = o.expr(recv.X, nil)
927                                 if !ir.IsAutoTmp(recv.X) {
928                                         recv.X = o.copyExpr(recv.X)
929                                 }
930                                 init := ir.TakeInit(r)
931
932                                 colas := r.Def
933                                 do := func(i int, t *types.Type) {
934                                         n := r.Lhs[i]
935                                         if ir.IsBlank(n) {
936                                                 return
937                                         }
938                                         // If this is case x := <-ch or case x, y := <-ch, the case has
939                                         // the ODCL nodes to declare x and y. We want to delay that
940                                         // declaration (and possible allocation) until inside the case body.
941                                         // Delete the ODCL nodes here and recreate them inside the body below.
942                                         if colas {
943                                                 if len(init) > 0 && init[0].Op() == ir.ODCL && init[0].(*ir.Decl).X == n {
944                                                         init = init[1:]
945
946                                                         // iimport may have added a default initialization assignment,
947                                                         // due to how it handles ODCL statements.
948                                                         if len(init) > 0 && init[0].Op() == ir.OAS && init[0].(*ir.AssignStmt).X == n {
949                                                                 init = init[1:]
950                                                         }
951                                                 }
952                                                 dcl := typecheck.Stmt(ir.NewDecl(base.Pos, ir.ODCL, n.(*ir.Name)))
953                                                 ncas.PtrInit().Append(dcl)
954                                         }
955                                         tmp := o.newTemp(t, t.HasPointers())
956                                         as := typecheck.Stmt(ir.NewAssignStmt(base.Pos, n, typecheck.Conv(tmp, n.Type())))
957                                         ncas.PtrInit().Append(as)
958                                         r.Lhs[i] = tmp
959                                 }
960                                 do(0, recv.X.Type().Elem())
961                                 do(1, types.Types[types.TBOOL])
962                                 if len(init) != 0 {
963                                         ir.DumpList("ninit", init)
964                                         base.Fatalf("ninit on select recv")
965                                 }
966                                 orderBlock(ncas.PtrInit(), o.free)
967
968                         case ir.OSEND:
969                                 r := r.(*ir.SendStmt)
970                                 if len(r.Init()) != 0 {
971                                         ir.DumpList("ninit", r.Init())
972                                         base.Fatalf("ninit on select send")
973                                 }
974
975                                 // case c <- x
976                                 // r->left is c, r->right is x, both are always evaluated.
977                                 r.Chan = o.expr(r.Chan, nil)
978
979                                 if !ir.IsAutoTmp(r.Chan) {
980                                         r.Chan = o.copyExpr(r.Chan)
981                                 }
982                                 r.Value = o.expr(r.Value, nil)
983                                 if !ir.IsAutoTmp(r.Value) {
984                                         r.Value = o.copyExpr(r.Value)
985                                 }
986                         }
987                 }
988                 // Now that we have accumulated all the temporaries, clean them.
989                 // Also insert any ninit queued during the previous loop.
990                 // (The temporary cleaning must follow that ninit work.)
991                 for _, cas := range n.Cases {
992                         orderBlock(&cas.Body, o.free)
993
994                         // TODO(mdempsky): Is this actually necessary?
995                         // walkSelect appears to walk Ninit.
996                         cas.Body.Prepend(ir.TakeInit(cas)...)
997                 }
998
999                 o.out = append(o.out, n)
1000                 o.popTemp(t)
1001
1002         // Special: value being sent is passed as a pointer; make it addressable.
1003         case ir.OSEND:
1004                 n := n.(*ir.SendStmt)
1005                 t := o.markTemp()
1006                 n.Chan = o.expr(n.Chan, nil)
1007                 n.Value = o.expr(n.Value, nil)
1008                 if base.Flag.Cfg.Instrumenting {
1009                         // Force copying to the stack so that (chan T)(nil) <- x
1010                         // is still instrumented as a read of x.
1011                         n.Value = o.copyExpr(n.Value)
1012                 } else {
1013                         n.Value = o.addrTemp(n.Value)
1014                 }
1015                 o.out = append(o.out, n)
1016                 o.popTemp(t)
1017
1018         // TODO(rsc): Clean temporaries more aggressively.
1019         // Note that because walkSwitch will rewrite some of the
1020         // switch into a binary search, this is not as easy as it looks.
1021         // (If we ran that code here we could invoke order.stmt on
1022         // the if-else chain instead.)
1023         // For now just clean all the temporaries at the end.
1024         // In practice that's fine.
1025         case ir.OSWITCH:
1026                 n := n.(*ir.SwitchStmt)
1027                 if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) {
1028                         // Add empty "default:" case for instrumentation.
1029                         n.Cases = append(n.Cases, ir.NewCaseStmt(base.Pos, nil, nil))
1030                 }
1031
1032                 t := o.markTemp()
1033                 n.Tag = o.expr(n.Tag, nil)
1034                 for _, ncas := range n.Cases {
1035                         o.exprListInPlace(ncas.List)
1036                         orderBlock(&ncas.Body, o.free)
1037                 }
1038
1039                 o.out = append(o.out, n)
1040                 o.popTemp(t)
1041         }
1042
1043         base.Pos = lno
1044 }
1045
1046 func hasDefaultCase(n *ir.SwitchStmt) bool {
1047         for _, ncas := range n.Cases {
1048                 if len(ncas.List) == 0 {
1049                         return true
1050                 }
1051         }
1052         return false
1053 }
1054
1055 // exprList orders the expression list l into o.
1056 func (o *orderState) exprList(l ir.Nodes) {
1057         s := l
1058         for i := range s {
1059                 s[i] = o.expr(s[i], nil)
1060         }
1061 }
1062
1063 // exprListInPlace orders the expression list l but saves
1064 // the side effects on the individual expression ninit lists.
1065 func (o *orderState) exprListInPlace(l ir.Nodes) {
1066         s := l
1067         for i := range s {
1068                 s[i] = o.exprInPlace(s[i])
1069         }
1070 }
1071
1072 func (o *orderState) exprNoLHS(n ir.Node) ir.Node {
1073         return o.expr(n, nil)
1074 }
1075
1076 // expr orders a single expression, appending side
1077 // effects to o.out as needed.
1078 // If this is part of an assignment lhs = *np, lhs is given.
1079 // Otherwise lhs == nil. (When lhs != nil it may be possible
1080 // to avoid copying the result of the expression to a temporary.)
1081 // The result of expr MUST be assigned back to n, e.g.
1082 //
1083 //      n.Left = o.expr(n.Left, lhs)
1084 func (o *orderState) expr(n, lhs ir.Node) ir.Node {
1085         if n == nil {
1086                 return n
1087         }
1088         lno := ir.SetPos(n)
1089         n = o.expr1(n, lhs)
1090         base.Pos = lno
1091         return n
1092 }
1093
1094 func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
1095         o.init(n)
1096
1097         switch n.Op() {
1098         default:
1099                 if o.edit == nil {
1100                         o.edit = o.exprNoLHS // create closure once
1101                 }
1102                 ir.EditChildren(n, o.edit)
1103                 return n
1104
1105         // Addition of strings turns into a function call.
1106         // Allocate a temporary to hold the strings.
1107         // Fewer than 5 strings use direct runtime helpers.
1108         case ir.OADDSTR:
1109                 n := n.(*ir.AddStringExpr)
1110                 o.exprList(n.List)
1111
1112                 if len(n.List) > 5 {
1113                         t := types.NewArray(types.Types[types.TSTRING], int64(len(n.List)))
1114                         n.Prealloc = o.newTemp(t, false)
1115                 }
1116
1117                 // Mark string(byteSlice) arguments to reuse byteSlice backing
1118                 // buffer during conversion. String concatenation does not
1119                 // memorize the strings for later use, so it is safe.
1120                 // However, we can do it only if there is at least one non-empty string literal.
1121                 // Otherwise if all other arguments are empty strings,
1122                 // concatstrings will return the reference to the temp string
1123                 // to the caller.
1124                 hasbyte := false
1125
1126                 haslit := false
1127                 for _, n1 := range n.List {
1128                         hasbyte = hasbyte || n1.Op() == ir.OBYTES2STR
1129                         haslit = haslit || n1.Op() == ir.OLITERAL && len(ir.StringVal(n1)) != 0
1130                 }
1131
1132                 if haslit && hasbyte {
1133                         for _, n2 := range n.List {
1134                                 if n2.Op() == ir.OBYTES2STR {
1135                                         n2 := n2.(*ir.ConvExpr)
1136                                         n2.SetOp(ir.OBYTES2STRTMP)
1137                                 }
1138                         }
1139                 }
1140                 return n
1141
1142         case ir.OINDEXMAP:
1143                 n := n.(*ir.IndexExpr)
1144                 n.X = o.expr(n.X, nil)
1145                 n.Index = o.expr(n.Index, nil)
1146                 needCopy := false
1147
1148                 if !n.Assigned {
1149                         // Enforce that any []byte slices we are not copying
1150                         // can not be changed before the map index by forcing
1151                         // the map index to happen immediately following the
1152                         // conversions. See copyExpr a few lines below.
1153                         needCopy = mapKeyReplaceStrConv(n.Index)
1154
1155                         if base.Flag.Cfg.Instrumenting {
1156                                 // Race detector needs the copy.
1157                                 needCopy = true
1158                         }
1159                 }
1160
1161                 // key must be addressable
1162                 n.Index = o.mapKeyTemp(n.Pos(), n.X.Type(), n.Index)
1163                 if needCopy {
1164                         return o.copyExpr(n)
1165                 }
1166                 return n
1167
1168         // concrete type (not interface) argument might need an addressable
1169         // temporary to pass to the runtime conversion routine.
1170         case ir.OCONVIFACE:
1171                 n := n.(*ir.ConvExpr)
1172                 n.X = o.expr(n.X, nil)
1173                 if n.X.Type().IsInterface() {
1174                         return n
1175                 }
1176                 if _, _, needsaddr := dataWordFuncName(n.X.Type()); needsaddr || isStaticCompositeLiteral(n.X) {
1177                         // Need a temp if we need to pass the address to the conversion function.
1178                         // We also process static composite literal node here, making a named static global
1179                         // whose address we can put directly in an interface (see OCONVIFACE case in walk).
1180                         n.X = o.addrTemp(n.X)
1181                 }
1182                 return n
1183
1184         case ir.OCONVNOP:
1185                 n := n.(*ir.ConvExpr)
1186                 if n.X.Op() == ir.OCALLMETH {
1187                         base.FatalfAt(n.X.Pos(), "OCALLMETH missed by typecheck")
1188                 }
1189                 if n.Type().IsKind(types.TUNSAFEPTR) && n.X.Type().IsKind(types.TUINTPTR) && (n.X.Op() == ir.OCALLFUNC || n.X.Op() == ir.OCALLINTER) {
1190                         call := n.X.(*ir.CallExpr)
1191                         // When reordering unsafe.Pointer(f()) into a separate
1192                         // statement, the conversion and function call must stay
1193                         // together. See golang.org/issue/15329.
1194                         o.init(call)
1195                         o.call(call)
1196                         if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1197                                 return o.copyExpr(n)
1198                         }
1199                 } else {
1200                         n.X = o.expr(n.X, nil)
1201                 }
1202                 return n
1203
1204         case ir.OANDAND, ir.OOROR:
1205                 // ... = LHS && RHS
1206                 //
1207                 // var r bool
1208                 // r = LHS
1209                 // if r {       // or !r, for OROR
1210                 //     r = RHS
1211                 // }
1212                 // ... = r
1213
1214                 n := n.(*ir.LogicalExpr)
1215                 r := o.newTemp(n.Type(), false)
1216
1217                 // Evaluate left-hand side.
1218                 lhs := o.expr(n.X, nil)
1219                 o.out = append(o.out, typecheck.Stmt(ir.NewAssignStmt(base.Pos, r, lhs)))
1220
1221                 // Evaluate right-hand side, save generated code.
1222                 saveout := o.out
1223                 o.out = nil
1224                 t := o.markTemp()
1225                 o.edge()
1226                 rhs := o.expr(n.Y, nil)
1227                 o.out = append(o.out, typecheck.Stmt(ir.NewAssignStmt(base.Pos, r, rhs)))
1228                 o.popTemp(t)
1229                 gen := o.out
1230                 o.out = saveout
1231
1232                 // If left-hand side doesn't cause a short-circuit, issue right-hand side.
1233                 nif := ir.NewIfStmt(base.Pos, r, nil, nil)
1234                 if n.Op() == ir.OANDAND {
1235                         nif.Body = gen
1236                 } else {
1237                         nif.Else = gen
1238                 }
1239                 o.out = append(o.out, nif)
1240                 return r
1241
1242         case ir.OCALLMETH:
1243                 base.FatalfAt(n.Pos(), "OCALLMETH missed by typecheck")
1244                 panic("unreachable")
1245
1246         case ir.OCALLFUNC,
1247                 ir.OCALLINTER,
1248                 ir.OCAP,
1249                 ir.OCOMPLEX,
1250                 ir.OCOPY,
1251                 ir.OIMAG,
1252                 ir.OLEN,
1253                 ir.OMAKECHAN,
1254                 ir.OMAKEMAP,
1255                 ir.OMAKESLICE,
1256                 ir.OMAKESLICECOPY,
1257                 ir.OMAX,
1258                 ir.OMIN,
1259                 ir.ONEW,
1260                 ir.OREAL,
1261                 ir.ORECOVERFP,
1262                 ir.OSTR2BYTES,
1263                 ir.OSTR2BYTESTMP,
1264                 ir.OSTR2RUNES:
1265
1266                 if isRuneCount(n) {
1267                         // len([]rune(s)) is rewritten to runtime.countrunes(s) later.
1268                         conv := n.(*ir.UnaryExpr).X.(*ir.ConvExpr)
1269                         conv.X = o.expr(conv.X, nil)
1270                 } else {
1271                         o.call(n)
1272                 }
1273
1274                 if lhs == nil || lhs.Op() != ir.ONAME || base.Flag.Cfg.Instrumenting {
1275                         return o.copyExpr(n)
1276                 }
1277                 return n
1278
1279         case ir.OINLCALL:
1280                 n := n.(*ir.InlinedCallExpr)
1281                 o.stmtList(n.Body)
1282                 return n.SingleResult()
1283
1284         case ir.OAPPEND:
1285                 // Check for append(x, make([]T, y)...) .
1286                 n := n.(*ir.CallExpr)
1287                 if isAppendOfMake(n) {
1288                         n.Args[0] = o.expr(n.Args[0], nil) // order x
1289                         mk := n.Args[1].(*ir.MakeExpr)
1290                         mk.Len = o.expr(mk.Len, nil) // order y
1291                 } else {
1292                         o.exprList(n.Args)
1293                 }
1294
1295                 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.Args[0]) {
1296                         return o.copyExpr(n)
1297                 }
1298                 return n
1299
1300         case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
1301                 n := n.(*ir.SliceExpr)
1302                 n.X = o.expr(n.X, nil)
1303                 n.Low = o.cheapExpr(o.expr(n.Low, nil))
1304                 n.High = o.cheapExpr(o.expr(n.High, nil))
1305                 n.Max = o.cheapExpr(o.expr(n.Max, nil))
1306                 if lhs == nil || lhs.Op() != ir.ONAME && !ir.SameSafeExpr(lhs, n.X) {
1307                         return o.copyExpr(n)
1308                 }
1309                 return n
1310
1311         case ir.OCLOSURE:
1312                 n := n.(*ir.ClosureExpr)
1313                 if n.Transient() && len(n.Func.ClosureVars) > 0 {
1314                         n.Prealloc = o.newTemp(typecheck.ClosureType(n), false)
1315                 }
1316                 return n
1317
1318         case ir.OMETHVALUE:
1319                 n := n.(*ir.SelectorExpr)
1320                 n.X = o.expr(n.X, nil)
1321                 if n.Transient() {
1322                         t := typecheck.MethodValueType(n)
1323                         n.Prealloc = o.newTemp(t, false)
1324                 }
1325                 return n
1326
1327         case ir.OSLICELIT:
1328                 n := n.(*ir.CompLitExpr)
1329                 o.exprList(n.List)
1330                 if n.Transient() {
1331                         t := types.NewArray(n.Type().Elem(), n.Len)
1332                         n.Prealloc = o.newTemp(t, false)
1333                 }
1334                 return n
1335
1336         case ir.ODOTTYPE, ir.ODOTTYPE2:
1337                 n := n.(*ir.TypeAssertExpr)
1338                 n.X = o.expr(n.X, nil)
1339                 if !types.IsDirectIface(n.Type()) || base.Flag.Cfg.Instrumenting {
1340                         return o.copyExprClear(n)
1341                 }
1342                 return n
1343
1344         case ir.ORECV:
1345                 n := n.(*ir.UnaryExpr)
1346                 n.X = o.expr(n.X, nil)
1347                 return o.copyExprClear(n)
1348
1349         case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
1350                 n := n.(*ir.BinaryExpr)
1351                 n.X = o.expr(n.X, nil)
1352                 n.Y = o.expr(n.Y, nil)
1353
1354                 t := n.X.Type()
1355                 switch {
1356                 case t.IsString():
1357                         // Mark string(byteSlice) arguments to reuse byteSlice backing
1358                         // buffer during conversion. String comparison does not
1359                         // memorize the strings for later use, so it is safe.
1360                         if n.X.Op() == ir.OBYTES2STR {
1361                                 n.X.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1362                         }
1363                         if n.Y.Op() == ir.OBYTES2STR {
1364                                 n.Y.(*ir.ConvExpr).SetOp(ir.OBYTES2STRTMP)
1365                         }
1366
1367                 case t.IsStruct() || t.IsArray():
1368                         // for complex comparisons, we need both args to be
1369                         // addressable so we can pass them to the runtime.
1370                         n.X = o.addrTemp(n.X)
1371                         n.Y = o.addrTemp(n.Y)
1372                 }
1373                 return n
1374
1375         case ir.OMAPLIT:
1376                 // Order map by converting:
1377                 //   map[int]int{
1378                 //     a(): b(),
1379                 //     c(): d(),
1380                 //     e(): f(),
1381                 //   }
1382                 // to
1383                 //   m := map[int]int{}
1384                 //   m[a()] = b()
1385                 //   m[c()] = d()
1386                 //   m[e()] = f()
1387                 // Then order the result.
1388                 // Without this special case, order would otherwise compute all
1389                 // the keys and values before storing any of them to the map.
1390                 // See issue 26552.
1391                 n := n.(*ir.CompLitExpr)
1392                 entries := n.List
1393                 statics := entries[:0]
1394                 var dynamics []*ir.KeyExpr
1395                 for _, r := range entries {
1396                         r := r.(*ir.KeyExpr)
1397
1398                         if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1399                                 dynamics = append(dynamics, r)
1400                                 continue
1401                         }
1402
1403                         // Recursively ordering some static entries can change them to dynamic;
1404                         // e.g., OCONVIFACE nodes. See #31777.
1405                         r = o.expr(r, nil).(*ir.KeyExpr)
1406                         if !isStaticCompositeLiteral(r.Key) || !isStaticCompositeLiteral(r.Value) {
1407                                 dynamics = append(dynamics, r)
1408                                 continue
1409                         }
1410
1411                         statics = append(statics, r)
1412                 }
1413                 n.List = statics
1414
1415                 if len(dynamics) == 0 {
1416                         return n
1417                 }
1418
1419                 // Emit the creation of the map (with all its static entries).
1420                 m := o.newTemp(n.Type(), false)
1421                 as := ir.NewAssignStmt(base.Pos, m, n)
1422                 typecheck.Stmt(as)
1423                 o.stmt(as)
1424
1425                 // Emit eval+insert of dynamic entries, one at a time.
1426                 for _, r := range dynamics {
1427                         lhs := typecheck.AssignExpr(ir.NewIndexExpr(base.Pos, m, r.Key)).(*ir.IndexExpr)
1428                         base.AssertfAt(lhs.Op() == ir.OINDEXMAP, lhs.Pos(), "want OINDEXMAP, have %+v", lhs)
1429                         lhs.RType = n.RType
1430
1431                         as := ir.NewAssignStmt(base.Pos, lhs, r.Value)
1432                         typecheck.Stmt(as)
1433                         o.stmt(as)
1434                 }
1435
1436                 // Remember that we issued these assignments so we can include that count
1437                 // in the map alloc hint.
1438                 // We're assuming here that all the keys in the map literal are distinct.
1439                 // If any are equal, this will be an overcount. Probably not worth accounting
1440                 // for that, as equal keys in map literals are rare, and at worst we waste
1441                 // a bit of space.
1442                 n.Len += int64(len(dynamics))
1443
1444                 return m
1445         }
1446
1447         // No return - type-assertions above. Each case must return for itself.
1448 }
1449
1450 // as2func orders OAS2FUNC nodes. It creates temporaries to ensure left-to-right assignment.
1451 // The caller should order the right-hand side of the assignment before calling order.as2func.
1452 // It rewrites,
1453 //
1454 //      a, b, a = ...
1455 //
1456 // as
1457 //
1458 //      tmp1, tmp2, tmp3 = ...
1459 //      a, b, a = tmp1, tmp2, tmp3
1460 //
1461 // This is necessary to ensure left to right assignment order.
1462 func (o *orderState) as2func(n *ir.AssignListStmt) {
1463         results := n.Rhs[0].Type()
1464         as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1465         for i, nl := range n.Lhs {
1466                 if !ir.IsBlank(nl) {
1467                         typ := results.Field(i).Type
1468                         tmp := o.newTemp(typ, typ.HasPointers())
1469                         n.Lhs[i] = tmp
1470                         as.Lhs = append(as.Lhs, nl)
1471                         as.Rhs = append(as.Rhs, tmp)
1472                 }
1473         }
1474
1475         o.out = append(o.out, n)
1476         o.stmt(typecheck.Stmt(as))
1477 }
1478
1479 // as2ok orders OAS2XXX with ok.
1480 // Just like as2func, this also adds temporaries to ensure left-to-right assignment.
1481 func (o *orderState) as2ok(n *ir.AssignListStmt) {
1482         as := ir.NewAssignListStmt(n.Pos(), ir.OAS2, nil, nil)
1483
1484         do := func(i int, typ *types.Type) {
1485                 if nl := n.Lhs[i]; !ir.IsBlank(nl) {
1486                         var tmp ir.Node = o.newTemp(typ, typ.HasPointers())
1487                         n.Lhs[i] = tmp
1488                         as.Lhs = append(as.Lhs, nl)
1489                         if i == 1 {
1490                                 // The "ok" result is an untyped boolean according to the Go
1491                                 // spec. We need to explicitly convert it to the LHS type in
1492                                 // case the latter is a defined boolean type (#8475).
1493                                 tmp = typecheck.Conv(tmp, nl.Type())
1494                         }
1495                         as.Rhs = append(as.Rhs, tmp)
1496                 }
1497         }
1498
1499         do(0, n.Rhs[0].Type())
1500         do(1, types.Types[types.TBOOL])
1501
1502         o.out = append(o.out, n)
1503         o.stmt(typecheck.Stmt(as))
1504 }