]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: factor out dcl stack ops into package types
authorRobert Griesemer <gri@golang.org>
Fri, 7 Apr 2017 03:57:46 +0000 (20:57 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 7 Apr 2017 20:06:02 +0000 (20:06 +0000)
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>
src/cmd/compile/internal/gc/alg.go
src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/types/scope.go [new file with mode: 0644]

index 8ee158c5f74f16a3af20df4b8e24c21c73f8dd05..fa09cb5b9626fde8b1c19776f462ed2e7979b745 100644 (file)
@@ -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()
        }
index 64f410fa802bcd78c14e0b9b79404c15d5b0361d..ea9c02dea871e07665dc8f29d6b0d095faf30bd9 100644 (file)
@@ -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:
index 0704d6ef5d84f9af61b7c4a95ac5de9e458f0d9d..222881771d6761790997a0156bd76eed086ae934 100644 (file)
@@ -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 {
index 00d44d885baa861c9e70b37a334c794898be822e..22314b7b2c451db56593da152b7fbdf5e09a392f 100644 (file)
@@ -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
index bd769b61261766353bc1be70970fea32f6aa1fb0..1ad19df7df39f73dc088c92c3a209d6e4c5185b4 100644 (file)
@@ -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.
index ddf6f77c07fe788c7afc48552cbf7f69ecfebce1..d9fdd76f233b9fdab474d93cff8af0af07b512b1 100644 (file)
@@ -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()
        }
diff --git a/src/cmd/compile/internal/types/scope.go b/src/cmd/compile/internal/types/scope.go
new file mode 100644 (file)
index 0000000..dfb63e9
--- /dev/null
@@ -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
+}