github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/cmd/compile/internal/gc/order.go (about)

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