mirror of
https://github.com/golang/go
synced 2024-09-30 01:24:33 -06:00
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: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
3cf1ce40bd
commit
fd44d872de
@ -191,7 +191,7 @@ func genhash(sym *types.Sym, t *types.Type) {
|
||||
|
||||
lineno = autogeneratedPos // less confusing than end of input
|
||||
dclcontext = PEXTERN
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
|
||||
// func sym(p *T, h uintptr) uintptr
|
||||
fn := nod(ODCLFUNC, nil, nil)
|
||||
@ -305,7 +305,7 @@ func genhash(sym *types.Sym, t *types.Type) {
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||
Curfn = nil
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
if debug_dclstack != 0 {
|
||||
testdclstack()
|
||||
}
|
||||
@ -369,7 +369,7 @@ func geneq(sym *types.Sym, t *types.Type) {
|
||||
|
||||
lineno = autogeneratedPos // less confusing than end of input
|
||||
dclcontext = PEXTERN
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
|
||||
// func sym(p, q *T) bool
|
||||
fn := nod(ODCLFUNC, nil, nil)
|
||||
@ -497,7 +497,7 @@ func geneq(sym *types.Sym, t *types.Type) {
|
||||
fn = typecheck(fn, Etop)
|
||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||
Curfn = nil
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
if debug_dclstack != 0 {
|
||||
testdclstack()
|
||||
}
|
||||
|
@ -1091,54 +1091,54 @@ func (p *importer) node() *Node {
|
||||
return nodl(p.pos(), op, p.expr(), nil)
|
||||
|
||||
case OIF:
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := nodl(p.pos(), OIF, nil, nil)
|
||||
n.Ninit.Set(p.stmtList())
|
||||
n.Left = p.expr()
|
||||
n.Nbody.Set(p.stmtList())
|
||||
n.Rlist.Set(p.stmtList())
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
|
||||
case OFOR:
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := nodl(p.pos(), OFOR, nil, nil)
|
||||
n.Ninit.Set(p.stmtList())
|
||||
n.Left, n.Right = p.exprsOrNil()
|
||||
n.Nbody.Set(p.stmtList())
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
|
||||
case ORANGE:
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := nodl(p.pos(), ORANGE, nil, nil)
|
||||
n.List.Set(p.stmtList())
|
||||
n.Right = p.expr()
|
||||
n.Nbody.Set(p.stmtList())
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
|
||||
case OSELECT, OSWITCH:
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := nodl(p.pos(), op, nil, nil)
|
||||
n.Ninit.Set(p.stmtList())
|
||||
n.Left, _ = p.exprsOrNil()
|
||||
n.List.Set(p.stmtList())
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
|
||||
// case OCASE, OXCASE:
|
||||
// unreachable - mapped to OXCASE case below by exporter
|
||||
|
||||
case OXCASE:
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := nodl(p.pos(), OXCASE, nil, nil)
|
||||
n.Xoffset = int64(block)
|
||||
n.Xoffset = int64(types.Block)
|
||||
n.List.Set(p.exprList())
|
||||
// TODO(gri) eventually we must declare variables for type switch
|
||||
// statements (type switch statements are not yet exported)
|
||||
n.Nbody.Set(p.stmtList())
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
|
||||
// case OFALL:
|
||||
@ -1146,7 +1146,7 @@ func (p *importer) node() *Node {
|
||||
|
||||
case OXFALL:
|
||||
n := nodl(p.pos(), OXFALL, nil, nil)
|
||||
n.Xoffset = int64(block)
|
||||
n.Xoffset = int64(types.Block)
|
||||
return n
|
||||
|
||||
case OBREAK, OCONTINUE:
|
||||
@ -1162,7 +1162,7 @@ func (p *importer) node() *Node {
|
||||
|
||||
case OGOTO, OLABEL:
|
||||
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
|
||||
|
||||
case OEND:
|
||||
|
@ -15,99 +15,12 @@ import (
|
||||
|
||||
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() {
|
||||
for d := dclstack; d != nil; d = d.Link {
|
||||
if d.Name == "" {
|
||||
if nerrors != 0 {
|
||||
errorexit()
|
||||
}
|
||||
Fatalf("mark left on the stack")
|
||||
if !types.IsDclstackValid() {
|
||||
if nerrors != 0 {
|
||||
errorexit()
|
||||
}
|
||||
Fatalf("mark left on the dclstack")
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +104,7 @@ func declare(n *Node, ctxt Class) {
|
||||
vargen++
|
||||
gen = vargen
|
||||
}
|
||||
pushdcl(s)
|
||||
types.Pushdcl(s, lineno)
|
||||
n.Name.Curfn = Curfn
|
||||
}
|
||||
|
||||
@ -199,7 +112,7 @@ func declare(n *Node, ctxt Class) {
|
||||
n.Xoffset = 0
|
||||
}
|
||||
|
||||
if s.Block == block {
|
||||
if s.Block == types.Block {
|
||||
// functype will print errors about duplicate function arguments.
|
||||
// Don't repeat the error here.
|
||||
if ctxt != PPARAM && ctxt != PPARAMOUT {
|
||||
@ -207,7 +120,7 @@ func declare(n *Node, ctxt Class) {
|
||||
}
|
||||
}
|
||||
|
||||
s.Block = block
|
||||
s.Block = types.Block
|
||||
s.Lastlineno = lineno
|
||||
s.Def = asTypesNode(n)
|
||||
n.Name.Vargen = int32(gen)
|
||||
@ -418,7 +331,7 @@ func colasdefn(left []*Node, defn *Node) {
|
||||
}
|
||||
|
||||
n.Sym.SetUniq(false)
|
||||
if n.Sym.Block == block {
|
||||
if n.Sym.Block == types.Block {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -597,7 +510,7 @@ var funcdepth int32 // len(funcstack) during parsing, but then forced to be th
|
||||
// start the function.
|
||||
// called before funcargs; undone at end of funcbody.
|
||||
func funcstart(n *Node) {
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
funcstack = append(funcstack, Curfn)
|
||||
funcdepth++
|
||||
Curfn = n
|
||||
@ -611,7 +524,7 @@ func funcbody(n *Node) {
|
||||
if dclcontext != PAUTO {
|
||||
Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
|
||||
}
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
|
||||
funcdepth--
|
||||
if funcdepth == 0 {
|
||||
|
@ -381,7 +381,6 @@ func Main(archInit func(*Arch)) {
|
||||
|
||||
initUniverse()
|
||||
|
||||
blockgen = 1
|
||||
dclcontext = PEXTERN
|
||||
nerrors = 0
|
||||
|
||||
@ -756,7 +755,7 @@ func findpkg(name string) (file string, ok bool) {
|
||||
// so that the compiler can generate calls to them,
|
||||
// but does not make them visible to user code.
|
||||
func loadsys() {
|
||||
block = 1
|
||||
types.Block = 1
|
||||
|
||||
inimport = true
|
||||
typecheckok = true
|
||||
|
@ -85,7 +85,7 @@ type linkname struct {
|
||||
}
|
||||
|
||||
func (p *noder) node() {
|
||||
block = 1
|
||||
types.Block = 1
|
||||
imported_unsafe = false
|
||||
|
||||
p.lineno(p.file.PkgName)
|
||||
@ -726,10 +726,10 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
|
||||
n.Left = p.newname(stmt.Label)
|
||||
}
|
||||
if op == OGOTO {
|
||||
n.Sym = dclstack // context, for goto restriction
|
||||
n.Sym = types.Dclstack // context, for goto restriction
|
||||
}
|
||||
if op == OXFALL {
|
||||
n.Xoffset = int64(block)
|
||||
n.Xoffset = int64(types.Block)
|
||||
}
|
||||
return n
|
||||
case *syntax.CallStmt:
|
||||
@ -777,14 +777,14 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
|
||||
}
|
||||
|
||||
func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
nodes := p.stmts(stmt.List)
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := p.nod(stmt, OIF, nil, nil)
|
||||
if stmt.Init != nil {
|
||||
n.Ninit.Set1(p.stmt(stmt.Init))
|
||||
@ -801,12 +801,12 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
|
||||
n.Rlist.Set1(e)
|
||||
}
|
||||
}
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
var n *Node
|
||||
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
|
||||
if stmt.Cond != nil || stmt.Post != nil {
|
||||
@ -835,12 +835,12 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
|
||||
}
|
||||
}
|
||||
n.Nbody.Set(p.blockStmt(stmt.Body))
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
}
|
||||
|
||||
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := p.nod(stmt, OSWITCH, nil, nil)
|
||||
if stmt.Init != nil {
|
||||
n.Ninit.Set1(p.stmt(stmt.Init))
|
||||
@ -856,7 +856,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
|
||||
|
||||
n.List.Set(p.caseClauses(stmt.Body, tswitch))
|
||||
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
return n
|
||||
}
|
||||
|
||||
@ -864,7 +864,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
|
||||
var nodes []*Node
|
||||
for _, clause := range clauses {
|
||||
p.lineno(clause)
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := p.nod(clause, OXCASE, nil, nil)
|
||||
if clause.Cases != nil {
|
||||
n.List.Set(p.exprList(clause.Cases))
|
||||
@ -876,9 +876,9 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
|
||||
// keep track of the instances for reporting unused
|
||||
nn.Name.Defn = tswitch
|
||||
}
|
||||
n.Xoffset = int64(block)
|
||||
n.Xoffset = int64(types.Block)
|
||||
n.Nbody.Set(p.stmts(clause.Body))
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
nodes = append(nodes, n)
|
||||
}
|
||||
return nodes
|
||||
@ -894,14 +894,14 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
|
||||
var nodes []*Node
|
||||
for _, clause := range clauses {
|
||||
p.lineno(clause)
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
n := p.nod(clause, OXCASE, nil, nil)
|
||||
if clause.Comm != nil {
|
||||
n.List.Set1(p.stmt(clause.Comm))
|
||||
}
|
||||
n.Xoffset = int64(block)
|
||||
n.Xoffset = int64(types.Block)
|
||||
n.Nbody.Set(p.stmts(clause.Body))
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
nodes = append(nodes, n)
|
||||
}
|
||||
return nodes
|
||||
@ -909,7 +909,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
|
||||
|
||||
func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
|
||||
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
|
||||
lhs.Sym = dclstack
|
||||
lhs.Sym = types.Dclstack
|
||||
|
||||
var ls *Node
|
||||
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
|
||||
lineno = autogeneratedPos
|
||||
|
||||
dclcontext = PEXTERN
|
||||
markdcl()
|
||||
types.Markdcl(lineno)
|
||||
|
||||
this := namedfield(".this", rcvr)
|
||||
this.Left.Name.Param.Ntype = this.Right
|
||||
@ -1784,7 +1784,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface
|
||||
|
||||
funcbody(fn)
|
||||
Curfn = fn
|
||||
popdcl()
|
||||
types.Popdcl()
|
||||
if debug_dclstack != 0 {
|
||||
testdclstack()
|
||||
}
|
||||
|
105
src/cmd/compile/internal/types/scope.go
Normal file
105
src/cmd/compile/internal/types/scope.go
Normal file
@ -0,0 +1,105 @@
|
||||
// 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user