github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/compile/internal/gc/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 gc
     6  
     7  import (
     8  	"cmd/internal/src"
     9  	"fmt"
    10  )
    11  
    12  // Rewrite tree to use separate statements to enforce
    13  // order of evaluation. Makes walk easier, because it
    14  // can (after this runs) reorder at will within an expression.
    15  //
    16  // Rewrite x op= y into x = x op y.
    17  //
    18  // Introduce temporaries as needed by runtime routines.
    19  // For example, the map runtime routines take the map key
    20  // by reference, so make sure all map keys are addressable
    21  // by copying them to temporaries as needed.
    22  // The same is true for channel operations.
    23  //
    24  // Arrange that map index expressions only appear in direct
    25  // assignments x = m[k] or m[k] = x, never in larger expressions.
    26  //
    27  // Arrange that receive expressions only appear in direct assignments
    28  // x = <-c or as standalone statements <-c, never in larger expressions.
    29  
    30  // TODO(rsc): The temporary introduction during multiple assignments
    31  // should be moved into this file, so that the temporaries can be cleaned
    32  // and so that conversions implicit in the OAS2FUNC and OAS2RECV
    33  // nodes can be made explicit and then have their temporaries cleaned.
    34  
    35  // TODO(rsc): Goto and multilevel break/continue can jump over
    36  // inserted VARKILL annotations. Work out a way to handle these.
    37  // The current implementation is safe, in that it will execute correctly.
    38  // But it won't reuse temporaries as aggressively as it might, and
    39  // it can result in unnecessary zeroing of those variables in the function
    40  // prologue.
    41  
    42  // Order holds state during the ordering process.
    43  type Order struct {
    44  	out  []*Node // list of generated statements
    45  	temp []*Node // stack of temporary variables
    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 *Node) {
    51  	if Debug['W'] > 1 {
    52  		s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
    53  		dumplist(s, fn.Nbody)
    54  	}
    55  
    56  	orderblockNodes(&fn.Nbody)
    57  }
    58  
    59  // Ordertemp allocates a new temporary with the given type,
    60  // pushes it onto the temp stack, and returns it.
    61  // If clear is true, ordertemp emits code to zero the temporary.
    62  func ordertemp(t *Type, order *Order, clear bool) *Node {
    63  	var_ := temp(t)
    64  	if clear {
    65  		a := nod(OAS, var_, nil)
    66  		a = typecheck(a, Etop)
    67  		order.out = append(order.out, a)
    68  	}
    69  
    70  	order.temp = append(order.temp, var_)
    71  	return var_
    72  }
    73  
    74  // Ordercopyexpr behaves like ordertemp but also emits
    75  // code to initialize the temporary to the value n.
    76  //
    77  // The clear argument is provided for use when the evaluation
    78  // of tmp = n turns into a function call that is passed a pointer
    79  // to the temporary as the output space. If the call blocks before
    80  // tmp has been written, the garbage collector will still treat the
    81  // temporary as live, so we must zero it before entering that call.
    82  // Today, this only happens for channel receive operations.
    83  // (The other candidate would be map access, but map access
    84  // returns a pointer to the result data instead of taking a pointer
    85  // to be filled in.)
    86  func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
    87  	var_ := ordertemp(t, order, clear != 0)
    88  	a := nod(OAS, var_, n)
    89  	a = typecheck(a, Etop)
    90  	order.out = append(order.out, a)
    91  	return var_
    92  }
    93  
    94  // Ordercheapexpr returns a cheap version of n.
    95  // The definition of cheap is that n is a variable or constant.
    96  // If not, ordercheapexpr allocates a new tmp, emits tmp = n,
    97  // and then returns tmp.
    98  func ordercheapexpr(n *Node, order *Order) *Node {
    99  	if n == nil {
   100  		return nil
   101  	}
   102  	switch n.Op {
   103  	case ONAME, OLITERAL:
   104  		return n
   105  	case OLEN, OCAP:
   106  		l := ordercheapexpr(n.Left, order)
   107  		if l == n.Left {
   108  			return n
   109  		}
   110  		a := *n
   111  		a.Orig = &a
   112  		a.Left = l
   113  		return typecheck(&a, Erv)
   114  	}
   115  
   116  	return ordercopyexpr(n, n.Type, order, 0)
   117  }
   118  
   119  // Ordersafeexpr returns a safe version of n.
   120  // The definition of safe is that n can appear multiple times
   121  // without violating the semantics of the original program,
   122  // and that assigning to the safe version has the same effect
   123  // as assigning to the original n.
   124  //
   125  // The intended use is to apply to x when rewriting x += y into x = x + y.
   126  func ordersafeexpr(n *Node, order *Order) *Node {
   127  	switch n.Op {
   128  	case ONAME, OLITERAL:
   129  		return n
   130  
   131  	case ODOT, OLEN, OCAP:
   132  		l := ordersafeexpr(n.Left, order)
   133  		if l == n.Left {
   134  			return n
   135  		}
   136  		a := *n
   137  		a.Orig = &a
   138  		a.Left = l
   139  		return typecheck(&a, Erv)
   140  
   141  	case ODOTPTR, OIND:
   142  		l := ordercheapexpr(n.Left, order)
   143  		if l == n.Left {
   144  			return n
   145  		}
   146  		a := *n
   147  		a.Orig = &a
   148  		a.Left = l
   149  		return typecheck(&a, Erv)
   150  
   151  	case OINDEX, OINDEXMAP:
   152  		var l *Node
   153  		if n.Left.Type.IsArray() {
   154  			l = ordersafeexpr(n.Left, order)
   155  		} else {
   156  			l = ordercheapexpr(n.Left, order)
   157  		}
   158  		r := ordercheapexpr(n.Right, order)
   159  		if l == n.Left && r == n.Right {
   160  			return n
   161  		}
   162  		a := *n
   163  		a.Orig = &a
   164  		a.Left = l
   165  		a.Right = r
   166  		return typecheck(&a, Erv)
   167  	default:
   168  		Fatalf("ordersafeexpr %v", n.Op)
   169  		return nil // not reached
   170  	}
   171  }
   172  
   173  // Isaddrokay reports whether it is okay to pass n's address to runtime routines.
   174  // Taking the address of a variable makes the liveness and optimization analyses
   175  // lose track of where the variable's lifetime ends. To avoid hurting the analyses
   176  // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay,
   177  // because we emit explicit VARKILL instructions marking the end of those
   178  // temporaries' lifetimes.
   179  func isaddrokay(n *Node) bool {
   180  	return islvalue(n) && (n.Op != ONAME || n.Class == PEXTERN || n.IsAutoTmp())
   181  }
   182  
   183  // Orderaddrtemp ensures that n is okay to pass by address to runtime routines.
   184  // If the original argument n is not okay, orderaddrtemp creates a tmp, emits
   185  // tmp = n, and then returns tmp.
   186  // The result of orderaddrtemp MUST be assigned back to n, e.g.
   187  // 	n.Left = orderaddrtemp(n.Left, order)
   188  func orderaddrtemp(n *Node, order *Order) *Node {
   189  	if consttype(n) >= 0 {
   190  		// TODO: expand this to all static composite literal nodes?
   191  		n = defaultlit(n, nil)
   192  		dowidth(n.Type)
   193  		vstat := staticname(n.Type)
   194  		vstat.Name.Readonly = true
   195  		var out []*Node
   196  		staticassign(vstat, n, &out)
   197  		if out != nil {
   198  			Fatalf("staticassign of const generated code: %+v", n)
   199  		}
   200  		vstat = typecheck(vstat, Erv)
   201  		return vstat
   202  	}
   203  	if isaddrokay(n) {
   204  		return n
   205  	}
   206  	return ordercopyexpr(n, n.Type, order, 0)
   207  }
   208  
   209  type ordermarker int
   210  
   211  // Marktemp returns the top of the temporary variable stack.
   212  func marktemp(order *Order) ordermarker {
   213  	return ordermarker(len(order.temp))
   214  }
   215  
   216  // Poptemp pops temporaries off the stack until reaching the mark,
   217  // which must have been returned by marktemp.
   218  func poptemp(mark ordermarker, order *Order) {
   219  	order.temp = order.temp[:mark]
   220  }
   221  
   222  // Cleantempnopop emits to *out VARKILL instructions for each temporary
   223  // above the mark on the temporary stack, but it does not pop them
   224  // from the stack.
   225  func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
   226  	var kill *Node
   227  
   228  	for i := len(order.temp) - 1; i >= int(mark); i-- {
   229  		n := order.temp[i]
   230  		if n.Name.Keepalive {
   231  			n.Name.Keepalive = false
   232  			n.Addrtaken = true // ensure SSA keeps the n variable
   233  			kill = nod(OVARLIVE, n, nil)
   234  			kill = typecheck(kill, Etop)
   235  			*out = append(*out, kill)
   236  		}
   237  		kill = nod(OVARKILL, n, nil)
   238  		kill = typecheck(kill, Etop)
   239  		*out = append(*out, kill)
   240  	}
   241  }
   242  
   243  // Cleantemp emits VARKILL instructions for each temporary above the
   244  // mark on the temporary stack and removes them from the stack.
   245  func cleantemp(top ordermarker, order *Order) {
   246  	cleantempnopop(top, order, &order.out)
   247  	poptemp(top, order)
   248  }
   249  
   250  // Orderstmtlist orders each of the statements in the list.
   251  func orderstmtlist(l Nodes, order *Order) {
   252  	for _, n := range l.Slice() {
   253  		orderstmt(n, order)
   254  	}
   255  }
   256  
   257  // Orderblock orders the block of statements l onto a new list,
   258  // and returns the ordered list.
   259  func orderblock(l Nodes) []*Node {
   260  	var order Order
   261  	mark := marktemp(&order)
   262  	orderstmtlist(l, &order)
   263  	cleantemp(mark, &order)
   264  	return order.out
   265  }
   266  
   267  // OrderblockNodes orders the block of statements in n into a new slice,
   268  // and then replaces the old slice in n with the new slice.
   269  func orderblockNodes(n *Nodes) {
   270  	var order Order
   271  	mark := marktemp(&order)
   272  	orderstmtlist(*n, &order)
   273  	cleantemp(mark, &order)
   274  	n.Set(order.out)
   275  }
   276  
   277  // Orderexprinplace orders the side effects in *np and
   278  // leaves them as the init list of the final *np.
   279  // The result of orderexprinplace MUST be assigned back to n, e.g.
   280  // 	n.Left = orderexprinplace(n.Left, outer)
   281  func orderexprinplace(n *Node, outer *Order) *Node {
   282  	var order Order
   283  	n = orderexpr(n, &order, nil)
   284  	n = addinit(n, order.out)
   285  
   286  	// insert new temporaries from order
   287  	// at head of outer list.
   288  	outer.temp = append(outer.temp, order.temp...)
   289  	return n
   290  }
   291  
   292  // Orderstmtinplace orders the side effects of the single statement *np
   293  // and replaces it with the resulting statement list.
   294  // The result of orderstmtinplace MUST be assigned back to n, e.g.
   295  // 	n.Left = orderstmtinplace(n.Left)
   296  func orderstmtinplace(n *Node) *Node {
   297  	var order Order
   298  	mark := marktemp(&order)
   299  	orderstmt(n, &order)
   300  	cleantemp(mark, &order)
   301  	return liststmt(order.out)
   302  }
   303  
   304  // Orderinit moves n's init list to order->out.
   305  func orderinit(n *Node, order *Order) {
   306  	orderstmtlist(n.Ninit, order)
   307  	n.Ninit.Set(nil)
   308  }
   309  
   310  // Ismulticall reports whether the list l is f() for a multi-value function.
   311  // Such an f() could appear as the lone argument to a multi-arg function.
   312  func ismulticall(l Nodes) bool {
   313  	// one arg only
   314  	if l.Len() != 1 {
   315  		return false
   316  	}
   317  	n := l.First()
   318  
   319  	// must be call
   320  	switch n.Op {
   321  	default:
   322  		return false
   323  
   324  	case OCALLFUNC, OCALLMETH, OCALLINTER:
   325  		break
   326  	}
   327  
   328  	// call must return multiple values
   329  	return n.Left.Type.Results().NumFields() > 1
   330  }
   331  
   332  // Copyret emits t1, t2, ... = n, where n is a function call,
   333  // and then returns the list t1, t2, ....
   334  func copyret(n *Node, order *Order) []*Node {
   335  	if !n.Type.IsFuncArgStruct() {
   336  		Fatalf("copyret %v %d", n.Type, n.Left.Type.Results().NumFields())
   337  	}
   338  
   339  	var l1 []*Node
   340  	var l2 []*Node
   341  	for _, t := range n.Type.Fields().Slice() {
   342  		tmp := temp(t.Type)
   343  		l1 = append(l1, tmp)
   344  		l2 = append(l2, tmp)
   345  	}
   346  
   347  	as := nod(OAS2, nil, nil)
   348  	as.List.Set(l1)
   349  	as.Rlist.Set1(n)
   350  	as = typecheck(as, Etop)
   351  	orderstmt(as, order)
   352  
   353  	return l2
   354  }
   355  
   356  // Ordercallargs orders the list of call arguments *l.
   357  func ordercallargs(l *Nodes, order *Order) {
   358  	if ismulticall(*l) {
   359  		// return f() where f() is multiple values.
   360  		l.Set(copyret(l.First(), order))
   361  	} else {
   362  		orderexprlist(*l, order)
   363  	}
   364  }
   365  
   366  // Ordercall orders the call expression n.
   367  // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
   368  func ordercall(n *Node, order *Order) {
   369  	n.Left = orderexpr(n.Left, order, nil)
   370  	n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp
   371  	ordercallargs(&n.List, order)
   372  
   373  	if n.Op == OCALLFUNC {
   374  		t, it := iterFields(n.Left.Type.Params())
   375  		for i := range n.List.Slice() {
   376  			// Check for "unsafe-uintptr" tag provided by escape analysis.
   377  			// If present and the argument is really a pointer being converted
   378  			// to uintptr, arrange for the pointer to be kept alive until the call
   379  			// returns, by copying it into a temp and marking that temp
   380  			// still alive when we pop the temp stack.
   381  			if t == nil {
   382  				break
   383  			}
   384  			if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
   385  				xp := n.List.Addr(i)
   386  				for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() {
   387  					xp = &(*xp).Left
   388  				}
   389  				x := *xp
   390  				if x.Type.IsPtr() {
   391  					x = ordercopyexpr(x, x.Type, order, 0)
   392  					x.Name.Keepalive = true
   393  					*xp = x
   394  				}
   395  			}
   396  			next := it.Next()
   397  			if next == nil && t.Isddd && t.Note == uintptrEscapesTag {
   398  				next = t
   399  			}
   400  			t = next
   401  		}
   402  	}
   403  }
   404  
   405  // Ordermapassign appends n to order->out, introducing temporaries
   406  // to make sure that all map assignments have the form m[k] = x.
   407  // (Note: orderexpr has already been called on n, so we know k is addressable.)
   408  //
   409  // If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is
   410  //	t1 = m
   411  //	t2 = k
   412  //	...., t3, ... = x
   413  //	t1[t2] = t3
   414  //
   415  // The temporaries t1, t2 are needed in case the ... being assigned
   416  // contain m or k. They are usually unnecessary, but in the unnecessary
   417  // cases they are also typically registerizable, so not much harm done.
   418  // And this only applies to the multiple-assignment form.
   419  // We could do a more precise analysis if needed, like in walk.go.
   420  //
   421  // Ordermapassign also inserts these temporaries if needed for
   422  // calling writebarrierfat with a pointer to n->right.
   423  func ordermapassign(n *Node, order *Order) {
   424  	switch n.Op {
   425  	default:
   426  		Fatalf("ordermapassign %v", n.Op)
   427  
   428  	case OAS:
   429  		order.out = append(order.out, n)
   430  
   431  		// We call writebarrierfat only for values > 4 pointers long. See walk.go.
   432  		// TODO(mdempsky): writebarrierfat doesn't exist anymore, but removing that
   433  		// logic causes net/http's tests to become flaky; see CL 21242.
   434  		if needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr) && n.Right != nil && !isaddrokay(n.Right) {
   435  			m := n.Left
   436  			n.Left = ordertemp(m.Type, order, false)
   437  			a := nod(OAS, m, n.Left)
   438  			a = typecheck(a, Etop)
   439  			order.out = append(order.out, a)
   440  		}
   441  
   442  	case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
   443  		var post []*Node
   444  		var m *Node
   445  		var a *Node
   446  		for i1, n1 := range n.List.Slice() {
   447  			if n1.Op == OINDEXMAP {
   448  				m = n1
   449  				if !m.Left.IsAutoTmp() {
   450  					m.Left = ordercopyexpr(m.Left, m.Left.Type, order, 0)
   451  				}
   452  				if !m.Right.IsAutoTmp() {
   453  					m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
   454  				}
   455  				n.List.SetIndex(i1, ordertemp(m.Type, order, false))
   456  				a = nod(OAS, m, n.List.Index(i1))
   457  				a = typecheck(a, Etop)
   458  				post = append(post, a)
   459  			} else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
   460  				m = n.List.Index(i1)
   461  				t := ordertemp(m.Type, order, false)
   462  				n.List.SetIndex(i1, t)
   463  				a = nod(OAS, m, t)
   464  				a = typecheck(a, Etop)
   465  				post = append(post, a)
   466  			}
   467  		}
   468  
   469  		order.out = append(order.out, n)
   470  		order.out = append(order.out, post...)
   471  	}
   472  }
   473  
   474  // Orderstmt orders the statement n, appending to order->out.
   475  // Temporaries created during the statement are cleaned
   476  // up using VARKILL instructions as possible.
   477  func orderstmt(n *Node, order *Order) {
   478  	if n == nil {
   479  		return
   480  	}
   481  
   482  	lno := setlineno(n)
   483  
   484  	orderinit(n, order)
   485  
   486  	switch n.Op {
   487  	default:
   488  		Fatalf("orderstmt %v", n.Op)
   489  
   490  	case OVARKILL, OVARLIVE:
   491  		order.out = append(order.out, n)
   492  
   493  	case OAS:
   494  		t := marktemp(order)
   495  		n.Left = orderexpr(n.Left, order, nil)
   496  		n.Right = orderexpr(n.Right, order, n.Left)
   497  		ordermapassign(n, order)
   498  		cleantemp(t, order)
   499  
   500  	case OAS2,
   501  		OCLOSE,
   502  		OCOPY,
   503  		OPRINT,
   504  		OPRINTN,
   505  		ORECOVER,
   506  		ORECV:
   507  		t := marktemp(order)
   508  		n.Left = orderexpr(n.Left, order, nil)
   509  		n.Right = orderexpr(n.Right, order, nil)
   510  		orderexprlist(n.List, order)
   511  		orderexprlist(n.Rlist, order)
   512  		switch n.Op {
   513  		case OAS2, OAS2DOTTYPE:
   514  			ordermapassign(n, order)
   515  		default:
   516  			order.out = append(order.out, n)
   517  		}
   518  		cleantemp(t, order)
   519  
   520  	case OASOP:
   521  		// Special: rewrite l op= r into l = l op r.
   522  		// This simplifies quite a few operations;
   523  		// most important is that it lets us separate
   524  		// out map read from map write when l is
   525  		// a map index expression.
   526  		t := marktemp(order)
   527  
   528  		n.Left = orderexpr(n.Left, order, nil)
   529  		n.Left = ordersafeexpr(n.Left, order)
   530  		tmp1 := treecopy(n.Left, src.NoXPos)
   531  		if tmp1.Op == OINDEXMAP {
   532  			tmp1.Etype = 0 // now an rvalue not an lvalue
   533  		}
   534  		tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
   535  		// TODO(marvin): Fix Node.EType type union.
   536  		n.Right = nod(Op(n.Etype), tmp1, n.Right)
   537  		n.Right = typecheck(n.Right, Erv)
   538  		n.Right = orderexpr(n.Right, order, nil)
   539  		n.Etype = 0
   540  		n.Op = OAS
   541  		ordermapassign(n, order)
   542  		cleantemp(t, order)
   543  
   544  	// Special: make sure key is addressable,
   545  	// and make sure OINDEXMAP is not copied out.
   546  	case OAS2MAPR:
   547  		t := marktemp(order)
   548  
   549  		orderexprlist(n.List, order)
   550  		r := n.Rlist.First()
   551  		r.Left = orderexpr(r.Left, order, nil)
   552  		r.Right = orderexpr(r.Right, order, nil)
   553  
   554  		// See case OINDEXMAP below.
   555  		if r.Right.Op == OARRAYBYTESTR {
   556  			r.Right.Op = OARRAYBYTESTRTMP
   557  		}
   558  		r.Right = orderaddrtemp(r.Right, order)
   559  		ordermapassign(n, order)
   560  		cleantemp(t, order)
   561  
   562  	// Special: avoid copy of func call n->rlist->n.
   563  	case OAS2FUNC:
   564  		t := marktemp(order)
   565  
   566  		orderexprlist(n.List, order)
   567  		ordercall(n.Rlist.First(), order)
   568  		ordermapassign(n, order)
   569  		cleantemp(t, order)
   570  
   571  	// Special: use temporary variables to hold result,
   572  	// so that assertI2Tetc can take address of temporary.
   573  	// No temporary for blank assignment.
   574  	case OAS2DOTTYPE:
   575  		t := marktemp(order)
   576  
   577  		orderexprlist(n.List, order)
   578  		n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
   579  
   580  		var tmp1, tmp2 *Node
   581  		if !isblank(n.List.First()) {
   582  			typ := n.Rlist.First().Type
   583  			tmp1 = ordertemp(typ, order, haspointers(typ))
   584  		}
   585  		if !isblank(n.List.Second()) && !n.List.Second().Type.IsBoolean() {
   586  			tmp2 = ordertemp(Types[TBOOL], order, false)
   587  		}
   588  
   589  		order.out = append(order.out, n)
   590  
   591  		if tmp1 != nil {
   592  			r := nod(OAS, n.List.First(), tmp1)
   593  			r = typecheck(r, Etop)
   594  			ordermapassign(r, order)
   595  			n.List.SetIndex(0, tmp1)
   596  		}
   597  		if tmp2 != nil {
   598  			r := okas(n.List.Second(), tmp2)
   599  			r = typecheck(r, Etop)
   600  			ordermapassign(r, order)
   601  			n.List.SetIndex(1, tmp2)
   602  		}
   603  
   604  		cleantemp(t, order)
   605  
   606  	// Special: use temporary variables to hold result,
   607  	// so that chanrecv can take address of temporary.
   608  	case OAS2RECV:
   609  		t := marktemp(order)
   610  
   611  		orderexprlist(n.List, order)
   612  		n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
   613  		ch := n.Rlist.First().Left.Type
   614  		tmp1 := ordertemp(ch.Elem(), order, haspointers(ch.Elem()))
   615  		tmp2 := ordertemp(Types[TBOOL], order, false)
   616  		order.out = append(order.out, n)
   617  		r := nod(OAS, n.List.First(), tmp1)
   618  		r = typecheck(r, Etop)
   619  		ordermapassign(r, order)
   620  		r = okas(n.List.Second(), tmp2)
   621  		r = typecheck(r, Etop)
   622  		ordermapassign(r, order)
   623  		n.List.Set([]*Node{tmp1, tmp2})
   624  		cleantemp(t, order)
   625  
   626  	// Special: does not save n onto out.
   627  	case OBLOCK, OEMPTY:
   628  		orderstmtlist(n.List, order)
   629  
   630  	// Special: n->left is not an expression; save as is.
   631  	case OBREAK,
   632  		OCONTINUE,
   633  		ODCL,
   634  		ODCLCONST,
   635  		ODCLTYPE,
   636  		OFALL,
   637  		OXFALL,
   638  		OGOTO,
   639  		OLABEL,
   640  		ORETJMP:
   641  		order.out = append(order.out, n)
   642  
   643  	// Special: handle call arguments.
   644  	case OCALLFUNC, OCALLINTER, OCALLMETH:
   645  		t := marktemp(order)
   646  
   647  		ordercall(n, order)
   648  		order.out = append(order.out, n)
   649  		cleantemp(t, order)
   650  
   651  	// Special: order arguments to inner call but not call itself.
   652  	case ODEFER, OPROC:
   653  		t := marktemp(order)
   654  
   655  		switch n.Left.Op {
   656  		// Delete will take the address of the key.
   657  		// Copy key into new temp and do not clean it
   658  		// (it persists beyond the statement).
   659  		case ODELETE:
   660  			orderexprlist(n.Left.List, order)
   661  
   662  			t1 := marktemp(order)
   663  			np := n.Left.List.Addr(1) // map key
   664  			*np = ordercopyexpr(*np, (*np).Type, order, 0)
   665  			poptemp(t1, order)
   666  
   667  		default:
   668  			ordercall(n.Left, order)
   669  		}
   670  
   671  		order.out = append(order.out, n)
   672  		cleantemp(t, order)
   673  
   674  	case ODELETE:
   675  		t := marktemp(order)
   676  		n.List.SetIndex(0, orderexpr(n.List.Index(0), order, nil))
   677  		n.List.SetIndex(1, orderexpr(n.List.Index(1), order, nil))
   678  		n.List.SetIndex(1, orderaddrtemp(n.List.Index(1), order)) // map key
   679  		order.out = append(order.out, n)
   680  		cleantemp(t, order)
   681  
   682  	// Clean temporaries from condition evaluation at
   683  	// beginning of loop body and after for statement.
   684  	case OFOR:
   685  		t := marktemp(order)
   686  
   687  		n.Left = orderexprinplace(n.Left, order)
   688  		var l []*Node
   689  		cleantempnopop(t, order, &l)
   690  		n.Nbody.Prepend(l...)
   691  		orderblockNodes(&n.Nbody)
   692  		n.Right = orderstmtinplace(n.Right)
   693  		order.out = append(order.out, n)
   694  		cleantemp(t, order)
   695  
   696  	// Clean temporaries from condition at
   697  	// beginning of both branches.
   698  	case OIF:
   699  		t := marktemp(order)
   700  
   701  		n.Left = orderexprinplace(n.Left, order)
   702  		var l []*Node
   703  		cleantempnopop(t, order, &l)
   704  		n.Nbody.Prepend(l...)
   705  		l = nil
   706  		cleantempnopop(t, order, &l)
   707  		n.Rlist.Prepend(l...)
   708  		poptemp(t, order)
   709  		orderblockNodes(&n.Nbody)
   710  		n.Rlist.Set(orderblock(n.Rlist))
   711  		order.out = append(order.out, n)
   712  
   713  	// Special: argument will be converted to interface using convT2E
   714  	// so make sure it is an addressable temporary.
   715  	case OPANIC:
   716  		t := marktemp(order)
   717  
   718  		n.Left = orderexpr(n.Left, order, nil)
   719  		if !n.Left.Type.IsInterface() {
   720  			n.Left = orderaddrtemp(n.Left, order)
   721  		}
   722  		order.out = append(order.out, n)
   723  		cleantemp(t, order)
   724  
   725  	case ORANGE:
   726  		// n.Right is the expression being ranged over.
   727  		// order it, and then make a copy if we need one.
   728  		// We almost always do, to ensure that we don't
   729  		// see any value changes made during the loop.
   730  		// Usually the copy is cheap (e.g., array pointer,
   731  		// chan, slice, string are all tiny).
   732  		// The exception is ranging over an array value
   733  		// (not a slice, not a pointer to array),
   734  		// which must make a copy to avoid seeing updates made during
   735  		// the range body. Ranging over an array value is uncommon though.
   736  
   737  		// Mark []byte(str) range expression to reuse string backing storage.
   738  		// It is safe because the storage cannot be mutated.
   739  		if n.Right.Op == OSTRARRAYBYTE {
   740  			n.Right.Op = OSTRARRAYBYTETMP
   741  		}
   742  
   743  		t := marktemp(order)
   744  		n.Right = orderexpr(n.Right, order, nil)
   745  		switch n.Type.Etype {
   746  		default:
   747  			Fatalf("orderstmt range %v", n.Type)
   748  
   749  		case TARRAY, TSLICE:
   750  			if n.List.Len() < 2 || isblank(n.List.Second()) {
   751  				// for i := range x will only use x once, to compute len(x).
   752  				// No need to copy it.
   753  				break
   754  			}
   755  			fallthrough
   756  
   757  		case TCHAN, TSTRING:
   758  			// chan, string, slice, array ranges use value multiple times.
   759  			// make copy.
   760  			r := n.Right
   761  
   762  			if r.Type.IsString() && r.Type != Types[TSTRING] {
   763  				r = nod(OCONV, r, nil)
   764  				r.Type = Types[TSTRING]
   765  				r = typecheck(r, Erv)
   766  			}
   767  
   768  			n.Right = ordercopyexpr(r, r.Type, order, 0)
   769  
   770  		case TMAP:
   771  			// copy the map value in case it is a map literal.
   772  			// TODO(rsc): Make tmp = literal expressions reuse tmp.
   773  			// For maps tmp is just one word so it hardly matters.
   774  			r := n.Right
   775  			n.Right = ordercopyexpr(r, r.Type, order, 0)
   776  
   777  			// n->alloc is the temp for the iterator.
   778  			prealloc[n] = ordertemp(Types[TUINT8], order, true)
   779  		}
   780  		for i := range n.List.Slice() {
   781  			n.List.SetIndex(i, orderexprinplace(n.List.Index(i), order))
   782  		}
   783  		orderblockNodes(&n.Nbody)
   784  		order.out = append(order.out, n)
   785  		cleantemp(t, order)
   786  
   787  	case ORETURN:
   788  		ordercallargs(&n.List, order)
   789  		order.out = append(order.out, n)
   790  
   791  	// Special: clean case temporaries in each block entry.
   792  	// Select must enter one of its blocks, so there is no
   793  	// need for a cleaning at the end.
   794  	// Doubly special: evaluation order for select is stricter
   795  	// than ordinary expressions. Even something like p.c
   796  	// has to be hoisted into a temporary, so that it cannot be
   797  	// reordered after the channel evaluation for a different
   798  	// case (if p were nil, then the timing of the fault would
   799  	// give this away).
   800  	case OSELECT:
   801  		t := marktemp(order)
   802  
   803  		var tmp1 *Node
   804  		var tmp2 *Node
   805  		var r *Node
   806  		for _, n2 := range n.List.Slice() {
   807  			if n2.Op != OXCASE {
   808  				Fatalf("order select case %v", n2.Op)
   809  			}
   810  			r = n2.Left
   811  			setlineno(n2)
   812  
   813  			// Append any new body prologue to ninit.
   814  			// The next loop will insert ninit into nbody.
   815  			if n2.Ninit.Len() != 0 {
   816  				Fatalf("order select ninit")
   817  			}
   818  			if r != nil {
   819  				switch r.Op {
   820  				default:
   821  					yyerror("unknown op in select %v", r.Op)
   822  					Dump("select case", r)
   823  
   824  				// If this is case x := <-ch or case x, y := <-ch, the case has
   825  				// the ODCL nodes to declare x and y. We want to delay that
   826  				// declaration (and possible allocation) until inside the case body.
   827  				// Delete the ODCL nodes here and recreate them inside the body below.
   828  				case OSELRECV, OSELRECV2:
   829  					if r.Colas {
   830  						i := 0
   831  						if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
   832  							i++
   833  						}
   834  						if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
   835  							i++
   836  						}
   837  						if i >= r.Ninit.Len() {
   838  							r.Ninit.Set(nil)
   839  						}
   840  					}
   841  
   842  					if r.Ninit.Len() != 0 {
   843  						yyerror("ninit on select recv")
   844  						dumplist("ninit", r.Ninit)
   845  					}
   846  
   847  					// case x = <-c
   848  					// case x, ok = <-c
   849  					// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
   850  					// r->left == N means 'case <-c'.
   851  					// c is always evaluated; x and ok are only evaluated when assigned.
   852  					r.Right.Left = orderexpr(r.Right.Left, order, nil)
   853  
   854  					if r.Right.Left.Op != ONAME {
   855  						r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
   856  					}
   857  
   858  					// Introduce temporary for receive and move actual copy into case body.
   859  					// avoids problems with target being addressed, as usual.
   860  					// NOTE: If we wanted to be clever, we could arrange for just one
   861  					// temporary per distinct type, sharing the temp among all receives
   862  					// with that temp. Similarly one ok bool could be shared among all
   863  					// the x,ok receives. Not worth doing until there's a clear need.
   864  					if r.Left != nil && isblank(r.Left) {
   865  						r.Left = nil
   866  					}
   867  					if r.Left != nil {
   868  						// use channel element type for temporary to avoid conversions,
   869  						// such as in case interfacevalue = <-intchan.
   870  						// the conversion happens in the OAS instead.
   871  						tmp1 = r.Left
   872  
   873  						if r.Colas {
   874  							tmp2 = nod(ODCL, tmp1, nil)
   875  							tmp2 = typecheck(tmp2, Etop)
   876  							n2.Ninit.Append(tmp2)
   877  						}
   878  
   879  						r.Left = ordertemp(r.Right.Left.Type.Elem(), order, haspointers(r.Right.Left.Type.Elem()))
   880  						tmp2 = nod(OAS, tmp1, r.Left)
   881  						tmp2 = typecheck(tmp2, Etop)
   882  						n2.Ninit.Append(tmp2)
   883  					}
   884  
   885  					if r.List.Len() != 0 && isblank(r.List.First()) {
   886  						r.List.Set(nil)
   887  					}
   888  					if r.List.Len() != 0 {
   889  						tmp1 = r.List.First()
   890  						if r.Colas {
   891  							tmp2 = nod(ODCL, tmp1, nil)
   892  							tmp2 = typecheck(tmp2, Etop)
   893  							n2.Ninit.Append(tmp2)
   894  						}
   895  
   896  						r.List.Set1(ordertemp(Types[TBOOL], order, false))
   897  						tmp2 = okas(tmp1, r.List.First())
   898  						tmp2 = typecheck(tmp2, Etop)
   899  						n2.Ninit.Append(tmp2)
   900  					}
   901  					n2.Ninit.Set(orderblock(n2.Ninit))
   902  
   903  				case OSEND:
   904  					if r.Ninit.Len() != 0 {
   905  						yyerror("ninit on select send")
   906  						dumplist("ninit", r.Ninit)
   907  					}
   908  
   909  					// case c <- x
   910  					// r->left is c, r->right is x, both are always evaluated.
   911  					r.Left = orderexpr(r.Left, order, nil)
   912  
   913  					if !r.Left.IsAutoTmp() {
   914  						r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
   915  					}
   916  					r.Right = orderexpr(r.Right, order, nil)
   917  					if !r.Right.IsAutoTmp() {
   918  						r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
   919  					}
   920  				}
   921  			}
   922  
   923  			orderblockNodes(&n2.Nbody)
   924  		}
   925  		// Now that we have accumulated all the temporaries, clean them.
   926  		// Also insert any ninit queued during the previous loop.
   927  		// (The temporary cleaning must follow that ninit work.)
   928  		for _, n3 := range n.List.Slice() {
   929  			s := n3.Ninit.Slice()
   930  			cleantempnopop(t, order, &s)
   931  			n3.Nbody.Prepend(s...)
   932  			n3.Ninit.Set(nil)
   933  		}
   934  
   935  		order.out = append(order.out, n)
   936  		poptemp(t, order)
   937  
   938  	// Special: value being sent is passed as a pointer; make it addressable.
   939  	case OSEND:
   940  		t := marktemp(order)
   941  
   942  		n.Left = orderexpr(n.Left, order, nil)
   943  		n.Right = orderexpr(n.Right, order, nil)
   944  		n.Right = orderaddrtemp(n.Right, order)
   945  		order.out = append(order.out, n)
   946  		cleantemp(t, order)
   947  
   948  	// TODO(rsc): Clean temporaries more aggressively.
   949  	// Note that because walkswitch will rewrite some of the
   950  	// switch into a binary search, this is not as easy as it looks.
   951  	// (If we ran that code here we could invoke orderstmt on
   952  	// the if-else chain instead.)
   953  	// For now just clean all the temporaries at the end.
   954  	// In practice that's fine.
   955  	case OSWITCH:
   956  		t := marktemp(order)
   957  
   958  		n.Left = orderexpr(n.Left, order, nil)
   959  		for _, n4 := range n.List.Slice() {
   960  			if n4.Op != OXCASE {
   961  				Fatalf("order switch case %v", n4.Op)
   962  			}
   963  			orderexprlistinplace(n4.List, order)
   964  			orderblockNodes(&n4.Nbody)
   965  		}
   966  
   967  		order.out = append(order.out, n)
   968  		cleantemp(t, order)
   969  	}
   970  
   971  	lineno = lno
   972  }
   973  
   974  // Orderexprlist orders the expression list l into order.
   975  func orderexprlist(l Nodes, order *Order) {
   976  	s := l.Slice()
   977  	for i := range s {
   978  		s[i] = orderexpr(s[i], order, nil)
   979  	}
   980  }
   981  
   982  // Orderexprlist orders the expression list l but saves
   983  // the side effects on the individual expression ninit lists.
   984  func orderexprlistinplace(l Nodes, order *Order) {
   985  	s := l.Slice()
   986  	for i := range s {
   987  		s[i] = orderexprinplace(s[i], order)
   988  	}
   989  }
   990  
   991  // prealloc[x] records the allocation to use for x.
   992  var prealloc = map[*Node]*Node{}
   993  
   994  // Orderexpr orders a single expression, appending side
   995  // effects to order->out as needed.
   996  // If this is part of an assignment lhs = *np, lhs is given.
   997  // Otherwise lhs == nil. (When lhs != nil it may be possible
   998  // to avoid copying the result of the expression to a temporary.)
   999  // The result of orderexpr MUST be assigned back to n, e.g.
  1000  // 	n.Left = orderexpr(n.Left, order, lhs)
  1001  func orderexpr(n *Node, order *Order, lhs *Node) *Node {
  1002  	if n == nil {
  1003  		return n
  1004  	}
  1005  
  1006  	lno := setlineno(n)
  1007  	orderinit(n, order)
  1008  
  1009  	switch n.Op {
  1010  	default:
  1011  		n.Left = orderexpr(n.Left, order, nil)
  1012  		n.Right = orderexpr(n.Right, order, nil)
  1013  		orderexprlist(n.List, order)
  1014  		orderexprlist(n.Rlist, order)
  1015  
  1016  	// Addition of strings turns into a function call.
  1017  	// Allocate a temporary to hold the strings.
  1018  	// Fewer than 5 strings use direct runtime helpers.
  1019  	case OADDSTR:
  1020  		orderexprlist(n.List, order)
  1021  
  1022  		if n.List.Len() > 5 {
  1023  			t := typArray(Types[TSTRING], int64(n.List.Len()))
  1024  			prealloc[n] = ordertemp(t, order, false)
  1025  		}
  1026  
  1027  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1028  		// buffer during conversion. String concatenation does not
  1029  		// memorize the strings for later use, so it is safe.
  1030  		// However, we can do it only if there is at least one non-empty string literal.
  1031  		// Otherwise if all other arguments are empty strings,
  1032  		// concatstrings will return the reference to the temp string
  1033  		// to the caller.
  1034  		hasbyte := false
  1035  
  1036  		haslit := false
  1037  		for _, n1 := range n.List.Slice() {
  1038  			hasbyte = hasbyte || n1.Op == OARRAYBYTESTR
  1039  			haslit = haslit || n1.Op == OLITERAL && len(n1.Val().U.(string)) != 0
  1040  		}
  1041  
  1042  		if haslit && hasbyte {
  1043  			for _, n2 := range n.List.Slice() {
  1044  				if n2.Op == OARRAYBYTESTR {
  1045  					n2.Op = OARRAYBYTESTRTMP
  1046  				}
  1047  			}
  1048  		}
  1049  
  1050  	case OCMPSTR:
  1051  		n.Left = orderexpr(n.Left, order, nil)
  1052  		n.Right = orderexpr(n.Right, order, nil)
  1053  
  1054  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1055  		// buffer during conversion. String comparison does not
  1056  		// memorize the strings for later use, so it is safe.
  1057  		if n.Left.Op == OARRAYBYTESTR {
  1058  			n.Left.Op = OARRAYBYTESTRTMP
  1059  		}
  1060  		if n.Right.Op == OARRAYBYTESTR {
  1061  			n.Right.Op = OARRAYBYTESTRTMP
  1062  		}
  1063  
  1064  		// key must be addressable
  1065  	case OINDEXMAP:
  1066  		n.Left = orderexpr(n.Left, order, nil)
  1067  		n.Right = orderexpr(n.Right, order, nil)
  1068  		needCopy := false
  1069  
  1070  		if n.Etype == 0 && instrumenting {
  1071  			// Race detector needs the copy so it can
  1072  			// call treecopy on the result.
  1073  			needCopy = true
  1074  		}
  1075  
  1076  		// For x = m[string(k)] where k is []byte, the allocation of
  1077  		// backing bytes for the string can be avoided by reusing
  1078  		// the []byte backing array. This is a special case that it
  1079  		// would be nice to handle more generally, but because
  1080  		// there are no []byte-keyed maps, this specific case comes
  1081  		// up in important cases in practice. See issue 3512.
  1082  		// Nothing can change the []byte we are not copying before
  1083  		// the map index, because the map access is going to
  1084  		// be forced to happen immediately following this
  1085  		// conversion (by the ordercopyexpr a few lines below).
  1086  		if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
  1087  			n.Right.Op = OARRAYBYTESTRTMP
  1088  			needCopy = true
  1089  		}
  1090  
  1091  		// Map calls need to take the address of the key.
  1092  		n.Right = orderaddrtemp(n.Right, order)
  1093  
  1094  		if needCopy {
  1095  			n = ordercopyexpr(n, n.Type, order, 0)
  1096  		}
  1097  
  1098  	// concrete type (not interface) argument must be addressable
  1099  	// temporary to pass to runtime.
  1100  	case OCONVIFACE:
  1101  		n.Left = orderexpr(n.Left, order, nil)
  1102  
  1103  		if !n.Left.Type.IsInterface() {
  1104  			n.Left = orderaddrtemp(n.Left, order)
  1105  		}
  1106  
  1107  	case OCONVNOP:
  1108  		if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) {
  1109  			// When reordering unsafe.Pointer(f()) into a separate
  1110  			// statement, the conversion and function call must stay
  1111  			// together. See golang.org/issue/15329.
  1112  			orderinit(n.Left, order)
  1113  			ordercall(n.Left, order)
  1114  			if lhs == nil || lhs.Op != ONAME || instrumenting {
  1115  				n = ordercopyexpr(n, n.Type, order, 0)
  1116  			}
  1117  		} else {
  1118  			n.Left = orderexpr(n.Left, order, nil)
  1119  		}
  1120  
  1121  	case OANDAND, OOROR:
  1122  		mark := marktemp(order)
  1123  		n.Left = orderexpr(n.Left, order, nil)
  1124  
  1125  		// Clean temporaries from first branch at beginning of second.
  1126  		// Leave them on the stack so that they can be killed in the outer
  1127  		// context in case the short circuit is taken.
  1128  		var s []*Node
  1129  
  1130  		cleantempnopop(mark, order, &s)
  1131  		n.Right.Ninit.Prepend(s...)
  1132  		n.Right = orderexprinplace(n.Right, order)
  1133  
  1134  	case OCALLFUNC,
  1135  		OCALLINTER,
  1136  		OCALLMETH,
  1137  		OCAP,
  1138  		OCOMPLEX,
  1139  		OCOPY,
  1140  		OIMAG,
  1141  		OLEN,
  1142  		OMAKECHAN,
  1143  		OMAKEMAP,
  1144  		OMAKESLICE,
  1145  		ONEW,
  1146  		OREAL,
  1147  		ORECOVER,
  1148  		OSTRARRAYBYTE,
  1149  		OSTRARRAYBYTETMP,
  1150  		OSTRARRAYRUNE:
  1151  		ordercall(n, order)
  1152  		if lhs == nil || lhs.Op != ONAME || instrumenting {
  1153  			n = ordercopyexpr(n, n.Type, order, 0)
  1154  		}
  1155  
  1156  	case OAPPEND:
  1157  		ordercallargs(&n.List, order)
  1158  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) {
  1159  			n = ordercopyexpr(n, n.Type, order, 0)
  1160  		}
  1161  
  1162  	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
  1163  		n.Left = orderexpr(n.Left, order, nil)
  1164  		low, high, max := n.SliceBounds()
  1165  		low = orderexpr(low, order, nil)
  1166  		low = ordercheapexpr(low, order)
  1167  		high = orderexpr(high, order, nil)
  1168  		high = ordercheapexpr(high, order)
  1169  		max = orderexpr(max, order, nil)
  1170  		max = ordercheapexpr(max, order)
  1171  		n.SetSliceBounds(low, high, max)
  1172  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
  1173  			n = ordercopyexpr(n, n.Type, order, 0)
  1174  		}
  1175  
  1176  	case OCLOSURE:
  1177  		if n.Noescape && n.Func.Cvars.Len() > 0 {
  1178  			prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
  1179  		}
  1180  
  1181  	case OARRAYLIT, OSLICELIT, OCALLPART:
  1182  		n.Left = orderexpr(n.Left, order, nil)
  1183  		n.Right = orderexpr(n.Right, order, nil)
  1184  		orderexprlist(n.List, order)
  1185  		orderexprlist(n.Rlist, order)
  1186  		if n.Noescape {
  1187  			prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
  1188  		}
  1189  
  1190  	case ODDDARG:
  1191  		if n.Noescape {
  1192  			// The ddd argument does not live beyond the call it is created for.
  1193  			// Allocate a temporary that will be cleaned up when this statement
  1194  			// completes. We could be more aggressive and try to arrange for it
  1195  			// to be cleaned up when the call completes.
  1196  			prealloc[n] = ordertemp(n.Type.Elem(), order, false)
  1197  		}
  1198  
  1199  	case ODOTTYPE, ODOTTYPE2:
  1200  		n.Left = orderexpr(n.Left, order, nil)
  1201  		// TODO(rsc): The isfat is for consistency with componentgen and walkexpr.
  1202  		// It needs to be removed in all three places.
  1203  		// That would allow inlining x.(struct{*int}) the same as x.(*int).
  1204  		if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting {
  1205  			n = ordercopyexpr(n, n.Type, order, 1)
  1206  		}
  1207  
  1208  	case ORECV:
  1209  		n.Left = orderexpr(n.Left, order, nil)
  1210  		n = ordercopyexpr(n, n.Type, order, 1)
  1211  
  1212  	case OEQ, ONE:
  1213  		n.Left = orderexpr(n.Left, order, nil)
  1214  		n.Right = orderexpr(n.Right, order, nil)
  1215  		t := n.Left.Type
  1216  		if t.IsStruct() || t.IsArray() {
  1217  			// for complex comparisons, we need both args to be
  1218  			// addressable so we can pass them to the runtime.
  1219  			n.Left = orderaddrtemp(n.Left, order)
  1220  			n.Right = orderaddrtemp(n.Right, order)
  1221  		}
  1222  	}
  1223  
  1224  	lineno = lno
  1225  	return n
  1226  }
  1227  
  1228  // okas creates and returns an assignment of val to ok,
  1229  // including an explicit conversion if necessary.
  1230  func okas(ok, val *Node) *Node {
  1231  	if !isblank(ok) {
  1232  		val = conv(val, ok.Type)
  1233  	}
  1234  	return nod(OAS, ok, val)
  1235  }