Commit f498929c authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: remove global var importpkg in favor of simple bool

Pass around the imported package explicitly instead of relying
on a global variable.

Unfortunately we still need a global variable to communicate to
the typechecker that we're in an import, but the semantic load
is significantly reduced as it's just a bool, set/reset in a
couple of places only.

Change-Id: I4ebeae4064eb76ca0c4e2a15e4ca53813f005c29
Reviewed-on: https://go-review.googlesource.com/38595
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 39e22f04
...@@ -50,8 +50,11 @@ type importer struct { ...@@ -50,8 +50,11 @@ type importer struct {
read int // bytes read read int // bytes read
} }
// Import populates imp from the serialized package data. // Import populates imp from the serialized package data read from in.
func Import(in *bufio.Reader, imp *Pkg) { func Import(imp *Pkg, in *bufio.Reader) {
inimport = true
defer func() { inimport = false }()
p := importer{ p := importer{
in: in, in: in,
imp: imp, imp: imp,
...@@ -319,13 +322,13 @@ func (p *importer) obj(tag int) { ...@@ -319,13 +322,13 @@ func (p *importer) obj(tag int) {
sym := p.qualifiedName() sym := p.qualifiedName()
typ := p.typ() typ := p.typ()
val := p.value(typ) val := p.value(typ)
importconst(sym, idealType(typ), nodlit(val)) importconst(p.imp, sym, idealType(typ), nodlit(val))
case aliasTag: case aliasTag:
p.pos() p.pos()
sym := p.qualifiedName() sym := p.qualifiedName()
typ := p.typ() typ := p.typ()
importalias(sym, typ) importalias(p.imp, sym, typ)
case typeTag: case typeTag:
p.typ() p.typ()
...@@ -334,7 +337,7 @@ func (p *importer) obj(tag int) { ...@@ -334,7 +337,7 @@ func (p *importer) obj(tag int) {
p.pos() p.pos()
sym := p.qualifiedName() sym := p.qualifiedName()
typ := p.typ() typ := p.typ()
importvar(sym, typ) importvar(p.imp, sym, typ)
case funcTag: case funcTag:
p.pos() p.pos()
...@@ -343,7 +346,7 @@ func (p *importer) obj(tag int) { ...@@ -343,7 +346,7 @@ func (p *importer) obj(tag int) {
result := p.paramList() result := p.paramList()
sig := functypefield(nil, params, result) sig := functypefield(nil, params, result)
importsym(sym, ONAME) importsym(p.imp, sym, ONAME)
if sym.Def != nil && sym.Def.Op == ONAME { if sym.Def != nil && sym.Def.Op == ONAME {
// function was imported before (via another import) // function was imported before (via another import)
if !eqtype(sig, sym.Def.Type) { if !eqtype(sig, sym.Def.Type) {
...@@ -441,7 +444,7 @@ func (p *importer) typ() *Type { ...@@ -441,7 +444,7 @@ func (p *importer) typ() *Type {
p.pos() p.pos()
tsym := p.qualifiedName() tsym := p.qualifiedName()
t = pkgtype(tsym) t = pkgtype(p.imp, tsym)
p.typList = append(p.typList, t) p.typList = append(p.typList, t)
// read underlying type // read underlying type
......
...@@ -165,7 +165,7 @@ func declare(n *Node, ctxt Class) { ...@@ -165,7 +165,7 @@ func declare(n *Node, ctxt Class) {
s := n.Sym s := n.Sym
// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
if importpkg == nil && !typecheckok && s.Pkg != localpkg { if !inimport && !typecheckok && s.Pkg != localpkg {
yyerror("cannot declare name %v", s) yyerror("cannot declare name %v", s)
} }
......
...@@ -176,9 +176,7 @@ func dumpexport() { ...@@ -176,9 +176,7 @@ func dumpexport() {
savedPkgs := pkgs savedPkgs := pkgs
pkgMap = make(map[string]*Pkg) pkgMap = make(map[string]*Pkg)
pkgs = nil pkgs = nil
importpkg = mkpkg("") Import(mkpkg(""), bufio.NewReader(&copy)) // must not die
Import(bufio.NewReader(&copy), importpkg) // must not die
importpkg = nil
pkgs = savedPkgs pkgs = savedPkgs
pkgMap = savedPkgMap pkgMap = savedPkgMap
} else { } else {
...@@ -192,9 +190,10 @@ func dumpexport() { ...@@ -192,9 +190,10 @@ func dumpexport() {
} }
// importsym declares symbol s as an imported object representable by op. // importsym declares symbol s as an imported object representable by op.
func importsym(s *Sym, op Op) { // pkg is the package being imported
func importsym(pkg *Pkg, s *Sym, op Op) {
if s.Def != nil && s.Def.Op != op { if s.Def != nil && s.Def.Op != op {
pkgstr := fmt.Sprintf("during import %q", importpkg.Path) pkgstr := fmt.Sprintf("during import %q", pkg.Path)
redeclare(s, pkgstr) redeclare(s, pkgstr)
} }
...@@ -210,8 +209,9 @@ func importsym(s *Sym, op Op) { ...@@ -210,8 +209,9 @@ func importsym(s *Sym, op Op) {
// pkgtype returns the named type declared by symbol s. // pkgtype returns the named type declared by symbol s.
// If no such type has been declared yet, a forward declaration is returned. // If no such type has been declared yet, a forward declaration is returned.
func pkgtype(s *Sym) *Type { // pkg is the package being imported
importsym(s, OTYPE) func pkgtype(pkg *Pkg, s *Sym) *Type {
importsym(pkg, s, OTYPE)
if s.Def == nil || s.Def.Op != OTYPE { if s.Def == nil || s.Def.Op != OTYPE {
t := typ(TFORW) t := typ(TFORW)
t.Sym = s t.Sym = s
...@@ -226,8 +226,9 @@ func pkgtype(s *Sym) *Type { ...@@ -226,8 +226,9 @@ func pkgtype(s *Sym) *Type {
} }
// importconst declares symbol s as an imported constant with type t and value n. // importconst declares symbol s as an imported constant with type t and value n.
func importconst(s *Sym, t *Type, n *Node) { // pkg is the package being imported
importsym(s, OLITERAL) func importconst(pkg *Pkg, s *Sym, t *Type, n *Node) {
importsym(pkg, s, OLITERAL)
n = convlit(n, t) n = convlit(n, t)
if s.Def != nil { // TODO: check if already the same. if s.Def != nil { // TODO: check if already the same.
...@@ -254,17 +255,18 @@ func importconst(s *Sym, t *Type, n *Node) { ...@@ -254,17 +255,18 @@ func importconst(s *Sym, t *Type, n *Node) {
} }
// importvar declares symbol s as an imported variable with type t. // importvar declares symbol s as an imported variable with type t.
func importvar(s *Sym, t *Type) { // pkg is the package being imported
importsym(s, ONAME) func importvar(pkg *Pkg, s *Sym, t *Type) {
importsym(pkg, s, ONAME)
if s.Def != nil && s.Def.Op == ONAME { if s.Def != nil && s.Def.Op == ONAME {
if eqtype(t, s.Def.Type) { if eqtype(t, s.Def.Type) {
return return
} }
yyerror("inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path) yyerror("inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, pkg.Path)
} }
n := newname(s) n := newname(s)
s.Importdef = importpkg s.Importdef = pkg
n.Type = t n.Type = t
declare(n, PEXTERN) declare(n, PEXTERN)
...@@ -274,18 +276,19 @@ func importvar(s *Sym, t *Type) { ...@@ -274,18 +276,19 @@ func importvar(s *Sym, t *Type) {
} }
// importalias declares symbol s as an imported type alias with type t. // importalias declares symbol s as an imported type alias with type t.
func importalias(s *Sym, t *Type) { // pkg is the package being imported
importsym(s, OTYPE) func importalias(pkg *Pkg, s *Sym, t *Type) {
importsym(pkg, s, OTYPE)
if s.Def != nil && s.Def.Op == OTYPE { if s.Def != nil && s.Def.Op == OTYPE {
if eqtype(t, s.Def.Type) { if eqtype(t, s.Def.Type) {
return return
} }
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path) yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, pkg.Path)
} }
n := newname(s) n := newname(s)
n.Op = OTYPE n.Op = OTYPE
s.Importdef = importpkg s.Importdef = pkg
n.Type = t n.Type = t
declare(n, PEXTERN) declare(n, PEXTERN)
......
...@@ -168,7 +168,7 @@ var Debug_typeassert int ...@@ -168,7 +168,7 @@ var Debug_typeassert int
var localpkg *Pkg // package being compiled var localpkg *Pkg // package being compiled
var importpkg *Pkg // package being imported var inimport bool // set during import
var itabpkg *Pkg // fake pkg for itab entries var itabpkg *Pkg // fake pkg for itab entries
......
...@@ -719,22 +719,22 @@ func findpkg(name string) (file string, ok bool) { ...@@ -719,22 +719,22 @@ func findpkg(name string) (file string, ok bool) {
func loadsys() { func loadsys() {
block = 1 block = 1
importpkg = Runtimepkg inimport = true
typecheckok = true typecheckok = true
defercheckwidth() defercheckwidth()
typs := runtimeTypes() typs := runtimeTypes()
for _, d := range runtimeDecls { for _, d := range runtimeDecls {
sym := Pkglookup(d.name, importpkg) sym := Pkglookup(d.name, Runtimepkg)
typ := typs[d.typ] typ := typs[d.typ]
switch d.tag { switch d.tag {
case funcTag: case funcTag:
importsym(sym, ONAME) importsym(Runtimepkg, sym, ONAME)
n := newfuncname(sym) n := newfuncname(sym)
n.Type = typ n.Type = typ
declare(n, PFUNC) declare(n, PFUNC)
case varTag: case varTag:
importvar(sym, typ) importvar(Runtimepkg, sym, typ)
default: default:
Fatalf("unhandled declaration tag %v", d.tag) Fatalf("unhandled declaration tag %v", d.tag)
} }
...@@ -742,27 +742,23 @@ func loadsys() { ...@@ -742,27 +742,23 @@ func loadsys() {
typecheckok = false typecheckok = false
resumecheckwidth() resumecheckwidth()
importpkg = nil inimport = false
} }
func importfile(f *Val, indent []byte) { func importfile(f *Val, indent []byte) *Pkg {
if importpkg != nil {
Fatalf("importpkg not nil")
}
path_, ok := f.U.(string) path_, ok := f.U.(string)
if !ok { if !ok {
yyerror("import statement not a string") yyerror("import statement not a string")
return return nil
} }
if len(path_) == 0 { if len(path_) == 0 {
yyerror("import path is empty") yyerror("import path is empty")
return return nil
} }
if isbadimport(path_) { if isbadimport(path_) {
return return nil
} }
// The package name main is no longer reserved, // The package name main is no longer reserved,
...@@ -789,15 +785,14 @@ func importfile(f *Val, indent []byte) { ...@@ -789,15 +785,14 @@ func importfile(f *Val, indent []byte) {
errorexit() errorexit()
} }
importpkg = unsafepkg
imported_unsafe = true imported_unsafe = true
return return unsafepkg
} }
if islocalname(path_) { if islocalname(path_) {
if path_[0] == '/' { if path_[0] == '/' {
yyerror("import path cannot be absolute path") yyerror("import path cannot be absolute path")
return return nil
} }
prefix := Ctxt.Pathname prefix := Ctxt.Pathname
...@@ -807,7 +802,7 @@ func importfile(f *Val, indent []byte) { ...@@ -807,7 +802,7 @@ func importfile(f *Val, indent []byte) {
path_ = path.Join(prefix, path_) path_ = path.Join(prefix, path_)
if isbadimport(path_) { if isbadimport(path_) {
return return nil
} }
} }
...@@ -817,10 +812,9 @@ func importfile(f *Val, indent []byte) { ...@@ -817,10 +812,9 @@ func importfile(f *Val, indent []byte) {
errorexit() errorexit()
} }
importpkg = mkpkg(path_) importpkg := mkpkg(path_)
if importpkg.Imported { if importpkg.Imported {
return return importpkg
} }
importpkg.Imported = true importpkg.Imported = true
...@@ -913,18 +907,21 @@ func importfile(f *Val, indent []byte) { ...@@ -913,18 +907,21 @@ func importfile(f *Val, indent []byte) {
switch c { switch c {
case '\n': case '\n':
yyerror("cannot import %s: old export format no longer supported (recompile library)", path_) yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
return nil
case 'B': case 'B':
if Debug_export != 0 { if Debug_export != 0 {
fmt.Printf("importing %s (%s)\n", path_, file) fmt.Printf("importing %s (%s)\n", path_, file)
} }
imp.ReadByte() // skip \n after $$B imp.ReadByte() // skip \n after $$B
Import(imp, importpkg) Import(importpkg, imp)
default: default:
yyerror("no import in %q", path_) yyerror("no import in %q", path_)
errorexit() errorexit()
} }
return importpkg
} }
func pkgnotused(lineno src.XPos, path string, name string) { func pkgnotused(lineno src.XPos, path string, name string) {
......
...@@ -136,9 +136,7 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) { ...@@ -136,9 +136,7 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
func (p *noder) importDecl(imp *syntax.ImportDecl) { func (p *noder) importDecl(imp *syntax.ImportDecl) {
val := p.basicLit(imp.Path) val := p.basicLit(imp.Path)
importfile(&val, nil) ipkg := importfile(&val, nil)
ipkg := importpkg
importpkg = nil
if ipkg == nil { if ipkg == nil {
if nerrors == 0 { if nerrors == 0 {
......
...@@ -718,7 +718,7 @@ func assignop(src *Type, dst *Type, why *string) Op { ...@@ -718,7 +718,7 @@ func assignop(src *Type, dst *Type, why *string) Op {
// TODO(rsc,lvd): This behaves poorly in the presence of inlining. // TODO(rsc,lvd): This behaves poorly in the presence of inlining.
// https://golang.org/issue/2795 // https://golang.org/issue/2795
if safemode && importpkg == nil && src != nil && src.Etype == TUNSAFEPTR { if safemode && !inimport && src != nil && src.Etype == TUNSAFEPTR {
yyerror("cannot use unsafe.Pointer") yyerror("cannot use unsafe.Pointer")
errorexit() errorexit()
} }
......
...@@ -2143,7 +2143,7 @@ OpSwitch: ...@@ -2143,7 +2143,7 @@ OpSwitch:
} }
} }
if safemode && importpkg == nil && compiling_wrappers == 0 && t != nil && t.Etype == TUNSAFEPTR { if safemode && !inimport && compiling_wrappers == 0 && t != nil && t.Etype == TUNSAFEPTR {
yyerror("cannot use unsafe.Pointer") yyerror("cannot use unsafe.Pointer")
} }
...@@ -3472,7 +3472,7 @@ func typecheckfunc(n *Node) { ...@@ -3472,7 +3472,7 @@ func typecheckfunc(n *Node) {
addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0) addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
} }
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil { if Ctxt.Flag_dynlink && !inimport && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym) makefuncsym(n.Func.Nname.Sym)
} }
} }
......
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