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