github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/order.go (about)

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