Commit fcfea247 authored by Daniel Martí's avatar Daniel Martí

cmd/compile: early return/continue to unindent some code

While at it, also simplify a couple of switches.

Doesn't pass toolstash -cmp on std cmd, because orderBlock(&n2.Nbody) is
moved further down to the n3 loop.

Change-Id: I20a2a6c21eb9a183a59572e0fca401a5041fc40a
Reviewed-on: https://go-review.googlesource.com/104416
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 97677273
...@@ -332,13 +332,10 @@ func ismulticall(l Nodes) bool { ...@@ -332,13 +332,10 @@ func ismulticall(l Nodes) bool {
switch n.Op { switch n.Op {
default: default:
return false return false
case OCALLFUNC, OCALLMETH, OCALLINTER: case OCALLFUNC, OCALLMETH, OCALLINTER:
break // call must return multiple values
return n.Left.Type.NumResults() > 1
} }
// call must return multiple values
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,
...@@ -381,37 +378,38 @@ func (o *Order) call(n *Node) { ...@@ -381,37 +378,38 @@ func (o *Order) call(n *Node) {
n.Right = o.expr(n.Right, nil) // ODDDARG temp n.Right = o.expr(n.Right, nil) // ODDDARG temp
o.callArgs(&n.List) o.callArgs(&n.List)
if n.Op == OCALLFUNC { if n.Op != OCALLFUNC {
keepAlive := func(i int) { return
// If the argument is really a pointer being converted to uintptr, }
// arrange for the pointer to be kept alive until the call returns, keepAlive := func(i int) {
// by copying it into a temp and marking that temp // If the argument is really a pointer being converted to uintptr,
// still alive when we pop the temp stack. // arrange for the pointer to be kept alive until the call returns,
xp := n.List.Addr(i) // by copying it into a temp and marking that temp
for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() { // still alive when we pop the temp stack.
xp = &(*xp).Left xp := n.List.Addr(i)
} for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() {
x := *xp xp = &(*xp).Left
if x.Type.IsUnsafePtr() { }
x = o.copyExpr(x, x.Type, false) x := *xp
x.Name.SetKeepalive(true) if x.Type.IsUnsafePtr() {
*xp = x x = o.copyExpr(x, x.Type, false)
} x.Name.SetKeepalive(true)
*xp = x
} }
}
for i, t := range n.Left.Type.Params().FieldSlice() { for i, t := range n.Left.Type.Params().FieldSlice() {
// Check for "unsafe-uintptr" tag provided by escape analysis. // Check for "unsafe-uintptr" tag provided by escape analysis.
if t.Isddd() && !n.Isddd() { if t.Isddd() && !n.Isddd() {
if t.Note == uintptrEscapesTag { if t.Note == uintptrEscapesTag {
for ; i < n.List.Len(); i++ { for ; i < n.List.Len(); i++ {
keepAlive(i)
}
}
} else {
if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
keepAlive(i) keepAlive(i)
} }
} }
} else {
if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
keepAlive(i)
}
} }
} }
} }
...@@ -766,117 +764,117 @@ func (o *Order) stmt(n *Node) { ...@@ -766,117 +764,117 @@ func (o *Order) stmt(n *Node) {
if n2.Ninit.Len() != 0 { if n2.Ninit.Len() != 0 {
Fatalf("order select ninit") Fatalf("order select ninit")
} }
if r != nil { if r == nil {
switch r.Op { continue
default: }
Dump("select case", r) switch r.Op {
Fatalf("unknown op in select %v", r.Op) default:
Dump("select case", r)
// If this is case x := <-ch or case x, y := <-ch, the case has Fatalf("unknown op in select %v", r.Op)
// the ODCL nodes to declare x and y. We want to delay that
// declaration (and possible allocation) until inside the case body. // If this is case x := <-ch or case x, y := <-ch, the case has
// Delete the ODCL nodes here and recreate them inside the body below. // the ODCL nodes to declare x and y. We want to delay that
case OSELRECV, OSELRECV2: // declaration (and possible allocation) until inside the case body.
if r.Colas() { // Delete the ODCL nodes here and recreate them inside the body below.
i := 0 case OSELRECV, OSELRECV2:
if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { if r.Colas() {
i++ i := 0
} if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() { i++
i++
}
if i >= r.Ninit.Len() {
r.Ninit.Set(nil)
}
} }
if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
if r.Ninit.Len() != 0 { i++
dumplist("ninit", r.Ninit) }
Fatalf("ninit on select recv") if i >= r.Ninit.Len() {
r.Ninit.Set(nil)
} }
}
// case x = <-c if r.Ninit.Len() != 0 {
// case x, ok = <-c dumplist("ninit", r.Ninit)
// r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c. Fatalf("ninit on select recv")
// r->left == N means 'case <-c'. }
// c is always evaluated; x and ok are only evaluated when assigned.
r.Right.Left = o.expr(r.Right.Left, nil)
if r.Right.Left.Op != ONAME { // case x = <-c
r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false) // case x, ok = <-c
} // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
// r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned.
r.Right.Left = o.expr(r.Right.Left, nil)
// Introduce temporary for receive and move actual copy into case body. if r.Right.Left.Op != ONAME {
// avoids problems with target being addressed, as usual. r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false)
// NOTE: If we wanted to be clever, we could arrange for just one }
// temporary per distinct type, sharing the temp among all receives
// with that temp. Similarly one ok bool could be shared among all // Introduce temporary for receive and move actual copy into case body.
// the x,ok receives. Not worth doing until there's a clear need. // avoids problems with target being addressed, as usual.
if r.Left != nil && isblank(r.Left) { // NOTE: If we wanted to be clever, we could arrange for just one
r.Left = nil // temporary per distinct type, sharing the temp among all receives
} // with that temp. Similarly one ok bool could be shared among all
if r.Left != nil { // the x,ok receives. Not worth doing until there's a clear need.
// use channel element type for temporary to avoid conversions, if r.Left != nil && isblank(r.Left) {
// such as in case interfacevalue = <-intchan. r.Left = nil
// the conversion happens in the OAS instead. }
tmp1 := r.Left if r.Left != nil {
// use channel element type for temporary to avoid conversions,
if r.Colas() { // such as in case interfacevalue = <-intchan.
tmp2 := nod(ODCL, tmp1, nil) // the conversion happens in the OAS instead.
tmp2 = typecheck(tmp2, Etop) tmp1 := r.Left
n2.Ninit.Append(tmp2)
} if r.Colas() {
tmp2 := nod(ODCL, tmp1, nil)
r.Left = o.newTemp(r.Right.Left.Type.Elem(), types.Haspointers(r.Right.Left.Type.Elem()))
tmp2 := nod(OAS, tmp1, r.Left)
tmp2 = typecheck(tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
if r.List.Len() != 0 && isblank(r.List.First()) { r.Left = o.newTemp(r.Right.Left.Type.Elem(), types.Haspointers(r.Right.Left.Type.Elem()))
r.List.Set(nil) tmp2 := nod(OAS, tmp1, r.Left)
} tmp2 = typecheck(tmp2, Etop)
if r.List.Len() != 0 { n2.Ninit.Append(tmp2)
tmp1 := r.List.First() }
if r.Colas() {
tmp2 := nod(ODCL, tmp1, nil) if r.List.Len() != 0 && isblank(r.List.First()) {
tmp2 = typecheck(tmp2, Etop) r.List.Set(nil)
n2.Ninit.Append(tmp2) }
} if r.List.Len() != 0 {
tmp1 := r.List.First()
r.List.Set1(o.newTemp(types.Types[TBOOL], false)) if r.Colas() {
tmp2 := okas(tmp1, r.List.First()) tmp2 := nod(ODCL, tmp1, nil)
tmp2 = typecheck(tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
orderBlock(&n2.Ninit)
case OSEND: r.List.Set1(o.newTemp(types.Types[TBOOL], false))
if r.Ninit.Len() != 0 { tmp2 := okas(tmp1, r.List.First())
dumplist("ninit", r.Ninit) tmp2 = typecheck(tmp2, Etop)
Fatalf("ninit on select send") n2.Ninit.Append(tmp2)
} }
orderBlock(&n2.Ninit)
// case c <- x case OSEND:
// r->left is c, r->right is x, both are always evaluated. if r.Ninit.Len() != 0 {
r.Left = o.expr(r.Left, nil) dumplist("ninit", r.Ninit)
Fatalf("ninit on select send")
}
if !r.Left.IsAutoTmp() { // case c <- x
r.Left = o.copyExpr(r.Left, r.Left.Type, false) // r->left is c, r->right is x, both are always evaluated.
} r.Left = o.expr(r.Left, nil)
r.Right = o.expr(r.Right, nil)
if !r.Right.IsAutoTmp() { if !r.Left.IsAutoTmp() {
r.Right = o.copyExpr(r.Right, r.Right.Type, false) r.Left = o.copyExpr(r.Left, r.Left.Type, false)
} }
r.Right = o.expr(r.Right, nil)
if !r.Right.IsAutoTmp() {
r.Right = o.copyExpr(r.Right, r.Right.Type, false)
} }
} }
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() {
orderBlock(&n3.Nbody)
n3.Nbody.Prepend(o.cleanTempNoPop(t)...) n3.Nbody.Prepend(o.cleanTempNoPop(t)...)
// TODO(mdempsky): Is this actually necessary? // TODO(mdempsky): Is this actually necessary?
......
...@@ -347,20 +347,21 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool { ...@@ -347,20 +347,21 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool {
n.Type = e.Expr.Type n.Type = e.Expr.Type
if e.Expr.Op == OLITERAL { if e.Expr.Op == OLITERAL {
gdata(n, e.Expr, int(n.Type.Width)) gdata(n, e.Expr, int(n.Type.Width))
} else { continue
ll := n.copy() }
ll.Orig = ll // completely separate copy ll := n.copy()
if !staticassign(ll, e.Expr, out) { ll.Orig = ll // completely separate copy
// Requires computation, but we're if staticassign(ll, e.Expr, out) {
// copying someone else's computation. continue
rr := orig.copy()
rr.Orig = rr // completely separate copy
rr.Type = ll.Type
rr.Xoffset += e.Xoffset
setlineno(rr)
*out = append(*out, nod(OAS, ll, rr))
}
} }
// Requires computation, but we're
// copying someone else's computation.
rr := orig.copy()
rr.Orig = rr // completely separate copy
rr.Type = ll.Type
rr.Xoffset += e.Xoffset
setlineno(rr)
*out = append(*out, nod(OAS, ll, rr))
} }
return true return true
...@@ -449,13 +450,13 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -449,13 +450,13 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
n.Type = e.Expr.Type n.Type = e.Expr.Type
if e.Expr.Op == OLITERAL { if e.Expr.Op == OLITERAL {
gdata(n, e.Expr, int(n.Type.Width)) gdata(n, e.Expr, int(n.Type.Width))
} else { continue
setlineno(e.Expr) }
a := n.copy() setlineno(e.Expr)
a.Orig = a // completely separate copy a := n.copy()
if !staticassign(a, e.Expr, out) { a.Orig = a // completely separate copy
*out = append(*out, nod(OAS, a, e.Expr)) if !staticassign(a, e.Expr, out) {
} *out = append(*out, nod(OAS, a, e.Expr))
} }
} }
......
...@@ -3089,20 +3089,20 @@ func typecheckcomplit(n *Node) *Node { ...@@ -3089,20 +3089,20 @@ func typecheckcomplit(n *Node) *Node {
if f == nil { if f == nil {
if ci := lookdot1(nil, l.Sym, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup. if ci := lookdot1(nil, l.Sym, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup.
yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym) yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym)
} else { continue
p, _ := dotpath(l.Sym, t, nil, true) }
if p == nil { p, _ := dotpath(l.Sym, t, nil, true)
yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t) if p == nil {
continue yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t)
} continue
// dotpath returns the parent embedded types in reverse order. }
var ep []string // dotpath returns the parent embedded types in reverse order.
for ei := len(p) - 1; ei >= 0; ei-- { var ep []string
ep = append(ep, p[ei].field.Type.Sym.Name) for ei := len(p) - 1; ei >= 0; ei-- {
} ep = append(ep, p[ei].field.Type.Sym.Name)
ep = append(ep, l.Sym.Name)
yyerror("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), t)
} }
ep = append(ep, l.Sym.Name)
yyerror("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), t)
continue continue
} }
fielddup(f.Sym.Name, hash) fielddup(f.Sym.Name, hash)
......
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