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