// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gc

import (
	"fmt"
	"strings"
)

// Rewrite tree to use separate statements to enforce
// order of evaluation.  Makes walk easier, because it
// can (after this runs) reorder at will within an expression.
//
// Rewrite x op= y into x = x op y.
//
// Introduce temporaries as needed by runtime routines.
// For example, the map runtime routines take the map key
// by reference, so make sure all map keys are addressable
// by copying them to temporaries as needed.
// The same is true for channel operations.
//
// Arrange that map index expressions only appear in direct
// assignments x = m[k] or m[k] = x, never in larger expressions.
//
// Arrange that receive expressions only appear in direct assignments
// x = <-c or as standalone statements <-c, never in larger expressions.

// TODO(rsc): The temporary introduction during multiple assignments
// should be moved into this file, so that the temporaries can be cleaned
// and so that conversions implicit in the OAS2FUNC and OAS2RECV
// nodes can be made explicit and then have their temporaries cleaned.

// TODO(rsc): Goto and multilevel break/continue can jump over
// inserted VARKILL annotations. Work out a way to handle these.
// The current implementation is safe, in that it will execute correctly.
// But it won't reuse temporaries as aggressively as it might, and
// it can result in unnecessary zeroing of those variables in the function
// prologue.

// Order holds state during the ordering process.
type Order struct {
	out  *NodeList
	temp *NodeList
	free *NodeList
}

// Order rewrites fn->nbody to apply the ordering constraints
// described in the comment at the top of the file.
func order(fn *Node) {
	if Debug['W'] > 1 {
		s := fmt.Sprintf("\nbefore order %v", Sconv(fn.Nname.Sym, 0))
		dumplist(s, fn.Nbody)
	}

	orderblock(&fn.Nbody)
}

// Ordertemp allocates a new temporary with the given type,
// pushes it onto the temp stack, and returns it.
// If clear is true, ordertemp emits code to zero the temporary.
func ordertemp(t *Type, order *Order, clear bool) *Node {
	var_ := temp(t)
	if clear {
		a := Nod(OAS, var_, nil)
		typecheck(&a, Etop)
		order.out = list(order.out, a)
	}

	l := order.free
	if l == nil {
		l = new(NodeList)
	}
	order.free = l.Next
	l.Next = order.temp
	l.N = var_
	order.temp = l
	return var_
}

// Ordercopyexpr behaves like ordertemp but also emits
// code to initialize the temporary to the value n.
//
// The clear argument is provided for use when the evaluation
// of tmp = n turns into a function call that is passed a pointer
// to the temporary as the output space. If the call blocks before
// tmp has been written, the garbage collector will still treat the
// temporary as live, so we must zero it before entering that call.
// Today, this only happens for channel receive operations.
// (The other candidate would be map access, but map access
// returns a pointer to the result data instead of taking a pointer
// to be filled in.)
func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
	var_ := ordertemp(t, order, clear != 0)
	a := Nod(OAS, var_, n)
	typecheck(&a, Etop)
	order.out = list(order.out, a)
	return var_
}

// Ordercheapexpr returns a cheap version of n.
// The definition of cheap is that n is a variable or constant.
// If not, ordercheapexpr allocates a new tmp, emits tmp = n,
// and then returns tmp.
func ordercheapexpr(n *Node, order *Order) *Node {
	switch n.Op {
	case ONAME,
		OLITERAL:
		return n
	}

	return ordercopyexpr(n, n.Type, order, 0)
}

// Ordersafeexpr returns a safe version of n.
// The definition of safe is that n can appear multiple times
// without violating the semantics of the original program,
// and that assigning to the safe version has the same effect
// as assigning to the original n.
//
// The intended use is to apply to x when rewriting x += y into x = x + y.
func ordersafeexpr(n *Node, order *Order) *Node {
	switch n.Op {
	case ONAME,
		OLITERAL:
		return n

	case ODOT:
		l := ordersafeexpr(n.Left, order)
		if l == n.Left {
			return n
		}
		a := Nod(OXXX, nil, nil)
		*a = *n
		a.Orig = a
		a.Left = l
		typecheck(&a, Erv)
		return a

	case ODOTPTR,
		OIND:
		l := ordercheapexpr(n.Left, order)
		if l == n.Left {
			return n
		}
		a := Nod(OXXX, nil, nil)
		*a = *n
		a.Orig = a
		a.Left = l
		typecheck(&a, Erv)
		return a

	case OINDEX,
		OINDEXMAP:
		var l *Node
		if Isfixedarray(n.Left.Type) {
			l = ordersafeexpr(n.Left, order)
		} else {
			l = ordercheapexpr(n.Left, order)
		}
		r := ordercheapexpr(n.Right, order)
		if l == n.Left && r == n.Right {
			return n
		}
		a := Nod(OXXX, nil, nil)
		*a = *n
		a.Orig = a
		a.Left = l
		a.Right = r
		typecheck(&a, Erv)
		return a
	}

	Fatal("ordersafeexpr %v", Oconv(int(n.Op), 0))
	return nil // not reached
}

// Istemp reports whether n is a temporary variable.
func istemp(n *Node) bool {
	if n.Op != ONAME {
		return false
	}
	return strings.HasPrefix(n.Sym.Name, "autotmp_")
}

// Isaddrokay reports whether it is okay to pass n's address to runtime routines.
// Taking the address of a variable makes the liveness and optimization analyses
// lose track of where the variable's lifetime ends. To avoid hurting the analyses
// of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay,
// because we emit explicit VARKILL instructions marking the end of those
// temporaries' lifetimes.
func isaddrokay(n *Node) bool {
	return islvalue(n) && (n.Op != ONAME || n.Class == PEXTERN || istemp(n))
}

// Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
// If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
// tmp = *np, and then sets *np to the tmp variable.
func orderaddrtemp(np **Node, order *Order) {
	n := *np
	if isaddrokay(n) {
		return
	}
	*np = ordercopyexpr(n, n.Type, order, 0)
}

// Marktemp returns the top of the temporary variable stack.
func marktemp(order *Order) *NodeList {
	return order.temp
}

// Poptemp pops temporaries off the stack until reaching the mark,
// which must have been returned by marktemp.
func poptemp(mark *NodeList, order *Order) {
	var l *NodeList

	for {
		l = order.temp
		if l == mark {
			break
		}
		order.temp = l.Next
		l.Next = order.free
		order.free = l
	}
}

// Cleantempnopop emits to *out VARKILL instructions for each temporary
// above the mark on the temporary stack, but it does not pop them
// from the stack.
func cleantempnopop(mark *NodeList, order *Order, out **NodeList) {
	var kill *Node

	for l := order.temp; l != mark; l = l.Next {
		kill = Nod(OVARKILL, l.N, nil)
		typecheck(&kill, Etop)
		*out = list(*out, kill)
	}
}

// Cleantemp emits VARKILL instructions for each temporary above the
// mark on the temporary stack and removes them from the stack.
func cleantemp(top *NodeList, order *Order) {
	cleantempnopop(top, order, &order.out)
	poptemp(top, order)
}

// Orderstmtlist orders each of the statements in the list.
func orderstmtlist(l *NodeList, order *Order) {
	for ; l != nil; l = l.Next {
		orderstmt(l.N, order)
	}
}

// Orderblock orders the block of statements *l onto a new list,
// and then replaces *l with that list.
func orderblock(l **NodeList) {
	order := Order{}
	mark := marktemp(&order)
	orderstmtlist(*l, &order)
	cleantemp(mark, &order)
	*l = order.out
}

// Orderexprinplace orders the side effects in *np and
// leaves them as the init list of the final *np.
func orderexprinplace(np **Node, outer *Order) {
	n := *np
	order := Order{}
	orderexpr(&n, &order)
	addinit(&n, order.out)

	// insert new temporaries from order
	// at head of outer list.
	lp := &order.temp

	for *lp != nil {
		lp = &(*lp).Next
	}
	*lp = outer.temp
	outer.temp = order.temp

	*np = n
}

// Orderstmtinplace orders the side effects of the single statement *np
// and replaces it with the resulting statement list.
func orderstmtinplace(np **Node) {
	n := *np
	order := Order{}
	mark := marktemp(&order)
	orderstmt(n, &order)
	cleantemp(mark, &order)
	*np = liststmt(order.out)
}

// Orderinit moves n's init list to order->out.
func orderinit(n *Node, order *Order) {
	orderstmtlist(n.Ninit, order)
	n.Ninit = nil
}

// Ismulticall reports whether the list l is f() for a multi-value function.
// Such an f() could appear as the lone argument to a multi-arg function.
func ismulticall(l *NodeList) bool {
	// one arg only
	if l == nil || l.Next != nil {
		return false
	}
	n := l.N

	// must be call
	switch n.Op {
	default:
		return false

	case OCALLFUNC,
		OCALLMETH,
		OCALLINTER:
		break
	}

	// call must return multiple values
	return n.Left.Type.Outtuple > 1
}

// Copyret emits t1, t2, ... = n, where n is a function call,
// and then returns the list t1, t2, ....
func copyret(n *Node, order *Order) *NodeList {
	if n.Type.Etype != TSTRUCT || n.Type.Funarg == 0 {
		Fatal("copyret %v %d", Tconv(n.Type, 0), n.Left.Type.Outtuple)
	}

	l1 := (*NodeList)(nil)
	l2 := (*NodeList)(nil)
	var tl Iter
	var tmp *Node
	for t := Structfirst(&tl, &n.Type); t != nil; t = structnext(&tl) {
		tmp = temp(t.Type)
		l1 = list(l1, tmp)
		l2 = list(l2, tmp)
	}

	as := Nod(OAS2, nil, nil)
	as.List = l1
	as.Rlist = list1(n)
	typecheck(&as, Etop)
	orderstmt(as, order)

	return l2
}

// Ordercallargs orders the list of call arguments *l.
func ordercallargs(l **NodeList, order *Order) {
	if ismulticall(*l) {
		// return f() where f() is multiple values.
		*l = copyret((*l).N, order)
	} else {
		orderexprlist(*l, order)
	}
}

// Ordercall orders the call expression n.
// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
func ordercall(n *Node, order *Order) {
	orderexpr(&n.Left, order)
	orderexpr(&n.Right, order) // ODDDARG temp
	ordercallargs(&n.List, order)
}

// Ordermapassign appends n to order->out, introducing temporaries
// to make sure that all map assignments have the form m[k] = x,
// where x is adressable.
// (Orderexpr has already been called on n, so we know k is addressable.)
//
// If n is m[k] = x where x is not addressable, the rewrite is:
//	tmp = x
//	m[k] = tmp
//
// If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is
//	t1 = m
//	t2 = k
//	...., t3, ... = x
//	t1[t2] = t3
//
// The temporaries t1, t2 are needed in case the ... being assigned
// contain m or k. They are usually unnecessary, but in the unnecessary
// cases they are also typically registerizable, so not much harm done.
// And this only applies to the multiple-assignment form.
// We could do a more precise analysis if needed, like in walk.c.
//
// Ordermapassign also inserts these temporaries if needed for
// calling writebarrierfat with a pointer to n->right.
func ordermapassign(n *Node, order *Order) {
	switch n.Op {
	default:
		Fatal("ordermapassign %v", Oconv(int(n.Op), 0))

	case OAS:
		order.out = list(order.out, n)

		// We call writebarrierfat only for values > 4 pointers long. See walk.c.
		if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
			m := n.Left
			n.Left = ordertemp(m.Type, order, false)
			a := Nod(OAS, m, n.Left)
			typecheck(&a, Etop)
			order.out = list(order.out, a)
		}

	case OAS2,
		OAS2DOTTYPE,
		OAS2MAPR,
		OAS2FUNC:
		post := (*NodeList)(nil)
		var m *Node
		var a *Node
		for l := n.List; l != nil; l = l.Next {
			if l.N.Op == OINDEXMAP {
				m = l.N
				if !istemp(m.Left) {
					m.Left = ordercopyexpr(m.Left, m.Left.Type, order, 0)
				}
				if !istemp(m.Right) {
					m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
				}
				l.N = ordertemp(m.Type, order, false)
				a = Nod(OAS, m, l.N)
				typecheck(&a, Etop)
				post = list(post, a)
			}
		}

		order.out = list(order.out, n)
		order.out = concat(order.out, post)
	}
}

