github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/walk/order.go (about)

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