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