}
// runtime interface and reflection data structures
-var signatlist []*Type
+var signatlist = make(map[*Type]bool)
var itabs []itabEntry
var ptabs []ptabEntry
func typenamesym(t *Type) *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 *Type) *Node {
+ s := typenamesym(t)
if s.Def == nil {
n := newnamel(src.NoXPos, s)
n.Type = Types[TUINT8]
n.Class = PEXTERN
n.Typecheck = 1
s.Def = n
-
- signatlist = append(signatlist, t)
}
-
- return s.Def.Sym
-}
-
-func typename(t *Type) *Node {
- s := typenamesym(t)
n := nod(OADDR, s.Def, nil)
n.Type = typPtr(s.Def.Type)
n.SetAddable(true)
return syms[methodnum]
}
+func addsignat(t *Type) {
+ signatlist[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(typPtr(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: t.LongString()})
+ delete(signatlist, t)
+ }
+ sort.Sort(typesByLongString(signats))
+ for _, ts := range signats {
+ t := ts.t
+ dtypesym(t)
+ if t.Sym != nil {
+ dtypesym(typPtr(t))
+ }
}
}
}
}
+type typeAndStr struct {
+ t *Type
+ s string
+}
+
+// TODO(josharian): simplify this to just use Type.cmp once issue 19869 has been fixed.
+type typesByLongString []typeAndStr
+
+func (a typesByLongString) Len() int { return len(a) }
+func (a typesByLongString) Less(i, j int) bool { return a[i].s < a[j].s }
+func (a typesByLongString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
type pkgByPath []*Pkg
func (a pkgByPath) Len() int { return len(a) }
// cmp compares two *Types t and x, returning ssa.CMPlt,
// ssa.CMPeq, ssa.CMPgt as t<x, t==x, t>x, for an arbitrary
// and optimizer-centric notion of comparison.
+// TODO(josharian): make this safe for recursive interface types
+// and use in signatlist sorting. See issue 19869.
func (t *Type) cmp(x *Type) ssa.Cmp {
// This follows the structure of eqtype in subr.go
// with two exceptions.