github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/cmd/compile/internal/gc/order.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"cmd/compile/internal/types"
     9  	"cmd/internal/src"
    10  	"fmt"
    11  )
    12  
    13  // Rewrite tree to use separate statements to enforce
    14  // order of evaluation. Makes walk easier, because it
    15  // can (after this runs) reorder at will within an expression.
    16  //
    17  // Rewrite x op= y into x = x op y.
    18  //
    19  // Introduce temporaries as needed by runtime routines.
    20  // For example, the map runtime routines take the map key
    21  // by reference, so make sure all map keys are addressable
    22  // by copying them to temporaries as needed.
    23  // The same is true for channel operations.
    24  //
    25  // Arrange that map index expressions only appear in direct
    26  // assignments x = m[k] or m[k] = x, never in larger expressions.
    27  //
    28  // Arrange that receive expressions only appear in direct assignments
    29  // x = <-c or as standalone statements <-c, never in larger expressions.
    30  
    31  // TODO(rsc): The temporary introduction during multiple assignments
    32  // should be moved into this file, so that the temporaries can be cleaned
    33  // and so that conversions implicit in the OAS2FUNC and OAS2RECV
    34  // nodes can be made explicit and then have their temporaries cleaned.
    35  
    36  // TODO(rsc): Goto and multilevel break/continue can jump over
    37  // inserted VARKILL annotations. Work out a way to handle these.
    38  // The current implementation is safe, in that it will execute correctly.
    39  // But it won't reuse temporaries as aggressively as it might, and
    40  // it can result in unnecessary zeroing of those variables in the function
    41  // prologue.
    42  
    43  // Order holds state during the ordering process.
    44  type Order struct {
    45  	out  []*Node // list of generated statements
    46  	temp []*Node // stack of temporary variables
    47  }
    48  
    49  // Order rewrites fn->nbody to apply the ordering constraints
    50  // described in the comment at the top of the file.
    51  func order(fn *Node) {
    52  	if Debug['W'] > 1 {
    53  		s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
    54  		dumplist(s, fn.Nbody)
    55  	}
    56  
    57  	orderblockNodes(&fn.Nbody)
    58  }
    59  
    60  // Ordertemp allocates a new temporary with the given type,
    61  // pushes it onto the temp stack, and returns it.
    62  // If clear is true, ordertemp emits code to zero the temporary.
    63  func ordertemp(t *types.Type, order *Order, clear bool) *Node {
    64  	var_ := temp(t)
    65  	if clear {
    66  		a := nod(OAS, var_, nil)
    67  		a = typecheck(a, Etop)
    68  		order.out = append(order.out, a)
    69  	}
    70  
    71  	order.temp = append(order.temp, var_)
    72  	return var_
    73  }
    74  
    75  // Ordercopyexpr behaves like ordertemp but also emits
    76  // code to initialize the temporary to the value n.
    77  //
    78  // The clear argument is provided for use when the evaluation
    79  // of tmp = n turns into a function call that is passed a pointer
    80  // to the temporary as the output space. If the call blocks before
    81  // tmp has been written, the garbage collector will still treat the
    82  // temporary as live, so we must zero it before entering that call.
    83  // Today, this only happens for channel receive operations.
    84  // (The other candidate would be map access, but map access
    85  // returns a pointer to the result data instead of taking a pointer
    86  // to be filled in.)
    87  func ordercopyexpr(n *Node, t *types.Type, order *Order, clear int) *Node {
    88  	var_ := ordertemp(t, order, clear != 0)
    89  	a := nod(OAS, var_, n)
    90  	a = typecheck(a, Etop)
    91  	order.out = append(order.out, a)
    92  	return var_
    93  }
    94  
    95  // Ordercheapexpr returns a cheap version of n.
    96  // The definition of cheap is that n is a variable or constant.
    97  // If not, ordercheapexpr allocates a new tmp, emits tmp = n,
    98  // and then returns tmp.
    99  func ordercheapexpr(n *Node, order *Order) *Node {
   100  	if n == nil {
   101  		return nil
   102  	}
   103  	switch n.Op {
   104  	case ONAME, OLITERAL:
   105  		return n
   106  	case OLEN, OCAP:
   107  		l := ordercheapexpr(n.Left, order)
   108  		if l == n.Left {
   109  			return n
   110  		}
   111  		a := *n
   112  		a.Orig = &a
   113  		a.Left = l
   114  		return typecheck(&a, Erv)
   115  	}
   116  
   117  	return ordercopyexpr(n, n.Type, order, 0)
   118  }
   119  
   120  // Ordersafeexpr returns a safe version of n.
   121  // The definition of safe is that n can appear multiple times
   122  // without violating the semantics of the original program,
   123  // and that assigning to the safe version has the same effect
   124  // as assigning to the original n.
   125  //
   126  // The intended use is to apply to x when rewriting x += y into x = x + y.
   127  func ordersafeexpr(n *Node, order *Order) *Node {
   128  	switch n.Op {
   129  	case ONAME, OLITERAL:
   130  		return n
   131  
   132  	case ODOT, OLEN, OCAP:
   133  		l := ordersafeexpr(n.Left, order)
   134  		if l == n.Left {
   135  			return n
   136  		}
   137  		a := *n
   138  		a.Orig = &a
   139  		a.Left = l
   140  		return typecheck(&a, Erv)
   141  
   142  	case ODOTPTR, OIND:
   143  		l := ordercheapexpr(n.Left, order)
   144  		if l == n.Left {
   145  			return n
   146  		}
   147  		a := *n
   148  		a.Orig = &a
   149  		a.Left = l
   150  		return typecheck(&a, Erv)
   151  
   152  	case OINDEX, OINDEXMAP:
   153  		var l *Node
   154  		if n.Left.Type.IsArray() {
   155  			l = ordersafeexpr(n.Left, order)
   156  		} else {
   157  			l = ordercheapexpr(n.Left, order)
   158  		}
   159  		r := ordercheapexpr(n.Right, order)
   160  		if l == n.Left && r == n.Right {
   161  			return n
   162  		}
   163  		a := *n
   164  		a.Orig = &a
   165  		a.Left = l
   166  		a.Right = r
   167  		return typecheck(&a, Erv)
   168  	default:
   169  		Fatalf("ordersafeexpr %v", n.Op)
   170  		return nil // not reached
   171  	}
   172  }
   173  
   174  // Isaddrokay reports whether it is okay to pass n's address to runtime routines.
   175  // Taking the address of a variable makes the liveness and optimization analyses
   176  // lose track of where the variable's lifetime ends. To avoid hurting the analyses
   177  // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay,
   178  // because we emit explicit VARKILL instructions marking the end of those
   179  // temporaries' lifetimes.
   180  func isaddrokay(n *Node) bool {
   181  	return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp())
   182  }
   183  
   184  // Orderaddrtemp ensures that n is okay to pass by address to runtime routines.
   185  // If the original argument n is not okay, orderaddrtemp creates a tmp, emits
   186  // tmp = n, and then returns tmp.
   187  // The result of orderaddrtemp MUST be assigned back to n, e.g.
   188  // 	n.Left = orderaddrtemp(n.Left, order)
   189  func orderaddrtemp(n *Node, order *Order) *Node {
   190  	if consttype(n) > 0 {
   191  		// TODO: expand this to all static composite literal nodes?
   192  		n = defaultlit(n, nil)
   193  		dowidth(n.Type)
   194  		vstat := staticname(n.Type)
   195  		vstat.Name.SetReadonly(true)
   196  		var out []*Node
   197  		staticassign(vstat, n, &out)
   198  		if out != nil {
   199  			Fatalf("staticassign of const generated code: %+v", n)
   200  		}
   201  		vstat = typecheck(vstat, Erv)
   202  		return vstat
   203  	}
   204  	if isaddrokay(n) {
   205  		return n
   206  	}
   207  	return ordercopyexpr(n, n.Type, order, 0)
   208  }
   209  
   210  // ordermapkeytemp prepares n to be a key in a map runtime call and returns n.
   211  // It should only be used for map runtime calls which have *_fast* versions.
   212  func ordermapkeytemp(t *types.Type, n *Node, order *Order) *Node {
   213  	// Most map calls need to take the address of the key.
   214  	// Exception: map*_fast* calls. See golang.org/issue/19015.
   215  	if mapfast(t) == mapslow {
   216  		return orderaddrtemp(n, order)
   217  	}
   218  	return n
   219  }
   220  
   221  type ordermarker int
   222  
   223  // Marktemp returns the top of the temporary variable stack.
   224  func marktemp(order *Order) ordermarker {
   225  	return ordermarker(len(order.temp))
   226  }
   227  
   228  // Poptemp pops temporaries off the stack until reaching the mark,
   229  // which must have been returned by marktemp.
   230  func poptemp(mark ordermarker, order *Order) {
   231  	order.temp = order.temp[:mark]
   232  }
   233  
   234  // Cleantempnopop emits to *out VARKILL instructions for each temporary
   235  // above the mark on the temporary stack, but it does not pop them
   236  // from the stack.
   237  func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
   238  	for i := len(order.temp) - 1; i >= int(mark); i-- {
   239  		n := order.temp[i]
   240  		if n.Name.Keepalive() {
   241  			n.Name.SetKeepalive(false)
   242  			n.SetAddrtaken(true) // ensure SSA keeps the n variable
   243  			kill := nod(OVARLIVE, n, nil)
   244  			kill = typecheck(kill, Etop)
   245  			*out = append(*out, kill)
   246  		}
   247  		kill := nod(OVARKILL, n, nil)
   248  		kill = typecheck(kill, Etop)
   249  		*out = append(*out, kill)
   250  	}
   251  }
   252  
   253  // Cleantemp emits VARKILL instructions for each temporary above the
   254  // mark on the temporary stack and removes them from the stack.
   255  func cleantemp(top ordermarker, order *Order) {
   256  	cleantempnopop(top, order, &order.out)
   257  	poptemp(top, order)
   258  }
   259  
   260  // Orderstmtlist orders each of the statements in the list.
   261  func orderstmtlist(l Nodes, order *Order) {
   262  	for _, n := range l.Slice() {
   263  		orderstmt(n, order)
   264  	}
   265  }
   266  
   267  // Orderblock orders the block of statements l onto a new list,
   268  // and returns the ordered list.
   269  func orderblock(l Nodes) []*Node {
   270  	var order Order
   271  	mark := marktemp(&order)
   272  	orderstmtlist(l, &order)
   273  	cleantemp(mark, &order)
   274  	return order.out
   275  }
   276  
   277  // OrderblockNodes orders the block of statements in n into a new slice,
   278  // and then replaces the old slice in n with the new slice.
   279  func orderblockNodes(n *Nodes) {
   280  	var order Order
   281  	mark := marktemp(&order)
   282  	orderstmtlist(*n, &order)
   283  	cleantemp(mark, &order)
   284  	n.Set(order.out)
   285  }
   286  
   287  // Orderexprinplace orders the side effects in *np and
   288  // leaves them as the init list of the final *np.
   289  // The result of orderexprinplace MUST be assigned back to n, e.g.
   290  // 	n.Left = orderexprinplace(n.Left, outer)
   291  func orderexprinplace(n *Node, outer *Order) *Node {
   292  	var order Order
   293  	n = orderexpr(n, &order, nil)
   294  	n = addinit(n, order.out)
   295  
   296  	// insert new temporaries from order
   297  	// at head of outer list.
   298  	outer.temp = append(outer.temp, order.temp...)
   299  	return n
   300  }
   301  
   302  // Orderstmtinplace orders the side effects of the single statement *np
   303  // and replaces it with the resulting statement list.
   304  // The result of orderstmtinplace MUST be assigned back to n, e.g.
   305  // 	n.Left = orderstmtinplace(n.Left)
   306  func orderstmtinplace(n *Node) *Node {
   307  	var order Order
   308  	mark := marktemp(&order)
   309  	orderstmt(n, &order)
   310  	cleantemp(mark, &order)
   311  	return liststmt(order.out)
   312  }
   313  
   314  // Orderinit moves n's init list to order->out.
   315  func orderinit(n *Node, order *Order) {
   316  	if n.mayBeShared() {
   317  		// For concurrency safety, don't mutate potentially shared nodes.
   318  		// First, ensure that no work is required here.
   319  		if n.Ninit.Len() > 0 {
   320  			Fatalf("orderinit shared node with ninit")
   321  		}
   322  		return
   323  	}
   324  	orderstmtlist(n.Ninit, order)
   325  	n.Ninit.Set(nil)
   326  }
   327  
   328  // Ismulticall reports whether the list l is f() for a multi-value function.
   329  // Such an f() could appear as the lone argument to a multi-arg function.
   330  func ismulticall(l Nodes) bool {
   331  	// one arg only
   332  	if l.Len() != 1 {
   333  		return false
   334  	}
   335  	n := l.First()
   336  
   337  	// must be call
   338  	switch n.Op {
   339  	default:
   340  		return false
   341  
   342  	case OCALLFUNC, OCALLMETH, OCALLINTER:
   343  		break
   344  	}
   345  
   346  	// call must return multiple values
   347  	return n.Left.Type.NumResults() > 1
   348  }
   349  
   350  // Copyret emits t1, t2, ... = n, where n is a function call,
   351  // and then returns the list t1, t2, ....
   352  func copyret(n *Node, order *Order) []*Node {
   353  	if !n.Type.IsFuncArgStruct() {
   354  		Fatalf("copyret %v %d", n.Type, n.Left.Type.NumResults())
   355  	}
   356  
   357  	var l1 []*Node
   358  	var l2 []*Node
   359  	for _, t := range n.Type.Fields().Slice() {
   360  		tmp := temp(t.Type)
   361  		l1 = append(l1, tmp)
   362  		l2 = append(l2, tmp)
   363  	}
   364  
   365  	as := nod(OAS2, nil, nil)
   366  	as.List.Set(l1)
   367  	as.Rlist.Set1(n)
   368  	as = typecheck(as, Etop)
   369  	orderstmt(as, order)
   370  
   371  	return l2
   372  }
   373  
   374  // Ordercallargs orders the list of call arguments *l.
   375  func ordercallargs(l *Nodes, order *Order) {
   376  	if ismulticall(*l) {
   377  		// return f() where f() is multiple values.
   378  		l.Set(copyret(l.First(), order))
   379  	} else {
   380  		orderexprlist(*l, order)
   381  	}
   382  }
   383  
   384  // Ordercall orders the call expression n.
   385  // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
   386  func ordercall(n *Node, order *Order) {
   387  	n.Left = orderexpr(n.Left, order, nil)
   388  	n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp
   389  	ordercallargs(&n.List, order)
   390  
   391  	if n.Op == OCALLFUNC {
   392  		keepAlive := func(i int) {
   393  			// If the argument is really a pointer being converted to uintptr,
   394  			// arrange for the pointer to be kept alive until the call returns,
   395  			// by copying it into a temp and marking that temp
   396  			// still alive when we pop the temp stack.
   397  			xp := n.List.Addr(i)
   398  			for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() {
   399  				xp = &(*xp).Left
   400  			}
   401  			x := *xp
   402  			if x.Type.IsUnsafePtr() {
   403  				x = ordercopyexpr(x, x.Type, order, 0)
   404  				x.Name.SetKeepalive(true)
   405  				*xp = x
   406  			}
   407  		}
   408  
   409  		for i, t := range n.Left.Type.Params().FieldSlice() {
   410  			// Check for "unsafe-uintptr" tag provided by escape analysis.
   411  			if t.Isddd() && !n.Isddd() {
   412  				if t.Note == uintptrEscapesTag {
   413  					for ; i < n.List.Len(); i++ {
   414  						keepAlive(i)
   415  					}
   416  				}
   417  			} else {
   418  				if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
   419  					keepAlive(i)
   420  				}
   421  			}
   422  		}
   423  	}
   424  }
   425  
   426  // Ordermapassign appends n to order->out, introducing temporaries
   427  // to make sure that all map assignments have the form m[k] = x.
   428  // (Note: orderexpr has already been called on n, so we know k is addressable.)
   429  //
   430  // If n is the multiple assignment form ..., m[k], ... = ..., 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, 0)
   461  				}
   462  				if !m.Right.IsAutoTmp() {
   463  					m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
   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, 0)
   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, OGOSECURE:
   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, 0)
   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, 0)
   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, 0)
   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  		for i, n1 := range n.List.Slice() {
   766  			n.List.SetIndex(i, orderexprinplace(n1, order))
   767  		}
   768  		orderblockNodes(&n.Nbody)
   769  		order.out = append(order.out, n)
   770  		cleantemp(t, order)
   771  
   772  	case ORETURN:
   773  		ordercallargs(&n.List, order)
   774  		order.out = append(order.out, n)
   775  
   776  	// Special: clean case temporaries in each block entry.
   777  	// Select must enter one of its blocks, so there is no
   778  	// need for a cleaning at the end.
   779  	// Doubly special: evaluation order for select is stricter
   780  	// than ordinary expressions. Even something like p.c
   781  	// has to be hoisted into a temporary, so that it cannot be
   782  	// reordered after the channel evaluation for a different
   783  	// case (if p were nil, then the timing of the fault would
   784  	// give this away).
   785  	case OSELECT:
   786  		t := marktemp(order)
   787  
   788  		for _, n2 := range n.List.Slice() {
   789  			if n2.Op != OXCASE {
   790  				Fatalf("order select case %v", n2.Op)
   791  			}
   792  			r := n2.Left
   793  			setlineno(n2)
   794  
   795  			// Append any new body prologue to ninit.
   796  			// The next loop will insert ninit into nbody.
   797  			if n2.Ninit.Len() != 0 {
   798  				Fatalf("order select ninit")
   799  			}
   800  			if r != nil {
   801  				switch r.Op {
   802  				default:
   803  					Dump("select case", r)
   804  					Fatalf("unknown op in select %v", r.Op)
   805  
   806  				// If this is case x := <-ch or case x, y := <-ch, the case has
   807  				// the ODCL nodes to declare x and y. We want to delay that
   808  				// declaration (and possible allocation) until inside the case body.
   809  				// Delete the ODCL nodes here and recreate them inside the body below.
   810  				case OSELRECV, OSELRECV2:
   811  					if r.Colas() {
   812  						i := 0
   813  						if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
   814  							i++
   815  						}
   816  						if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
   817  							i++
   818  						}
   819  						if i >= r.Ninit.Len() {
   820  							r.Ninit.Set(nil)
   821  						}
   822  					}
   823  
   824  					if r.Ninit.Len() != 0 {
   825  						dumplist("ninit", r.Ninit)
   826  						Fatalf("ninit on select recv")
   827  					}
   828  
   829  					// case x = <-c
   830  					// case x, ok = <-c
   831  					// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
   832  					// r->left == N means 'case <-c'.
   833  					// c is always evaluated; x and ok are only evaluated when assigned.
   834  					r.Right.Left = orderexpr(r.Right.Left, order, nil)
   835  
   836  					if r.Right.Left.Op != ONAME {
   837  						r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
   838  					}
   839  
   840  					// Introduce temporary for receive and move actual copy into case body.
   841  					// avoids problems with target being addressed, as usual.
   842  					// NOTE: If we wanted to be clever, we could arrange for just one
   843  					// temporary per distinct type, sharing the temp among all receives
   844  					// with that temp. Similarly one ok bool could be shared among all
   845  					// the x,ok receives. Not worth doing until there's a clear need.
   846  					if r.Left != nil && isblank(r.Left) {
   847  						r.Left = nil
   848  					}
   849  					if r.Left != nil {
   850  						// use channel element type for temporary to avoid conversions,
   851  						// such as in case interfacevalue = <-intchan.
   852  						// the conversion happens in the OAS instead.
   853  						tmp1 := r.Left
   854  
   855  						if r.Colas() {
   856  							tmp2 := nod(ODCL, tmp1, nil)
   857  							tmp2 = typecheck(tmp2, Etop)
   858  							n2.Ninit.Append(tmp2)
   859  						}
   860  
   861  						r.Left = ordertemp(r.Right.Left.Type.Elem(), order, types.Haspointers(r.Right.Left.Type.Elem()))
   862  						tmp2 := nod(OAS, tmp1, r.Left)
   863  						tmp2 = typecheck(tmp2, Etop)
   864  						n2.Ninit.Append(tmp2)
   865  					}
   866  
   867  					if r.List.Len() != 0 && isblank(r.List.First()) {
   868  						r.List.Set(nil)
   869  					}
   870  					if r.List.Len() != 0 {
   871  						tmp1 := r.List.First()
   872  						if r.Colas() {
   873  							tmp2 := nod(ODCL, tmp1, nil)
   874  							tmp2 = typecheck(tmp2, Etop)
   875  							n2.Ninit.Append(tmp2)
   876  						}
   877  
   878  						r.List.Set1(ordertemp(types.Types[TBOOL], order, false))
   879  						tmp2 := okas(tmp1, r.List.First())
   880  						tmp2 = typecheck(tmp2, Etop)
   881  						n2.Ninit.Append(tmp2)
   882  					}
   883  					n2.Ninit.Set(orderblock(n2.Ninit))
   884  
   885  				case OSEND:
   886  					if r.Ninit.Len() != 0 {
   887  						dumplist("ninit", r.Ninit)
   888  						Fatalf("ninit on select send")
   889  					}
   890  
   891  					// case c <- x
   892  					// r->left is c, r->right is x, both are always evaluated.
   893  					r.Left = orderexpr(r.Left, order, nil)
   894  
   895  					if !r.Left.IsAutoTmp() {
   896  						r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
   897  					}
   898  					r.Right = orderexpr(r.Right, order, nil)
   899  					if !r.Right.IsAutoTmp() {
   900  						r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
   901  					}
   902  				}
   903  			}
   904  
   905  			orderblockNodes(&n2.Nbody)
   906  		}
   907  		// Now that we have accumulated all the temporaries, clean them.
   908  		// Also insert any ninit queued during the previous loop.
   909  		// (The temporary cleaning must follow that ninit work.)
   910  		for _, n3 := range n.List.Slice() {
   911  			s := n3.Ninit.Slice()
   912  			cleantempnopop(t, order, &s)
   913  			n3.Nbody.Prepend(s...)
   914  			n3.Ninit.Set(nil)
   915  		}
   916  
   917  		order.out = append(order.out, n)
   918  		poptemp(t, order)
   919  
   920  	// Special: value being sent is passed as a pointer; make it addressable.
   921  	case OSEND:
   922  		t := marktemp(order)
   923  
   924  		n.Left = orderexpr(n.Left, order, nil)
   925  		n.Right = orderexpr(n.Right, order, nil)
   926  		if instrumenting {
   927  			// Force copying to the stack so that (chan T)(nil) <- x
   928  			// is still instrumented as a read of x.
   929  			n.Right = ordercopyexpr(n.Right, n.Right.Type, order, 0)
   930  		} else {
   931  			n.Right = orderaddrtemp(n.Right, order)
   932  		}
   933  		order.out = append(order.out, n)
   934  		cleantemp(t, order)
   935  
   936  	// TODO(rsc): Clean temporaries more aggressively.
   937  	// Note that because walkswitch will rewrite some of the
   938  	// switch into a binary search, this is not as easy as it looks.
   939  	// (If we ran that code here we could invoke orderstmt on
   940  	// the if-else chain instead.)
   941  	// For now just clean all the temporaries at the end.
   942  	// In practice that's fine.
   943  	case OSWITCH:
   944  		t := marktemp(order)
   945  
   946  		n.Left = orderexpr(n.Left, order, nil)
   947  		for _, n4 := range n.List.Slice() {
   948  			if n4.Op != OXCASE {
   949  				Fatalf("order switch case %v", n4.Op)
   950  			}
   951  			orderexprlistinplace(n4.List, order)
   952  			orderblockNodes(&n4.Nbody)
   953  		}
   954  
   955  		order.out = append(order.out, n)
   956  		cleantemp(t, order)
   957  	}
   958  
   959  	lineno = lno
   960  }
   961  
   962  // Orderexprlist orders the expression list l into order.
   963  func orderexprlist(l Nodes, order *Order) {
   964  	s := l.Slice()
   965  	for i := range s {
   966  		s[i] = orderexpr(s[i], order, nil)
   967  	}
   968  }
   969  
   970  // Orderexprlist orders the expression list l but saves
   971  // the side effects on the individual expression ninit lists.
   972  func orderexprlistinplace(l Nodes, order *Order) {
   973  	s := l.Slice()
   974  	for i := range s {
   975  		s[i] = orderexprinplace(s[i], order)
   976  	}
   977  }
   978  
   979  // prealloc[x] records the allocation to use for x.
   980  var prealloc = map[*Node]*Node{}
   981  
   982  // Orderexpr orders a single expression, appending side
   983  // effects to order->out as needed.
   984  // If this is part of an assignment lhs = *np, lhs is given.
   985  // Otherwise lhs == nil. (When lhs != nil it may be possible
   986  // to avoid copying the result of the expression to a temporary.)
   987  // The result of orderexpr MUST be assigned back to n, e.g.
   988  // 	n.Left = orderexpr(n.Left, order, lhs)
   989  func orderexpr(n *Node, order *Order, lhs *Node) *Node {
   990  	if n == nil {
   991  		return n
   992  	}
   993  
   994  	lno := setlineno(n)
   995  	orderinit(n, order)
   996  
   997  	switch n.Op {
   998  	default:
   999  		n.Left = orderexpr(n.Left, order, nil)
  1000  		n.Right = orderexpr(n.Right, order, nil)
  1001  		orderexprlist(n.List, order)
  1002  		orderexprlist(n.Rlist, order)
  1003  
  1004  	// Addition of strings turns into a function call.
  1005  	// Allocate a temporary to hold the strings.
  1006  	// Fewer than 5 strings use direct runtime helpers.
  1007  	case OADDSTR:
  1008  		orderexprlist(n.List, order)
  1009  
  1010  		if n.List.Len() > 5 {
  1011  			t := types.NewArray(types.Types[TSTRING], int64(n.List.Len()))
  1012  			prealloc[n] = ordertemp(t, order, false)
  1013  		}
  1014  
  1015  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1016  		// buffer during conversion. String concatenation does not
  1017  		// memorize the strings for later use, so it is safe.
  1018  		// However, we can do it only if there is at least one non-empty string literal.
  1019  		// Otherwise if all other arguments are empty strings,
  1020  		// concatstrings will return the reference to the temp string
  1021  		// to the caller.
  1022  		hasbyte := false
  1023  
  1024  		haslit := false
  1025  		for _, n1 := range n.List.Slice() {
  1026  			hasbyte = hasbyte || n1.Op == OARRAYBYTESTR
  1027  			haslit = haslit || n1.Op == OLITERAL && len(n1.Val().U.(string)) != 0
  1028  		}
  1029  
  1030  		if haslit && hasbyte {
  1031  			for _, n2 := range n.List.Slice() {
  1032  				if n2.Op == OARRAYBYTESTR {
  1033  					n2.Op = OARRAYBYTESTRTMP
  1034  				}
  1035  			}
  1036  		}
  1037  
  1038  	case OCMPSTR:
  1039  		n.Left = orderexpr(n.Left, order, nil)
  1040  		n.Right = orderexpr(n.Right, order, nil)
  1041  
  1042  		// Mark string(byteSlice) arguments to reuse byteSlice backing
  1043  		// buffer during conversion. String comparison does not
  1044  		// memorize the strings for later use, so it is safe.
  1045  		if n.Left.Op == OARRAYBYTESTR {
  1046  			n.Left.Op = OARRAYBYTESTRTMP
  1047  		}
  1048  		if n.Right.Op == OARRAYBYTESTR {
  1049  			n.Right.Op = OARRAYBYTESTRTMP
  1050  		}
  1051  
  1052  		// key must be addressable
  1053  	case OINDEXMAP:
  1054  		n.Left = orderexpr(n.Left, order, nil)
  1055  		n.Right = orderexpr(n.Right, order, nil)
  1056  		needCopy := false
  1057  
  1058  		if n.Etype == 0 && instrumenting {
  1059  			// Race detector needs the copy so it can
  1060  			// call treecopy on the result.
  1061  			needCopy = true
  1062  		}
  1063  
  1064  		// For x = m[string(k)] where k is []byte, the allocation of
  1065  		// backing bytes for the string can be avoided by reusing
  1066  		// the []byte backing array. This is a special case that it
  1067  		// would be nice to handle more generally, but because
  1068  		// there are no []byte-keyed maps, this specific case comes
  1069  		// up in important cases in practice. See issue 3512.
  1070  		// Nothing can change the []byte we are not copying before
  1071  		// the map index, because the map access is going to
  1072  		// be forced to happen immediately following this
  1073  		// conversion (by the ordercopyexpr a few lines below).
  1074  		if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
  1075  			n.Right.Op = OARRAYBYTESTRTMP
  1076  			needCopy = true
  1077  		}
  1078  
  1079  		n.Right = ordermapkeytemp(n.Left.Type, n.Right, order)
  1080  		if needCopy {
  1081  			n = ordercopyexpr(n, n.Type, order, 0)
  1082  		}
  1083  
  1084  	// concrete type (not interface) argument must be addressable
  1085  	// temporary to pass to runtime.
  1086  	case OCONVIFACE:
  1087  		n.Left = orderexpr(n.Left, order, nil)
  1088  
  1089  		if !n.Left.Type.IsInterface() {
  1090  			n.Left = orderaddrtemp(n.Left, order)
  1091  		}
  1092  
  1093  	case OCONVNOP:
  1094  		if n.Type.IsKind(TUNSAFEPTR) && n.Left.Type.IsKind(TUINTPTR) && (n.Left.Op == OCALLFUNC || n.Left.Op == OCALLINTER || n.Left.Op == OCALLMETH) {
  1095  			// When reordering unsafe.Pointer(f()) into a separate
  1096  			// statement, the conversion and function call must stay
  1097  			// together. See golang.org/issue/15329.
  1098  			orderinit(n.Left, order)
  1099  			ordercall(n.Left, order)
  1100  			if lhs == nil || lhs.Op != ONAME || instrumenting {
  1101  				n = ordercopyexpr(n, n.Type, order, 0)
  1102  			}
  1103  		} else {
  1104  			n.Left = orderexpr(n.Left, order, nil)
  1105  		}
  1106  
  1107  	case OANDAND, OOROR:
  1108  		mark := marktemp(order)
  1109  		n.Left = orderexpr(n.Left, order, nil)
  1110  
  1111  		// Clean temporaries from first branch at beginning of second.
  1112  		// Leave them on the stack so that they can be killed in the outer
  1113  		// context in case the short circuit is taken.
  1114  		var s []*Node
  1115  
  1116  		cleantempnopop(mark, order, &s)
  1117  		n.Right = addinit(n.Right, s)
  1118  		n.Right = orderexprinplace(n.Right, order)
  1119  
  1120  	case OCALLFUNC,
  1121  		OCALLINTER,
  1122  		OCALLMETH,
  1123  		OCAP,
  1124  		OCOMPLEX,
  1125  		OCOPY,
  1126  		OIMAG,
  1127  		OLEN,
  1128  		OMAKECHAN,
  1129  		OMAKEMAP,
  1130  		OMAKESLICE,
  1131  		ONEW,
  1132  		OREAL,
  1133  		ORECOVER,
  1134  		OSTRARRAYBYTE,
  1135  		OSTRARRAYBYTETMP,
  1136  		OSTRARRAYRUNE:
  1137  		ordercall(n, order)
  1138  		if lhs == nil || lhs.Op != ONAME || instrumenting {
  1139  			n = ordercopyexpr(n, n.Type, order, 0)
  1140  		}
  1141  
  1142  	case OAPPEND:
  1143  		ordercallargs(&n.List, order)
  1144  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) {
  1145  			n = ordercopyexpr(n, n.Type, order, 0)
  1146  		}
  1147  
  1148  	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
  1149  		n.Left = orderexpr(n.Left, order, nil)
  1150  		low, high, max := n.SliceBounds()
  1151  		low = orderexpr(low, order, nil)
  1152  		low = ordercheapexpr(low, order)
  1153  		high = orderexpr(high, order, nil)
  1154  		high = ordercheapexpr(high, order)
  1155  		max = orderexpr(max, order, nil)
  1156  		max = ordercheapexpr(max, order)
  1157  		n.SetSliceBounds(low, high, max)
  1158  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
  1159  			n = ordercopyexpr(n, n.Type, order, 0)
  1160  		}
  1161  
  1162  	case OCLOSURE:
  1163  		if n.Noescape() && n.Func.Cvars.Len() > 0 {
  1164  			prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type
  1165  		}
  1166  
  1167  	case OARRAYLIT, OSLICELIT, OCALLPART:
  1168  		n.Left = orderexpr(n.Left, order, nil)
  1169  		n.Right = orderexpr(n.Right, order, nil)
  1170  		orderexprlist(n.List, order)
  1171  		orderexprlist(n.Rlist, order)
  1172  		if n.Noescape() {
  1173  			prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type
  1174  		}
  1175  
  1176  	case ODDDARG:
  1177  		if n.Noescape() {
  1178  			// The ddd argument does not live beyond the call it is created for.
  1179  			// Allocate a temporary that will be cleaned up when this statement
  1180  			// completes. We could be more aggressive and try to arrange for it
  1181  			// to be cleaned up when the call completes.
  1182  			prealloc[n] = ordertemp(n.Type.Elem(), order, false)
  1183  		}
  1184  
  1185  	case ODOTTYPE, ODOTTYPE2:
  1186  		n.Left = orderexpr(n.Left, order, nil)
  1187  		// TODO(rsc): The isfat is for consistency with componentgen and walkexpr.
  1188  		// It needs to be removed in all three places.
  1189  		// That would allow inlining x.(struct{*int}) the same as x.(*int).
  1190  		if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting {
  1191  			n = ordercopyexpr(n, n.Type, order, 1)
  1192  		}
  1193  
  1194  	case ORECV:
  1195  		n.Left = orderexpr(n.Left, order, nil)
  1196  		n = ordercopyexpr(n, n.Type, order, 1)
  1197  
  1198  	case OEQ, ONE:
  1199  		n.Left = orderexpr(n.Left, order, nil)
  1200  		n.Right = orderexpr(n.Right, order, nil)
  1201  		t := n.Left.Type
  1202  		if t.IsStruct() || t.IsArray() {
  1203  			// for complex comparisons, we need both args to be
  1204  			// addressable so we can pass them to the runtime.
  1205  			n.Left = orderaddrtemp(n.Left, order)
  1206  			n.Right = orderaddrtemp(n.Right, order)
  1207  		}
  1208  	}
  1209  
  1210  	lineno = lno
  1211  	return n
  1212  }
  1213  
  1214  // okas creates and returns an assignment of val to ok,
  1215  // including an explicit conversion if necessary.
  1216  func okas(ok, val *Node) *Node {
  1217  	if !isblank(ok) {
  1218  		val = conv(val, ok.Type)
  1219  	}
  1220  	return nod(OAS, ok, val)
  1221  }
  1222  
  1223  // orderas2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment.
  1224  // The caller should order the right-hand side of the assignment before calling orderas2.
  1225  // It rewrites,
  1226  // 	a, b, a = ...
  1227  // as
  1228  //	tmp1, tmp2, tmp3 = ...
  1229  // 	a, b, a = tmp1, tmp2, tmp3
  1230  // This is necessary to ensure left to right assignment order.
  1231  func orderas2(n *Node, order *Order) {
  1232  	tmplist := []*Node{}
  1233  	left := []*Node{}
  1234  	for _, l := range n.List.Slice() {
  1235  		if !isblank(l) {
  1236  			tmp := ordertemp(l.Type, order, types.Haspointers(l.Type))
  1237  			tmplist = append(tmplist, tmp)
  1238  			left = append(left, l)
  1239  		}
  1240  	}
  1241  
  1242  	order.out = append(order.out, n)
  1243  
  1244  	as := nod(OAS2, nil, nil)
  1245  	as.List.Set(left)
  1246  	as.Rlist.Set(tmplist)
  1247  	as = typecheck(as, Etop)
  1248  	orderstmt(as, order)
  1249  
  1250  	ti := 0
  1251  	for ni, l := range n.List.Slice() {
  1252  		if !isblank(l) {
  1253  			n.List.SetIndex(ni, tmplist[ti])
  1254  			ti++
  1255  		}
  1256  	}
  1257  }
  1258  
  1259  // orderokas2 orders OAS2 with ok.
  1260  // Just like orderas2(), this also adds temporaries to ensure left-to-right assignment.
  1261  func orderokas2(n *Node, order *Order) {
  1262  	var tmp1, tmp2 *Node
  1263  	if !isblank(n.List.First()) {
  1264  		typ := n.Rlist.First().Type
  1265  		tmp1 = ordertemp(typ, order, types.Haspointers(typ))
  1266  	}
  1267  
  1268  	if !isblank(n.List.Second()) {
  1269  		tmp2 = ordertemp(types.Types[TBOOL], order, false)
  1270  	}
  1271  
  1272  	order.out = append(order.out, n)
  1273  
  1274  	if tmp1 != nil {
  1275  		r := nod(OAS, n.List.First(), tmp1)
  1276  		r = typecheck(r, Etop)
  1277  		ordermapassign(r, order)
  1278  		n.List.SetFirst(tmp1)
  1279  	}
  1280  	if tmp2 != nil {
  1281  		r := okas(n.List.Second(), tmp2)
  1282  		r = typecheck(r, Etop)
  1283  		ordermapassign(r, order)
  1284  		n.List.SetSecond(tmp2)
  1285  	}
  1286  }