[dev.regabi] cmd/compile: simplify declaration importing

Rather than creating Names w/ ONONAME earlier and later adding in the
details, this CL changes the import logic to create and add details at
the same time.

Passes buildall w/ toolstash -cmp.

Change-Id: Ifaabade3cef8cd80ddd6644bff79393b934255d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/279313
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Matthew Dempsky 2020-12-18 19:38:13 -08:00
parent 06915ac14d
commit cb4898a77d
3 changed files with 58 additions and 127 deletions

View file

@ -77,126 +77,70 @@ func dumpexport(bout *bio.Writer) {
}
}
func importsym(ipkg *types.Pkg, s *types.Sym, op ir.Op) *ir.Name {
n := ir.AsNode(s.PkgDef())
if n == nil {
// iimport should have created a stub ONONAME
// declaration for all imported symbols. The exception
// is declarations for Runtimepkg, which are populated
// by loadsys instead.
if s.Pkg != Runtimepkg {
base.Fatalf("missing ONONAME for %v\n", s)
func importsym(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class) *ir.Name {
if n := s.PkgDef(); n != nil {
base.Fatalf("importsym of symbol that already exists: %v", n)
}
n = ir.NewDeclNameAt(src.NoXPos, s)
n := ir.NewDeclNameAt(pos, s)
n.SetOp(op) // TODO(mdempsky): Add as argument to NewDeclNameAt.
n.SetClass(ctxt)
s.SetPkgDef(n)
s.Importdef = ipkg
}
if n.Op() != ir.ONONAME && n.Op() != op {
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
}
return n.(*ir.Name)
return n
}
// importtype returns the named type declared by symbol s.
// If no such type has been declared yet, a forward declaration is returned.
// ipkg is the package being imported
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
n := importsym(ipkg, s, ir.OTYPE)
if n.Op() != ir.OTYPE {
t := types.NewNamed(n)
n.SetOp(ir.OTYPE)
n.SetPos(pos)
n.SetType(t)
n.SetClass(ir.PEXTERN)
}
t := n.Type()
if t == nil {
base.Fatalf("importtype %v", s)
}
return t
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *ir.Name {
n := importsym(ipkg, pos, s, ir.OTYPE, ir.PEXTERN)
n.SetType(types.NewNamed(n))
return n
}
// importobj declares symbol s as an imported object representable by op.
// ipkg is the package being imported
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) ir.Node {
n := importsym(ipkg, s, op)
if n.Op() != ir.ONONAME {
if n.Op() == op && (op == ir.ONAME && n.Class() != ctxt || !types.Identical(n.Type(), t)) {
redeclare(base.Pos, s, fmt.Sprintf("during import %q", ipkg.Path))
}
return nil
}
n.SetOp(op)
n.SetPos(pos)
n.SetClass(ctxt)
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op ir.Op, ctxt ir.Class, t *types.Type) *ir.Name {
n := importsym(ipkg, pos, s, op, ctxt)
n.SetType(t)
if ctxt == ir.PFUNC {
n.Sym().SetFunc(true)
}
n.SetType(t)
return n
}
// importconst declares symbol s as an imported constant with type t and value val.
// ipkg is the package being imported
func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) {
func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val constant.Value) *ir.Name {
n := importobj(ipkg, pos, s, ir.OLITERAL, ir.PEXTERN, t)
if n == nil { // TODO: Check that value matches.
return
}
n.SetVal(val)
if base.Flag.E != 0 {
fmt.Printf("import const %v %L = %v\n", s, t, val)
}
return n
}
// importfunc declares symbol s as an imported function with type t.
// ipkg is the package being imported
func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name {
n := importobj(ipkg, pos, s, ir.ONAME, ir.PFUNC, t)
if n == nil {
return
}
name := n.(*ir.Name)
fn := ir.NewFunc(pos)
fn.SetType(t)
name.SetFunc(fn)
fn.Nname = name
n.SetFunc(fn)
fn.Nname = n
if base.Flag.E != 0 {
fmt.Printf("import func %v%S\n", s, t)
}
return n
}
// importvar declares symbol s as an imported variable with type t.
// ipkg is the package being imported
func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
n := importobj(ipkg, pos, s, ir.ONAME, ir.PEXTERN, t)
if n == nil {
return
}
if base.Flag.E != 0 {
fmt.Printf("import var %v %L\n", s, t)
}
func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name {
return importobj(ipkg, pos, s, ir.ONAME, ir.PEXTERN, t)
}
// importalias declares symbol s as an imported type alias with type t.
// ipkg is the package being imported
func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
n := importobj(ipkg, pos, s, ir.OTYPE, ir.PEXTERN, t)
if n == nil {
return
}
if base.Flag.E != 0 {
fmt.Printf("import type %v = %L\n", s, t)
}
func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) *ir.Name {
return importobj(ipkg, pos, s, ir.OTYPE, ir.PEXTERN, t)
}
func dumpasmhdr() {

View file

@ -41,18 +41,23 @@ var (
inlineImporter = map[*types.Sym]iimporterAndOffset{}
)
func expandDecl(n *ir.Name) {
if n.Op() != ir.ONONAME {
return
func expandDecl(n ir.Node) ir.Node {
if n, ok := n.(*ir.Name); ok {
return n
}
r := importReaderFor(n, declImporter)
id := n.(*ir.Ident)
if n := id.Sym().PkgDef(); n != nil {
return n.(*ir.Name)
}
r := importReaderFor(id.Sym(), declImporter)
if r == nil {
// Can happen if user tries to reference an undeclared name.
return
return n
}
r.doDecl(n)
return r.doDecl(n.Sym())
}
func expandInline(fn *ir.Func) {
@ -60,7 +65,7 @@ func expandInline(fn *ir.Func) {
return
}
r := importReaderFor(fn.Nname, inlineImporter)
r := importReaderFor(fn.Nname.Sym(), inlineImporter)
if r == nil {
base.Fatalf("missing import reader for %v", fn)
}
@ -68,13 +73,13 @@ func expandInline(fn *ir.Func) {
r.doInline(fn)
}
func importReaderFor(n *ir.Name, importers map[*types.Sym]iimporterAndOffset) *importReader {
x, ok := importers[n.Sym()]
func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
x, ok := importers[sym]
if !ok {
return nil
}
return x.p.newReader(x.off, n.Sym().Pkg)
return x.p.newReader(x.off, sym.Pkg)
}
type intReader struct {
@ -272,11 +277,7 @@ func (r *importReader) setPkg() {
r.currPkg = r.pkg()
}
func (r *importReader) doDecl(n ir.Node) {
if n.Op() != ir.ONONAME {
base.Fatalf("doDecl: unexpected Op for %v: %v", n.Sym(), n.Op())
}
func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
tag := r.byte()
pos := r.pos()
@ -284,24 +285,26 @@ func (r *importReader) doDecl(n ir.Node) {
case 'A':
typ := r.typ()
importalias(r.p.ipkg, pos, n.Sym(), typ)
return importalias(r.p.ipkg, pos, sym, typ)
case 'C':
typ := r.typ()
val := r.value(typ)
importconst(r.p.ipkg, pos, n.Sym(), typ, val)
return importconst(r.p.ipkg, pos, sym, typ, val)
case 'F':
typ := r.signature(nil)
importfunc(r.p.ipkg, pos, n.Sym(), typ)
n := importfunc(r.p.ipkg, pos, sym, typ)
r.funcExt(n)
return n
case 'T':
// Types can be recursive. We need to setup a stub
// declaration before recursing.
t := importtype(r.p.ipkg, pos, n.Sym())
n := importtype(r.p.ipkg, pos, sym)
t := n.Type()
// We also need to defer width calculations until
// after the underlying type has been assigned.
@ -312,7 +315,7 @@ func (r *importReader) doDecl(n ir.Node) {
if underlying.IsInterface() {
r.typeExt(t)
break
return n
}
ms := make([]*types.Field, r.uint64())
@ -339,15 +342,18 @@ func (r *importReader) doDecl(n ir.Node) {
for _, m := range ms {
r.methExt(m)
}
return n
case 'V':
typ := r.typ()
importvar(r.p.ipkg, pos, n.Sym(), typ)
n := importvar(r.p.ipkg, pos, sym, typ)
r.varExt(n)
return n
default:
base.Fatalf("unexpected tag: %v", tag)
panic("unreachable")
}
}
@ -433,16 +439,11 @@ func (r *importReader) ident() *types.Sym {
return pkg.Lookup(name)
}
func (r *importReader) qualifiedIdent() *ir.Name {
func (r *importReader) qualifiedIdent() *ir.Ident {
name := r.string()
pkg := r.pkg()
sym := pkg.Lookup(name)
n := sym.PkgDef()
if n == nil {
n = ir.NewDeclNameAt(src.NoXPos, sym)
sym.SetPkgDef(n)
}
return n.(*ir.Name)
return ir.NewIdent(src.NoXPos, sym)
}
func (r *importReader) pos() src.XPos {
@ -498,10 +499,7 @@ func (r *importReader) typ1() *types.Type {
// support inlining functions with local defined
// types. Therefore, this must be a package-scope
// type.
n := r.qualifiedIdent()
if n.Op() == ir.ONONAME {
expandDecl(n)
}
n := expandDecl(r.qualifiedIdent())
if n.Op() != ir.OTYPE {
base.Fatalf("expected OTYPE, got %v: %v, %v", n.Op(), n.Sym(), n)
}

View file

@ -8,7 +8,6 @@ import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/src"
"fmt"
"go/constant"
"go/token"
@ -97,23 +96,13 @@ func resolve(n ir.Node) (res ir.Node) {
if pkgName := dotImportRefs[id]; pkgName != nil {
pkgName.Used = true
}
if sym.Def == nil {
if _, ok := declImporter[sym]; !ok {
return n // undeclared name
}
sym.Def = ir.NewDeclNameAt(src.NoXPos, sym)
}
n = ir.AsNode(sym.Def)
}
// Stub ir.Name left for us by iimport.
n := n.(*ir.Name)
if inimport {
base.Fatalf("recursive inimport")
}
inimport = true
expandDecl(n)
n = expandDecl(n)
inimport = false
return n
}