Commit 2dda040f authored by Matthew Dempsky's avatar Matthew Dempsky

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: default avatarRobert Griesemer <gri@golang.org>
parent c68e3bcb
...@@ -621,23 +621,23 @@ func (e *EscState) escloopdepth(n *Node) { ...@@ -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: ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) []* ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 ( ...@@ -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 ( ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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
} }
......
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