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.
12 // Rewrite tree to use separate statements to enforce
13 // order of evaluation. Makes walk easier, because it
14 // can (after this runs) reorder at will within an expression.
16 // Rewrite x op= y into x = x op y.
18 // Introduce temporaries as needed by runtime routines.
19 // For example, the map runtime routines take the map key
20 // by reference, so make sure all map keys are addressable
21 // by copying them to temporaries as needed.
22 // The same is true for channel operations.
24 // Arrange that map index expressions only appear in direct
25 // assignments x = m[k] or m[k] = x, never in larger expressions.
27 // Arrange that receive expressions only appear in direct assignments
28 // x = <-c or as standalone statements <-c, never in larger expressions.
30 // TODO(rsc): The temporary introduction during multiple assignments
31 // should be moved into this file, so that the temporaries can be cleaned
32 // and so that conversions implicit in the OAS2FUNC and OAS2RECV
33 // nodes can be made explicit and then have their temporaries cleaned.
35 // TODO(rsc): Goto and multilevel break/continue can jump over
36 // inserted VARKILL annotations. Work out a way to handle these.
37 // The current implementation is safe, in that it will execute correctly.
38 // But it won't reuse temporaries as aggressively as it might, and
39 // it can result in unnecessary zeroing of those variables in the function
42 // Order holds state during the ordering process.
44 out *NodeList // list of generated statements
45 temp []*Node // stack of temporary variables
48 // Order rewrites fn->nbody to apply the ordering constraints
49 // described in the comment at the top of the file.
50 func order(fn *Node) {
52 s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
59 // Ordertemp allocates a new temporary with the given type,
60 // pushes it onto the temp stack, and returns it.
61 // If clear is true, ordertemp emits code to zero the temporary.
62 func ordertemp(t *Type, order *Order, clear bool) *Node {
65 a := Nod(OAS, var_, nil)
67 order.out = list(order.out, a)
70 order.temp = append(order.temp, var_)
74 // Ordercopyexpr behaves like ordertemp but also emits
75 // code to initialize the temporary to the value n.
77 // The clear argument is provided for use when the evaluation
78 // of tmp = n turns into a function call that is passed a pointer
79 // to the temporary as the output space. If the call blocks before
80 // tmp has been written, the garbage collector will still treat the
81 // temporary as live, so we must zero it before entering that call.
82 // Today, this only happens for channel receive operations.
83 // (The other candidate would be map access, but map access
84 // returns a pointer to the result data instead of taking a pointer
86 func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
87 var_ := ordertemp(t, order, clear != 0)
88 a := Nod(OAS, var_, n)
90 order.out = list(order.out, a)
94 // Ordercheapexpr returns a cheap version of n.
95 // The definition of cheap is that n is a variable or constant.
96 // If not, ordercheapexpr allocates a new tmp, emits tmp = n,
97 // and then returns tmp.
98 func ordercheapexpr(n *Node, order *Order) *Node {
103 case ONAME, OLITERAL:
106 l := ordercheapexpr(n.Left, order)
110 a := Nod(OXXX, nil, nil)
118 return ordercopyexpr(n, n.Type, order, 0)
121 // Ordersafeexpr returns a safe version of n.
122 // The definition of safe is that n can appear multiple times
123 // without violating the semantics of the original program,
124 // and that assigning to the safe version has the same effect
125 // as assigning to the original n.
127 // The intended use is to apply to x when rewriting x += y into x = x + y.
128 func ordersafeexpr(n *Node, order *Order) *Node {
130 case ONAME, OLITERAL:
133 case ODOT, OLEN, OCAP:
134 l := ordersafeexpr(n.Left, order)
138 a := Nod(OXXX, nil, nil)
146 l := ordercheapexpr(n.Left, order)
150 a := Nod(OXXX, nil, nil)
157 case OINDEX, OINDEXMAP:
159 if Isfixedarray(n.Left.Type) {
160 l = ordersafeexpr(n.Left, order)
162 l = ordercheapexpr(n.Left, order)
164 r := ordercheapexpr(n.Right, order)
165 if l == n.Left && r == n.Right {
168 a := Nod(OXXX, nil, nil)
177 Fatalf("ordersafeexpr %v", Oconv(int(n.Op), 0))
178 return nil // not reached
181 // Istemp reports whether n is a temporary variable.
182 func istemp(n *Node) bool {
186 return strings.HasPrefix(n.Sym.Name, "autotmp_")
189 // Isaddrokay reports whether it is okay to pass n's address to runtime routines.
190 // Taking the address of a variable makes the liveness and optimization analyses
191 // lose track of where the variable's lifetime ends. To avoid hurting the analyses
192 // of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay,
193 // because we emit explicit VARKILL instructions marking the end of those
194 // temporaries' lifetimes.
195 func isaddrokay(n *Node) bool {
196 return islvalue(n) && (n.Op != ONAME || n.Class == PEXTERN || istemp(n))
199 // Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
200 // If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
201 // tmp = *np, and then sets *np to the tmp variable.
202 func orderaddrtemp(np **Node, order *Order) {
207 *np = ordercopyexpr(n, n.Type, order, 0)
212 // Marktemp returns the top of the temporary variable stack.
213 func marktemp(order *Order) ordermarker {
214 return ordermarker(len(order.temp))
217 // Poptemp pops temporaries off the stack until reaching the mark,
218 // which must have been returned by marktemp.
219 func poptemp(mark ordermarker, order *Order) {
220 order.temp = order.temp[:mark]
223 // Cleantempnopop emits to *out VARKILL instructions for each temporary
224 // above the mark on the temporary stack, but it does not pop them
226 func cleantempnopop(mark ordermarker, order *Order, out **NodeList) {
229 for i := len(order.temp) - 1; i >= int(mark); i-- {
231 if n.Name.Keepalive {
232 n.Name.Keepalive = false
233 n.Addrtaken = true // ensure SSA keeps the n variable
234 kill = Nod(OVARLIVE, n, nil)
235 typecheck(&kill, Etop)
236 *out = list(*out, kill)
238 kill = Nod(OVARKILL, n, nil)
239 typecheck(&kill, Etop)
240 *out = list(*out, kill)
244 // Cleantemp emits VARKILL instructions for each temporary above the
245 // mark on the temporary stack and removes them from the stack.
246 func cleantemp(top ordermarker, order *Order) {
247 cleantempnopop(top, order, &order.out)
251 // Orderstmtlist orders each of the statements in the list.
252 func orderstmtlist(l *NodeList, order *Order) {
253 for ; l != nil; l = l.Next {
254 orderstmt(l.N, order)
258 // Orderblock orders the block of statements *l onto a new list,
259 // and then replaces *l with that list.
260 func orderblock(l **NodeList) {
262 mark := marktemp(&order)
263 orderstmtlist(*l, &order)
264 cleantemp(mark, &order)
268 // Orderexprinplace orders the side effects in *np and
269 // leaves them as the init list of the final *np.
270 func orderexprinplace(np **Node, outer *Order) {
273 orderexpr(&n, &order, nil)
274 addinit(&n, order.out)
276 // insert new temporaries from order
277 // at head of outer list.
278 outer.temp = append(outer.temp, order.temp...)
283 // Orderstmtinplace orders the side effects of the single statement *np
284 // and replaces it with the resulting statement list.
285 func orderstmtinplace(np **Node) {
288 mark := marktemp(&order)
290 cleantemp(mark, &order)
291 *np = liststmt(order.out)
294 // Orderinit moves n's init list to order->out.
295 func orderinit(n *Node, order *Order) {
296 orderstmtlist(n.Ninit, order)
300 // Ismulticall reports whether the list l is f() for a multi-value function.
301 // Such an f() could appear as the lone argument to a multi-arg function.
302 func ismulticall(l *NodeList) bool {
304 if l == nil || l.Next != nil {
314 case OCALLFUNC, OCALLMETH, OCALLINTER:
318 // call must return multiple values
319 return n.Left.Type.Outtuple > 1
322 // Copyret emits t1, t2, ... = n, where n is a function call,
323 // and then returns the list t1, t2, ....
324 func copyret(n *Node, order *Order) *NodeList {
325 if n.Type.Etype != TSTRUCT || !n.Type.Funarg {
326 Fatalf("copyret %v %d", n.Type, n.Left.Type.Outtuple)
333 for t := Structfirst(&tl, &n.Type); t != nil; t = structnext(&tl) {
339 as := Nod(OAS2, nil, nil)
348 // Ordercallargs orders the list of call arguments *l.
349 func ordercallargs(l **NodeList, order *Order) {
351 // return f() where f() is multiple values.
352 *l = copyret((*l).N, order)
354 orderexprlist(*l, order)
358 // Ordercall orders the call expression n.
359 // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
360 func ordercall(n *Node, order *Order) {
361 orderexpr(&n.Left, order, nil)
362 orderexpr(&n.Right, order, nil) // ODDDARG temp
363 ordercallargs(&n.List, order)
365 if n.Op == OCALLFUNC {
366 for l, t := n.List, getinargx(n.Left.Type).Type; l != nil && t != nil; l, t = l.Next, t.Down {
367 // Check for "unsafe-uintptr" tag provided by escape analysis.
368 // If present and the argument is really a pointer being converted
369 // to uintptr, arrange for the pointer to be kept alive until the call
370 // returns, by copying it into a temp and marking that temp
371 // still alive when we pop the temp stack.
372 if t.Note != nil && *t.Note == unsafeUintptrTag {
374 for (*xp).Op == OCONVNOP && !Isptr[(*xp).Type.Etype] {
378 if Isptr[x.Type.Etype] {
379 x = ordercopyexpr(x, x.Type, order, 0)
380 x.Name.Keepalive = true
388 // Ordermapassign appends n to order->out, introducing temporaries
389 // to make sure that all map assignments have the form m[k] = x,
390 // where x is addressable.
391 // (Orderexpr has already been called on n, so we know k is addressable.)
393 // If n is m[k] = x where x is not addressable, the rewrite is:
397 // If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is
403 // The temporaries t1, t2 are needed in case the ... being assigned
404 // contain m or k. They are usually unnecessary, but in the unnecessary
405 // cases they are also typically registerizable, so not much harm done.
406 // And this only applies to the multiple-assignment form.
407 // We could do a more precise analysis if needed, like in walk.go.
409 // Ordermapassign also inserts these temporaries if needed for
410 // calling writebarrierfat with a pointer to n->right.
411 func ordermapassign(n *Node, order *Order) {
414 Fatalf("ordermapassign %v", Oconv(int(n.Op), 0))
417 order.out = list(order.out, n)
419 // We call writebarrierfat only for values > 4 pointers long. See walk.go.
420 if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
422 n.Left = ordertemp(m.Type, order, false)
423 a := Nod(OAS, m, n.Left)
425 order.out = list(order.out, a)
428 case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
432 for l := n.List; l != nil; l = l.Next {
433 if l.N.Op == OINDEXMAP {
436 m.Left = ordercopyexpr(m.Left, m.Left.Type, order, 0)
438 if !istemp(m.Right) {
439 m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
441 l.N = ordertemp(m.Type, order, false)
445 } else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
447 l.N = ordertemp(m.Type, order, false)
454 order.out = list(order.out, n)
455 order.out = concat(order.out, post)
459 // Orderstmt orders the statement n, appending to order->out.
460 // Temporaries created during the statement are cleaned
461 // up using VARKILL instructions as possible.
462 func orderstmt(n *Node, order *Order) {
467 lno := int(setlineno(n))
473 Fatalf("orderstmt %v", Oconv(int(n.Op), 0))
475 case OVARKILL, OVARLIVE:
476 order.out = list(order.out, n)
480 orderexpr(&n.Left, order, nil)
481 orderexpr(&n.Right, order, n.Left)
482 ordermapassign(n, order)
493 orderexpr(&n.Left, order, nil)
494 orderexpr(&n.Right, order, nil)
495 orderexprlist(n.List, order)
496 orderexprlist(n.Rlist, order)
498 case OAS2, OAS2DOTTYPE:
499 ordermapassign(n, order)
501 order.out = list(order.out, n)
506 // Special: rewrite l op= r into l = l op r.
507 // This simplifies quite a few operations;
508 // most important is that it lets us separate
509 // out map read from map write when l is
510 // a map index expression.
513 orderexpr(&n.Left, order, nil)
514 n.Left = ordersafeexpr(n.Left, order)
515 tmp1 := treecopy(n.Left, 0)
516 if tmp1.Op == OINDEXMAP {
517 tmp1.Etype = 0 // now an rvalue not an lvalue
519 tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
520 // TODO(marvin): Fix Node.EType type union.
521 n.Right = Nod(Op(n.Etype), tmp1, n.Right)
522 typecheck(&n.Right, Erv)
523 orderexpr(&n.Right, order, nil)
526 ordermapassign(n, order)
529 // Special: make sure key is addressable,
530 // and make sure OINDEXMAP is not copied out.
534 orderexprlist(n.List, order)
536 orderexpr(&r.Left, order, nil)
537 orderexpr(&r.Right, order, nil)
539 // See case OINDEXMAP below.
540 if r.Right.Op == OARRAYBYTESTR {
541 r.Right.Op = OARRAYBYTESTRTMP
543 orderaddrtemp(&r.Right, order)
544 ordermapassign(n, order)
547 // Special: avoid copy of func call n->rlist->n.
551 orderexprlist(n.List, order)
552 ordercall(n.Rlist.N, order)
553 ordermapassign(n, order)
556 // Special: use temporary variables to hold result,
557 // so that assertI2Tetc can take address of temporary.
558 // No temporary for blank assignment.
562 orderexprlist(n.List, order)
563 orderexpr(&n.Rlist.N.Left, order, nil) // i in i.(T)
564 if isblank(n.List.N) {
565 order.out = list(order.out, n)
567 typ := n.Rlist.N.Type
568 tmp1 := ordertemp(typ, order, haspointers(typ))
569 order.out = list(order.out, n)
570 r := Nod(OAS, n.List.N, tmp1)
572 ordermapassign(r, order)
573 n.List = list(list1(tmp1), n.List.Next.N)
578 // Special: use temporary variables to hold result,
579 // so that chanrecv can take address of temporary.
583 orderexprlist(n.List, order)
584 orderexpr(&n.Rlist.N.Left, order, nil) // arg to recv
585 ch := n.Rlist.N.Left.Type
586 tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
588 if !isblank(n.List.Next.N) {
589 tmp2 = ordertemp(n.List.Next.N.Type, order, false)
591 tmp2 = ordertemp(Types[TBOOL], order, false)
593 order.out = list(order.out, n)
594 r := Nod(OAS, n.List.N, tmp1)
596 ordermapassign(r, order)
597 r = Nod(OAS, n.List.Next.N, tmp2)
599 ordermapassign(r, order)
600 n.List = list(list1(tmp1), tmp2)
603 // Special: does not save n onto out.
605 orderstmtlist(n.List, order)
607 // Special: n->left is not an expression; save as is.
618 order.out = list(order.out, n)
620 // Special: handle call arguments.
621 case OCALLFUNC, OCALLINTER, OCALLMETH:
625 order.out = list(order.out, n)
628 // Special: order arguments to inner call but not call itself.
633 // Delete will take the address of the key.
634 // Copy key into new temp and do not clean it
635 // (it persists beyond the statement).
637 orderexprlist(n.Left.List, order)
639 t1 := marktemp(order)
640 np := &n.Left.List.Next.N // map key
641 *np = ordercopyexpr(*np, (*np).Type, order, 0)
645 ordercall(n.Left, order)
648 order.out = list(order.out, n)
653 orderexpr(&n.List.N, order, nil)
654 orderexpr(&n.List.Next.N, order, nil)
655 orderaddrtemp(&n.List.Next.N, order) // map key
656 order.out = list(order.out, n)
659 // Clean temporaries from condition evaluation at
660 // beginning of loop body and after for statement.
664 orderexprinplace(&n.Left, order)
666 cleantempnopop(t, order, &l)
667 n.Nbody = concat(l, n.Nbody)
669 orderstmtinplace(&n.Right)
670 order.out = list(order.out, n)
673 // Clean temporaries from condition at
674 // beginning of both branches.
678 orderexprinplace(&n.Left, order)
680 cleantempnopop(t, order, &l)
681 n.Nbody = concat(l, n.Nbody)
683 cleantempnopop(t, order, &l)
684 n.Rlist = concat(l, n.Rlist)
688 order.out = list(order.out, n)
690 // Special: argument will be converted to interface using convT2E
691 // so make sure it is an addressable temporary.
695 orderexpr(&n.Left, order, nil)
696 if !Isinter(n.Left.Type) {
697 orderaddrtemp(&n.Left, order)
699 order.out = list(order.out, n)
702 // n->right is the expression being ranged over.
703 // order it, and then make a copy if we need one.
704 // We almost always do, to ensure that we don't
705 // see any value changes made during the loop.
706 // Usually the copy is cheap (e.g., array pointer, chan, slice, string are all tiny).
707 // The exception is ranging over an array value (not a slice, not a pointer to array),
708 // which must make a copy to avoid seeing updates made during
709 // the range body. Ranging over an array value is uncommon though.
713 orderexpr(&n.Right, order, nil)
714 switch n.Type.Etype {
716 Fatalf("orderstmt range %v", n.Type)
718 // Mark []byte(str) range expression to reuse string backing storage.
719 // It is safe because the storage cannot be mutated.
721 if n.Right.Op == OSTRARRAYBYTE {
722 n.Right.Op = OSTRARRAYBYTETMP
724 if count(n.List) < 2 || isblank(n.List.Next.N) {
725 // for i := range x will only use x once, to compute len(x).
726 // No need to copy it.
731 // chan, string, slice, array ranges use value multiple times.
737 if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] {
738 r = Nod(OCONV, r, nil)
739 r.Type = Types[TSTRING]
743 n.Right = ordercopyexpr(r, r.Type, order, 0)
745 // copy the map value in case it is a map literal.
746 // TODO(rsc): Make tmp = literal expressions reuse tmp.
747 // For maps tmp is just one word so it hardly matters.
751 n.Right = ordercopyexpr(r, r.Type, order, 0)
753 // n->alloc is the temp for the iterator.
754 prealloc[n] = ordertemp(Types[TUINT8], order, true)
757 for l := n.List; l != nil; l = l.Next {
758 orderexprinplace(&l.N, order)
761 order.out = list(order.out, n)
765 ordercallargs(&n.List, order)
766 order.out = list(order.out, n)
768 // Special: clean case temporaries in each block entry.
769 // Select must enter one of its blocks, so there is no
770 // need for a cleaning at the end.
771 // Doubly special: evaluation order for select is stricter
772 // than ordinary expressions. Even something like p.c
773 // has to be hoisted into a temporary, so that it cannot be
774 // reordered after the channel evaluation for a different
775 // case (if p were nil, then the timing of the fault would
783 for l := n.List; l != nil; l = l.Next {
784 if l.N.Op != OXCASE {
785 Fatalf("order select case %v", Oconv(int(l.N.Op), 0))
790 // Append any new body prologue to ninit.
791 // The next loop will insert ninit into nbody.
792 if l.N.Ninit != nil {
793 Fatalf("order select ninit")
798 Yyerror("unknown op in select %v", Oconv(int(r.Op), 0))
799 Dump("select case", r)
801 // If this is case x := <-ch or case x, y := <-ch, the case has
802 // the ODCL nodes to declare x and y. We want to delay that
803 // declaration (and possible allocation) until inside the case body.
804 // Delete the ODCL nodes here and recreate them inside the body below.
805 case OSELRECV, OSELRECV2:
808 if init != nil && init.N.Op == ODCL && init.N.Left == r.Left {
811 if init != nil && init.N.Op == ODCL && r.List != nil && init.N.Left == r.List.N {
820 Yyerror("ninit on select recv")
821 dumplist("ninit", r.Ninit)
826 // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
827 // r->left == N means 'case <-c'.
828 // c is always evaluated; x and ok are only evaluated when assigned.
829 orderexpr(&r.Right.Left, order, nil)
831 if r.Right.Left.Op != ONAME {
832 r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
835 // Introduce temporary for receive and move actual copy into case body.
836 // avoids problems with target being addressed, as usual.
837 // NOTE: If we wanted to be clever, we could arrange for just one
838 // temporary per distinct type, sharing the temp among all receives
839 // with that temp. Similarly one ok bool could be shared among all
840 // the x,ok receives. Not worth doing until there's a clear need.
841 if r.Left != nil && isblank(r.Left) {
845 // use channel element type for temporary to avoid conversions,
846 // such as in case interfacevalue = <-intchan.
847 // the conversion happens in the OAS instead.
851 tmp2 = Nod(ODCL, tmp1, nil)
852 typecheck(&tmp2, Etop)
853 l.N.Ninit = list(l.N.Ninit, tmp2)
856 r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type))
857 tmp2 = Nod(OAS, tmp1, r.Left)
858 typecheck(&tmp2, Etop)
859 l.N.Ninit = list(l.N.Ninit, tmp2)
862 if r.List != nil && isblank(r.List.N) {
868 tmp2 = Nod(ODCL, tmp1, nil)
869 typecheck(&tmp2, Etop)
870 l.N.Ninit = list(l.N.Ninit, tmp2)
873 r.List = list1(ordertemp(tmp1.Type, order, false))
874 tmp2 = Nod(OAS, tmp1, r.List.N)
875 typecheck(&tmp2, Etop)
876 l.N.Ninit = list(l.N.Ninit, tmp2)
879 orderblock(&l.N.Ninit)
883 Yyerror("ninit on select send")
884 dumplist("ninit", r.Ninit)
888 // r->left is c, r->right is x, both are always evaluated.
889 orderexpr(&r.Left, order, nil)
892 r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
894 orderexpr(&r.Right, order, nil)
895 if !istemp(r.Right) {
896 r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
901 orderblock(&l.N.Nbody)
904 // Now that we have accumulated all the temporaries, clean them.
905 // Also insert any ninit queued during the previous loop.
906 // (The temporary cleaning must follow that ninit work.)
907 for l := n.List; l != nil; l = l.Next {
908 cleantempnopop(t, order, &l.N.Ninit)
909 l.N.Nbody = concat(l.N.Ninit, l.N.Nbody)
913 order.out = list(order.out, n)
916 // Special: value being sent is passed as a pointer; make it addressable.
920 orderexpr(&n.Left, order, nil)
921 orderexpr(&n.Right, order, nil)
922 orderaddrtemp(&n.Right, order)
923 order.out = list(order.out, n)
926 // TODO(rsc): Clean temporaries more aggressively.
927 // Note that because walkswitch will rewrite some of the
928 // switch into a binary search, this is not as easy as it looks.
929 // (If we ran that code here we could invoke orderstmt on
930 // the if-else chain instead.)
931 // For now just clean all the temporaries at the end.
932 // In practice that's fine.
936 orderexpr(&n.Left, order, nil)
937 for l := n.List; l != nil; l = l.Next {
938 if l.N.Op != OXCASE {
939 Fatalf("order switch case %v", Oconv(int(l.N.Op), 0))
941 orderexprlistinplace(l.N.List, order)
942 orderblock(&l.N.Nbody)
945 order.out = list(order.out, n)
952 // Orderexprlist orders the expression list l into order.
953 func orderexprlist(l *NodeList, order *Order) {
954 for ; l != nil; l = l.Next {
955 orderexpr(&l.N, order, nil)
959 // Orderexprlist orders the expression list l but saves
960 // the side effects on the individual expression ninit lists.
961 func orderexprlistinplace(l *NodeList, order *Order) {
962 for ; l != nil; l = l.Next {
963 orderexprinplace(&l.N, order)
967 // prealloc[x] records the allocation to use for x.
968 var prealloc = map[*Node]*Node{}
970 // Orderexpr orders a single expression, appending side
971 // effects to order->out as needed.
972 // If this is part of an assignment lhs = *np, lhs is given.
973 // Otherwise lhs == nil. (When lhs != nil it may be possible
974 // to avoid copying the result of the expression to a temporary.)
975 func orderexpr(np **Node, order *Order, lhs *Node) {
981 lno := int(setlineno(n))
986 orderexpr(&n.Left, order, nil)
987 orderexpr(&n.Right, order, nil)
988 orderexprlist(n.List, order)
989 orderexprlist(n.Rlist, order)
991 // Addition of strings turns into a function call.
992 // Allocate a temporary to hold the strings.
993 // Fewer than 5 strings use direct runtime helpers.
995 orderexprlist(n.List, order)
997 if count(n.List) > 5 {
999 t.Bound = int64(count(n.List))
1000 t.Type = Types[TSTRING]
1001 prealloc[n] = ordertemp(t, order, false)
1004 // Mark string(byteSlice) arguments to reuse byteSlice backing
1005 // buffer during conversion. String concatenation does not
1006 // memorize the strings for later use, so it is safe.
1007 // However, we can do it only if there is at least one non-empty string literal.
1008 // Otherwise if all other arguments are empty strings,
1009 // concatstrings will return the reference to the temp string
1014 for l := n.List; l != nil; l = l.Next {
1015 hasbyte = hasbyte || l.N.Op == OARRAYBYTESTR
1016 haslit = haslit || l.N.Op == OLITERAL && len(l.N.Val().U.(string)) != 0
1019 if haslit && hasbyte {
1020 for l := n.List; l != nil; l = l.Next {
1021 if l.N.Op == OARRAYBYTESTR {
1022 l.N.Op = OARRAYBYTESTRTMP
1028 orderexpr(&n.Left, order, nil)
1029 orderexpr(&n.Right, order, nil)
1031 // Mark string(byteSlice) arguments to reuse byteSlice backing
1032 // buffer during conversion. String comparison does not
1033 // memorize the strings for later use, so it is safe.
1034 if n.Left.Op == OARRAYBYTESTR {
1035 n.Left.Op = OARRAYBYTESTRTMP
1037 if n.Right.Op == OARRAYBYTESTR {
1038 n.Right.Op = OARRAYBYTESTRTMP
1041 // key must be addressable
1043 orderexpr(&n.Left, order, nil)
1045 orderexpr(&n.Right, order, nil)
1047 // For x = m[string(k)] where k is []byte, the allocation of
1048 // backing bytes for the string can be avoided by reusing
1049 // the []byte backing array. This is a special case that it
1050 // would be nice to handle more generally, but because
1051 // there are no []byte-keyed maps, this specific case comes
1052 // up in important cases in practice. See issue 3512.
1053 // Nothing can change the []byte we are not copying before
1054 // the map index, because the map access is going to
1055 // be forced to happen immediately following this
1056 // conversion (by the ordercopyexpr a few lines below).
1057 if n.Etype == 0 && n.Right.Op == OARRAYBYTESTR {
1058 n.Right.Op = OARRAYBYTESTRTMP
1061 orderaddrtemp(&n.Right, order)
1063 // use of value (not being assigned);
1064 // make copy in temporary.
1065 n = ordercopyexpr(n, n.Type, order, 0)
1068 // concrete type (not interface) argument must be addressable
1069 // temporary to pass to runtime.
1071 orderexpr(&n.Left, order, nil)
1073 if !Isinter(n.Left.Type) {
1074 orderaddrtemp(&n.Left, order)
1077 case OANDAND, OOROR:
1078 mark := marktemp(order)
1079 orderexpr(&n.Left, order, nil)
1081 // Clean temporaries from first branch at beginning of second.
1082 // Leave them on the stack so that they can be killed in the outer
1083 // context in case the short circuit is taken.
1086 cleantempnopop(mark, order, &l)
1087 n.Right.Ninit = concat(l, n.Right.Ninit)
1088 orderexprinplace(&n.Right, order)
1108 if lhs == nil || lhs.Op != ONAME || instrumenting {
1109 n = ordercopyexpr(n, n.Type, order, 0)
1113 ordercallargs(&n.List, order)
1114 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.N) {
1115 n = ordercopyexpr(n, n.Type, order, 0)
1118 case OSLICE, OSLICEARR, OSLICESTR:
1119 orderexpr(&n.Left, order, nil)
1120 orderexpr(&n.Right.Left, order, nil)
1121 n.Right.Left = ordercheapexpr(n.Right.Left, order)
1122 orderexpr(&n.Right.Right, order, nil)
1123 n.Right.Right = ordercheapexpr(n.Right.Right, order)
1124 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
1125 n = ordercopyexpr(n, n.Type, order, 0)
1128 case OSLICE3, OSLICE3ARR:
1129 orderexpr(&n.Left, order, nil)
1130 orderexpr(&n.Right.Left, order, nil)
1131 n.Right.Left = ordercheapexpr(n.Right.Left, order)
1132 orderexpr(&n.Right.Right.Left, order, nil)
1133 n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
1134 orderexpr(&n.Right.Right.Right, order, nil)
1135 n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
1136 if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
1137 n = ordercopyexpr(n, n.Type, order, 0)
1141 if n.Noescape && len(n.Func.Cvars.Slice()) > 0 {
1142 prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
1145 case OARRAYLIT, OCALLPART:
1146 orderexpr(&n.Left, order, nil)
1147 orderexpr(&n.Right, order, nil)
1148 orderexprlist(n.List, order)
1149 orderexprlist(n.Rlist, order)
1151 prealloc[n] = ordertemp(Types[TUINT8], order, false) // walk will fill in correct type
1156 // The ddd argument does not live beyond the call it is created for.
1157 // Allocate a temporary that will be cleaned up when this statement
1158 // completes. We could be more aggressive and try to arrange for it
1159 // to be cleaned up when the call completes.
1160 prealloc[n] = ordertemp(n.Type.Type, order, false)
1163 case ODOTTYPE, ODOTTYPE2:
1164 orderexpr(&n.Left, order, nil)
1165 // TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
1166 // It needs to be removed in all three places.
1167 // That would allow inlining x.(struct{*int}) the same as x.(*int).
1168 if !isdirectiface(n.Type) || Isfat(n.Type) || instrumenting {
1169 n = ordercopyexpr(n, n.Type, order, 1)
1173 orderexpr(&n.Left, order, nil)
1174 n = ordercopyexpr(n, n.Type, order, 1)
1177 orderexpr(&n.Left, order, nil)
1178 orderexpr(&n.Right, order, nil)
1180 if t.Etype == TSTRUCT || Isfixedarray(t) {
1181 // for complex comparisons, we need both args to be
1182 // addressable so we can pass them to the runtime.
1183 orderaddrtemp(&n.Left, order)
1184 orderaddrtemp(&n.Right, order)