// 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 // list of generated statements
	temp *NodeList // head of stack of temporary variables
	free *NodeList // free list of NodeList* structs (for use in temp)
}

// 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) {
	var 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
	var 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
	var 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)
	}

	var l1 *NodeList
	var l2 *NodeList
	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:
		var post *NodeList
		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)
		var l *NodeList
		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)
		var l *NodeList
		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) != 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.
		var l *NodeList

		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 ODOTTYPE, ODOTTYPE2:
		orderexpr(&n.Left, order)
		// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
		// It needs to be removed in all three places.
		// That would allow inlining x.(struct{*int}) the same as x.(*int).
		if !isdirectiface(n.Type) || Isfat(n.Type) || flag_race != 0 {
			n = ordercopyexpr(n, n.Type, order, 1)
		}

	case ORECV:
		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
}
