mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/gc: represent labels as bare Syms
Avoids allocating an ONAME for OLABEL, OGOTO, and named OBREAK and OCONTINUE nodes. Passes toolstash-check. Change-Id: I359142cd48e8987b5bf29ac100752f8c497261c1 Reviewed-on: https://go-review.googlesource.com/c/145200 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
c68e3bcb03
commit
2dda040f19
11 changed files with 47 additions and 39 deletions
|
|
@ -621,23 +621,23 @@ func (e *EscState) escloopdepth(n *Node) {
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
if n.Left == nil || n.Left.Sym == nil {
|
if n.Sym == nil {
|
||||||
Fatalf("esc:label without label: %+v", n)
|
Fatalf("esc:label without label: %+v", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk will complain about this label being already defined, but that's not until
|
// Walk will complain about this label being already defined, but that's not until
|
||||||
// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
|
// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
|
||||||
n.Left.Sym.Label = asTypesNode(&nonlooping)
|
n.Sym.Label = asTypesNode(&nonlooping)
|
||||||
|
|
||||||
case OGOTO:
|
case OGOTO:
|
||||||
if n.Left == nil || n.Left.Sym == nil {
|
if n.Sym == nil {
|
||||||
Fatalf("esc:goto without label: %+v", n)
|
Fatalf("esc:goto without label: %+v", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we come past one that's uninitialized, this must be a (harmless) forward jump
|
// If we come past one that's uninitialized, this must be a (harmless) forward jump
|
||||||
// but if it's set to nonlooping the label must have preceded this goto.
|
// but if it's set to nonlooping the label must have preceded this goto.
|
||||||
if asNode(n.Left.Sym.Label) == &nonlooping {
|
if asNode(n.Sym.Label) == &nonlooping {
|
||||||
n.Left.Sym.Label = asTypesNode(&looping)
|
n.Sym.Label = asTypesNode(&looping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -851,18 +851,19 @@ opSwitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
if asNode(n.Left.Sym.Label) == &nonlooping {
|
switch asNode(n.Sym.Label) {
|
||||||
|
case &nonlooping:
|
||||||
if Debug['m'] > 2 {
|
if Debug['m'] > 2 {
|
||||||
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
} else if asNode(n.Left.Sym.Label) == &looping {
|
case &looping:
|
||||||
if Debug['m'] > 2 {
|
if Debug['m'] > 2 {
|
||||||
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
e.loopdepth++
|
e.loopdepth++
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Left.Sym.Label = nil
|
n.Sym.Label = nil
|
||||||
|
|
||||||
case ORANGE:
|
case ORANGE:
|
||||||
if n.List.Len() >= 2 {
|
if n.List.Len() >= 2 {
|
||||||
|
|
|
||||||
|
|
@ -1045,8 +1045,8 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
|
||||||
mode.Fprintf(s, ": %v", n.Nbody)
|
mode.Fprintf(s, ": %v", n.Nbody)
|
||||||
|
|
||||||
case OBREAK, OCONTINUE, OGOTO, OFALL:
|
case OBREAK, OCONTINUE, OGOTO, OFALL:
|
||||||
if n.Left != nil {
|
if n.Sym != nil {
|
||||||
mode.Fprintf(s, "%#v %v", n.Op, n.Left)
|
mode.Fprintf(s, "%#v %v", n.Op, n.Sym)
|
||||||
} else {
|
} else {
|
||||||
mode.Fprintf(s, "%#v", n.Op)
|
mode.Fprintf(s, "%#v", n.Op)
|
||||||
}
|
}
|
||||||
|
|
@ -1055,7 +1055,7 @@ func (n *Node) stmtfmt(s fmt.State, mode fmtMode) {
|
||||||
break
|
break
|
||||||
|
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
mode.Fprintf(s, "%v: ", n.Left)
|
mode.Fprintf(s, "%v: ", n.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
if extrablock {
|
if extrablock {
|
||||||
|
|
|
||||||
|
|
@ -1102,7 +1102,8 @@ func (w *exportWriter) stmt(n *Node) {
|
||||||
case OGOTO, OLABEL:
|
case OGOTO, OLABEL:
|
||||||
w.op(op)
|
w.op(op)
|
||||||
w.pos(n.Pos)
|
w.pos(n.Pos)
|
||||||
w.expr(n.Left)
|
w.op(ONAME) // TODO(mdempsky): Remove toolstash hack.
|
||||||
|
w.string(n.Sym.Name)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
|
Fatalf("exporter: CANNOT EXPORT: %v\nPlease notify gri@\n", n.Op)
|
||||||
|
|
|
||||||
|
|
@ -1043,7 +1043,12 @@ func (r *importReader) node() *Node {
|
||||||
// unreachable - not emitted by exporter
|
// unreachable - not emitted by exporter
|
||||||
|
|
||||||
case OGOTO, OLABEL:
|
case OGOTO, OLABEL:
|
||||||
return nodl(r.pos(), op, newname(r.expr().Sym), nil)
|
n := nodl(r.pos(), op, nil, nil)
|
||||||
|
if op := r.op(); op != ONAME { // TODO(mdempsky): Remove toolstash check.
|
||||||
|
Fatalf("got %v, want ONAME", op)
|
||||||
|
}
|
||||||
|
n.Sym = lookup(r.string())
|
||||||
|
return n
|
||||||
|
|
||||||
case OEND:
|
case OEND:
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -1072,7 +1072,7 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
|
||||||
|
|
||||||
body := subst.list(asNodes(fn.Func.Inl.Body))
|
body := subst.list(asNodes(fn.Func.Inl.Body))
|
||||||
|
|
||||||
lab := nod(OLABEL, retlabel, nil)
|
lab := nodSym(OLABEL, nil, retlabel)
|
||||||
body = append(body, lab)
|
body = append(body, lab)
|
||||||
|
|
||||||
typecheckslice(body, Etop)
|
typecheckslice(body, Etop)
|
||||||
|
|
@ -1158,7 +1158,7 @@ func argvar(t *types.Type, i int) *Node {
|
||||||
// function call.
|
// function call.
|
||||||
type inlsubst struct {
|
type inlsubst struct {
|
||||||
// Target of the goto substituted in place of a return.
|
// Target of the goto substituted in place of a return.
|
||||||
retlabel *Node
|
retlabel *types.Sym
|
||||||
|
|
||||||
// Temporary result variables.
|
// Temporary result variables.
|
||||||
retvars []*Node
|
retvars []*Node
|
||||||
|
|
@ -1218,7 +1218,7 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||||
|
|
||||||
// dump("Return before substitution", n);
|
// dump("Return before substitution", n);
|
||||||
case ORETURN:
|
case ORETURN:
|
||||||
m := nod(OGOTO, subst.retlabel, nil)
|
m := nodSym(OGOTO, nil, subst.retlabel)
|
||||||
m.Ninit.Set(subst.list(n.Ninit))
|
m.Ninit.Set(subst.list(n.Ninit))
|
||||||
|
|
||||||
if len(subst.retvars) != 0 && n.List.Len() != 0 {
|
if len(subst.retvars) != 0 && n.List.Len() != 0 {
|
||||||
|
|
@ -1245,8 +1245,8 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||||
m := n.copy()
|
m := n.copy()
|
||||||
m.Pos = subst.updatedPos(m.Pos)
|
m.Pos = subst.updatedPos(m.Pos)
|
||||||
m.Ninit.Set(nil)
|
m.Ninit.Set(nil)
|
||||||
p := fmt.Sprintf("%s·%d", n.Left.Sym.Name, inlgen)
|
p := fmt.Sprintf("%s·%d", n.Sym.Name, inlgen)
|
||||||
m.Left = newname(lookup(p))
|
m.Sym = lookup(p)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -941,7 +941,7 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node {
|
||||||
}
|
}
|
||||||
n := p.nod(stmt, op, nil, nil)
|
n := p.nod(stmt, op, nil, nil)
|
||||||
if stmt.Label != nil {
|
if stmt.Label != nil {
|
||||||
n.Left = p.newname(stmt.Label)
|
n.Sym = p.name(stmt.Label)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
case *syntax.CallStmt:
|
case *syntax.CallStmt:
|
||||||
|
|
@ -1205,7 +1205,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node {
|
func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node {
|
||||||
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
|
lhs := p.nodSym(label, OLABEL, nil, p.name(label.Label))
|
||||||
|
|
||||||
var ls *Node
|
var ls *Node
|
||||||
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
|
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
|
||||||
|
|
|
||||||
|
|
@ -845,7 +845,7 @@ func (s *state) stmt(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
sym := n.Left.Sym
|
sym := n.Sym
|
||||||
lab := s.label(sym)
|
lab := s.label(sym)
|
||||||
|
|
||||||
// Associate label with its control flow node, if any
|
// Associate label with its control flow node, if any
|
||||||
|
|
@ -867,7 +867,7 @@ func (s *state) stmt(n *Node) {
|
||||||
s.startBlock(lab.target)
|
s.startBlock(lab.target)
|
||||||
|
|
||||||
case OGOTO:
|
case OGOTO:
|
||||||
sym := n.Left.Sym
|
sym := n.Sym
|
||||||
|
|
||||||
lab := s.label(sym)
|
lab := s.label(sym)
|
||||||
if lab.target == nil {
|
if lab.target == nil {
|
||||||
|
|
@ -1033,7 +1033,7 @@ func (s *state) stmt(n *Node) {
|
||||||
|
|
||||||
case OCONTINUE, OBREAK:
|
case OCONTINUE, OBREAK:
|
||||||
var to *ssa.Block
|
var to *ssa.Block
|
||||||
if n.Left == nil {
|
if n.Sym == nil {
|
||||||
// plain break/continue
|
// plain break/continue
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCONTINUE:
|
case OCONTINUE:
|
||||||
|
|
@ -1043,7 +1043,7 @@ func (s *state) stmt(n *Node) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// labeled break/continue; look up the target
|
// labeled break/continue; look up the target
|
||||||
sym := n.Left.Sym
|
sym := n.Sym
|
||||||
lab := s.label(sym)
|
lab := s.label(sym)
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCONTINUE:
|
case OCONTINUE:
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ func lookupN(prefix string, n int) *types.Sym {
|
||||||
// to help with debugging.
|
// to help with debugging.
|
||||||
// It should begin with "." to avoid conflicts with
|
// It should begin with "." to avoid conflicts with
|
||||||
// user labels.
|
// user labels.
|
||||||
func autolabel(prefix string) *Node {
|
func autolabel(prefix string) *types.Sym {
|
||||||
if prefix[0] != '.' {
|
if prefix[0] != '.' {
|
||||||
Fatalf("autolabel prefix must start with '.', have %q", prefix)
|
Fatalf("autolabel prefix must start with '.', have %q", prefix)
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ func autolabel(prefix string) *Node {
|
||||||
}
|
}
|
||||||
n := fn.Func.Label
|
n := fn.Func.Label
|
||||||
fn.Func.Label++
|
fn.Func.Label++
|
||||||
return newname(lookupN(prefix, int(n)))
|
return lookupN(prefix, int(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
func restrictlookup(name string, pkg *types.Pkg) *types.Sym {
|
func restrictlookup(name string, pkg *types.Pkg) *types.Sym {
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,8 @@ func casebody(sw *Node, typeswvar *Node) {
|
||||||
n.Op = OCASE
|
n.Op = OCASE
|
||||||
needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL
|
needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL
|
||||||
|
|
||||||
jmp := nod(OGOTO, autolabel(".s"), nil)
|
lbl := autolabel(".s")
|
||||||
|
jmp := nodSym(OGOTO, nil, lbl)
|
||||||
switch n.List.Len() {
|
switch n.List.Len() {
|
||||||
case 0:
|
case 0:
|
||||||
// default
|
// default
|
||||||
|
|
@ -486,7 +487,7 @@ func casebody(sw *Node, typeswvar *Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stat = append(stat, nod(OLABEL, jmp.Left, nil))
|
stat = append(stat, nodSym(OLABEL, nil, lbl))
|
||||||
if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
|
if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
|
||||||
l := []*Node{
|
l := []*Node{
|
||||||
nod(ODCL, n.Rlist.First(), nil),
|
nod(ODCL, n.Rlist.First(), nil),
|
||||||
|
|
@ -778,10 +779,10 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
} else {
|
} else {
|
||||||
// Jump to default case.
|
// Jump to default case.
|
||||||
lbl := autolabel(".s")
|
lbl := autolabel(".s")
|
||||||
i.Nbody.Set1(nod(OGOTO, lbl, nil))
|
i.Nbody.Set1(nodSym(OGOTO, nil, lbl))
|
||||||
// Wrap default case with label.
|
// Wrap default case with label.
|
||||||
blk := nod(OBLOCK, nil, nil)
|
blk := nod(OBLOCK, nil, nil)
|
||||||
blk.List.Set2(nod(OLABEL, lbl, nil), def)
|
blk.List.Set2(nodSym(OLABEL, nil, lbl), def)
|
||||||
def = blk
|
def = blk
|
||||||
}
|
}
|
||||||
i.Left = typecheck(i.Left, Erv)
|
i.Left = typecheck(i.Left, Erv)
|
||||||
|
|
|
||||||
|
|
@ -698,10 +698,10 @@ const (
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
OBLOCK // { List } (block of code)
|
OBLOCK // { List } (block of code)
|
||||||
OBREAK // break
|
OBREAK // break [Sym]
|
||||||
OCASE // case Left or List[0]..List[1]: Nbody (select case after processing; Left==nil and List==nil means default)
|
OCASE // case Left or List[0]..List[1]: Nbody (select case after processing; Left==nil and List==nil means default)
|
||||||
OXCASE // case List: Nbody (select case before processing; List==nil means default)
|
OXCASE // case List: Nbody (select case before processing; List==nil means default)
|
||||||
OCONTINUE // continue
|
OCONTINUE // continue [Sym]
|
||||||
ODEFER // defer Left (Left must be call)
|
ODEFER // defer Left (Left must be call)
|
||||||
OEMPTY // no-op (empty statement)
|
OEMPTY // no-op (empty statement)
|
||||||
OFALL // fallthrough
|
OFALL // fallthrough
|
||||||
|
|
@ -716,9 +716,9 @@ const (
|
||||||
// }
|
// }
|
||||||
// OFORUNTIL is created by walk. There's no way to write this in Go code.
|
// OFORUNTIL is created by walk. There's no way to write this in Go code.
|
||||||
OFORUNTIL
|
OFORUNTIL
|
||||||
OGOTO // goto Left
|
OGOTO // goto Sym
|
||||||
OIF // if Ninit; Left { Nbody } else { Rlist }
|
OIF // if Ninit; Left { Nbody } else { Rlist }
|
||||||
OLABEL // Left:
|
OLABEL // Sym:
|
||||||
OPROC // go Left (Left must be call)
|
OPROC // go Left (Left must be call)
|
||||||
ORANGE // for List = range Right { Nbody }
|
ORANGE // for List = range Right { Nbody }
|
||||||
ORETURN // return List
|
ORETURN // return List
|
||||||
|
|
|
||||||
|
|
@ -1984,7 +1984,7 @@ func typecheck1(n *Node, top int) *Node {
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
decldepth++
|
decldepth++
|
||||||
if n.Left.Sym.IsBlank() {
|
if n.Sym.IsBlank() {
|
||||||
// Empty identifier is valid but useless.
|
// Empty identifier is valid but useless.
|
||||||
// Eliminate now to simplify life later.
|
// Eliminate now to simplify life later.
|
||||||
// See issues 7538, 11589, 11593.
|
// See issues 7538, 11589, 11593.
|
||||||
|
|
@ -3831,12 +3831,12 @@ func markbreak(n *Node, implicit *Node) {
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OBREAK:
|
case OBREAK:
|
||||||
if n.Left == nil {
|
if n.Sym == nil {
|
||||||
if implicit != nil {
|
if implicit != nil {
|
||||||
implicit.SetHasBreak(true)
|
implicit.SetHasBreak(true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lab := asNode(n.Left.Sym.Label)
|
lab := asNode(n.Sym.Label)
|
||||||
if lab != nil {
|
if lab != nil {
|
||||||
lab.SetHasBreak(true)
|
lab.SetHasBreak(true)
|
||||||
}
|
}
|
||||||
|
|
@ -3864,9 +3864,9 @@ func markbreaklist(l Nodes, implicit *Node) {
|
||||||
if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] {
|
if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] {
|
||||||
switch n.Name.Defn.Op {
|
switch n.Name.Defn.Op {
|
||||||
case OFOR, OFORUNTIL, OSWITCH, OTYPESW, OSELECT, ORANGE:
|
case OFOR, OFORUNTIL, OSWITCH, OTYPESW, OSELECT, ORANGE:
|
||||||
n.Left.Sym.Label = asTypesNode(n.Name.Defn)
|
n.Sym.Label = asTypesNode(n.Name.Defn)
|
||||||
markbreak(n.Name.Defn, n.Name.Defn)
|
markbreak(n.Name.Defn, n.Name.Defn)
|
||||||
n.Left.Sym.Label = nil
|
n.Sym.Label = nil
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue