Commit fd44d872 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: factor out dcl stack ops into package types

Change-Id: I000bb530e00d0f0bc59e0f1366b5fb586adf4f37
Reviewed-on: https://go-review.googlesource.com/39912
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 3cf1ce40
...@@ -191,7 +191,7 @@ func genhash(sym *types.Sym, t *types.Type) { ...@@ -191,7 +191,7 @@ func genhash(sym *types.Sym, t *types.Type) {
lineno = autogeneratedPos // less confusing than end of input lineno = autogeneratedPos // less confusing than end of input
dclcontext = PEXTERN dclcontext = PEXTERN
markdcl() types.Markdcl(lineno)
// func sym(p *T, h uintptr) uintptr // func sym(p *T, h uintptr) uintptr
fn := nod(ODCLFUNC, nil, nil) fn := nod(ODCLFUNC, nil, nil)
...@@ -305,7 +305,7 @@ func genhash(sym *types.Sym, t *types.Type) { ...@@ -305,7 +305,7 @@ func genhash(sym *types.Sym, t *types.Type) {
fn = typecheck(fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() types.Popdcl()
if debug_dclstack != 0 { if debug_dclstack != 0 {
testdclstack() testdclstack()
} }
...@@ -369,7 +369,7 @@ func geneq(sym *types.Sym, t *types.Type) { ...@@ -369,7 +369,7 @@ func geneq(sym *types.Sym, t *types.Type) {
lineno = autogeneratedPos // less confusing than end of input lineno = autogeneratedPos // less confusing than end of input
dclcontext = PEXTERN dclcontext = PEXTERN
markdcl() types.Markdcl(lineno)
// func sym(p, q *T) bool // func sym(p, q *T) bool
fn := nod(ODCLFUNC, nil, nil) fn := nod(ODCLFUNC, nil, nil)
...@@ -497,7 +497,7 @@ func geneq(sym *types.Sym, t *types.Type) { ...@@ -497,7 +497,7 @@ func geneq(sym *types.Sym, t *types.Type) {
fn = typecheck(fn, Etop) fn = typecheck(fn, Etop)
typecheckslice(fn.Nbody.Slice(), Etop) typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil Curfn = nil
popdcl() types.Popdcl()
if debug_dclstack != 0 { if debug_dclstack != 0 {
testdclstack() testdclstack()
} }
......
...@@ -1091,54 +1091,54 @@ func (p *importer) node() *Node { ...@@ -1091,54 +1091,54 @@ func (p *importer) node() *Node {
return nodl(p.pos(), op, p.expr(), nil) return nodl(p.pos(), op, p.expr(), nil)
case OIF: case OIF:
markdcl() types.Markdcl(lineno)
n := nodl(p.pos(), OIF, nil, nil) n := nodl(p.pos(), OIF, nil, nil)
n.Ninit.Set(p.stmtList()) n.Ninit.Set(p.stmtList())
n.Left = p.expr() n.Left = p.expr()
n.Nbody.Set(p.stmtList()) n.Nbody.Set(p.stmtList())
n.Rlist.Set(p.stmtList()) n.Rlist.Set(p.stmtList())
popdcl() types.Popdcl()
return n return n
case OFOR: case OFOR:
markdcl() types.Markdcl(lineno)
n := nodl(p.pos(), OFOR, nil, nil) n := nodl(p.pos(), OFOR, nil, nil)
n.Ninit.Set(p.stmtList()) n.Ninit.Set(p.stmtList())
n.Left, n.Right = p.exprsOrNil() n.Left, n.Right = p.exprsOrNil()
n.Nbody.Set(p.stmtList()) n.Nbody.Set(p.stmtList())
popdcl() types.Popdcl()
return n return n
case ORANGE: case ORANGE:
markdcl() types.Markdcl(lineno)
n := nodl(p.pos(), ORANGE, nil, nil) n := nodl(p.pos(), ORANGE, nil, nil)
n.List.Set(p.stmtList()) n.List.Set(p.stmtList())
n.Right = p.expr() n.Right = p.expr()
n.Nbody.Set(p.stmtList()) n.Nbody.Set(p.stmtList())
popdcl() types.Popdcl()
return n return n
case OSELECT, OSWITCH: case OSELECT, OSWITCH:
markdcl() types.Markdcl(lineno)
n := nodl(p.pos(), op, nil, nil) n := nodl(p.pos(), op, nil, nil)
n.Ninit.Set(p.stmtList()) n.Ninit.Set(p.stmtList())
n.Left, _ = p.exprsOrNil() n.Left, _ = p.exprsOrNil()
n.List.Set(p.stmtList()) n.List.Set(p.stmtList())
popdcl() types.Popdcl()
return n return n
// case OCASE, OXCASE: // case OCASE, OXCASE:
// unreachable - mapped to OXCASE case below by exporter // unreachable - mapped to OXCASE case below by exporter
case OXCASE: case OXCASE:
markdcl() types.Markdcl(lineno)
n := nodl(p.pos(), OXCASE, nil, nil) n := nodl(p.pos(), OXCASE, nil, nil)
n.Xoffset = int64(block) n.Xoffset = int64(types.Block)
n.List.Set(p.exprList()) n.List.Set(p.exprList())
// TODO(gri) eventually we must declare variables for type switch // TODO(gri) eventually we must declare variables for type switch
// statements (type switch statements are not yet exported) // statements (type switch statements are not yet exported)
n.Nbody.Set(p.stmtList()) n.Nbody.Set(p.stmtList())
popdcl() types.Popdcl()
return n return n
// case OFALL: // case OFALL:
...@@ -1146,7 +1146,7 @@ func (p *importer) node() *Node { ...@@ -1146,7 +1146,7 @@ func (p *importer) node() *Node {
case OXFALL: case OXFALL:
n := nodl(p.pos(), OXFALL, nil, nil) n := nodl(p.pos(), OXFALL, nil, nil)
n.Xoffset = int64(block) n.Xoffset = int64(types.Block)
return n return n
case OBREAK, OCONTINUE: case OBREAK, OCONTINUE:
...@@ -1162,7 +1162,7 @@ func (p *importer) node() *Node { ...@@ -1162,7 +1162,7 @@ func (p *importer) node() *Node {
case OGOTO, OLABEL: case OGOTO, OLABEL:
n := nodl(p.pos(), op, newname(p.expr().Sym), nil) n := nodl(p.pos(), op, newname(p.expr().Sym), nil)
n.Sym = dclstack // context, for goto restrictions n.Sym = types.Dclstack // context, for goto restrictions
return n return n
case OEND: case OEND:
......
...@@ -15,99 +15,12 @@ import ( ...@@ -15,99 +15,12 @@ import (
var externdcl []*Node var externdcl []*Node
var blockgen int32 // max block number
var block int32 // current block number
// dclstack maintains a stack of shadowed symbol declarations so that
// popdcl can restore their declarations when a block scope ends.
// The stack is maintained as a linked list, using Sym's Link field.
//
// In practice, the "stack" actually ends up forming a tree: goto and label
// statements record the current state of dclstack so that checkgoto can
// validate that a goto statement does not jump over any declarations or
// into a new block scope.
//
// Finally, the Syms in this list are not "real" Syms as they don't actually
// represent object names. Sym is just a convenient type for saving shadowed
// Sym definitions, and only a subset of its fields are actually used.
var dclstack *types.Sym
func dcopy(a, b *types.Sym) {
a.Pkg = b.Pkg
a.Name = b.Name
a.Def = b.Def
a.Block = b.Block
a.Lastlineno = b.Lastlineno
}
func push() *types.Sym {
d := new(types.Sym)
d.Lastlineno = lineno
d.Link = dclstack
dclstack = d
return d
}
// pushdcl pushes the current declaration for symbol s (if any) so that
// it can be shadowed by a new declaration within a nested block scope.
func pushdcl(s *types.Sym) *types.Sym {
d := push()
dcopy(d, s)
return d
}
// popdcl pops the innermost block scope and restores all symbol declarations
// to their previous state.
func popdcl() {
d := dclstack
for ; d != nil && d.Name != ""; d = d.Link {
s := d.Pkg.Lookup(d.Name)
lno := s.Lastlineno
dcopy(s, d)
d.Lastlineno = lno
}
if d == nil {
Fatalf("popdcl: no mark")
}
dclstack = d.Link // pop mark
block = d.Block
}
// markdcl records the start of a new block scope for declarations.
func markdcl() {
d := push()
d.Name = "" // used as a mark in fifo
d.Block = block
blockgen++
block = blockgen
}
// keep around for debugging
func dumpdclstack() {
i := 0
for d := dclstack; d != nil; d = d.Link {
fmt.Printf("%6d %p", i, d)
if d.Name != "" {
fmt.Printf(" '%s' %v\n", d.Name, d.Pkg.Lookup(d.Name))
} else {
fmt.Printf(" ---\n")
}
i++
}
}
func testdclstack() { func testdclstack() {
for d := dclstack; d != nil; d = d.Link { if !types.IsDclstackValid() {
if d.Name == "" {
if nerrors != 0 { if nerrors != 0 {
errorexit() errorexit()
} }
Fatalf("mark left on the stack") Fatalf("mark left on the dclstack")
}
} }
} }
...@@ -191,7 +104,7 @@ func declare(n *Node, ctxt Class) { ...@@ -191,7 +104,7 @@ func declare(n *Node, ctxt Class) {
vargen++ vargen++
gen = vargen gen = vargen
} }
pushdcl(s) types.Pushdcl(s, lineno)
n.Name.Curfn = Curfn n.Name.Curfn = Curfn
} }
...@@ -199,7 +112,7 @@ func declare(n *Node, ctxt Class) { ...@@ -199,7 +112,7 @@ func declare(n *Node, ctxt Class) {
n.Xoffset = 0 n.Xoffset = 0
} }
if s.Block == block { if s.Block == types.Block {
// functype will print errors about duplicate function arguments. // functype will print errors about duplicate function arguments.
// Don't repeat the error here. // Don't repeat the error here.
if ctxt != PPARAM && ctxt != PPARAMOUT { if ctxt != PPARAM && ctxt != PPARAMOUT {
...@@ -207,7 +120,7 @@ func declare(n *Node, ctxt Class) { ...@@ -207,7 +120,7 @@ func declare(n *Node, ctxt Class) {
} }
} }
s.Block = block s.Block = types.Block
s.Lastlineno = lineno s.Lastlineno = lineno
s.Def = asTypesNode(n) s.Def = asTypesNode(n)
n.Name.Vargen = int32(gen) n.Name.Vargen = int32(gen)
...@@ -418,7 +331,7 @@ func colasdefn(left []*Node, defn *Node) { ...@@ -418,7 +331,7 @@ func colasdefn(left []*Node, defn *Node) {
} }
n.Sym.SetUniq(false) n.Sym.SetUniq(false)
if n.Sym.Block == block { if n.Sym.Block == types.Block {
continue continue
} }
...@@ -597,7 +510,7 @@ var funcdepth int32 // len(funcstack) during parsing, but then forced to be th ...@@ -597,7 +510,7 @@ var funcdepth int32 // len(funcstack) during parsing, but then forced to be th
// start the function. // start the function.
// called before funcargs; undone at end of funcbody. // called before funcargs; undone at end of funcbody.
func funcstart(n *Node) { func funcstart(n *Node) {
markdcl() types.Markdcl(lineno)
funcstack = append(funcstack, Curfn) funcstack = append(funcstack, Curfn)
funcdepth++ funcdepth++
Curfn = n Curfn = n
...@@ -611,7 +524,7 @@ func funcbody(n *Node) { ...@@ -611,7 +524,7 @@ func funcbody(n *Node) {
if dclcontext != PAUTO { if dclcontext != PAUTO {
Fatalf("funcbody: unexpected dclcontext %d", dclcontext) Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
} }
popdcl() types.Popdcl()
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1] funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
funcdepth-- funcdepth--
if funcdepth == 0 { if funcdepth == 0 {
......
...@@ -381,7 +381,6 @@ func Main(archInit func(*Arch)) { ...@@ -381,7 +381,6 @@ func Main(archInit func(*Arch)) {
initUniverse() initUniverse()
blockgen = 1
dclcontext = PEXTERN dclcontext = PEXTERN
nerrors = 0 nerrors = 0
...@@ -756,7 +755,7 @@ func findpkg(name string) (file string, ok bool) { ...@@ -756,7 +755,7 @@ func findpkg(name string) (file string, ok bool) {
// so that the compiler can generate calls to them, // so that the compiler can generate calls to them,
// but does not make them visible to user code. // but does not make them visible to user code.
func loadsys() { func loadsys() {
block = 1 types.Block = 1
inimport = true inimport = true
typecheckok = true typecheckok = true
......
...@@ -85,7 +85,7 @@ type linkname struct { ...@@ -85,7 +85,7 @@ type linkname struct {
} }
func (p *noder) node() { func (p *noder) node() {
block = 1 types.Block = 1
imported_unsafe = false imported_unsafe = false
p.lineno(p.file.PkgName) p.lineno(p.file.PkgName)
...@@ -726,10 +726,10 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node { ...@@ -726,10 +726,10 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
n.Left = p.newname(stmt.Label) n.Left = p.newname(stmt.Label)
} }
if op == OGOTO { if op == OGOTO {
n.Sym = dclstack // context, for goto restriction n.Sym = types.Dclstack // context, for goto restriction
} }
if op == OXFALL { if op == OXFALL {
n.Xoffset = int64(block) n.Xoffset = int64(types.Block)
} }
return n return n
case *syntax.CallStmt: case *syntax.CallStmt:
...@@ -777,14 +777,14 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node { ...@@ -777,14 +777,14 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
} }
func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node { func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {
markdcl() types.Markdcl(lineno)
nodes := p.stmts(stmt.List) nodes := p.stmts(stmt.List)
popdcl() types.Popdcl()
return nodes return nodes
} }
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
markdcl() types.Markdcl(lineno)
n := p.nod(stmt, OIF, nil, nil) n := p.nod(stmt, OIF, nil, nil)
if stmt.Init != nil { if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init)) n.Ninit.Set1(p.stmt(stmt.Init))
...@@ -801,12 +801,12 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { ...@@ -801,12 +801,12 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
n.Rlist.Set1(e) n.Rlist.Set1(e)
} }
} }
popdcl() types.Popdcl()
return n return n
} }
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
markdcl() types.Markdcl(lineno)
var n *Node var n *Node
if r, ok := stmt.Init.(*syntax.RangeClause); ok { if r, ok := stmt.Init.(*syntax.RangeClause); ok {
if stmt.Cond != nil || stmt.Post != nil { if stmt.Cond != nil || stmt.Post != nil {
...@@ -835,12 +835,12 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { ...@@ -835,12 +835,12 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
} }
} }
n.Nbody.Set(p.blockStmt(stmt.Body)) n.Nbody.Set(p.blockStmt(stmt.Body))
popdcl() types.Popdcl()
return n return n
} }
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
markdcl() types.Markdcl(lineno)
n := p.nod(stmt, OSWITCH, nil, nil) n := p.nod(stmt, OSWITCH, nil, nil)
if stmt.Init != nil { if stmt.Init != nil {
n.Ninit.Set1(p.stmt(stmt.Init)) n.Ninit.Set1(p.stmt(stmt.Init))
...@@ -856,7 +856,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { ...@@ -856,7 +856,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
n.List.Set(p.caseClauses(stmt.Body, tswitch)) n.List.Set(p.caseClauses(stmt.Body, tswitch))
popdcl() types.Popdcl()
return n return n
} }
...@@ -864,7 +864,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node ...@@ -864,7 +864,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
var nodes []*Node var nodes []*Node
for _, clause := range clauses { for _, clause := range clauses {
p.lineno(clause) p.lineno(clause)
markdcl() types.Markdcl(lineno)
n := p.nod(clause, OXCASE, nil, nil) n := p.nod(clause, OXCASE, nil, nil)
if clause.Cases != nil { if clause.Cases != nil {
n.List.Set(p.exprList(clause.Cases)) n.List.Set(p.exprList(clause.Cases))
...@@ -876,9 +876,9 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node ...@@ -876,9 +876,9 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
// keep track of the instances for reporting unused // keep track of the instances for reporting unused
nn.Name.Defn = tswitch nn.Name.Defn = tswitch
} }
n.Xoffset = int64(block) n.Xoffset = int64(types.Block)
n.Nbody.Set(p.stmts(clause.Body)) n.Nbody.Set(p.stmts(clause.Body))
popdcl() types.Popdcl()
nodes = append(nodes, n) nodes = append(nodes, n)
} }
return nodes return nodes
...@@ -894,14 +894,14 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node { ...@@ -894,14 +894,14 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
var nodes []*Node var nodes []*Node
for _, clause := range clauses { for _, clause := range clauses {
p.lineno(clause) p.lineno(clause)
markdcl() types.Markdcl(lineno)
n := p.nod(clause, OXCASE, nil, nil) n := p.nod(clause, OXCASE, nil, nil)
if clause.Comm != nil { if clause.Comm != nil {
n.List.Set1(p.stmt(clause.Comm)) n.List.Set1(p.stmt(clause.Comm))
} }
n.Xoffset = int64(block) n.Xoffset = int64(types.Block)
n.Nbody.Set(p.stmts(clause.Body)) n.Nbody.Set(p.stmts(clause.Body))
popdcl() types.Popdcl()
nodes = append(nodes, n) nodes = append(nodes, n)
} }
return nodes return nodes
...@@ -909,7 +909,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node { ...@@ -909,7 +909,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node { func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil) lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
lhs.Sym = dclstack lhs.Sym = types.Dclstack
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.
......
...@@ -1687,7 +1687,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface ...@@ -1687,7 +1687,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface
lineno = autogeneratedPos lineno = autogeneratedPos
dclcontext = PEXTERN dclcontext = PEXTERN
markdcl() types.Markdcl(lineno)
this := namedfield(".this", rcvr) this := namedfield(".this", rcvr)
this.Left.Name.Param.Ntype = this.Right this.Left.Name.Param.Ntype = this.Right
...@@ -1784,7 +1784,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface ...@@ -1784,7 +1784,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface
funcbody(fn) funcbody(fn)
Curfn = fn Curfn = fn
popdcl() types.Popdcl()
if debug_dclstack != 0 { if debug_dclstack != 0 {
testdclstack() testdclstack()
} }
......
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package types
import (
"cmd/internal/src"
"fmt"
)
// Declaration stack & operations
var blockgen int32 = 1 // max block number
var Block int32 // current block number
// Dclstack maintains a stack of shadowed symbol declarations so that
// popdcl can restore their declarations when a block scope ends.
// The stack is maintained as a linked list, using Sym's Link field.
//
// In practice, the "stack" actually ends up forming a tree: goto and label
// statements record the current state of Dclstack so that checkgoto can
// validate that a goto statement does not jump over any declarations or
// into a new block scope.
//
// Finally, the Syms in this list are not "real" Syms as they don't actually
// represent object names. Sym is just a convenient type for saving shadowed
// Sym definitions, and only a subset of its fields are actually used.
var Dclstack *Sym
func dcopy(a, b *Sym) {
a.Pkg = b.Pkg
a.Name = b.Name
a.Def = b.Def
a.Block = b.Block
a.Lastlineno = b.Lastlineno
}
func push(pos src.XPos) *Sym {
d := new(Sym)
d.Lastlineno = pos
d.Link = Dclstack
Dclstack = d
return d
}
// Pushdcl pushes the current declaration for symbol s (if any) so that
// it can be shadowed by a new declaration within a nested block scope.
func Pushdcl(s *Sym, pos src.XPos) *Sym {
d := push(pos)
dcopy(d, s)
return d
}
// Popdcl pops the innermost block scope and restores all symbol declarations
// to their previous state.
func Popdcl() {
d := Dclstack
for ; d != nil && d.Name != ""; d = d.Link {
s := d.Pkg.Lookup(d.Name)
lno := s.Lastlineno
dcopy(s, d)
d.Lastlineno = lno
}
if d == nil {
Fatalf("popdcl: no mark")
}
Dclstack = d.Link // pop mark
Block = d.Block
}
// Markdcl records the start of a new block scope for declarations.
func Markdcl(lineno src.XPos) {
d := push(lineno)
d.Name = "" // used as a mark in fifo
d.Block = Block
blockgen++
Block = blockgen
}
// keep around for debugging
func DumpDclstack() {
i := 0
for d := Dclstack; d != nil; d = d.Link {
fmt.Printf("%6d %p", i, d)
if d.Name != "" {
fmt.Printf(" '%s' %v\n", d.Name, d.Pkg.Lookup(d.Name))
} else {
fmt.Printf(" ---\n")
}
i++
}
}
func IsDclstackValid() bool {
for d := Dclstack; d != nil; d = d.Link {
if d.Name == "" {
return false
}
}
return true
}
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