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