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