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