mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
9767727353
commit
fcfea24742
3 changed files with 163 additions and 164 deletions
|
|
@ -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) {
|
||||||
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.Name.SetKeepalive(true)
|
|
||||||
*xp = x
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
x := *xp
|
||||||
|
if x.Type.IsUnsafePtr() {
|
||||||
|
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) {
|
||||||
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)
|
||||||
|
Fatalf("unknown op in select %v", r.Op)
|
||||||
|
|
||||||
// If this is case x := <-ch or case x, y := <-ch, the case has
|
// If this is case x := <-ch or case x, y := <-ch, the case has
|
||||||
// the ODCL nodes to declare x and y. We want to delay that
|
// the ODCL nodes to declare x and y. We want to delay that
|
||||||
// declaration (and possible allocation) until inside the case body.
|
// declaration (and possible allocation) until inside the case body.
|
||||||
// Delete the ODCL nodes here and recreate them inside the body below.
|
// Delete the ODCL nodes here and recreate them inside the body below.
|
||||||
case OSELRECV, OSELRECV2:
|
case OSELRECV, OSELRECV2:
|
||||||
if r.Colas() {
|
if r.Colas() {
|
||||||
i := 0
|
i := 0
|
||||||
if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
|
if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
|
||||||
i++
|
i++
|
||||||
}
|
|
||||||
if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
|
|
||||||
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() {
|
||||||
// case x = <-c
|
r.Ninit.Set(nil)
|
||||||
// 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)
|
|
||||||
|
|
||||||
if r.Right.Left.Op != ONAME {
|
|
||||||
r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Introduce temporary for receive and move actual copy into case body.
|
|
||||||
// avoids problems with target being addressed, as usual.
|
|
||||||
// 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
|
|
||||||
// the x,ok receives. Not worth doing until there's a clear need.
|
|
||||||
if r.Left != nil && isblank(r.Left) {
|
|
||||||
r.Left = nil
|
|
||||||
}
|
|
||||||
if r.Left != nil {
|
|
||||||
// use channel element type for temporary to avoid conversions,
|
|
||||||
// such as in case interfacevalue = <-intchan.
|
|
||||||
// the conversion happens in the OAS instead.
|
|
||||||
tmp1 := r.Left
|
|
||||||
|
|
||||||
if r.Colas() {
|
|
||||||
tmp2 := nod(ODCL, tmp1, nil)
|
|
||||||
tmp2 = typecheck(tmp2, Etop)
|
|
||||||
n2.Ninit.Append(tmp2)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
n2.Ninit.Append(tmp2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.List.Len() != 0 && isblank(r.List.First()) {
|
|
||||||
r.List.Set(nil)
|
|
||||||
}
|
|
||||||
if r.List.Len() != 0 {
|
|
||||||
tmp1 := r.List.First()
|
|
||||||
if r.Colas() {
|
|
||||||
tmp2 := nod(ODCL, tmp1, nil)
|
|
||||||
tmp2 = typecheck(tmp2, Etop)
|
|
||||||
n2.Ninit.Append(tmp2)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.List.Set1(o.newTemp(types.Types[TBOOL], false))
|
|
||||||
tmp2 := okas(tmp1, r.List.First())
|
|
||||||
tmp2 = typecheck(tmp2, Etop)
|
|
||||||
n2.Ninit.Append(tmp2)
|
|
||||||
}
|
|
||||||
orderBlock(&n2.Ninit)
|
|
||||||
|
|
||||||
case OSEND:
|
|
||||||
if r.Ninit.Len() != 0 {
|
|
||||||
dumplist("ninit", r.Ninit)
|
|
||||||
Fatalf("ninit on select send")
|
|
||||||
}
|
|
||||||
|
|
||||||
// case c <- x
|
|
||||||
// r->left is c, r->right is x, both are always evaluated.
|
|
||||||
r.Left = o.expr(r.Left, nil)
|
|
||||||
|
|
||||||
if !r.Left.IsAutoTmp() {
|
|
||||||
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)
|
if r.Ninit.Len() != 0 {
|
||||||
|
dumplist("ninit", r.Ninit)
|
||||||
|
Fatalf("ninit on select recv")
|
||||||
|
}
|
||||||
|
|
||||||
|
// case x = <-c
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
if r.Right.Left.Op != ONAME {
|
||||||
|
r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Introduce temporary for receive and move actual copy into case body.
|
||||||
|
// avoids problems with target being addressed, as usual.
|
||||||
|
// 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
|
||||||
|
// the x,ok receives. Not worth doing until there's a clear need.
|
||||||
|
if r.Left != nil && isblank(r.Left) {
|
||||||
|
r.Left = nil
|
||||||
|
}
|
||||||
|
if r.Left != nil {
|
||||||
|
// use channel element type for temporary to avoid conversions,
|
||||||
|
// such as in case interfacevalue = <-intchan.
|
||||||
|
// the conversion happens in the OAS instead.
|
||||||
|
tmp1 := r.Left
|
||||||
|
|
||||||
|
if r.Colas() {
|
||||||
|
tmp2 := nod(ODCL, tmp1, nil)
|
||||||
|
tmp2 = typecheck(tmp2, Etop)
|
||||||
|
n2.Ninit.Append(tmp2)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
n2.Ninit.Append(tmp2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.List.Len() != 0 && isblank(r.List.First()) {
|
||||||
|
r.List.Set(nil)
|
||||||
|
}
|
||||||
|
if r.List.Len() != 0 {
|
||||||
|
tmp1 := r.List.First()
|
||||||
|
if r.Colas() {
|
||||||
|
tmp2 := nod(ODCL, tmp1, nil)
|
||||||
|
tmp2 = typecheck(tmp2, Etop)
|
||||||
|
n2.Ninit.Append(tmp2)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.List.Set1(o.newTemp(types.Types[TBOOL], false))
|
||||||
|
tmp2 := okas(tmp1, r.List.First())
|
||||||
|
tmp2 = typecheck(tmp2, Etop)
|
||||||
|
n2.Ninit.Append(tmp2)
|
||||||
|
}
|
||||||
|
orderBlock(&n2.Ninit)
|
||||||
|
|
||||||
|
case OSEND:
|
||||||
|
if r.Ninit.Len() != 0 {
|
||||||
|
dumplist("ninit", r.Ninit)
|
||||||
|
Fatalf("ninit on select send")
|
||||||
|
}
|
||||||
|
|
||||||
|
// case c <- x
|
||||||
|
// r->left is c, r->right is x, both are always evaluated.
|
||||||
|
r.Left = o.expr(r.Left, nil)
|
||||||
|
|
||||||
|
if !r.Left.IsAutoTmp() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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 {
|
||||||
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
|
|
||||||
if !staticassign(ll, e.Expr, out) {
|
|
||||||
// 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))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ll := n.copy()
|
||||||
|
ll.Orig = ll // completely separate copy
|
||||||
|
if staticassign(ll, e.Expr, out) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 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 {
|
||||||
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 {
|
||||||
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 {
|
|
||||||
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
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
p, _ := dotpath(l.Sym, t, nil, true)
|
||||||
|
if p == nil {
|
||||||
|
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
|
||||||
|
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)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fielddup(f.Sym.Name, hash)
|
fielddup(f.Sym.Name, hash)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue