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