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