github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/order.go (about)

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