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