From: Daniel Martí Date: Tue, 3 Apr 2018 12:17:28 +0000 (+0100) Subject: cmd/compile: early return/continue to unindent some code X-Git-Tag: go1.11beta1~963 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fcfea247426703e6daaa0fa3383e762bf7ec081f;p=gostls13.git 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í TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 4161b273d0..6ba6f91a9a 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -332,13 +332,10 @@ func ismulticall(l Nodes) bool { switch n.Op { default: return false - 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, @@ -381,37 +378,38 @@ func (o *Order) call(n *Node) { n.Right = o.expr(n.Right, nil) // ODDDARG temp o.callArgs(&n.List) - if n.Op == OCALLFUNC { - keepAlive := func(i int) { - // If the argument is really a pointer being converted to uintptr, - // arrange for the pointer to be kept alive until the call returns, - // by copying it into a temp and marking that temp - // still alive when we pop the temp stack. - xp := n.List.Addr(i) - for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() { - xp = &(*xp).Left - } - x := *xp - if x.Type.IsUnsafePtr() { - x = o.copyExpr(x, x.Type, false) - x.Name.SetKeepalive(true) - *xp = x - } + if n.Op != OCALLFUNC { + return + } + keepAlive := func(i int) { + // If the argument is really a pointer being converted to uintptr, + // arrange for the pointer to be kept alive until the call returns, + // by copying it into a temp and marking that temp + // still alive when we pop the temp stack. + xp := n.List.Addr(i) + for (*xp).Op == OCONVNOP && !(*xp).Type.IsUnsafePtr() { + xp = &(*xp).Left + } + 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() { - // Check for "unsafe-uintptr" tag provided by escape analysis. - if t.Isddd() && !n.Isddd() { - if t.Note == uintptrEscapesTag { - for ; i < n.List.Len(); i++ { - keepAlive(i) - } - } - } else { - if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag { + for i, t := range n.Left.Type.Params().FieldSlice() { + // Check for "unsafe-uintptr" tag provided by escape analysis. + if t.Isddd() && !n.Isddd() { + if t.Note == uintptrEscapesTag { + for ; i < n.List.Len(); 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 { Fatalf("order select ninit") } - if r != nil { - switch 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 - // the ODCL nodes to declare x and y. We want to delay that - // declaration (and possible allocation) until inside the case body. - // Delete the ODCL nodes here and recreate them inside the body below. - case OSELRECV, OSELRECV2: - if r.Colas() { - i := 0 - if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { - 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 r == nil { + continue + } + switch 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 + // the ODCL nodes to declare x and y. We want to delay that + // declaration (and possible allocation) until inside the case body. + // Delete the ODCL nodes here and recreate them inside the body below. + case OSELRECV, OSELRECV2: + if r.Colas() { + i := 0 + if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left { + i++ } - - if r.Ninit.Len() != 0 { - dumplist("ninit", r.Ninit) - Fatalf("ninit on select recv") + 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) } + } - // 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.Ninit.Len() != 0 { + dumplist("ninit", r.Ninit) + Fatalf("ninit on select recv") + } - if r.Right.Left.Op != ONAME { - r.Right.Left = o.copyExpr(r.Right.Left, r.Right.Left.Type, false) - } + // 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) - // 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) + 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) } - 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()) + 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) } - orderBlock(&n2.Ninit) - case OSEND: - if r.Ninit.Len() != 0 { - dumplist("ninit", r.Ninit) - Fatalf("ninit on select send") - } + 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 c <- x - // r->left is c, r->right is x, both are always evaluated. - r.Left = o.expr(r.Left, nil) + case OSEND: + if r.Ninit.Len() != 0 { + dumplist("ninit", r.Ninit) + Fatalf("ninit on select send") + } - 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) - } + // 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) } // Now that we have accumulated all the temporaries, clean them. // Also insert any ninit queued during the previous loop. // (The temporary cleaning must follow that ninit work.) for _, n3 := range n.List.Slice() { + orderBlock(&n3.Nbody) n3.Nbody.Prepend(o.cleanTempNoPop(t)...) // TODO(mdempsky): Is this actually necessary? diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index b63ac23ae3..edd098b1ec 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -347,20 +347,21 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool { n.Type = e.Expr.Type if e.Expr.Op == OLITERAL { gdata(n, e.Expr, int(n.Type.Width)) - } else { - 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)) - } + continue + } + 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 @@ -449,13 +450,13 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { n.Type = e.Expr.Type if e.Expr.Op == OLITERAL { gdata(n, e.Expr, int(n.Type.Width)) - } else { - setlineno(e.Expr) - a := n.copy() - a.Orig = a // completely separate copy - if !staticassign(a, e.Expr, out) { - *out = append(*out, nod(OAS, a, e.Expr)) - } + continue + } + setlineno(e.Expr) + a := n.copy() + a.Orig = a // completely separate copy + if !staticassign(a, e.Expr, out) { + *out = append(*out, nod(OAS, a, e.Expr)) } } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 02cac2e86c..0b01d803ea 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3089,20 +3089,20 @@ func typecheckcomplit(n *Node) *Node { if f == nil { 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) - } else { - 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 + } + 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 } fielddup(f.Sym.Name, hash)