github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/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 bool) *Node {
    88  	var_ := ordertemp(t, order, clear)
    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, false)
   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, false)
   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 VARKILL and if needed VARLIVE instructions
   235  // to *out for each temporary above the mark on the temporary stack.
   236  // It does not pop the temporaries 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  			live := nod(OVARLIVE, n, nil)
   244  			live = typecheck(live, Etop)
   245  			*out = append(*out, live)
   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.IsUnsafePtr() {
   399  				xp = &(*xp).Left
   400  			}
   401  			x := *xp
   402  			if x.Type.IsUnsafePtr() {
   403  				x = ordercopyexpr(x, x.Type, order, false)
   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], ... = ..., x, ..., 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  		if n.Left.Op == OINDEXMAP {
   448  			// Make sure we evaluate the RHS before starting the map insert.
   449  			// We need to make sure the RHS won't panic.  See issue 22881.
   450  			n.Right = ordercheapexpr(n.Right, order)
   451  		}
   452  		order.out = append(order.out, n)
   453  
   454  	case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
   455  		var post []*Node
   456  		for i, m := range n.List.Slice() {
   457  			switch {
   458  			case m.Op == OINDEXMAP:
   459  				if !m.Left.IsAutoTmp() {
   460  					m.Left = ordercopyexpr(m.Left, m.Left.Type, order, false)
   461  				}
   462  				if !m.Right.IsAutoTmp() {
   463  					m.Right = ordercopyexpr(m.Right, m.Right.Type, order, false)
   464  				}
   465  				fallthrough
   466  			case instrumenting && n.Op == OAS2FUNC && !isblank(m):
   467  				t := ordertemp(m.Type, order, false)
   468  				n.List.SetIndex(i, t)
   469  				a := nod(OAS, m, t)
   470  				a = typecheck(a, Etop)
   471  				post = append(post, a)
   472  			}
   473  		}
   474  
   475  		order.out = append(order.out, n)
   476  		order.out = append(order.out, post...)
   477  	}
   478  }
   479  
   480  // Orderstmt orders the statement n, appending to order->out.
   481  // Temporaries created during the statement are cleaned
   482  // up using VARKILL instructions as possible.
   483  func orderstmt(n *Node, order *Order) {
   484  	if n == nil {
   485  		return
   486  	}
   487  
   488  	lno := setlineno(n)
   489  
   490  	orderinit(n, order)
   491  
   492  	switch n.Op {
   493  	default:
   494  		Fatalf("orderstmt %v", n.Op)
   495  
   496  	case OVARKILL, OVARLIVE:
   497  		order.out = append(order.out, n)
   498  
   499  	case OAS:
   500  		t := marktemp(order)
   501  		n.Left = orderexpr(n.Left, order, nil)
   502  		n.Right = orderexpr(n.Right, order, n.Left)
   503  		ordermapassign(n, order)
   504  		cleantemp(t, order)
   505  
   506  	case OAS2,
   507  		OCLOSE,
   508  		OCOPY,
   509  		OPRINT,
   510  		OPRINTN,
   511  		ORECOVER,
   512  		ORECV:
   513  		t := marktemp(order)
   514  		n.Left = orderexpr(n.Left, order, nil)
   515  		n.Right = orderexpr(n.Right, order, nil)
   516  		orderexprlist(n.List, order)
   517  		orderexprlist(n.Rlist, order)
   518  		switch n.Op {
   519  		case OAS2:
   520  			ordermapassign(n, order)
   521  		default:
   522  			order.out = append(order.out, n)
   523  		}
   524  		cleantemp(t, order)
   525  
   526  	case OASOP:
   527  		// Special: rewrite l op= r into l = l op r.
   528  		// This simplifies quite a few operations;
   529  		// most important is that it lets us separate
   530  		// out map read from map write when l is
   531  		// a map index expression.
   532  		t := marktemp(order)
   533  		n.Left = orderexpr(n.Left, order, nil)
   534  		n.Right = orderexpr(n.Right, order, nil)
   535  
   536  		n.Left = ordersafeexpr(n.Left, order)
   537  		tmp1 := treecopy(n.Left, src.NoXPos)
   538  		if tmp1.Op == OINDEXMAP {
   539  			tmp1.Etype = 0 // now an rvalue not an lvalue
   540  		}
   541  		tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, false)
   542  		// TODO(marvin): Fix Node.EType type union.
   543  		n.Right = nod(Op(n.Etype), tmp1, n.Right)
   544  		n.Right = typecheck(n.Right, Erv)
   545  		n.Right = orderexpr(n.Right, order, nil)
   546  		n.Etype = 0
   547  		n.Op = OAS
   548  		ordermapassign(n, order)
   549  		cleantemp(t, order)
   550  
   551  	// Special: make sure key is addressable if needed,
   552  	// and make sure OINDEXMAP is not copied out.
   553  	case OAS2MAPR:
   554  		t := marktemp(order)
   555  
   556  		orderexprlist(n.List, order)
   557  		r := n.Rlist.First()
   558  		r.Left = orderexpr(r.Left, order, nil)
   559  		r.Right = orderexpr(r.Right, order, nil)
   560  
   561  		// See case OINDEXMAP below.
   562  		if r.Right.Op == OARRAYBYTESTR {
   563  			r.Right.Op = OARRAYBYTESTRTMP
   564  		}
   565  		r.Right = ordermapkeytemp(r.Left.Type, r.Right, order)
   566  		orderokas2(n, order)
   567  		cleantemp(t, order)
   568  
   569  	// Special: avoid copy of func call n->rlist->n.
   570  	case OAS2FUNC:
   571  		t := marktemp(order)
   572  
   573  		orderexprlist(n.List, order)
   574  		ordercall(n.Rlist.First(), order)
   575  		orderas2(n, order)
   576  		cleantemp(t, order)
   577  
   578  	// Special: use temporary variables to hold result,
   579  	// so that assertI2Tetc can take address of temporary.
   580  	// No temporary for blank assignment.
   581  	case OAS2DOTTYPE:
   582  		t := marktemp(order)
   583  
   584  		orderexprlist(n.List, order)
   585  		n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
   586  		orderokas2(n, order)
   587  		cleantemp(t, order)
   588  
   589  	// Special: use temporary variables to hold result,
   590  	// so that chanrecv can take address of temporary.
   591  	case OAS2RECV:
   592  		t := marktemp(order)
   593  
   594  		orderexprlist(n.List, order)
   595  		n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
   596  		ch := n.Rlist.First().Left.Type
   597  		tmp1 := ordertemp(ch.Elem(), order, types.Haspointers(ch.Elem()))
   598  		tmp2 := ordertemp(types.Types[TBOOL], order, false)
   599  		order.out = append(order.out, n)
   600  		r := nod(OAS, n.List.First(), tmp1)
   601  		r = typecheck(r, Etop)
   602  		ordermapassign(r, order)
   603  		r = okas(n.List.Second(), tmp2)
   604  		r = typecheck(r, Etop)
   605  		ordermapassign(r, order)
   606  		n.List.Set2(tmp1, tmp2)
   607  		cleantemp(t, order)
   608  
   609  	// Special: does not save n onto out.
   610  	case OBLOCK, OEMPTY:
   611  		orderstmtlist(n.List, order)
   612  
   613  	// Special: n->left is not an expression; save as is.
   614  	case OBREAK,
   615  		OCONTINUE,
   616  		ODCL,
   617  		ODCLCONST,
   618  		ODCLTYPE,
   619  		OFALL,
   620  		OGOTO,
   621  		OLABEL,
   622  		ORETJMP:
   623  		order.out = append(order.out, n)
   624  
   625  	// Special: handle call arguments.
   626  	case OCALLFUNC, OCALLINTER, OCALLMETH:
   627  		t := marktemp(order)
   628  
   629  		ordercall(n, order)
   630  		order.out = append(order.out, n)
   631  		cleantemp(t, order)
   632  
   633  	// Special: order arguments to inner call but not call itself.
   634  	case ODEFER, OPROC:
   635  		t := marktemp(order)
   636  
   637  		switch n.Left.Op {
   638  		// Delete will take the address of the key.
   639  		// Copy key into new temp and do not clean it
   640  		// (it persists beyond the statement).
   641  		case ODELETE:
   642  			orderexprlist(n.Left.List, order)
   643  
   644  			if mapfast(n.Left.List.First().Type) == mapslow {
   645  				t1 := marktemp(order)
   646  				np := n.Left.List.Addr(1) // map key
   647  				*np = ordercopyexpr(*np, (*np).Type, order, false)
   648  				poptemp(t1, order)
   649  			}
   650  
   651  		default:
   652  			ordercall(n.Left, order)
   653  		}
   654  
   655  		order.out = append(order.out, n)
   656  		cleantemp(t, order)
   657  
   658  	case ODELETE:
   659  		t := marktemp(order)
   660  		n.List.SetFirst(orderexpr(n.List.First(), order, nil))
   661  		n.List.SetSecond(orderexpr(n.List.Second(), order, nil))
   662  		n.List.SetSecond(ordermapkeytemp(n.List.First().Type, n.List.Second(), order))
   663  		order.out = append(order.out, n)
   664  		cleantemp(t, order)
   665  
   666  	// Clean temporaries from condition evaluation at
   667  	// beginning of loop body and after for statement.
   668  	case OFOR:
   669  		t := marktemp(order)
   670  
   671  		n.Left = orderexprinplace(n.Left, order)
   672  		var l []*Node
   673  		cleantempnopop(t, order, &l)
   674  		n.Nbody.Prepend(l...)
   675  		orderblockNodes(&n.Nbody)
   676  		n.Right = orderstmtinplace(n.Right)
   677  		order.out = append(order.out, n)
   678  		cleantemp(t, order)
   679  
   680  	// Clean temporaries from condition at
   681  	// beginning of both branches.
   682  	case OIF:
   683  		t := marktemp(order)
   684  
   685  		n.Left = orderexprinplace(n.Left, order)
   686  		var l []*Node
   687  		cleantempnopop(t, order, &l)
   688  		n.Nbody.Prepend(l...)
   689  		l = nil
   690  		cleantempnopop(t, order, &l)
   691  		n.Rlist.Prepend(l...)
   692  		poptemp(t, order)
   693  		orderblockNodes(&n.Nbody)
   694  		n.Rlist.Set(orderblock(n.Rlist))
   695  		order.out = append(order.out, n)
   696  
   697  	// Special: argument will be converted to interface using convT2E
   698  	// so make sure it is an addressable temporary.
   699  	case OPANIC:
   700  		t := marktemp(order)
   701  
   702  		n.Left = orderexpr(n.Left, order, nil)
   703  		if !n.Left.Type.IsInterface() {
   704  			n.Left = orderaddrtemp(n.Left, order)
   705  		}
   706  		order.out = append(order.out, n)
   707  		cleantemp(t, order)
   708  
   709  	case ORANGE:
   710  		// n.Right is the expression being ranged over.
   711  		// order it, and then make a copy if we need one.
   712  		// We almost always do, to ensure that we don't
   713  		// see any value changes made during the loop.
   714  		// Usually the copy is cheap (e.g., array pointer,
   715  		// chan, slice, string are all tiny).
   716  		// The exception is ranging over an array value
   717  		// (not a slice, not a pointer to array),
   718  		// which must make a copy to avoid seeing updates made during
   719  		// the range body. Ranging over an array value is uncommon though.
   720  
   721  		// Mark []byte(str) range expression to reuse string backing storage.
   722  		// It is safe because the storage cannot be mutated.
   723  		if n.Right.Op == OSTRARRAYBYTE {
   724  			n.Right.Op = OSTRARRAYBYTETMP
   725  		}
   726  
   727  		t := marktemp(order)
   728  		n.Right = orderexpr(n.Right, order, nil)
   729  		switch n.Type.Etype {
   730  		default:
   731  			Fatalf("orderstmt range %v", n.Type)
   732  
   733  		case TARRAY, TSLICE:
   734  			if n.List.Len() < 2 || isblank(n.List.Second()) {
   735  				// for i := range x will only use x once, to compute len(x).
   736  				// No need to copy it.
   737  				break
   738  			}
   739  			fallthrough
   740  
   741  		case TCHAN, TSTRING:
   742  			// chan, string, slice, array ranges use value multiple times.
   743  			// make copy.
   744  			r := n.Right
   745  
   746  			if r.Type.IsString() && r.Type != types.Types[TSTRING] {
   747  				r = nod(OCONV, r, nil)
   748  				r.Type = types.Types[TSTRING]
   749  				r = typecheck(r, Erv)
   750  			}
   751  
   752  			n.Right = ordercopyexpr(r, r.Type, order, false)
   753  
   754  		case TMAP:
   755  			// copy the map value in case it is a map literal.
   756  			// TODO(rsc): Make tmp = literal expressions reuse tmp.
   757  			// For maps tmp is just one word so it hardly matters.
   758  			r := n.Right
   759  			n.Right = ordercopyexpr(r, r.Type, order, false)
   760  
   761  			// prealloc[n] is the temp for the iterator.
   762  			// hiter contains pointers and needs to be zeroed.
   763  			prealloc[n] = ordertemp(hiter(n.Type), order, true)
   764  		}
   765  		orderexprlistinplace(n.List, order)
   766  		orderblockNodes(&n.Nbody)
   767  		order.out = append(order.out, n)
   768  		cleantemp(t, order)
   769  
   770  	case ORETURN:
   771  		ordercallargs(&n.List, order)
   772  		order.out = append(order.out, n)
   773  
   774  	// Special: clean case temporaries in each block entry.
   775  	// Select must enter one of its blocks, so there is no
   776  	// need for a cleaning at the end.
   777  	// Doubly special: evaluation order for select is stricter
   778  	// than ordinary expressions. Even something like p.c
   779  	// has to be hoisted into a temporary, so that it cannot be
   780  	// reordered after the channel evaluation for a different
   781  	// case (if p were nil, then the timing of the fault would
   782  	// give this away).
   783  	case OSELECT:
   784  		t := marktemp(order)
   785  
   786  		for _, n2 := range n.List.Slice() {
   787  			if n2.Op != OXCASE {
   788  				Fatalf("order select case %v", n2.Op)
   789  			}
   790  			r := n2.Left
   791  			setlineno(n2)
   792  
   793  			// Append any new body prologue to ninit.
   794  			// The next loop will insert ninit into nbody.
   795  			if n2.Ninit.Len() != 0 {
   796  				Fatalf("order select ninit")
   797  			}
   798  			if r != nil {
   799  				switch r.Op {
   800  				default:
   801  					Dump("select case", r)
   802  					Fatalf("unknown op in select %v", r.Op)
   803  
   804  				// If this is case x := <-ch or case x, y := <-ch, the case has
   805  				// the ODCL nodes to declare x and y. We want to delay that
   806  				// declaration (and possible allocation) until inside the case body.
   807  				// Delete the ODCL nodes here and recreate them inside the body below.
   808  				case OSELRECV, OSELRECV2:
   809  					if r.Colas() {
   810  						i := 0
   811  						if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
   812  							i++
   813  						}
   814  						if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
   815  							i++
   816  						}
   817  						if i >= r.Ninit.Len() {
   818  							r.Ninit.Set(nil)
   819  						}
   820  					}
   821  
   822  					if r.Ninit.Len() != 0 {
   823  						dumplist("ninit", r.Ninit)
   824  						Fatalf("ninit on select recv")
   825  					}
   826  
   827  					// case x = <-c
   828  					// case x, ok = <-c
   829  					// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
   830  					// r->left == N means 'case <-c'.
   831  					// c is always evaluated; x and ok are only evaluated when assigned.
   832  					r.Right.Left = orderexpr(r.Right.Left, order, nil)
   833  
   834  					if r.Right.Left.Op != ONAME {
   835  						r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, false)
   836  					}
   837  
   838  					// Introduce temporary for receive and move actual copy into case body.
   839  					// avoids problems with target being addressed, as usual.
   840  					// NOTE: If we wanted to be clever, we could arrange for just one
   841  					// temporary per distinct type, sharing the temp among all receives
   842  					// with that temp. Similarly one ok bool could be shared among all
   843  					// the x,ok receives. Not worth doing until there's a clear need.
   844  					if r.Left != nil && isblank(r.Left) {
   845  						r.Left = nil
   846  					}
   847  					if r.Left != nil {
   848  						// use channel element type for temporary to avoid conversions,
   849  						// such as in case interfacevalue = <-intchan.
   850  						// the conversion happens in the OAS instead.
   851  						tmp1 := r.Left
   852  
   853  						if r.Colas() {
   854  							tmp2 := nod(ODCL, tmp1, nil)
   855  							tmp2 = typecheck(tmp2, Etop)
   856  							n2.Ninit.Append(tmp2)
   857  						}
   858  
   859  						r.Left = ordertemp(r.Right.Left.Type.Elem(), order, types.Haspointers(r.Right.Left.Type.Elem()))
   860  						tmp2 := nod(OAS, tmp1, r.Left)
   861  						tmp2 = typecheck(tmp2, Etop)
   862  						n2.Ninit.Append(tmp2)
   863  					}
   864  
   865  					if r.List.Len() != 0 && isblank(r.List.First()) {
   866  						r.List.Set(nil)
   867  					}
   868  					if r.List.Len() != 0 {
   869  						tmp1 := r.List.First()
   870  						if r.Colas() {
   871  							tmp2 := nod(ODCL, tmp1, nil)
   872  							tmp2 = typecheck(tmp2, Etop)
   873  							n2.Ninit.Append(tmp2)
   874  						}
   875  
   876  						r.List.Set1(ordertemp(types.Types[TBOOL], order, false))
   877  						tmp2 := okas(tmp1, r.List.First())
   878  						tmp2 = typecheck(tmp2, Etop)
   879  						n2.Ninit.Append(tmp2)
   880  					}
   881  					n2.Ninit.Set(orderblock(n2.Ninit))
   882  
   883  				case OSEND:
   884  					if r.Ninit.Len() != 0 {
   885  						dumplist("ninit", r.Ninit)
   886  						Fatalf("ninit on select send")
   887  					}
   888  
   889  					// case c <- x
   890  					// r->left is c, r->right is x, both are always evaluated.
   891  					r.Left = orderexpr(r.Left, order, nil)
   892  
   893  					if !r.Left.IsAutoTmp() {
   894  						r.Left = ordercopyexpr(r.Left, r.Left.Type, order, false)
   895  					}
   896  					r.Right = orderexpr(r.Right, order, nil)
   897  					if !r.Right.IsAutoTmp() {
   898  						r.Right = ordercopyexpr(r.Right, r.Right.Type, order, false)
   899  					}
   900  				}
   901  			}
   902  
   903  			orderblockNodes(&n2.Nbody)
   904  		}
   905  		// Now that we have accumulated all the temporaries, clean them.
   906  		// Also insert any ninit queued during the previous loop.
   907  		// (The temporary cleaning must follow that ninit work.)
   908  		for _, n3 := range n.List.Slice() {
   909  			s := n3.Ninit.Slice()
   910  			cleantempnopop(t, order, &s)
   911  			n3.Nbody.Prepend(s...)
   912  			n3.Ninit.Set(nil)
   913  		}
   914  
   915  		order.out = append(order.out, n)
   916  		poptemp(t, order)
   917  
   918  	// Special: value being sent is passed as a pointer; make it addressable.
   919  	case OSEND:
   920  		t := marktemp(order)
   921  
   922  		n.Left = orderexpr(n.Left, order, nil)
   923  		n.Right = orderexpr(n.Right, order, nil)
   924  		if instrumenting {
   925  			// Force copying to the stack so that (chan T)(nil) <- x
   926  			// is still instrumented as a read of x.
   927  			n.Right = ordercopyexpr(n.Right, n.Right.Type, order, false)
   928  		} else {
   929  			n.Right = orderaddrtemp(n.Right, order)
   930  		}
   931  		order.out = append(order.out, n)
   932  		cleantemp(t, order)
   933  
   934  	// TODO(rsc): Clean temporaries more aggressively.
   935  	// Note that because walkswitch will rewrite some of the
   936  	// switch into a binary search, this is not as easy as it looks.
   937  	// (If we ran that code here we could invoke orderstmt on
   938  	// the if-else chain instead.)
   939  	// For now just clean all the temporaries at the end.
   940  	// In practice that's fine.
   941  	case OSWITCH:
   942  		t := marktemp(order)
   943  
   944  		n.Left = orderexpr(n.Left, order, nil)
   945  		for _, n4 := range n.List.Slice() {
   946  			if n4.Op != OXCASE {
   947  				Fatalf("order switch case %v", n4.Op)
   948  			}
   949  			orderexprlistinplace(n4.List, order)
   950  			orderblockNodes(&n4.Nbody)
   951  		}
   952  
   953  		order.out = append(order.out, n)
   954  		cleantemp(t, order)
   955  	}
   956  
   957  	lineno = lno
   958  }
   959  
   960  // Orderexprlist orders the expression list l into order.
   961  func orderexprlist(l Nodes, order *Order) {
   962  	s := l.Slice()
   963  	for i := range s {
   964  		s[i] = orderexpr(s[i], order, nil)
   965  	}
   966  }
   967  
   968  // Orderexprlist orders the expression list l but saves
   969  // the side effects on the individual expression ninit lists.
   970  func orderexprlistinplace(l Nodes, order *Order) {
   971  	s := l.Slice()
   972  	for i := range s {
   973  		s[i] = orderexprinplace(s[i], order)
   974  	}
   975  }
   976  
   977  // prealloc[x] records the allocation to use for x.
   978  var prealloc = map[*Node]*Node{}
   979  
   980  // Orderexpr orders a single expression, appending side
   981  // effects to order->out as needed.
   982  // If this is part of an assignment lhs = *np, lhs is given.
   983  // Otherwise lhs == nil. (When lhs != nil it may be possible
   984  // to avoid copying the result of the expression to a temporary.)
   985  // The result of orderexpr MUST be assigned back to n, e.g.
   986  // 	n.Left = orderexpr(n.Left, order, lhs)
   987  func orderexpr(n *Node, order *Order, lhs *Node) *Node {
   988  	if n == nil {
   989  		return n
   990  	}
   991  
   992  	lno := setlineno(n)
   993  	orderinit(n, order)
   994  
   995  	switch n.Op {
   996  	default:
   997  		n.Left = orderexpr(n.Left, order, nil)
   998  		n.Right = orderexpr(n.Right, order, nil)
   999  		orderexprlist(n.List, order)
  1000  		orderexprlist(n.Rlist, order)
  1001  
  1002  	// Addition of strings turns into a function call.
  1003  	// Allocate a temporary to hold the strings.
  1004  	// Fewer than 5 strings use direct runtime helpers.
  1005  	case OADDSTR:
  1006  		orderexprlist(n.List, order)
  1007  
  1008  		if n.List.Len() > 5 {
  1009  			t := types.NewArray(types.Types[TSTRING], int64(n.List.Len()))
  1010  			prealloc[n] = ordertemp(t, order, false)
  1011  		}
  1012  
  1013  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1014  		// buffer during conversion. String concatenation does not
  1015  		// memorize the strings for later use, so it is safe.
  1016  		// However, we can do it only if there is at least one non-empty string literal.
  1017  		// Otherwise if all other arguments are empty strings,
  1018  		// concatstrings will return the reference to the temp string
  1019  		// to the caller.
  1020  		hasbyte := false
  1021  
  1022  		haslit := false
  1023  		for _, n1 := range n.List.Slice() {
  1024  			hasbyte = hasbyte || n1.Op == OARRAYBYTESTR
  1025  			haslit = haslit || n1.Op == OLITERAL && len(n1.Val().U.(string)) != 0
  1026  		}
  1027  
  1028  		if haslit && hasbyte {
  1029  			for _, n2 := range n.List.Slice() {
  1030  				if n2.Op == OARRAYBYTESTR {
  1031  					n2.Op = OARRAYBYTESTRTMP
  1032  				}
  1033  			}
  1034  		}
  1035  
  1036  	case OCMPSTR:
  1037  		n.Left = orderexpr(n.Left, order, nil)
  1038  		n.Right = orderexpr(n.Right, order, nil)
  1039  
  1040  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1041  		// buffer during conversion. String comparison does not
  1042  		// memorize the strings for later use, so it is safe.
  1043  		if n.Left.Op == OARRAYBYTESTR {
  1044  			n.Left.Op = OARRAYBYTESTRTMP
  1045  		}
  1046  		if n.Right.Op == OARRAYBYTESTR {
  1047  			n.Right.Op = OARRAYBYTESTRTMP
  1048  		}
  1049  
  1050  		// key must be addressable
  1051  	case OINDEXMAP:
  1052  		n.Left = orderexpr(n.Left, order, nil)
  1053  		n.Right = orderexpr(n.Right, order, nil)
  1054  		needCopy := false
  1055  
  1056  		if n.Etype == 0 && instrumenting {
  1057  			// Race detector needs the copy so it can
  1058  			// call treecopy on the result.
  1059  			needCopy = true
  1060  		}
  1061  
  1062  		// For x = m[string(k)] where k is []byte, the allocation of
  1063  		// backing bytes for the string can be avoided by reusing
  1064  		// the []byte backing array. This is a special case that it
  1065  		// would be nice to handle more generally, but because
  1066  		// there are no []byte-keyed maps, this specific case comes
  1067  		// up in important cases in practice. See issue 3512.
  1068  		// Nothing can change the []byte we are not copying before
  1069  		// the map index, because the map access is going to
  1070  		// be forced to happen immediately following this
  1071  		// conversion (by the ordercopyexpr a few lines below).
  1072  		if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
  1073  			n.Right.Op = OARRAYBYTESTRTMP
  1074  			needCopy = true
  1075  		}
  1076  
  1077  		n.Right = ordermapkeytemp(n.Left.Type, n.Right, order)
  1078  		if needCopy {
  1079  			n = ordercopyexpr(n, n.Type, order, false)
  1080  		}
  1081  
  1082  	// concrete type (not interface) argument must be addressable
  1083  	// temporary to pass to runtime.
  1084  	case OCONVIFACE:
  1085  		n.Left = orderexpr(n.Left, order, nil)
  1086  
  1087  		if !n.Left.Type.IsInterface() {
  1088  			n.Left = orderaddrtemp(n.Left, order)
  1089  		}
  1090  
  1091  	case OCONVNOP:
  1092  		if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) {
  1093  			// When reordering unsafe.Pointer(f()) into a separate
  1094  			// statement, the conversion and function call must stay
  1095  			// together. See golang.org/issue/15329.
  1096  			orderinit(n.Left, order)
  1097  			ordercall(n.Left, order)
  1098  			if lhs == nil || lhs.Op != ONAME || instrumenting {
  1099  				n = ordercopyexpr(n, n.Type, order, false)
  1100  			}
  1101  		} else {
  1102  			n.Left = orderexpr(n.Left, order, nil)
  1103  		}
  1104  
  1105  	case OANDAND, OOROR:
  1106  		mark := marktemp(order)
  1107  		n.Left = orderexpr(n.Left, order, nil)
  1108  
  1109  		// Clean temporaries from first branch at beginning of second.
  1110  		// Leave them on the stack so that they can be killed in the outer
  1111  		// context in case the short circuit is taken.
  1112  		var s []*Node
  1113  
  1114  		cleantempnopop(mark, order, &s)
  1115  		n.Right = addinit(n.Right, s)
  1116  		n.Right = orderexprinplace(n.Right, order)
  1117  
  1118  	case OCALLFUNC,
  1119  		OCALLINTER,
  1120  		OCALLMETH,
  1121  		OCAP,
  1122  		OCOMPLEX,
  1123  		OCOPY,
  1124  		OIMAG,
  1125  		OLEN,
  1126  		OMAKECHAN,
  1127  		OMAKEMAP,
  1128  		OMAKESLICE,
  1129  		ONEW,
  1130  		OREAL,
  1131  		ORECOVER,
  1132  		OSTRARRAYBYTE,
  1133  		OSTRARRAYBYTETMP,
  1134  		OSTRARRAYRUNE:
  1135  		ordercall(n, order)
  1136  		if lhs == nil || lhs.Op != ONAME || instrumenting {
  1137  			n = ordercopyexpr(n, n.Type, order, false)
  1138  		}
  1139  
  1140  	case OAPPEND:
  1141  		ordercallargs(&n.List, order)
  1142  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) {
  1143  			n = ordercopyexpr(n, n.Type, order, false)
  1144  		}
  1145  
  1146  	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
  1147  		n.Left = orderexpr(n.Left, order, nil)
  1148  		low, high, max := n.SliceBounds()
  1149  		low = orderexpr(low, order, nil)
  1150  		low = ordercheapexpr(low, order)
  1151  		high = orderexpr(high, order, nil)
  1152  		high = ordercheapexpr(high, order)
  1153  		max = orderexpr(max, order, nil)
  1154  		max = ordercheapexpr(max, order)
  1155  		n.SetSliceBounds(low, high, max)
  1156  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
  1157  			n = ordercopyexpr(n, n.Type, order, false)
  1158  		}
  1159  
  1160  	case OCLOSURE:
  1161  		if n.Noescape() && n.Func.Cvars.Len() > 0 {
  1162  			prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type
  1163  		}
  1164  
  1165  	case OARRAYLIT, OSLICELIT, OCALLPART:
  1166  		n.Left = orderexpr(n.Left, order, nil)
  1167  		n.Right = orderexpr(n.Right, order, nil)
  1168  		orderexprlist(n.List, order)
  1169  		orderexprlist(n.Rlist, order)
  1170  		if n.Noescape() {
  1171  			prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type
  1172  		}
  1173  
  1174  	case ODDDARG:
  1175  		if n.Noescape() {
  1176  			// The ddd argument does not live beyond the call it is created for.
  1177  			// Allocate a temporary that will be cleaned up when this statement
  1178  			// completes. We could be more aggressive and try to arrange for it
  1179  			// to be cleaned up when the call completes.
  1180  			prealloc[n] = ordertemp(n.Type.Elem(), order, false)
  1181  		}
  1182  
  1183  	case ODOTTYPE, ODOTTYPE2:
  1184  		n.Left = orderexpr(n.Left, order, nil)
  1185  		// TODO(rsc): The isfat is for consistency with componentgen and walkexpr.
  1186  		// It needs to be removed in all three places.
  1187  		// That would allow inlining x.(struct{*int}) the same as x.(*int).
  1188  		if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting {
  1189  			n = ordercopyexpr(n, n.Type, order, true)
  1190  		}
  1191  
  1192  	case ORECV:
  1193  		n.Left = orderexpr(n.Left, order, nil)
  1194  		n = ordercopyexpr(n, n.Type, order, true)
  1195  
  1196  	case OEQ, ONE:
  1197  		n.Left = orderexpr(n.Left, order, nil)
  1198  		n.Right = orderexpr(n.Right, order, nil)
  1199  		t := n.Left.Type
  1200  		if t.IsStruct() || t.IsArray() {
  1201  			// for complex comparisons, we need both args to be
  1202  			// addressable so we can pass them to the runtime.
  1203  			n.Left = orderaddrtemp(n.Left, order)
  1204  			n.Right = orderaddrtemp(n.Right, order)
  1205  		}
  1206  	}
  1207  
  1208  	lineno = lno
  1209  	return n
  1210  }
  1211  
  1212  // okas creates and returns an assignment of val to ok,
  1213  // including an explicit conversion if necessary.
  1214  func okas(ok, val *Node) *Node {
  1215  	if !isblank(ok) {
  1216  		val = conv(val, ok.Type)
  1217  	}
  1218  	return nod(OAS, ok, val)
  1219  }
  1220  
  1221  // orderas2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment.
  1222  // The caller should order the right-hand side of the assignment before calling orderas2.
  1223  // It rewrites,
  1224  // 	a, b, a = ...
  1225  // as
  1226  //	tmp1, tmp2, tmp3 = ...
  1227  // 	a, b, a = tmp1, tmp2, tmp3
  1228  // This is necessary to ensure left to right assignment order.
  1229  func orderas2(n *Node, order *Order) {
  1230  	tmplist := []*Node{}
  1231  	left := []*Node{}
  1232  	for _, l := range n.List.Slice() {
  1233  		if !isblank(l) {
  1234  			tmp := ordertemp(l.Type, order, types.Haspointers(l.Type))
  1235  			tmplist = append(tmplist, tmp)
  1236  			left = append(left, l)
  1237  		}
  1238  	}
  1239  
  1240  	order.out = append(order.out, n)
  1241  
  1242  	as := nod(OAS2, nil, nil)
  1243  	as.List.Set(left)
  1244  	as.Rlist.Set(tmplist)
  1245  	as = typecheck(as, Etop)
  1246  	orderstmt(as, order)
  1247  
  1248  	ti := 0
  1249  	for ni, l := range n.List.Slice() {
  1250  		if !isblank(l) {
  1251  			n.List.SetIndex(ni, tmplist[ti])
  1252  			ti++
  1253  		}
  1254  	}
  1255  }
  1256  
  1257  // orderokas2 orders OAS2 with ok.
  1258  // Just like orderas2(), this also adds temporaries to ensure left-to-right assignment.
  1259  func orderokas2(n *Node, order *Order) {
  1260  	var tmp1, tmp2 *Node
  1261  	if !isblank(n.List.First()) {
  1262  		typ := n.Rlist.First().Type
  1263  		tmp1 = ordertemp(typ, order, types.Haspointers(typ))
  1264  	}
  1265  
  1266  	if !isblank(n.List.Second()) {
  1267  		tmp2 = ordertemp(types.Types[TBOOL], order, false)
  1268  	}
  1269  
  1270  	order.out = append(order.out, n)
  1271  
  1272  	if tmp1 != nil {
  1273  		r := nod(OAS, n.List.First(), tmp1)
  1274  		r = typecheck(r, Etop)
  1275  		ordermapassign(r, order)
  1276  		n.List.SetFirst(tmp1)
  1277  	}
  1278  	if tmp2 != nil {
  1279  		r := okas(n.List.Second(), tmp2)
  1280  		r = typecheck(r, Etop)
  1281  		ordermapassign(r, order)
  1282  		n.List.SetSecond(tmp2)
  1283  	}
  1284  }