// Orderstmt orders the statement n, appending to order->out.
// Temporaries created during the statement are cleaned
// up using VARKILL instructions as possible.
func orderstmt(n *Node, order *Order) {
	if n == nil {
		return
	}

	lno := int(setlineno(n))

	orderinit(n, order)

	switch n.Op {
	default:
		Fatal("orderstmt %v", Oconv(int(n.Op), 0))

	case OVARKILL:
		order.out = list(order.out, n)

	case OAS,
		OAS2,
		OCLOSE,
		OCOPY,
		OPRINT,
		OPRINTN,
		ORECOVER,
		ORECV:
		t := marktemp(order)
		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)
		orderexprlist(n.List, order)
		orderexprlist(n.Rlist, order)
		switch n.Op {
		case OAS,
			OAS2,
			OAS2DOTTYPE:
			ordermapassign(n, order)

		default:
			order.out = list(order.out, n)
		}

		cleantemp(t, order)

		// Special: rewrite l op= r into l = l op r.
	// This simplies quite a few operations;
	// most important is that it lets us separate
	// out map read from map write when l is
	// a map index expression.
	case OASOP:
		t := marktemp(order)

		orderexpr(&n.Left, order)
		n.Left = ordersafeexpr(n.Left, order)
		tmp1 := treecopy(n.Left)
		if tmp1.Op == OINDEXMAP {
			tmp1.Etype = 0 // now an rvalue not an lvalue
		}
		tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
		n.Right = Nod(int(n.Etype), tmp1, n.Right)
		typecheck(&n.Right, Erv)
		orderexpr(&n.Right, order)
		n.Etype = 0
		n.Op = OAS
		ordermapassign(n, order)
		cleantemp(t, order)

		// Special: make sure key is addressable,
	// and make sure OINDEXMAP is not copied out.
	case OAS2MAPR:
		t := marktemp(order)

		orderexprlist(n.List, order)
		r := n.Rlist.N
		orderexpr(&r.Left, order)
		orderexpr(&r.Right, order)

		// See case OINDEXMAP below.
		if r.Right.Op == OARRAYBYTESTR {
			r.Right.Op = OARRAYBYTESTRTMP
		}
		orderaddrtemp(&r.Right, order)
		ordermapassign(n, order)
		cleantemp(t, order)

		// Special: avoid copy of func call n->rlist->n.
	case OAS2FUNC:
		t := marktemp(order)

		orderexprlist(n.List, order)
		ordercall(n.Rlist.N, order)
		ordermapassign(n, order)
		cleantemp(t, order)

		// Special: use temporary variables to hold result,
	// so that assertI2Tetc can take address of temporary.
	// No temporary for blank assignment.
	case OAS2DOTTYPE:
		t := marktemp(order)

		orderexprlist(n.List, order)
		orderexpr(&n.Rlist.N.Left, order) // i in i.(T)
		if isblank(n.List.N) {
			order.out = list(order.out, n)
		} else {
			typ := n.Rlist.N.Type
			tmp1 := ordertemp(typ, order, haspointers(typ))
			order.out = list(order.out, n)
			r := Nod(OAS, n.List.N, tmp1)
			typecheck(&r, Etop)
			ordermapassign(r, order)
			n.List = list(list1(tmp1), n.List.Next.N)
		}

		cleantemp(t, order)

		// Special: use temporary variables to hold result,
	// so that chanrecv can take address of temporary.
	case OAS2RECV:
		t := marktemp(order)

		orderexprlist(n.List, order)
		orderexpr(&n.Rlist.N.Left, order) // arg to recv
		ch := n.Rlist.N.Left.Type
		tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
		var tmp2 *Node
		if !isblank(n.List.Next.N) {
			tmp2 = ordertemp(n.List.Next.N.Type, order, false)
		} else {
			tmp2 = ordertemp(Types[TBOOL], order, false)
		}
		order.out = list(order.out, n)
		r := Nod(OAS, n.List.N, tmp1)
		typecheck(&r, Etop)
		ordermapassign(r, order)
		r = Nod(OAS, n.List.Next.N, tmp2)
		typecheck(&r, Etop)
		ordermapassign(r, order)
		n.List = list(list1(tmp1), tmp2)
		cleantemp(t, order)

		// Special: does not save n onto out.
	case OBLOCK,
		OEMPTY:
		orderstmtlist(n.List, order)

		// Special: n->left is not an expression; save as is.
	case OBREAK,
		OCONTINUE,
		ODCL,
		ODCLCONST,
		ODCLTYPE,
		OFALL,
		OXFALL,
		OGOTO,
		OLABEL,
		ORETJMP:
		order.out = list(order.out, n)

		// Special: handle call arguments.
	case OCALLFUNC,
		OCALLINTER,
		OCALLMETH:
		t := marktemp(order)

		ordercall(n, order)
		order.out = list(order.out, n)
		cleantemp(t, order)

		// Special: order arguments to inner call but not call itself.
	case ODEFER,
		OPROC:
		t := marktemp(order)

		switch n.Left.Op {
		// Delete will take the address of the key.
		// Copy key into new temp and do not clean it
		// (it persists beyond the statement).
		case ODELETE:
			orderexprlist(n.Left.List, order)

			t1 := marktemp(order)
			np := &n.Left.List.Next.N // map key
			*np = ordercopyexpr(*np, (*np).Type, order, 0)
			poptemp(t1, order)

		default:
			ordercall(n.Left, order)
		}

		order.out = list(order.out, n)
		cleantemp(t, order)

	case ODELETE:
		t := marktemp(order)
		orderexpr(&n.List.N, order)
		orderexpr(&n.List.Next.N, order)
		orderaddrtemp(&n.List.Next.N, order) // map key
		order.out = list(order.out, n)
		cleantemp(t, order)

		// Clean temporaries from condition evaluation at
	// beginning of loop body and after for statement.
	case OFOR:
		t := marktemp(order)

		orderexprinplace(&n.Ntest, order)
		l := (*NodeList)(nil)
		cleantempnopop(t, order, &l)
		n.Nbody = concat(l, n.Nbody)
		orderblock(&n.Nbody)
		orderstmtinplace(&n.Nincr)
		order.out = list(order.out, n)
		cleantemp(t, order)

		// Clean temporaries from condition at
	// beginning of both branches.
	case OIF:
		t := marktemp(order)

		orderexprinplace(&n.Ntest, order)
		l := (*NodeList)(nil)
		cleantempnopop(t, order, &l)
		n.Nbody = concat(l, n.Nbody)
		l = nil
		cleantempnopop(t, order, &l)
		n.Nelse = concat(l, n.Nelse)
		poptemp(t, order)
		orderblock(&n.Nbody)
		orderblock(&n.Nelse)
		order.out = list(order.out, n)

		// Special: argument will be converted to interface using convT2E
	// so make sure it is an addressable temporary.
	case OPANIC:
		t := marktemp(order)

		orderexpr(&n.Left, order)
		if !Isinter(n.Left.Type) {
			orderaddrtemp(&n.Left, order)
		}
		order.out = list(order.out, n)
		cleantemp(t, order)

		// n->right is the expression being ranged over.
	// order it, and then make a copy if we need one.
	// We almost always do, to ensure that we don't
	// see any value changes made during the loop.
	// Usually the copy is cheap (e.g., array pointer, chan, slice, string are all tiny).
	// The exception is ranging over an array value (not a slice, not a pointer to array),
	// which must make a copy to avoid seeing updates made during
	// the range body. Ranging over an array value is uncommon though.
	case ORANGE:
		t := marktemp(order)

		orderexpr(&n.Right, order)
		switch n.Type.Etype {
		default:
			Fatal("orderstmt range %v", Tconv(n.Type, 0))

			// Mark []byte(str) range expression to reuse string backing storage.
		// It is safe because the storage cannot be mutated.
		case TARRAY:
			if n.Right.Op == OSTRARRAYBYTE {
				n.Right.Op = OSTRARRAYBYTETMP
			}
			if count(n.List) < 2 || isblank(n.List.Next.N) {
				// for i := range x will only use x once, to compute len(x).
				// No need to copy it.
				break
			}
			fallthrough

			// chan, string, slice, array ranges use value multiple times.
		// make copy.
		// fall through
		case TCHAN,
			TSTRING:
			r := n.Right

			if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] {
				r = Nod(OCONV, r, nil)
				r.Type = Types[TSTRING]
				typecheck(&r, Erv)
			}

			n.Right = ordercopyexpr(r, r.Type, order, 0)

			// copy the map value in case it is a map literal.
		// TODO(rsc): Make tmp = literal expressions reuse tmp.
		// For maps tmp is just one word so it hardly matters.
		case TMAP:
			r := n.Right

			n.Right = ordercopyexpr(r, r.Type, order, 0)

			// n->alloc is the temp for the iterator.
			n.Alloc = ordertemp(Types[TUINT8], order, true)
		}

		for l := n.List; l != nil; l = l.Next {
			orderexprinplace(&l.N, order)
		}
		orderblock(&n.Nbody)
		order.out = list(order.out, n)
		cleantemp(t, order)

	case ORETURN:
		ordercallargs(&n.List, order)
		order.out = list(order.out, n)

		// Special: clean case temporaries in each block entry.
	// Select must enter one of its blocks, so there is no
	// need for a cleaning at the end.
	// Doubly special: evaluation order for select is stricter
	// than ordinary expressions. Even something like p.c
	// has to be hoisted into a temporary, so that it cannot be
	// reordered after the channel evaluation for a different
	// case (if p were nil, then the timing of the fault would
	// give this away).
	case OSELECT:
		t := marktemp(order)

		var tmp1 *Node
		var tmp2 *Node
		var r *Node
		for l := n.List; l != nil; l = l.Next {
			if l.N.Op != OXCASE {
				Fatal("order select case %v", Oconv(int(l.N.Op), 0))
			}
			r = l.N.Left
			setlineno(l.N)

			// Append any new body prologue to ninit.
			// The next loop will insert ninit into nbody.
			if l.N.Ninit != nil {
				Fatal("order select ninit")
			}
			if r != nil {
				switch r.Op {
				default:
					Yyerror("unknown op in select %v", Oconv(int(r.Op), 0))
					Dump("select case", r)

					// If this is case x := <-ch or case x, y := <-ch, the case has
				// the ODCL nodes to declare x and y. We want to delay that
				// declaration (and possible allocation) until inside the case body.
				// Delete the ODCL nodes here and recreate them inside the body below.
				case OSELRECV,
					OSELRECV2:
					if r.Colas != 0 {
						t = r.Ninit
						if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
							t = t.Next
						}
						if t != nil && t.N.Op == ODCL && t.N.Left == r.Ntest {
							t = t.Next
						}
						if t == nil {
							r.Ninit = nil
						}
					}

					if r.Ninit != nil {
						Yyerror("ninit on select recv")
						dumplist("ninit", r.Ninit)
					}

					// case x = <-c
					// case x, ok = <-c
					// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
					// r->left == N means 'case <-c'.
					// c is always evaluated; x and ok are only evaluated when assigned.
					orderexpr(&r.Right.Left, order)

					if r.Right.Left.Op != ONAME {
						r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
					}

					// Introduce temporary for receive and move actual copy into case body.
					// avoids problems with target being addressed, as usual.
					// NOTE: If we wanted to be clever, we could arrange for just one
					// temporary per distinct type, sharing the temp among all receives
					// with that temp. Similarly one ok bool could be shared among all
					// the x,ok receives. Not worth doing until there's a clear need.
					if r.Left != nil && isblank(r.Left) {
						r.Left = nil
					}
					if r.Left != nil {
						// use channel element type for temporary to avoid conversions,
						// such as in case interfacevalue = <-intchan.
						// the conversion happens in the OAS instead.
						tmp1 = r.Left

						if r.Colas != 0 {
							tmp2 = Nod(ODCL, tmp1, nil)
							typecheck(&tmp2, Etop)
							l.N.Ninit = list(l.N.Ninit, tmp2)
						}

						r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type))
						tmp2 = Nod(OAS, tmp1, r.Left)
						typecheck(&tmp2, Etop)
						l.N.Ninit = list(l.N.Ninit, tmp2)
					}

					if r.Ntest != nil && isblank(r.Ntest) {
						r.Ntest = nil
					}
					if r.Ntest != nil {
						tmp1 = r.Ntest
						if r.Colas != 0 {
							tmp2 = Nod(ODCL, tmp1, nil)
							typecheck(&tmp2, Etop)
							l.N.Ninit = list(l.N.Ninit, tmp2)
						}

						r.Ntest = ordertemp(tmp1.Type, order, false)
						tmp2 = Nod(OAS, tmp1, r.Ntest)
						typecheck(&tmp2, Etop)
						l.N.Ninit = list(l.N.Ninit, tmp2)
					}

					orderblock(&l.N.Ninit)

				case OSEND:
					if r.Ninit != nil {
						Yyerror("ninit on select send")
						dumplist("ninit", r.Ninit)
					}

					// case c <- x
					// r->left is c, r->right is x, both are always evaluated.
					orderexpr(&r.Left, order)

					if !istemp(r.Left) {
						r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
					}
					orderexpr(&r.Right, order)
					if !istemp(r.Right) {
						r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
					}
				}
			}

			orderblock(&l.N.Nbody)
		}

		// Now that we have accumulated all the temporaries, clean them.
		// Also insert any ninit queued during the previous loop.
		// (The temporary cleaning must follow that ninit work.)
		for l := n.List; l != nil; l = l.Next {
			cleantempnopop(t, order, &l.N.Ninit)
			l.N.Nbody = concat(l.N.Ninit, l.N.Nbody)
			l.N.Ninit = nil
		}

		order.out = list(order.out, n)
		poptemp(t, order)

		// Special: value being sent is passed as a pointer; make it addressable.
	case OSEND:
		t := marktemp(order)

		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)
		orderaddrtemp(&n.Right, order)
		order.out = list(order.out, n)
		cleantemp(t, order)

		// TODO(rsc): Clean temporaries more aggressively.
	// Note that because walkswitch will rewrite some of the
	// switch into a binary search, this is not as easy as it looks.
	// (If we ran that code here we could invoke orderstmt on
	// the if-else chain instead.)
	// For now just clean all the temporaries at the end.
	// In practice that's fine.
	case OSWITCH:
		t := marktemp(order)

		orderexpr(&n.Ntest, order)
		for l := n.List; l != nil; l = l.Next {
			if l.N.Op != OXCASE {
				Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
			}
			orderexprlistinplace(l.N.List, order)
			orderblock(&l.N.Nbody)
		}

		order.out = list(order.out, n)
		cleantemp(t, order)
	}

	lineno = int32(lno)
}

// Orderexprlist orders the expression list l into order.
func orderexprlist(l *NodeList, order *Order) {
	for ; l != nil; l = l.Next {
		orderexpr(&l.N, order)
	}
}

// Orderexprlist orders the expression list l but saves
// the side effects on the individual expression ninit lists.
func orderexprlistinplace(l *NodeList, order *Order) {
	for ; l != nil; l = l.Next {
		orderexprinplace(&l.N, order)
	}
}

// Orderexpr orders a single expression, appending side
// effects to order->out as needed.
func orderexpr(np **Node, order *Order) {
	n := *np
	if n == nil {
		return
	}

	lno := int(setlineno(n))
	orderinit(n, order)

	switch n.Op {
	default:
		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)
		orderexprlist(n.List, order)
		orderexprlist(n.Rlist, order)

		// Addition of strings turns into a function call.
	// Allocate a temporary to hold the strings.
	// Fewer than 5 strings use direct runtime helpers.
	case OADDSTR:
		orderexprlist(n.List, order)

		if count(n.List) > 5 {
			t := typ(TARRAY)
			t.Bound = int64(count(n.List))
			t.Type = Types[TSTRING]
			n.Alloc = ordertemp(t, order, false)
		}

		// Mark string(byteSlice) arguments to reuse byteSlice backing
		// buffer during conversion. String concatenation does not
		// memorize the strings for later use, so it is safe.
		// However, we can do it only if there is at least one non-empty string literal.
		// Otherwise if all other arguments are empty strings,
		// concatstrings will return the reference to the temp string
		// to the caller.
		hasbyte := false

		haslit := false
		for l := n.List; l != nil; l = l.Next {
			hasbyte = hasbyte || l.N.Op == OARRAYBYTESTR
			haslit = haslit || l.N.Op == OLITERAL && len(l.N.Val.U.Sval.S) != 0
		}

		if haslit && hasbyte {
			for l := n.List; l != nil; l = l.Next {
				if l.N.Op == OARRAYBYTESTR {
					l.N.Op = OARRAYBYTESTRTMP
				}
			}
		}

	case OCMPSTR:
		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)

		// Mark string(byteSlice) arguments to reuse byteSlice backing
		// buffer during conversion. String comparison does not
		// memorize the strings for later use, so it is safe.
		if n.Left.Op == OARRAYBYTESTR {
			n.Left.Op = OARRAYBYTESTRTMP
		}
		if n.Right.Op == OARRAYBYTESTR {
			n.Right.Op = OARRAYBYTESTRTMP
		}

		// key must be addressable
	case OINDEXMAP:
		orderexpr(&n.Left, order)

		orderexpr(&n.Right, order)

		// For x = m[string(k)] where k is []byte, the allocation of
		// backing bytes for the string can be avoided by reusing
		// the []byte backing array. This is a special case that it
		// would be nice to handle more generally, but because
		// there are no []byte-keyed maps, this specific case comes
		// up in important cases in practice. See issue 3512.
		// Nothing can change the []byte we are not copying before
		// the map index, because the map access is going to
		// be forced to happen immediately following this
		// conversion (by the ordercopyexpr a few lines below).
		if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
			n.Right.Op = OARRAYBYTESTRTMP
		}

		orderaddrtemp(&n.Right, order)
		if n.Etype == 0 {
			// use of value (not being assigned);
			// make copy in temporary.
			n = ordercopyexpr(n, n.Type, order, 0)
		}

		// concrete type (not interface) argument must be addressable
	// temporary to pass to runtime.
	case OCONVIFACE:
		orderexpr(&n.Left, order)

		if !Isinter(n.Left.Type) {
			orderaddrtemp(&n.Left, order)
		}

	case OANDAND,
		OOROR:
		mark := marktemp(order)
		orderexpr(&n.Left, order)

		// Clean temporaries from first branch at beginning of second.
		// Leave them on the stack so that they can be killed in the outer
		// context in case the short circuit is taken.
		l := (*NodeList)(nil)

		cleantempnopop(mark, order, &l)
		n.Right.Ninit = concat(l, n.Right.Ninit)
		orderexprinplace(&n.Right, order)

	case OAPPEND,
		OCALLFUNC,
		OCALLINTER,
		OCALLMETH,
		OCAP,
		OCOMPLEX,
		OCOPY,
		OIMAG,
		OLEN,
		OMAKECHAN,
		OMAKEMAP,
		OMAKESLICE,
		ONEW,
		OREAL,
		ORECOVER:
		ordercall(n, order)
		n = ordercopyexpr(n, n.Type, order, 0)

	case OCLOSURE:
		if n.Noescape && n.Cvars != nil {
			n.Alloc = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
		}

	case OARRAYLIT,
		OCALLPART:
		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)
		orderexprlist(n.List, order)
		orderexprlist(n.Rlist, order)
		if n.Noescape {
			n.Alloc = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
		}

	case ODDDARG:
		if n.Noescape {
			// The ddd argument does not live beyond the call it is created for.
			// Allocate a temporary that will be cleaned up when this statement
			// completes. We could be more aggressive and try to arrange for it
			// to be cleaned up when the call completes.
			n.Alloc = ordertemp(n.Type.Type, order, false)
		}

	case ORECV,
		ODOTTYPE:
		orderexpr(&n.Left, order)
		n = ordercopyexpr(n, n.Type, order, 1)

	case OEQ,
		ONE:
		orderexpr(&n.Left, order)
		orderexpr(&n.Right, order)
		t := n.Left.Type
		if t.Etype == TSTRUCT || Isfixedarray(t) {
			// for complex comparisons, we need both args to be
			// addressable so we can pass them to the runtime.
			orderaddrtemp(&n.Left, order)

			orderaddrtemp(&n.Right, order)
		}
	}

	lineno = int32(lno)

	*np = n
}
