aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/decl.go3
-rw-r--r--src/cmd/compile/internal/noder/func.go3
-rw-r--r--src/cmd/compile/internal/noder/import.go4
-rw-r--r--src/cmd/compile/internal/noder/irgen.go8
-rw-r--r--src/cmd/compile/internal/noder/noder.go2
-rw-r--r--src/cmd/compile/internal/noder/reader.go4
-rw-r--r--src/cmd/compile/internal/noder/stencil.go2
-rw-r--r--src/cmd/compile/internal/noder/types.go161
8 files changed, 108 insertions, 79 deletions
diff --git a/src/cmd/compile/internal/noder/decl.go b/src/cmd/compile/internal/noder/decl.go
index b23dd476008..54a13b498b9 100644
--- a/src/cmd/compile/internal/noder/decl.go
+++ b/src/cmd/compile/internal/noder/decl.go
@@ -154,8 +154,7 @@ func (g *irgen) typeDecl(out *ir.Nodes, decl *syntax.TypeDecl) {
name, obj := g.def(decl.Name)
ntyp, otyp := name.Type(), obj.Type()
if ir.CurFunc != nil {
- typecheck.TypeGen++
- ntyp.Vargen = typecheck.TypeGen
+ ntyp.SetVargen()
}
pragmas := g.pragmaFlags(decl.Pragma, typePragmas)
diff --git a/src/cmd/compile/internal/noder/func.go b/src/cmd/compile/internal/noder/func.go
index 702138157c5..6077b348a5c 100644
--- a/src/cmd/compile/internal/noder/func.go
+++ b/src/cmd/compile/internal/noder/func.go
@@ -37,8 +37,7 @@ func (g *irgen) funcBody(fn *ir.Func, recv *syntax.Field, sig *syntax.FuncType,
// calculated its size, including parameter offsets. Now that we've
// created the parameter Names, force a recalculation to ensure
// their offsets are correct.
- typ.Align = 0
- types.CalcSize(typ)
+ types.RecalcSize(typ)
if block != nil {
typecheck.DeclContext = ir.PAUTO
diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go
index 48f0e480284..c26340c9604 100644
--- a/src/cmd/compile/internal/noder/import.go
+++ b/src/cmd/compile/internal/noder/import.go
@@ -198,7 +198,7 @@ func importfile(decl *syntax.ImportDecl) *types.Pkg {
return nil
}
- if pkg != ir.Pkgs.Unsafe && pkg.Height >= myheight {
+ if pkg != types.UnsafePkg && pkg.Height >= myheight {
myheight = pkg.Height + 1
}
return pkg
@@ -231,7 +231,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack
}
if path == "unsafe" {
- pkg1, pkg2 = ir.Pkgs.Unsafe, types2.Unsafe
+ pkg1, pkg2 = types.UnsafePkg, types2.Unsafe
// TODO(mdempsky): Investigate if this actually matters. Why would
// the linker or runtime care whether a package imported unsafe?
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index 29882eb7731..d53c254001c 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -149,6 +149,9 @@ type irgen struct {
// statements yet.
exprStmtOK bool
+ // types which we need to finish, by doing g.fillinMethods.
+ typesToFinalize []*typeDelayInfo
+
// Fully-instantiated generic types whose methods should be instantiated
instTypeList []*types.Type
@@ -184,6 +187,11 @@ type delayInfo struct {
off int
}
+type typeDelayInfo struct {
+ typ *types2.Named
+ ntyp *types.Type
+}
+
func (g *irgen) generate(noders []*noder) {
types.LocalPkg.Name = g.self.Name()
types.LocalPkg.Height = g.self.Height()
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
index e1b485b2b35..61a7f8aad48 100644
--- a/src/cmd/compile/internal/noder/noder.go
+++ b/src/cmd/compile/internal/noder/noder.go
@@ -384,7 +384,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
return
}
- if ipkg == ir.Pkgs.Unsafe {
+ if ipkg == types.UnsafePkg {
p.importedUnsafe = true
}
if ipkg.Path == "embed" {
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 985453a1bb3..e7a9d9655b1 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -428,7 +428,7 @@ func (r *reader) interfaceType() *types.Type {
pos := r.pos()
pkg, sym := r.selector()
tpkg = pkg
- mtyp := r.signature(pkg, typecheck.FakeRecv())
+ mtyp := r.signature(pkg, types.FakeRecv())
methods[i] = types.NewField(pos, sym, mtyp)
}
for i := range embeddeds {
@@ -540,7 +540,7 @@ func (pr *pkgReader) objIdx(idx int, implicits, explicits []*types.Type) ir.Node
if tag == objStub {
assert(!sym.IsBlank())
switch sym.Pkg {
- case types.BuiltinPkg, ir.Pkgs.Unsafe:
+ case types.BuiltinPkg, types.UnsafePkg:
return sym.Def.(ir.Node)
}
if pri, ok := objReader[sym]; ok {
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index b3ff4b8855c..0c6bb5100c6 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -903,7 +903,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
ir.EditChildren(m, edit)
m.SetTypecheck(1)
- if typecheck.IsCmp(x.Op()) {
+ if x.Op().IsCmp() {
transformCompare(m.(*ir.BinaryExpr))
} else {
switch x.Op() {
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index c9f7c2bbe47..e00a3a5da91 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -22,7 +22,7 @@ func (g *irgen) pkg(pkg *types2.Package) *types.Pkg {
case g.self:
return types.LocalPkg
case types2.Unsafe:
- return ir.Pkgs.Unsafe
+ return types.UnsafePkg
}
return types.NewPkg(pkg.Path(), pkg.Name())
}
@@ -35,6 +35,16 @@ func (g *irgen) typ(typ types2.Type) *types.Type {
types.DeferCheckSize()
res := g.typ1(typ)
types.ResumeCheckSize()
+
+ // Finish up any types on typesToFinalize, now that we are at the top of a
+ // fully-defined (possibly recursive) type. fillinMethods could create more
+ // types to finalize.
+ for len(g.typesToFinalize) > 0 {
+ l := len(g.typesToFinalize)
+ info := g.typesToFinalize[l-1]
+ g.typesToFinalize = g.typesToFinalize[:l-1]
+ g.fillinMethods(info.typ, info.ntyp)
+ }
return res
}
@@ -118,9 +128,14 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
return s.Def.Type()
}
+ // Make sure the base generic type exists in type1 (it may
+ // not yet if we are referecing an imported generic type, as
+ // opposed to a generic type declared in this package).
+ _ = g.obj(typ.Orig().Obj())
+
// Create a forwarding type first and put it in the g.typs
// map, in order to deal with recursive generic types
- // (including via method signatures).. Set up the extra
+ // (including via method signatures). Set up the extra
// ntyp information (Def, RParams, which may set
// HasTParam) before translating the underlying type
// itself, so we handle recursion correctly.
@@ -146,10 +161,19 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
ntyp.SetRParams(rparams)
//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
- ntyp.SetUnderlying(g.typ1(typ.Underlying()))
- g.fillinMethods(typ, ntyp)
// Save the symbol for the base generic type.
ntyp.OrigSym = g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name())
+ ntyp.SetUnderlying(g.typ1(typ.Underlying()))
+ if typ.NumMethods() != 0 {
+ // Save a delayed call to g.fillinMethods() (once
+ // potentially recursive types have been fully
+ // resolved).
+ g.typesToFinalize = append(g.typesToFinalize,
+ &typeDelayInfo{
+ typ: typ,
+ ntyp: ntyp,
+ })
+ }
return ntyp
}
obj := g.obj(typ.Obj())
@@ -201,7 +225,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
methods := make([]*types.Field, typ.NumExplicitMethods())
for i := range methods {
m := typ.ExplicitMethod(i)
- mtyp := g.signature(typecheck.FakeRecv(), m.Type().(*types2.Signature))
+ mtyp := g.signature(types.FakeRecv(), m.Type().(*types2.Signature))
methods[i] = types.NewField(g.pos(m), g.selector(m), mtyp)
}
@@ -261,76 +285,75 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
}
}
-// fillinMethods fills in the method name nodes and types for a defined type. This
-// is needed for later typechecking when looking up methods of instantiated types,
-// and for actually generating the methods for instantiated types.
+// fillinMethods fills in the method name nodes and types for a defined type with at
+// least one method. This is needed for later typechecking when looking up methods of
+// instantiated types, and for actually generating the methods for instantiated
+// types.
func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
- if typ.NumMethods() != 0 {
- targs2 := typ.TArgs()
- targs := make([]*types.Type, targs2.Len())
- for i := range targs {
- targs[i] = g.typ1(targs2.At(i))
- }
+ targs2 := typ.TArgs()
+ targs := make([]*types.Type, targs2.Len())
+ for i := range targs {
+ targs[i] = g.typ1(targs2.At(i))
+ }
- methods := make([]*types.Field, typ.NumMethods())
- for i := range methods {
- m := typ.Method(i)
- recvType := deref2(types2.AsSignature(m.Type()).Recv().Type())
- var meth *ir.Name
- if m.Pkg() != g.self {
- // Imported methods cannot be loaded by name (what
- // g.obj() does) - they must be loaded via their
- // type.
- meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name)
+ methods := make([]*types.Field, typ.NumMethods())
+ for i := range methods {
+ m := typ.Method(i)
+ recvType := deref2(types2.AsSignature(m.Type()).Recv().Type())
+ var meth *ir.Name
+ if m.Pkg() != g.self {
+ // Imported methods cannot be loaded by name (what
+ // g.obj() does) - they must be loaded via their
+ // type.
+ meth = g.obj(recvType.(*types2.Named).Obj()).Type().Methods().Index(i).Nname.(*ir.Name)
+ } else {
+ meth = g.obj(m)
+ }
+ if recvType != types2.Type(typ) {
+ // Unfortunately, meth is the type of the method of the
+ // generic type, so we have to do a substitution to get
+ // the name/type of the method of the instantiated type,
+ // using m.Type().RParams() and typ.TArgs()
+ inst2 := instTypeName2("", typ.TArgs())
+ name := meth.Sym().Name
+ i1 := strings.Index(name, "[")
+ i2 := strings.Index(name[i1:], "]")
+ assert(i1 >= 0 && i2 >= 0)
+ // Generate the name of the instantiated method.
+ name = name[0:i1] + inst2 + name[i1+i2+1:]
+ newsym := meth.Sym().Pkg.Lookup(name)
+ var meth2 *ir.Name
+ if newsym.Def != nil {
+ meth2 = newsym.Def.(*ir.Name)
} else {
- meth = g.obj(m)
- }
- if recvType != types2.Type(typ) {
- // Unfortunately, meth is the type of the method of the
- // generic type, so we have to do a substitution to get
- // the name/type of the method of the instantiated type,
- // using m.Type().RParams() and typ.TArgs()
- inst2 := instTypeName2("", typ.TArgs())
- name := meth.Sym().Name
- i1 := strings.Index(name, "[")
- i2 := strings.Index(name[i1:], "]")
- assert(i1 >= 0 && i2 >= 0)
- // Generate the name of the instantiated method.
- name = name[0:i1] + inst2 + name[i1+i2+1:]
- newsym := meth.Sym().Pkg.Lookup(name)
- var meth2 *ir.Name
- if newsym.Def != nil {
- meth2 = newsym.Def.(*ir.Name)
- } else {
- meth2 = ir.NewNameAt(meth.Pos(), newsym)
- rparams := types2.AsSignature(m.Type()).RParams()
- tparams := make([]*types.Type, rparams.Len())
- for i := range tparams {
- tparams[i] = g.typ1(rparams.At(i))
- }
- assert(len(tparams) == len(targs))
- ts := typecheck.Tsubster{
- Tparams: tparams,
- Targs: targs,
- }
- // Do the substitution of the type
- meth2.SetType(ts.Typ(meth.Type()))
- // Add any new fully instantiated types
- // seen during the substitution to
- // g.instTypeList.
- g.instTypeList = append(g.instTypeList, ts.InstTypeList...)
- newsym.Def = meth2
+ meth2 = ir.NewNameAt(meth.Pos(), newsym)
+ rparams := types2.AsSignature(m.Type()).RParams()
+ tparams := make([]*types.Type, rparams.Len())
+ for i := range tparams {
+ tparams[i] = g.typ1(rparams.At(i))
}
- meth = meth2
+ assert(len(tparams) == len(targs))
+ ts := typecheck.Tsubster{
+ Tparams: tparams,
+ Targs: targs,
+ }
+ // Do the substitution of the type
+ meth2.SetType(ts.Typ(meth.Type()))
+ // Add any new fully instantiated types
+ // seen during the substitution to
+ // g.instTypeList.
+ g.instTypeList = append(g.instTypeList, ts.InstTypeList...)
+ newsym.Def = meth2
}
- methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
- methods[i].Nname = meth
- }
- ntyp.Methods().Set(methods)
- if !ntyp.HasTParam() && !ntyp.HasShape() {
- // Generate all the methods for a new fully-instantiated type.
- g.instTypeList = append(g.instTypeList, ntyp)
+ meth = meth2
}
+ methods[i] = types.NewField(meth.Pos(), g.selector(m), meth.Type())
+ methods[i].Nname = meth
+ }
+ ntyp.Methods().Set(methods)
+ if !ntyp.HasTParam() && !ntyp.HasShape() {
+ // Generate all the methods for a new fully-instantiated type.
+ g.instTypeList = append(g.instTypeList, ntyp)
}
}