github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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  		OSTRARRAYBYTE,
  1097  		OSTRARRAYBYTETMP,
  1098  		OSTRARRAYRUNE:
  1099  		ordercall(n, order)
  1100  		if lhs == nil || lhs.Op != ONAME || instrumenting {
  1101  			n = ordercopyexpr(n, n.Type, order, 0)
  1102  		}
  1103  
  1104  	case OAPPEND:
  1105  		ordercallargs(&n.List, order)
  1106  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.N) {
  1107  			n = ordercopyexpr(n, n.Type, order, 0)
  1108  		}
  1109  
  1110  	case OSLICE, OSLICEARR, OSLICESTR:
  1111  		orderexpr(&n.Left, order, nil)
  1112  		orderexpr(&n.Right.Left, order, nil)
  1113  		n.Right.Left = ordercheapexpr(n.Right.Left, order)
  1114  		orderexpr(&n.Right.Right, order, nil)
  1115  		n.Right.Right = ordercheapexpr(n.Right.Right, order)
  1116  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
  1117  			n = ordercopyexpr(n, n.Type, order, 0)
  1118  		}
  1119  
  1120  	case OSLICE3, OSLICE3ARR:
  1121  		orderexpr(&n.Left, order, nil)
  1122  		orderexpr(&n.Right.Left, order, nil)
  1123  		n.Right.Left = ordercheapexpr(n.Right.Left, order)
  1124  		orderexpr(&n.Right.Right.Left, order, nil)
  1125  		n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
  1126  		orderexpr(&n.Right.Right.Right, order, nil)
  1127  		n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
  1128  		if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
  1129  			n = ordercopyexpr(n, n.Type, order, 0)
  1130  		}
  1131  
  1132  	case OCLOSURE:
  1133  		if n.Noescape && n.Func.Cvars != nil {
  1134  			prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
  1135  		}
  1136  
  1137  	case OARRAYLIT, OCALLPART:
  1138  		orderexpr(&n.Left, order, nil)
  1139  		orderexpr(&n.Right, order, nil)
  1140  		orderexprlist(n.List, order)
  1141  		orderexprlist(n.Rlist, order)
  1142  		if n.Noescape {
  1143  			prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
  1144  		}
  1145  
  1146  	case ODDDARG:
  1147  		if n.Noescape {
  1148  			// The ddd argument does not live beyond the call it is created for.
  1149  			// Allocate a temporary that will be cleaned up when this statement
  1150  			// completes. We could be more aggressive and try to arrange for it
  1151  			// to be cleaned up when the call completes.
  1152  			prealloc[n] = ordertemp(n.Type.Type, order, false)
  1153  		}
  1154  
  1155  	case ODOTTYPE, ODOTTYPE2:
  1156  		orderexpr(&n.Left, order, nil)
  1157  		// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
  1158  		// It needs to be removed in all three places.
  1159  		// That would allow inlining x.(struct{*int}) the same as x.(*int).
  1160  		if !isdirectiface(n.Type) || Isfat(n.Type) || instrumenting {
  1161  			n = ordercopyexpr(n, n.Type, order, 1)
  1162  		}
  1163  
  1164  	case ORECV:
  1165  		orderexpr(&n.Left, order, nil)
  1166  		n = ordercopyexpr(n, n.Type, order, 1)
  1167  
  1168  	case OEQ, ONE:
  1169  		orderexpr(&n.Left, order, nil)
  1170  		orderexpr(&n.Right, order, nil)
  1171  		t := n.Left.Type
  1172  		if t.Etype == TSTRUCT || Isfixedarray(t) {
  1173  			// for complex comparisons, we need both args to be
  1174  			// addressable so we can pass them to the runtime.
  1175  			orderaddrtemp(&n.Left, order)
  1176  			orderaddrtemp(&n.Right, order)
  1177  		}
  1178  	}
  1179  
  1180  	lineno = int32(lno)
  1181  
  1182  	*np = n
  1183  }