}
// runtime interface and reflection data structures
-var signatlist []*types.Type
+var signatlist = make(map[*types.Type]bool)
var itabs []itabEntry
var ptabs []ptabEntry
return ot
}
-func typesym(t *types.Type) *types.Sym {
+func typesymname(t *types.Type) string {
name := t.ShortString()
-
// Use a separate symbol name for Noalg types for #17752.
if a, bad := algtype1(t); a == ANOEQ && bad.Noalg() {
name = "noalg." + name
}
+ return name
+}
- return typepkg.Lookup(name)
+func typesym(t *types.Type) *types.Sym {
+ return typepkg.Lookup(typesymname(t))
}
// tracksym returns the symbol for tracking use of field/method f, assumed
func typenamesym(t *types.Type) *types.Sym {
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
- Fatalf("typename %v", t)
+ Fatalf("typenamesym %v", t)
}
s := typesym(t)
+ addsignat(t)
+ return s
+}
+
+func typename(t *types.Type) *Node {
+ s := typenamesym(t)
if s.Def == nil {
n := newnamel(src.NoXPos, s)
n.Type = types.Types[TUINT8]
n.Class = PEXTERN
n.Typecheck = 1
s.Def = asTypesNode(n)
-
- signatlist = append(signatlist, t)
}
- return asNode(s.Def).Sym
-}
-
-func typename(t *types.Type) *Node {
- s := typenamesym(t)
n := nod(OADDR, asNode(s.Def), nil)
n.Type = types.NewPtr(asNode(s.Def).Type)
n.SetAddable(true)
}
}
-func dtypesym(t *types.Type) *types.Sym {
- // Replace byte, rune aliases with real type.
- // They've been separate internally to make error messages
- // better, but we have to merge them in the reflect tables.
+// formalType replaces byte and rune aliases with real types.
+// They've been separate internally to make error messages
+// better, but we have to merge them in the reflect tables.
+func formalType(t *types.Type) *types.Type {
if t == types.Bytetype || t == types.Runetype {
- t = types.Types[t.Etype]
+ return types.Types[t.Etype]
}
+ return t
+}
+func dtypesym(t *types.Type) *types.Sym {
+ t = formalType(t)
if t.IsUntyped() {
Fatalf("dtypesym %v", t)
}
return syms[methodnum]
}
+func addsignat(t *types.Type) {
+ signatlist[formalType(t)] = true
+}
+
func dumptypestructs() {
// copy types from externdcl list to signatlist
for _, n := range externdcl {
if n.Op == OTYPE {
- signatlist = append(signatlist, n.Type)
+ addsignat(n.Type)
}
}
- // Process signatlist. This can't use range, as entries are
- // added to the list while it is being processed.
- for i := 0; i < len(signatlist); i++ {
- t := signatlist[i]
- dtypesym(t)
- if t.Sym != nil {
- dtypesym(types.NewPtr(t))
+ // Process signatlist. Use a loop, as dtypesym adds
+ // entries to signatlist while it is being processed.
+ signats := make([]typeAndStr, len(signatlist))
+ for len(signatlist) > 0 {
+ signats = signats[:0]
+ // Transfer entries to a slice and sort, for reproducible builds.
+ for t := range signatlist {
+ signats = append(signats, typeAndStr{t: t, s: typesymname(t)})
+ delete(signatlist, t)
+ }
+ sort.Sort(typesByString(signats))
+ for _, ts := range signats {
+ t := ts.t
+ dtypesym(t)
+ if t.Sym != nil {
+ dtypesym(types.NewPtr(t))
+ }
}
}
}
}
+type typeAndStr struct {
+ t *types.Type
+ s string
+}
+
+type typesByString []typeAndStr
+
+func (a typesByString) Len() int { return len(a) }
+func (a typesByString) Less(i, j int) bool { return a[i].s < a[j].s }
+func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
type pkgByPath []*types.Pkg
func (a pkgByPath) Len() int { return len(a) }