Commit 26708439 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: refactor order.go into methods

No functional changes, just changing all the orderfoo functions
into (*Order).foo methods.

Passes toolstash-check.

Change-Id: Ib9833daa98aff3c645ce56794a414f8472689152
Reviewed-on: https://go-review.googlesource.com/98617
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 43b64762
...@@ -46,7 +46,7 @@ type Order struct { ...@@ -46,7 +46,7 @@ type Order struct {
temp []*Node // stack of temporary variables temp []*Node // stack of temporary variables
} }
// Order rewrites fn->nbody to apply the ordering constraints // Order rewrites fn.Nbody to apply the ordering constraints
// described in the comment at the top of the file. // described in the comment at the top of the file.
func order(fn *Node) { func order(fn *Node) {
if Debug['W'] > 1 { if Debug['W'] > 1 {
...@@ -54,25 +54,25 @@ func order(fn *Node) { ...@@ -54,25 +54,25 @@ func order(fn *Node) {
dumplist(s, fn.Nbody) dumplist(s, fn.Nbody)
} }
orderblockNodes(&fn.Nbody) orderBlock(&fn.Nbody)
} }
// Ordertemp allocates a new temporary with the given type, // newTemp allocates a new temporary with the given type,
// pushes it onto the temp stack, and returns it. // pushes it onto the temp stack, and returns it.
// If clear is true, ordertemp emits code to zero the temporary. // If clear is true, newTemp emits code to zero the temporary.
func ordertemp(t *types.Type, order *Order, clear bool) *Node { func (o *Order) newTemp(t *types.Type, clear bool) *Node {
var_ := temp(t) v := temp(t)
if clear { if clear {
a := nod(OAS, var_, nil) a := nod(OAS, v, nil)
a = typecheck(a, Etop) a = typecheck(a, Etop)
order.out = append(order.out, a) o.out = append(o.out, a)
} }
order.temp = append(order.temp, var_) o.temp = append(o.temp, v)
return var_ return v
} }
// Ordercopyexpr behaves like ordertemp but also emits // copyExpr behaves like ordertemp but also emits
// code to initialize the temporary to the value n. // code to initialize the temporary to the value n.
// //
// The clear argument is provided for use when the evaluation // The clear argument is provided for use when the evaluation
...@@ -84,27 +84,28 @@ func ordertemp(t *types.Type, order *Order, clear bool) *Node { ...@@ -84,27 +84,28 @@ func ordertemp(t *types.Type, order *Order, clear bool) *Node {
// (The other candidate would be map access, but map access // (The other candidate would be map access, but map access
// returns a pointer to the result data instead of taking a pointer // returns a pointer to the result data instead of taking a pointer
// to be filled in.) // to be filled in.)
func ordercopyexpr(n *Node, t *types.Type, order *Order, clear bool) *Node { func (o *Order) copyExpr(n *Node, t *types.Type, clear bool) *Node {
var_ := ordertemp(t, order, clear) v := o.newTemp(t, clear)
a := nod(OAS, var_, n) a := nod(OAS, v, n)
a = typecheck(a, Etop) a = typecheck(a, Etop)
order.out = append(order.out, a) o.out = append(o.out, a)
return var_ return v
} }
// Ordercheapexpr returns a cheap version of n. // cheapExpr returns a cheap version of n.
// The definition of cheap is that n is a variable or constant. // The definition of cheap is that n is a variable or constant.
// If not, ordercheapexpr allocates a new tmp, emits tmp = n, // If not, cheapExpr allocates a new tmp, emits tmp = n,
// and then returns tmp. // and then returns tmp.
func ordercheapexpr(n *Node, order *Order) *Node { func (o *Order) cheapExpr(n *Node) *Node {
if n == nil { if n == nil {
return nil return nil
} }
switch n.Op { switch n.Op {
case ONAME, OLITERAL: case ONAME, OLITERAL:
return n return n
case OLEN, OCAP: case OLEN, OCAP:
l := ordercheapexpr(n.Left, order) l := o.cheapExpr(n.Left)
if l == n.Left { if l == n.Left {
return n return n
} }
...@@ -114,23 +115,23 @@ func ordercheapexpr(n *Node, order *Order) *Node { ...@@ -114,23 +115,23 @@ func ordercheapexpr(n *Node, order *Order) *Node {
return typecheck(&a, Erv) return typecheck(&a, Erv)
} }
return ordercopyexpr(n, n.Type, order, false) return o.copyExpr(n, n.Type, false)
} }
// Ordersafeexpr returns a safe version of n. // safeExpr returns a safe version of n.
// The definition of safe is that n can appear multiple times // The definition of safe is that n can appear multiple times
// without violating the semantics of the original program, // without violating the semantics of the original program,
// and that assigning to the safe version has the same effect // and that assigning to the safe version has the same effect
// as assigning to the original n. // as assigning to the original n.
// //
// The intended use is to apply to x when rewriting x += y into x = x + y. // The intended use is to apply to x when rewriting x += y into x = x + y.
func ordersafeexpr(n *Node, order *Order) *Node { func (o *Order) safeExpr(n *Node) *Node {
switch n.Op { switch n.Op {
case ONAME, OLITERAL: case ONAME, OLITERAL:
return n return n
case ODOT, OLEN, OCAP: case ODOT, OLEN, OCAP:
l := ordersafeexpr(n.Left, order) l := o.safeExpr(n.Left)
if l == n.Left { if l == n.Left {
return n return n
} }
...@@ -140,7 +141,7 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -140,7 +141,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
return typecheck(&a, Erv) return typecheck(&a, Erv)
case ODOTPTR, OIND: case ODOTPTR, OIND:
l := ordercheapexpr(n.Left, order) l := o.cheapExpr(n.Left)
if l == n.Left { if l == n.Left {
return n return n
} }
...@@ -152,11 +153,11 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -152,11 +153,11 @@ func ordersafeexpr(n *Node, order *Order) *Node {
case OINDEX, OINDEXMAP: case OINDEX, OINDEXMAP:
var l *Node var l *Node
if n.Left.Type.IsArray() { if n.Left.Type.IsArray() {
l = ordersafeexpr(n.Left, order) l = o.safeExpr(n.Left)
} else { } else {
l = ordercheapexpr(n.Left, order) l = o.cheapExpr(n.Left)
} }
r := ordercheapexpr(n.Right, order) r := o.cheapExpr(n.Right)
if l == n.Left && r == n.Right { if l == n.Left && r == n.Right {
return n return n
} }
...@@ -165,6 +166,7 @@ func ordersafeexpr(n *Node, order *Order) *Node { ...@@ -165,6 +166,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
a.Left = l a.Left = l
a.Right = r a.Right = r
return typecheck(&a, Erv) return typecheck(&a, Erv)
default: default:
Fatalf("ordersafeexpr %v", n.Op) Fatalf("ordersafeexpr %v", n.Op)
return nil // not reached return nil // not reached
...@@ -181,12 +183,12 @@ func isaddrokay(n *Node) bool { ...@@ -181,12 +183,12 @@ func isaddrokay(n *Node) bool {
return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp()) return islvalue(n) && (n.Op != ONAME || n.Class() == PEXTERN || n.IsAutoTmp())
} }
// Orderaddrtemp ensures that n is okay to pass by address to runtime routines. // addrTemp ensures that n is okay to pass by address to runtime routines.
// If the original argument n is not okay, orderaddrtemp creates a tmp, emits // If the original argument n is not okay, addrTemp creates a tmp, emits
// tmp = n, and then returns tmp. // tmp = n, and then returns tmp.
// The result of orderaddrtemp MUST be assigned back to n, e.g. // The result of addrTemp MUST be assigned back to n, e.g.
// n.Left = orderaddrtemp(n.Left, order) // n.Left = o.addrTemp(n.Left)
func orderaddrtemp(n *Node, order *Order) *Node { func (o *Order) addrTemp(n *Node) *Node {
if consttype(n) > 0 { if consttype(n) > 0 {
// TODO: expand this to all static composite literal nodes? // TODO: expand this to all static composite literal nodes?
n = defaultlit(n, nil) n = defaultlit(n, nil)
...@@ -204,16 +206,16 @@ func orderaddrtemp(n *Node, order *Order) *Node { ...@@ -204,16 +206,16 @@ func orderaddrtemp(n *Node, order *Order) *Node {
if isaddrokay(n) { if isaddrokay(n) {
return n return n
} }
return ordercopyexpr(n, n.Type, order, false) return o.copyExpr(n, n.Type, false)
} }
// ordermapkeytemp prepares n to be a key in a map runtime call and returns n. // mapKeyTemp prepares n to be a key in a map runtime call and returns n.
// It should only be used for map runtime calls which have *_fast* versions. // It should only be used for map runtime calls which have *_fast* versions.
func ordermapkeytemp(t *types.Type, n *Node, order *Order) *Node { func (o *Order) mapKeyTemp(t *types.Type, n *Node) *Node {
// Most map calls need to take the address of the key. // Most map calls need to take the address of the key.
// Exception: map*_fast* calls. See golang.org/issue/19015. // Exception: map*_fast* calls. See golang.org/issue/19015.
if mapfast(t) == mapslow { if mapfast(t) == mapslow {
return orderaddrtemp(n, order) return o.addrTemp(n)
} }
return n return n
} }
...@@ -221,22 +223,22 @@ func ordermapkeytemp(t *types.Type, n *Node, order *Order) *Node { ...@@ -221,22 +223,22 @@ func ordermapkeytemp(t *types.Type, n *Node, order *Order) *Node {
type ordermarker int type ordermarker int
// Marktemp returns the top of the temporary variable stack. // Marktemp returns the top of the temporary variable stack.
func marktemp(order *Order) ordermarker { func (o *Order) markTemp() ordermarker {
return ordermarker(len(order.temp)) return ordermarker(len(o.temp))
} }
// Poptemp pops temporaries off the stack until reaching the mark, // Poptemp pops temporaries off the stack until reaching the mark,
// which must have been returned by marktemp. // which must have been returned by marktemp.
func poptemp(mark ordermarker, order *Order) { func (o *Order) popTemp(mark ordermarker) {
order.temp = order.temp[:mark] o.temp = o.temp[:mark]
} }
// Cleantempnopop emits VARKILL and if needed VARLIVE instructions // Cleantempnopop emits VARKILL and if needed VARLIVE instructions
// to *out for each temporary above the mark on the temporary stack. // to *out for each temporary above the mark on the temporary stack.
// It does not pop the temporaries from the stack. // It does not pop the temporaries from the stack.
func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) { func (o *Order) cleanTempNoPop(mark ordermarker, out *[]*Node) {
for i := len(order.temp) - 1; i >= int(mark); i-- { for i := len(o.temp) - 1; i >= int(mark); i-- {
n := order.temp[i] n := o.temp[i]
if n.Name.Keepalive() { if n.Name.Keepalive() {
n.Name.SetKeepalive(false) n.Name.SetKeepalive(false)
n.SetAddrtaken(true) // ensure SSA keeps the n variable n.SetAddrtaken(true) // ensure SSA keeps the n variable
...@@ -250,69 +252,59 @@ func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) { ...@@ -250,69 +252,59 @@ func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
} }
} }
// Cleantemp emits VARKILL instructions for each temporary above the // cleanTemp emits VARKILL instructions for each temporary above the
// mark on the temporary stack and removes them from the stack. // mark on the temporary stack and removes them from the stack.
func cleantemp(top ordermarker, order *Order) { func (o *Order) cleanTemp(top ordermarker) {
cleantempnopop(top, order, &order.out) o.cleanTempNoPop(top, &o.out)
poptemp(top, order) o.popTemp(top)
} }
// Orderstmtlist orders each of the statements in the list. // stmtList orders each of the statements in the list.
func orderstmtlist(l Nodes, order *Order) { func (o *Order) stmtList(l Nodes) {
for _, n := range l.Slice() { for _, n := range l.Slice() {
orderstmt(n, order) o.stmt(n)
} }
} }
// Orderblock orders the block of statements l onto a new list, // orderBlock orders the block of statements in n into a new slice,
// and returns the ordered list.
func orderblock(l Nodes) []*Node {
var order Order
mark := marktemp(&order)
orderstmtlist(l, &order)
cleantemp(mark, &order)
return order.out
}
// OrderblockNodes orders the block of statements in n into a new slice,
// and then replaces the old slice in n with the new slice. // and then replaces the old slice in n with the new slice.
func orderblockNodes(n *Nodes) { func orderBlock(n *Nodes) {
var order Order var order Order
mark := marktemp(&order) mark := order.markTemp()
orderstmtlist(*n, &order) order.stmtList(*n)
cleantemp(mark, &order) order.cleanTemp(mark)
n.Set(order.out) n.Set(order.out)
} }
// Orderexprinplace orders the side effects in *np and // exprInPlace orders the side effects in *np and
// leaves them as the init list of the final *np. // leaves them as the init list of the final *np.
// The result of orderexprinplace MUST be assigned back to n, e.g. // The result of exprInPlace MUST be assigned back to n, e.g.
// n.Left = orderexprinplace(n.Left, outer) // n.Left = o.exprInPlace(n.Left)
func orderexprinplace(n *Node, outer *Order) *Node { func (o *Order) exprInPlace(n *Node) *Node {
var order Order var order Order
n = orderexpr(n, &order, nil) n = order.expr(n, nil)
n = addinit(n, order.out) n = addinit(n, order.out)
// insert new temporaries from order // insert new temporaries from order
// at head of outer list. // at head of outer list.
outer.temp = append(outer.temp, order.temp...) o.temp = append(o.temp, order.temp...)
return n return n
} }
// Orderstmtinplace orders the side effects of the single statement *np // orderStmtInPlace orders the side effects of the single statement *np
// and replaces it with the resulting statement list. // and replaces it with the resulting statement list.
// The result of orderstmtinplace MUST be assigned back to n, e.g. // The result of orderStmtInPlace MUST be assigned back to n, e.g.
// n.Left = orderstmtinplace(n.Left) // n.Left = orderStmtInPlace(n.Left)
func orderstmtinplace(n *Node) *Node { func orderStmtInPlace(n *Node) *Node {
var order Order var order Order
mark := marktemp(&order) mark := order.markTemp()
orderstmt(n, &order) order.stmt(n)
cleantemp(mark, &order) order.cleanTemp(mark)
return liststmt(order.out) return liststmt(order.out)
} }
// Orderinit moves n's init list to order->out. // init moves n's init list to o.out.
func orderinit(n *Node, order *Order) { func (o *Order) init(n *Node) {
if n.mayBeShared() { if n.mayBeShared() {
// For concurrency safety, don't mutate potentially shared nodes. // For concurrency safety, don't mutate potentially shared nodes.
// First, ensure that no work is required here. // First, ensure that no work is required here.
...@@ -321,7 +313,7 @@ func orderinit(n *Node, order *Order) { ...@@ -321,7 +313,7 @@ func orderinit(n *Node, order *Order) {
} }
return return
} }
orderstmtlist(n.Ninit, order) o.stmtList(n.Ninit)
n.Ninit.Set(nil) n.Ninit.Set(nil)
} }
...@@ -347,17 +339,16 @@ func ismulticall(l Nodes) bool { ...@@ -347,17 +339,16 @@ func ismulticall(l Nodes) bool {
return n.Left.Type.NumResults() > 1 return n.Left.Type.NumResults() > 1
} }
// Copyret emits t1, t2, ... = n, where n is a function call, // copyRet emits t1, t2, ... = n, where n is a function call,
// and then returns the list t1, t2, .... // and then returns the list t1, t2, ....
func copyret(n *Node, order *Order) []*Node { func (o *Order) copyRet(n *Node) []*Node {
if !n.Type.IsFuncArgStruct() { if !n.Type.IsFuncArgStruct() {
Fatalf("copyret %v %d", n.Type, n.Left.Type.NumResults()) Fatalf("copyret %v %d", n.Type, n.Left.Type.NumResults())
} }
var l1 []*Node var l1, l2 []*Node
var l2 []*Node for _, f := range n.Type.Fields().Slice() {
for _, t := range n.Type.Fields().Slice() { tmp := temp(f.Type)
tmp := temp(t.Type)
l1 = append(l1, tmp) l1 = append(l1, tmp)
l2 = append(l2, tmp) l2 = append(l2, tmp)
} }
...@@ -366,27 +357,27 @@ func copyret(n *Node, order *Order) []*Node { ...@@ -366,27 +357,27 @@ func copyret(n *Node, order *Order) []*Node {
as.List.Set(l1) as.List.Set(l1)
as.Rlist.Set1(n) as.Rlist.Set1(n)
as = typecheck(as, Etop) as = typecheck(as, Etop)
orderstmt(as, order) o.stmt(as)
return l2 return l2
} }
// Ordercallargs orders the list of call arguments *l. // callArgs orders the list of call arguments *l.
func ordercallargs(l *Nodes, order *Order) { func (o *Order) callArgs(l *Nodes) {
if ismulticall(*l) { if ismulticall(*l) {
// return f() where f() is multiple values. // return f() where f() is multiple values.
l.Set(copyret(l.First(), order)) l.Set(o.copyRet(l.First()))
} else { } else {
orderexprlist(*l, order) o.exprList(*l)
} }
} }
// Ordercall orders the call expression n. // call orders the call expression n.
// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY. // n.Op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
func ordercall(n *Node, order *Order) { func (o *Order) call(n *Node) {
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp n.Right = o.expr(n.Right, nil) // ODDDARG temp
ordercallargs(&n.List, order) o.callArgs(&n.List)
if n.Op == OCALLFUNC { if n.Op == OCALLFUNC {
keepAlive := func(i int) { keepAlive := func(i int) {
...@@ -400,7 +391,7 @@ func ordercall(n *Node, order *Order) { ...@@ -400,7 +391,7 @@ func ordercall(n *Node, order *Order) {
} }
x := *xp x := *xp
if x.Type.IsUnsafePtr() { if x.Type.IsUnsafePtr() {
x = ordercopyexpr(x, x.Type, order, false) x = o.copyExpr(x, x.Type, false)
x.Name.SetKeepalive(true) x.Name.SetKeepalive(true)
*xp = x *xp = x
} }
...@@ -423,9 +414,9 @@ func ordercall(n *Node, order *Order) { ...@@ -423,9 +414,9 @@ func ordercall(n *Node, order *Order) {
} }
} }
// Ordermapassign appends n to order->out, introducing temporaries // mapAssign appends n to o.out, introducing temporaries
// to make sure that all map assignments have the form m[k] = x. // to make sure that all map assignments have the form m[k] = x.
// (Note: orderexpr has already been called on n, so we know k is addressable.) // (Note: expr has already been called on n, so we know k is addressable.)
// //
// If n is the multiple assignment form ..., m[k], ... = ..., x, ..., the rewrite is // If n is the multiple assignment form ..., m[k], ... = ..., x, ..., the rewrite is
// t1 = m // t1 = m
...@@ -438,7 +429,7 @@ func ordercall(n *Node, order *Order) { ...@@ -438,7 +429,7 @@ func ordercall(n *Node, order *Order) {
// cases they are also typically registerizable, so not much harm done. // cases they are also typically registerizable, so not much harm done.
// And this only applies to the multiple-assignment form. // And this only applies to the multiple-assignment form.
// We could do a more precise analysis if needed, like in walk.go. // We could do a more precise analysis if needed, like in walk.go.
func ordermapassign(n *Node, order *Order) { func (o *Order) mapAssign(n *Node) {
switch n.Op { switch n.Op {
default: default:
Fatalf("ordermapassign %v", n.Op) Fatalf("ordermapassign %v", n.Op)
...@@ -447,9 +438,9 @@ func ordermapassign(n *Node, order *Order) { ...@@ -447,9 +438,9 @@ func ordermapassign(n *Node, order *Order) {
if n.Left.Op == OINDEXMAP { if n.Left.Op == OINDEXMAP {
// Make sure we evaluate the RHS before starting the map insert. // Make sure we evaluate the RHS before starting the map insert.
// We need to make sure the RHS won't panic. See issue 22881. // We need to make sure the RHS won't panic. See issue 22881.
n.Right = ordercheapexpr(n.Right, order) n.Right = o.cheapExpr(n.Right)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC: case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
var post []*Node var post []*Node
...@@ -457,14 +448,14 @@ func ordermapassign(n *Node, order *Order) { ...@@ -457,14 +448,14 @@ func ordermapassign(n *Node, order *Order) {
switch { switch {
case m.Op == OINDEXMAP: case m.Op == OINDEXMAP:
if !m.Left.IsAutoTmp() { if !m.Left.IsAutoTmp() {
m.Left = ordercopyexpr(m.Left, m.Left.Type, order, false) m.Left = o.copyExpr(m.Left, m.Left.Type, false)
} }
if !m.Right.IsAutoTmp() { if !m.Right.IsAutoTmp() {
m.Right = ordercopyexpr(m.Right, m.Right.Type, order, false) m.Right = o.copyExpr(m.Right, m.Right.Type, false)
} }
fallthrough fallthrough
case instrumenting && n.Op == OAS2FUNC && !isblank(m): case instrumenting && n.Op == OAS2FUNC && !isblank(m):
t := ordertemp(m.Type, order, false) t := o.newTemp(m.Type, false)
n.List.SetIndex(i, t) n.List.SetIndex(i, t)
a := nod(OAS, m, t) a := nod(OAS, m, t)
a = typecheck(a, Etop) a = typecheck(a, Etop)
...@@ -472,36 +463,35 @@ func ordermapassign(n *Node, order *Order) { ...@@ -472,36 +463,35 @@ func ordermapassign(n *Node, order *Order) {
} }
} }
order.out = append(order.out, n) o.out = append(o.out, n)
order.out = append(order.out, post...) o.out = append(o.out, post...)
} }
} }
// Orderstmt orders the statement n, appending to order->out. // stmt orders the statement n, appending to o.out.
// Temporaries created during the statement are cleaned // Temporaries created during the statement are cleaned
// up using VARKILL instructions as possible. // up using VARKILL instructions as possible.
func orderstmt(n *Node, order *Order) { func (o *Order) stmt(n *Node) {
if n == nil { if n == nil {
return return
} }
lno := setlineno(n) lno := setlineno(n)
o.init(n)
orderinit(n, order)
switch n.Op { switch n.Op {
default: default:
Fatalf("orderstmt %v", n.Op) Fatalf("orderstmt %v", n.Op)
case OVARKILL, OVARLIVE: case OVARKILL, OVARLIVE:
order.out = append(order.out, n) o.out = append(o.out, n)
case OAS: case OAS:
t := marktemp(order) t := o.markTemp()
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, n.Left) n.Right = o.expr(n.Right, n.Left)
ordermapassign(n, order) o.mapAssign(n)
cleantemp(t, order) o.cleanTemp(t)
case OAS2, case OAS2,
OCLOSE, OCLOSE,
...@@ -510,18 +500,18 @@ func orderstmt(n *Node, order *Order) { ...@@ -510,18 +500,18 @@ func orderstmt(n *Node, order *Order) {
OPRINTN, OPRINTN,
ORECOVER, ORECOVER,
ORECV: ORECV:
t := marktemp(order) t := o.markTemp()
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
orderexprlist(n.List, order) o.exprList(n.List)
orderexprlist(n.Rlist, order) o.exprList(n.Rlist)
switch n.Op { switch n.Op {
case OAS2: case OAS2:
ordermapassign(n, order) o.mapAssign(n)
default: default:
order.out = append(order.out, n) o.out = append(o.out, n)
} }
cleantemp(t, order) o.cleanTemp(t)
case OASOP: case OASOP:
// Special: rewrite l op= r into l = l op r. // Special: rewrite l op= r into l = l op r.
...@@ -529,86 +519,82 @@ func orderstmt(n *Node, order *Order) { ...@@ -529,86 +519,82 @@ func orderstmt(n *Node, order *Order) {
// most important is that it lets us separate // most important is that it lets us separate
// out map read from map write when l is // out map read from map write when l is
// a map index expression. // a map index expression.
t := marktemp(order) t := o.markTemp()
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
n.Left = ordersafeexpr(n.Left, order) n.Left = o.safeExpr(n.Left)
tmp1 := treecopy(n.Left, src.NoXPos) tmp1 := treecopy(n.Left, src.NoXPos)
if tmp1.Op == OINDEXMAP { if tmp1.Op == OINDEXMAP {
tmp1.Etype = 0 // now an rvalue not an lvalue tmp1.Etype = 0 // now an rvalue not an lvalue
} }
tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, false) tmp1 = o.copyExpr(tmp1, n.Left.Type, false)
// TODO(marvin): Fix Node.EType type union. // TODO(marvin): Fix Node.EType type union.
n.Right = nod(Op(n.Etype), tmp1, n.Right) n.Right = nod(Op(n.Etype), tmp1, n.Right)
n.Right = typecheck(n.Right, Erv) n.Right = typecheck(n.Right, Erv)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
n.Etype = 0 n.Etype = 0
n.Op = OAS n.Op = OAS
ordermapassign(n, order) o.mapAssign(n)
cleantemp(t, order) o.cleanTemp(t)
// Special: make sure key is addressable if needed, // Special: make sure key is addressable if needed,
// and make sure OINDEXMAP is not copied out. // and make sure OINDEXMAP is not copied out.
case OAS2MAPR: case OAS2MAPR:
t := marktemp(order) t := o.markTemp()
o.exprList(n.List)
orderexprlist(n.List, order)
r := n.Rlist.First() r := n.Rlist.First()
r.Left = orderexpr(r.Left, order, nil) r.Left = o.expr(r.Left, nil)
r.Right = orderexpr(r.Right, order, nil) r.Right = o.expr(r.Right, nil)
// See case OINDEXMAP below. // See case OINDEXMAP below.
if r.Right.Op == OARRAYBYTESTR { if r.Right.Op == OARRAYBYTESTR {
r.Right.Op = OARRAYBYTESTRTMP r.Right.Op = OARRAYBYTESTRTMP
} }
r.Right = ordermapkeytemp(r.Left.Type, r.Right, order) r.Right = o.mapKeyTemp(r.Left.Type, r.Right)
orderokas2(n, order) o.okAs2(n)
cleantemp(t, order) o.cleanTemp(t)
// Special: avoid copy of func call n->rlist->n. // Special: avoid copy of func call n.Rlist.First().
case OAS2FUNC: case OAS2FUNC:
t := marktemp(order) t := o.markTemp()
o.exprList(n.List)
orderexprlist(n.List, order) o.call(n.Rlist.First())
ordercall(n.Rlist.First(), order) o.as2(n)
orderas2(n, order) o.cleanTemp(t)
cleantemp(t, order)
// Special: use temporary variables to hold result, // Special: use temporary variables to hold result,
// so that assertI2Tetc can take address of temporary. // so that assertI2Tetc can take address of temporary.
// No temporary for blank assignment. // No temporary for blank assignment.
case OAS2DOTTYPE: case OAS2DOTTYPE:
t := marktemp(order) t := o.markTemp()
o.exprList(n.List)
orderexprlist(n.List, order) n.Rlist.First().Left = o.expr(n.Rlist.First().Left, nil) // i in i.(T)
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T) o.okAs2(n)
orderokas2(n, order) o.cleanTemp(t)
cleantemp(t, order)
// Special: use temporary variables to hold result, // Special: use temporary variables to hold result,
// so that chanrecv can take address of temporary. // so that chanrecv can take address of temporary.
case OAS2RECV: case OAS2RECV:
t := marktemp(order) t := o.markTemp()
o.exprList(n.List)
orderexprlist(n.List, order) n.Rlist.First().Left = o.expr(n.Rlist.First().Left, nil) // arg to recv
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
ch := n.Rlist.First().Left.Type ch := n.Rlist.First().Left.Type
tmp1 := ordertemp(ch.Elem(), order, types.Haspointers(ch.Elem())) tmp1 := o.newTemp(ch.Elem(), types.Haspointers(ch.Elem()))
tmp2 := ordertemp(types.Types[TBOOL], order, false) tmp2 := o.newTemp(types.Types[TBOOL], false)
order.out = append(order.out, n) o.out = append(o.out, n)
r := nod(OAS, n.List.First(), tmp1) r := nod(OAS, n.List.First(), tmp1)
r = typecheck(r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) o.mapAssign(r)
r = okas(n.List.Second(), tmp2) r = okas(n.List.Second(), tmp2)
r = typecheck(r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) o.mapAssign(r)
n.List.Set2(tmp1, tmp2) n.List.Set2(tmp1, tmp2)
cleantemp(t, order) o.cleanTemp(t)
// Special: does not save n onto out. // Special: does not save n onto out.
case OBLOCK, OEMPTY: case OBLOCK, OEMPTY:
orderstmtlist(n.List, order) o.stmtList(n.List)
// Special: n->left is not an expression; save as is. // Special: n->left is not an expression; save as is.
case OBREAK, case OBREAK,
...@@ -620,91 +606,87 @@ func orderstmt(n *Node, order *Order) { ...@@ -620,91 +606,87 @@ func orderstmt(n *Node, order *Order) {
OGOTO, OGOTO,
OLABEL, OLABEL,
ORETJMP: ORETJMP:
order.out = append(order.out, n) o.out = append(o.out, n)
// Special: handle call arguments. // Special: handle call arguments.
case OCALLFUNC, OCALLINTER, OCALLMETH: case OCALLFUNC, OCALLINTER, OCALLMETH:
t := marktemp(order) t := o.markTemp()
o.call(n)
ordercall(n, order) o.out = append(o.out, n)
order.out = append(order.out, n) o.cleanTemp(t)
cleantemp(t, order)
// Special: order arguments to inner call but not call itself. // Special: order arguments to inner call but not call itself.
case ODEFER, OPROC: case ODEFER, OPROC:
t := marktemp(order) t := o.markTemp()
switch n.Left.Op { switch n.Left.Op {
// Delete will take the address of the key. // Delete will take the address of the key.
// Copy key into new temp and do not clean it // Copy key into new temp and do not clean it
// (it persists beyond the statement). // (it persists beyond the statement).
case ODELETE: case ODELETE:
orderexprlist(n.Left.List, order) o.exprList(n.Left.List)
if mapfast(n.Left.List.First().Type) == mapslow { if mapfast(n.Left.List.First().Type) == mapslow {
t1 := marktemp(order) t1 := o.markTemp()
np := n.Left.List.Addr(1) // map key np := n.Left.List.Addr(1) // map key
*np = ordercopyexpr(*np, (*np).Type, order, false) *np = o.copyExpr(*np, (*np).Type, false)
poptemp(t1, order) o.popTemp(t1)
} }
default: default:
ordercall(n.Left, order) o.call(n.Left)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
case ODELETE: case ODELETE:
t := marktemp(order) t := o.markTemp()
n.List.SetFirst(orderexpr(n.List.First(), order, nil)) n.List.SetFirst(o.expr(n.List.First(), nil))
n.List.SetSecond(orderexpr(n.List.Second(), order, nil)) n.List.SetSecond(o.expr(n.List.Second(), nil))
n.List.SetSecond(ordermapkeytemp(n.List.First().Type, n.List.Second(), order)) n.List.SetSecond(o.mapKeyTemp(n.List.First().Type, n.List.Second()))
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
// Clean temporaries from condition evaluation at // Clean temporaries from condition evaluation at
// beginning of loop body and after for statement. // beginning of loop body and after for statement.
case OFOR: case OFOR:
t := marktemp(order) t := o.markTemp()
n.Left = o.exprInPlace(n.Left)
n.Left = orderexprinplace(n.Left, order)
var l []*Node var l []*Node
cleantempnopop(t, order, &l) o.cleanTempNoPop(t, &l)
n.Nbody.Prepend(l...) n.Nbody.Prepend(l...)
orderblockNodes(&n.Nbody) orderBlock(&n.Nbody)
n.Right = orderstmtinplace(n.Right) n.Right = orderStmtInPlace(n.Right)
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
// Clean temporaries from condition at // Clean temporaries from condition at
// beginning of both branches. // beginning of both branches.
case OIF: case OIF:
t := marktemp(order) t := o.markTemp()
n.Left = o.exprInPlace(n.Left)
n.Left = orderexprinplace(n.Left, order)
var l []*Node var l []*Node
cleantempnopop(t, order, &l) o.cleanTempNoPop(t, &l)
n.Nbody.Prepend(l...) n.Nbody.Prepend(l...)
l = nil l = nil
cleantempnopop(t, order, &l) o.cleanTempNoPop(t, &l)
n.Rlist.Prepend(l...) n.Rlist.Prepend(l...)
poptemp(t, order) o.popTemp(t)
orderblockNodes(&n.Nbody) orderBlock(&n.Nbody)
n.Rlist.Set(orderblock(n.Rlist)) orderBlock(&n.Rlist)
order.out = append(order.out, n) o.out = append(o.out, n)
// Special: argument will be converted to interface using convT2E // Special: argument will be converted to interface using convT2E
// so make sure it is an addressable temporary. // so make sure it is an addressable temporary.
case OPANIC: case OPANIC:
t := marktemp(order) t := o.markTemp()
n.Left = o.expr(n.Left, nil)
n.Left = orderexpr(n.Left, order, nil)
if !n.Left.Type.IsInterface() { if !n.Left.Type.IsInterface() {
n.Left = orderaddrtemp(n.Left, order) n.Left = o.addrTemp(n.Left)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
case ORANGE: case ORANGE:
// n.Right is the expression being ranged over. // n.Right is the expression being ranged over.
...@@ -724,8 +706,8 @@ func orderstmt(n *Node, order *Order) { ...@@ -724,8 +706,8 @@ func orderstmt(n *Node, order *Order) {
n.Right.Op = OSTRARRAYBYTETMP n.Right.Op = OSTRARRAYBYTETMP
} }
t := marktemp(order) t := o.markTemp()
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
switch n.Type.Etype { switch n.Type.Etype {
default: default:
Fatalf("orderstmt range %v", n.Type) Fatalf("orderstmt range %v", n.Type)
...@@ -749,27 +731,27 @@ func orderstmt(n *Node, order *Order) { ...@@ -749,27 +731,27 @@ func orderstmt(n *Node, order *Order) {
r = typecheck(r, Erv) r = typecheck(r, Erv)
} }
n.Right = ordercopyexpr(r, r.Type, order, false) n.Right = o.copyExpr(r, r.Type, false)
case TMAP: case TMAP:
// copy the map value in case it is a map literal. // copy the map value in case it is a map literal.
// TODO(rsc): Make tmp = literal expressions reuse tmp. // TODO(rsc): Make tmp = literal expressions reuse tmp.
// For maps tmp is just one word so it hardly matters. // For maps tmp is just one word so it hardly matters.
r := n.Right r := n.Right
n.Right = ordercopyexpr(r, r.Type, order, false) n.Right = o.copyExpr(r, r.Type, false)
// prealloc[n] is the temp for the iterator. // prealloc[n] is the temp for the iterator.
// hiter contains pointers and needs to be zeroed. // hiter contains pointers and needs to be zeroed.
prealloc[n] = ordertemp(hiter(n.Type), order, true) prealloc[n] = o.newTemp(hiter(n.Type), true)
} }
orderexprlistinplace(n.List, order) o.exprListInPlace(n.List)
orderblockNodes(&n.Nbody) orderBlock(&n.Nbody)
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
case ORETURN: case ORETURN:
ordercallargs(&n.List, order) o.callArgs(&n.List)
order.out = append(order.out, n) o.out = append(o.out, n)
// Special: clean case temporaries in each block entry. // Special: clean case temporaries in each block entry.
// Select must enter one of its blocks, so there is no // Select must enter one of its blocks, so there is no
...@@ -781,7 +763,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -781,7 +763,7 @@ func orderstmt(n *Node, order *Order) {
// case (if p were nil, then the timing of the fault would // case (if p were nil, then the timing of the fault would
// give this away). // give this away).
case OSELECT: case OSELECT:
t := marktemp(order) t := o.markTemp()
for _, n2 := range n.List.Slice() { for _, n2 := range n.List.Slice() {
if n2.Op != OXCASE { if n2.Op != OXCASE {
...@@ -829,10 +811,10 @@ func orderstmt(n *Node, order *Order) { ...@@ -829,10 +811,10 @@ func orderstmt(n *Node, order *Order) {
// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c. // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
// r->left == N means 'case <-c'. // r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned. // c is always evaluated; x and ok are only evaluated when assigned.
r.Right.Left = orderexpr(r.Right.Left, order, nil) r.Right.Left = o.expr(r.Right.Left, nil)
if r.Right.Left.Op != ONAME { if r.Right.Left.Op != ONAME {
r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, false) r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false)
} }
// Introduce temporary for receive and move actual copy into case body. // Introduce temporary for receive and move actual copy into case body.
...@@ -856,7 +838,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -856,7 +838,7 @@ func orderstmt(n *Node, order *Order) {
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
r.Left = ordertemp(r.Right.Left.Type.Elem(), order, types.Haspointers(r.Right.Left.Type.Elem())) r.Left = o.newTemp(r.Right.Left.Type.Elem(), types.Haspointers(r.Right.Left.Type.Elem()))
tmp2 := nod(OAS, tmp1, r.Left) tmp2 := nod(OAS, tmp1, r.Left)
tmp2 = typecheck(tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
...@@ -873,12 +855,12 @@ func orderstmt(n *Node, order *Order) { ...@@ -873,12 +855,12 @@ func orderstmt(n *Node, order *Order) {
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
r.List.Set1(ordertemp(types.Types[TBOOL], order, false)) r.List.Set1(o.newTemp(types.Types[TBOOL], false))
tmp2 := okas(tmp1, r.List.First()) tmp2 := okas(tmp1, r.List.First())
tmp2 = typecheck(tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
n2.Ninit.Set(orderblock(n2.Ninit)) orderBlock(&n2.Ninit)
case OSEND: case OSEND:
if r.Ninit.Len() != 0 { if r.Ninit.Len() != 0 {
...@@ -888,48 +870,47 @@ func orderstmt(n *Node, order *Order) { ...@@ -888,48 +870,47 @@ func orderstmt(n *Node, order *Order) {
// case c <- x // case c <- x
// r->left is c, r->right is x, both are always evaluated. // r->left is c, r->right is x, both are always evaluated.
r.Left = orderexpr(r.Left, order, nil) r.Left = o.expr(r.Left, nil)
if !r.Left.IsAutoTmp() { if !r.Left.IsAutoTmp() {
r.Left = ordercopyexpr(r.Left, r.Left.Type, order, false) r.Left = o.copyExpr(r.Left, r.Left.Type, false)
} }
r.Right = orderexpr(r.Right, order, nil) r.Right = o.expr(r.Right, nil)
if !r.Right.IsAutoTmp() { if !r.Right.IsAutoTmp() {
r.Right = ordercopyexpr(r.Right, r.Right.Type, order, false) r.Right = o.copyExpr(r.Right, r.Right.Type, false)
} }
} }
} }
orderblockNodes(&n2.Nbody) orderBlock(&n2.Nbody)
} }
// Now that we have accumulated all the temporaries, clean them. // Now that we have accumulated all the temporaries, clean them.
// Also insert any ninit queued during the previous loop. // Also insert any ninit queued during the previous loop.
// (The temporary cleaning must follow that ninit work.) // (The temporary cleaning must follow that ninit work.)
for _, n3 := range n.List.Slice() { for _, n3 := range n.List.Slice() {
s := n3.Ninit.Slice() s := n3.Ninit.Slice()
cleantempnopop(t, order, &s) o.cleanTempNoPop(t, &s)
n3.Nbody.Prepend(s...) n3.Nbody.Prepend(s...)
n3.Ninit.Set(nil) n3.Ninit.Set(nil)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
poptemp(t, order) o.popTemp(t)
// Special: value being sent is passed as a pointer; make it addressable. // Special: value being sent is passed as a pointer; make it addressable.
case OSEND: case OSEND:
t := marktemp(order) t := o.markTemp()
n.Left = o.expr(n.Left, nil)
n.Left = orderexpr(n.Left, order, nil) n.Right = o.expr(n.Right, nil)
n.Right = orderexpr(n.Right, order, nil)
if instrumenting { if instrumenting {
// Force copying to the stack so that (chan T)(nil) <- x // Force copying to the stack so that (chan T)(nil) <- x
// is still instrumented as a read of x. // is still instrumented as a read of x.
n.Right = ordercopyexpr(n.Right, n.Right.Type, order, false) n.Right = o.copyExpr(n.Right, n.Right.Type, false)
} else { } else {
n.Right = orderaddrtemp(n.Right, order) n.Right = o.addrTemp(n.Right)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
// TODO(rsc): Clean temporaries more aggressively. // TODO(rsc): Clean temporaries more aggressively.
// Note that because walkswitch will rewrite some of the // Note that because walkswitch will rewrite some of the
...@@ -939,75 +920,74 @@ func orderstmt(n *Node, order *Order) { ...@@ -939,75 +920,74 @@ func orderstmt(n *Node, order *Order) {
// For now just clean all the temporaries at the end. // For now just clean all the temporaries at the end.
// In practice that's fine. // In practice that's fine.
case OSWITCH: case OSWITCH:
t := marktemp(order) t := o.markTemp()
n.Left = o.expr(n.Left, nil)
n.Left = orderexpr(n.Left, order, nil) for _, ncas := range n.List.Slice() {
for _, n4 := range n.List.Slice() { if ncas.Op != OXCASE {
if n4.Op != OXCASE { Fatalf("order switch case %v", ncas.Op)
Fatalf("order switch case %v", n4.Op)
} }
orderexprlistinplace(n4.List, order) o.exprListInPlace(ncas.List)
orderblockNodes(&n4.Nbody) orderBlock(&ncas.Nbody)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
cleantemp(t, order) o.cleanTemp(t)
} }
lineno = lno lineno = lno
} }
// Orderexprlist orders the expression list l into order. // exprList orders the expression list l into o.
func orderexprlist(l Nodes, order *Order) { func (o *Order) exprList(l Nodes) {
s := l.Slice() s := l.Slice()
for i := range s { for i := range s {
s[i] = orderexpr(s[i], order, nil) s[i] = o.expr(s[i], nil)
} }
} }
// Orderexprlist orders the expression list l but saves // exprListInPlace orders the expression list l but saves
// the side effects on the individual expression ninit lists. // the side effects on the individual expression ninit lists.
func orderexprlistinplace(l Nodes, order *Order) { func (o *Order) exprListInPlace(l Nodes) {
s := l.Slice() s := l.Slice()
for i := range s { for i := range s {
s[i] = orderexprinplace(s[i], order) s[i] = o.exprInPlace(s[i])
} }
} }
// prealloc[x] records the allocation to use for x. // prealloc[x] records the allocation to use for x.
var prealloc = map[*Node]*Node{} var prealloc = map[*Node]*Node{}
// Orderexpr orders a single expression, appending side // expr orders a single expression, appending side
// effects to order->out as needed. // effects to o.out as needed.
// If this is part of an assignment lhs = *np, lhs is given. // If this is part of an assignment lhs = *np, lhs is given.
// Otherwise lhs == nil. (When lhs != nil it may be possible // Otherwise lhs == nil. (When lhs != nil it may be possible
// to avoid copying the result of the expression to a temporary.) // to avoid copying the result of the expression to a temporary.)
// The result of orderexpr MUST be assigned back to n, e.g. // The result of expr MUST be assigned back to n, e.g.
// n.Left = orderexpr(n.Left, order, lhs) // n.Left = o.expr(n.Left, lhs)
func orderexpr(n *Node, order *Order, lhs *Node) *Node { func (o *Order) expr(n, lhs *Node) *Node {
if n == nil { if n == nil {
return n return n
} }
lno := setlineno(n) lno := setlineno(n)
orderinit(n, order) o.init(n)
switch n.Op { switch n.Op {
default: default:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
orderexprlist(n.List, order) o.exprList(n.List)
orderexprlist(n.Rlist, order) o.exprList(n.Rlist)
// Addition of strings turns into a function call. // Addition of strings turns into a function call.
// Allocate a temporary to hold the strings. // Allocate a temporary to hold the strings.
// Fewer than 5 strings use direct runtime helpers. // Fewer than 5 strings use direct runtime helpers.
case OADDSTR: case OADDSTR:
orderexprlist(n.List, order) o.exprList(n.List)
if n.List.Len() > 5 { if n.List.Len() > 5 {
t := types.NewArray(types.Types[TSTRING], int64(n.List.Len())) t := types.NewArray(types.Types[TSTRING], int64(n.List.Len()))
prealloc[n] = ordertemp(t, order, false) prealloc[n] = o.newTemp(t, false)
} }
// Mark string(byteSlice) arguments to reuse byteSlice backing // Mark string(byteSlice) arguments to reuse byteSlice backing
...@@ -1034,8 +1014,8 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1034,8 +1014,8 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
} }
case OCMPSTR: case OCMPSTR:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
// Mark string(byteSlice) arguments to reuse byteSlice backing // Mark string(byteSlice) arguments to reuse byteSlice backing
// buffer during conversion. String comparison does not // buffer during conversion. String comparison does not
...@@ -1049,8 +1029,8 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1049,8 +1029,8 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// key must be addressable // key must be addressable
case OINDEXMAP: case OINDEXMAP:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
needCopy := false needCopy := false
if n.Etype == 0 && instrumenting { if n.Etype == 0 && instrumenting {
...@@ -1074,18 +1054,18 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1074,18 +1054,18 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
needCopy = true needCopy = true
} }
n.Right = ordermapkeytemp(n.Left.Type, n.Right, order) n.Right = o.mapKeyTemp(n.Left.Type, n.Right)
if needCopy { if needCopy {
n = ordercopyexpr(n, n.Type, order, false) n = o.copyExpr(n, n.Type, false)
} }
// concrete type (not interface) argument must be addressable // concrete type (not interface) argument must be addressable
// temporary to pass to runtime. // temporary to pass to runtime.
case OCONVIFACE: case OCONVIFACE:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
if !n.Left.Type.IsInterface() { if !n.Left.Type.IsInterface() {
n.Left = orderaddrtemp(n.Left, order) n.Left = o.addrTemp(n.Left)
} }
case OCONVNOP: case OCONVNOP:
...@@ -1093,27 +1073,27 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1093,27 +1073,27 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// When reordering unsafe.Pointer(f()) into a separate // When reordering unsafe.Pointer(f()) into a separate
// statement, the conversion and function call must stay // statement, the conversion and function call must stay
// together. See golang.org/issue/15329. // together. See golang.org/issue/15329.
orderinit(n.Left, order) o.init(n.Left)
ordercall(n.Left, order) o.call(n.Left)
if lhs == nil || lhs.Op != ONAME || instrumenting { if lhs == nil || lhs.Op != ONAME || instrumenting {
n = ordercopyexpr(n, n.Type, order, false) n = o.copyExpr(n, n.Type, false)
} }
} else { } else {
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
} }
case OANDAND, OOROR: case OANDAND, OOROR:
mark := marktemp(order) mark := o.markTemp()
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
// Clean temporaries from first branch at beginning of second. // Clean temporaries from first branch at beginning of second.
// Leave them on the stack so that they can be killed in the outer // Leave them on the stack so that they can be killed in the outer
// context in case the short circuit is taken. // context in case the short circuit is taken.
var s []*Node var s []*Node
cleantempnopop(mark, order, &s) o.cleanTempNoPop(mark, &s)
n.Right = addinit(n.Right, s) n.Right = addinit(n.Right, s)
n.Right = orderexprinplace(n.Right, order) n.Right = o.exprInPlace(n.Right)
case OCALLFUNC, case OCALLFUNC,
OCALLINTER, OCALLINTER,
...@@ -1132,43 +1112,43 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1132,43 +1112,43 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
OSTRARRAYBYTE, OSTRARRAYBYTE,
OSTRARRAYBYTETMP, OSTRARRAYBYTETMP,
OSTRARRAYRUNE: OSTRARRAYRUNE:
ordercall(n, order) o.call(n)
if lhs == nil || lhs.Op != ONAME || instrumenting { if lhs == nil || lhs.Op != ONAME || instrumenting {
n = ordercopyexpr(n, n.Type, order, false) n = o.copyExpr(n, n.Type, false)
} }
case OAPPEND: case OAPPEND:
ordercallargs(&n.List, order) o.callArgs(&n.List)
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) { if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.List.First()) {
n = ordercopyexpr(n, n.Type, order, false) n = o.copyExpr(n, n.Type, false)
} }
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
low, high, max := n.SliceBounds() low, high, max := n.SliceBounds()
low = orderexpr(low, order, nil) low = o.expr(low, nil)
low = ordercheapexpr(low, order) low = o.cheapExpr(low)
high = orderexpr(high, order, nil) high = o.expr(high, nil)
high = ordercheapexpr(high, order) high = o.cheapExpr(high)
max = orderexpr(max, order, nil) max = o.expr(max, nil)
max = ordercheapexpr(max, order) max = o.cheapExpr(max)
n.SetSliceBounds(low, high, max) n.SetSliceBounds(low, high, max)
if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) { if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
n = ordercopyexpr(n, n.Type, order, false) n = o.copyExpr(n, n.Type, false)
} }
case OCLOSURE: case OCLOSURE:
if n.Noescape() && n.Func.Cvars.Len() > 0 { if n.Noescape() && n.Func.Cvars.Len() > 0 {
prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type prealloc[n] = o.newTemp(types.Types[TUINT8], false) // walk will fill in correct type
} }
case OARRAYLIT, OSLICELIT, OCALLPART: case OARRAYLIT, OSLICELIT, OCALLPART:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
orderexprlist(n.List, order) o.exprList(n.List)
orderexprlist(n.Rlist, order) o.exprList(n.Rlist)
if n.Noescape() { if n.Noescape() {
prealloc[n] = ordertemp(types.Types[TUINT8], order, false) // walk will fill in correct type prealloc[n] = o.newTemp(types.Types[TUINT8], false) // walk will fill in correct type
} }
case ODDDARG: case ODDDARG:
...@@ -1177,31 +1157,31 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1177,31 +1157,31 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// Allocate a temporary that will be cleaned up when this statement // Allocate a temporary that will be cleaned up when this statement
// completes. We could be more aggressive and try to arrange for it // completes. We could be more aggressive and try to arrange for it
// to be cleaned up when the call completes. // to be cleaned up when the call completes.
prealloc[n] = ordertemp(n.Type.Elem(), order, false) prealloc[n] = o.newTemp(n.Type.Elem(), false)
} }
case ODOTTYPE, ODOTTYPE2: case ODOTTYPE, ODOTTYPE2:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
// TODO(rsc): The isfat is for consistency with componentgen and walkexpr. // TODO(rsc): The isfat is for consistency with componentgen and walkexpr.
// It needs to be removed in all three places. // It needs to be removed in all three places.
// That would allow inlining x.(struct{*int}) the same as x.(*int). // That would allow inlining x.(struct{*int}) the same as x.(*int).
if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting { if !isdirectiface(n.Type) || isfat(n.Type) || instrumenting {
n = ordercopyexpr(n, n.Type, order, true) n = o.copyExpr(n, n.Type, true)
} }
case ORECV: case ORECV:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n = ordercopyexpr(n, n.Type, order, true) n = o.copyExpr(n, n.Type, true)
case OEQ, ONE: case OEQ, ONE:
n.Left = orderexpr(n.Left, order, nil) n.Left = o.expr(n.Left, nil)
n.Right = orderexpr(n.Right, order, nil) n.Right = o.expr(n.Right, nil)
t := n.Left.Type t := n.Left.Type
if t.IsStruct() || t.IsArray() { if t.IsStruct() || t.IsArray() {
// for complex comparisons, we need both args to be // for complex comparisons, we need both args to be
// addressable so we can pass them to the runtime. // addressable so we can pass them to the runtime.
n.Left = orderaddrtemp(n.Left, order) n.Left = o.addrTemp(n.Left)
n.Right = orderaddrtemp(n.Right, order) n.Right = o.addrTemp(n.Right)
} }
} }
...@@ -1218,7 +1198,7 @@ func okas(ok, val *Node) *Node { ...@@ -1218,7 +1198,7 @@ func okas(ok, val *Node) *Node {
return nod(OAS, ok, val) return nod(OAS, ok, val)
} }
// orderas2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment. // as2 orders OAS2XXXX nodes. It creates temporaries to ensure left-to-right assignment.
// The caller should order the right-hand side of the assignment before calling orderas2. // The caller should order the right-hand side of the assignment before calling orderas2.
// It rewrites, // It rewrites,
// a, b, a = ... // a, b, a = ...
...@@ -1226,24 +1206,24 @@ func okas(ok, val *Node) *Node { ...@@ -1226,24 +1206,24 @@ func okas(ok, val *Node) *Node {
// tmp1, tmp2, tmp3 = ... // tmp1, tmp2, tmp3 = ...
// a, b, a = tmp1, tmp2, tmp3 // a, b, a = tmp1, tmp2, tmp3
// This is necessary to ensure left to right assignment order. // This is necessary to ensure left to right assignment order.
func orderas2(n *Node, order *Order) { func (o *Order) as2(n *Node) {
tmplist := []*Node{} tmplist := []*Node{}
left := []*Node{} left := []*Node{}
for _, l := range n.List.Slice() { for _, l := range n.List.Slice() {
if !isblank(l) { if !isblank(l) {
tmp := ordertemp(l.Type, order, types.Haspointers(l.Type)) tmp := o.newTemp(l.Type, types.Haspointers(l.Type))
tmplist = append(tmplist, tmp) tmplist = append(tmplist, tmp)
left = append(left, l) left = append(left, l)
} }
} }
order.out = append(order.out, n) o.out = append(o.out, n)
as := nod(OAS2, nil, nil) as := nod(OAS2, nil, nil)
as.List.Set(left) as.List.Set(left)
as.Rlist.Set(tmplist) as.Rlist.Set(tmplist)
as = typecheck(as, Etop) as = typecheck(as, Etop)
orderstmt(as, order) o.stmt(as)
ti := 0 ti := 0
for ni, l := range n.List.Slice() { for ni, l := range n.List.Slice() {
...@@ -1254,31 +1234,31 @@ func orderas2(n *Node, order *Order) { ...@@ -1254,31 +1234,31 @@ func orderas2(n *Node, order *Order) {
} }
} }
// orderokas2 orders OAS2 with ok. // okAs2 orders OAS2 with ok.
// Just like orderas2(), this also adds temporaries to ensure left-to-right assignment. // Just like as2, this also adds temporaries to ensure left-to-right assignment.
func orderokas2(n *Node, order *Order) { func (o *Order) okAs2(n *Node) {
var tmp1, tmp2 *Node var tmp1, tmp2 *Node
if !isblank(n.List.First()) { if !isblank(n.List.First()) {
typ := n.Rlist.First().Type typ := n.Rlist.First().Type
tmp1 = ordertemp(typ, order, types.Haspointers(typ)) tmp1 = o.newTemp(typ, types.Haspointers(typ))
} }
if !isblank(n.List.Second()) { if !isblank(n.List.Second()) {
tmp2 = ordertemp(types.Types[TBOOL], order, false) tmp2 = o.newTemp(types.Types[TBOOL], false)
} }
order.out = append(order.out, n) o.out = append(o.out, n)
if tmp1 != nil { if tmp1 != nil {
r := nod(OAS, n.List.First(), tmp1) r := nod(OAS, n.List.First(), tmp1)
r = typecheck(r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) o.mapAssign(r)
n.List.SetFirst(tmp1) n.List.SetFirst(tmp1)
} }
if tmp2 != nil { if tmp2 != nil {
r := okas(n.List.Second(), tmp2) r := okas(n.List.Second(), tmp2)
r = typecheck(r, Etop) r = typecheck(r, Etop)
ordermapassign(r, order) o.mapAssign(r)
n.List.SetSecond(tmp2) n.List.SetSecond(tmp2)
} }
} }
...@@ -760,7 +760,7 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) ...@@ -760,7 +760,7 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes)
case initKindStatic: case initKindStatic:
genAsStatic(a) genAsStatic(a)
case initKindDynamic, initKindLocalCode: case initKindDynamic, initKindLocalCode:
a = orderstmtinplace(a) a = orderStmtInPlace(a)
a = walkstmt(a) a = walkstmt(a)
init.Append(a) init.Append(a)
default: default:
...@@ -911,7 +911,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { ...@@ -911,7 +911,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
a = nod(OAS, a, value) a = nod(OAS, a, value)
a = typecheck(a, Etop) a = typecheck(a, Etop)
a = orderstmtinplace(a) a = orderStmtInPlace(a)
a = walkstmt(a) a = walkstmt(a)
init.Append(a) init.Append(a)
} }
...@@ -920,7 +920,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { ...@@ -920,7 +920,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
a = nod(OAS, var_, nod(OSLICE, vauto, nil)) a = nod(OAS, var_, nod(OSLICE, vauto, nil))
a = typecheck(a, Etop) a = typecheck(a, Etop)
a = orderstmtinplace(a) a = orderStmtInPlace(a)
a = walkstmt(a) a = walkstmt(a)
init.Append(a) init.Append(a)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment