Permalink
Browse files

cmd/compile/internal/types: simplify dclstack

We used to backup symbol declarations using complete Syms, but this
was unnecessary: very few of Sym's fields were actually needed. Also,
to restore a symbol, we had to re-Lookup the Sym in its Pkg.

By introducing a new dedicated dsym type for this purpose, we can
address both of these deficiencies.

Passes toolstash-check.

Change-Id: I39f3d672b301f84a3a62b9b34b4b2770cb25df79
Reviewed-on: https://go-review.googlesource.com/64811
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
  • Loading branch information...
mdempsky committed Sep 19, 2017
1 parent 7e10a2f commit a53e853964cc9220ebc4b35aeb81a382939fb479
Showing with 38 additions and 28 deletions.
  1. +35 −26 src/cmd/compile/internal/types/scope.go
  2. +3 −2 src/cmd/compile/internal/types/sym.go
@@ -4,65 +4,74 @@
package types
import "cmd/internal/src"
// 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 Syms on this stack 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
// A dsym stores a symbol's shadowed declaration so that it can be
// restored once the block scope ends.
type dsym struct {
sym *Sym // sym == nil indicates stack mark
def *Node
block int32
lastlineno src.XPos // last declaration for diagnostic
}
func push() *Sym {
d := new(Sym)
dclstack = append(dclstack, d)
return d
}
// dclstack maintains a stack of shadowed symbol declarations so that
// Popdcl can restore their declarations when a block scope ends.
var dclstack []dsym
// 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) {
dcopy(push(), s)
dclstack = append(dclstack, dsym{
sym: s,
def: s.Def,
block: s.Block,
lastlineno: s.Lastlineno,
})
}
// Popdcl pops the innermost block scope and restores all symbol declarations
// to their previous state.
func Popdcl() {
for i := len(dclstack); i > 0; i-- {
d := dclstack[i-1]
if d.Name == "" {
d := &dclstack[i-1]
s := d.sym
if s == nil {
// pop stack mark
Block = d.Block
Block = d.block
dclstack = dclstack[:i-1]
return
}
dcopy(d.Pkg.Lookup(d.Name), d)
s.Def = d.def
s.Block = d.block
s.Lastlineno = d.lastlineno
// Clear dead pointer fields.
d.sym = nil
d.def = nil
}
Fatalf("popdcl: no stack mark")
}
// Markdcl records the start of a new block scope for declarations.
func Markdcl() {
push().Block = Block // stack mark (Name == "")
dclstack = append(dclstack, dsym{
sym: nil, // stack mark
block: Block,
})
blockgen++
Block = blockgen
}
func IsDclstackValid() bool {
for _, d := range dclstack {
if d.Name == "" {
if d.sym == nil {
return false
}
}
@@ -21,9 +21,10 @@ type Sym struct {
Importdef *Pkg // where imported definition was found
Linkname string // link name
Pkg *Pkg
Name string // object name
// saved and restored by dcopy
Pkg *Pkg
Name string // object name
Def *Node // definition: ONAME OTYPE OPACK or OLITERAL
Block int32 // blocknumber to catch redeclaration
Lastlineno src.XPos // last declaration for diagnostic

0 comments on commit a53e853

Please sign in to comment.