t := n.Type
if t.IsInterface() {
+ w.typeExt(t)
break
}
w.signature(m.Type)
}
+ w.typeExt(t)
for _, m := range ms.Slice() {
w.methExt(m)
}
}
}
+func (w *exportWriter) typeExt(t *types.Type) {
+ // For type T, export the index of type descriptor symbols of T and *T.
+ if i, ok := typeSymIdx[t]; ok {
+ w.int64(i[0])
+ w.int64(i[1])
+ return
+ }
+ w.symIdx(typesym(t))
+ w.symIdx(typesym(t.PtrTo()))
+}
+
// Inline bodies.
func (w *exportWriter) stmtList(list Nodes) {
resumecheckwidth()
if underlying.IsInterface() {
+ r.typeExt(t)
break
}
}
t.Methods().Set(ms)
+ r.typeExt(t)
for _, m := range ms {
r.methExt(m)
}
}
}
+func (r *importReader) typeExt(t *types.Type) {
+ i, pi := r.int64(), r.int64()
+ if i != -1 && pi != -1 {
+ typeSymIdx[t] = [2]int64{i, pi}
+ }
+}
+
+// Map imported type T to the index of type descriptor symbols of T and *T,
+// so we can use index to reference the symbol.
+var typeSymIdx = make(map[*types.Type][2]int64)
+
func (r *importReader) doInline(n *Node) {
if len(n.Func.Inl.Body) != 0 {
Fatalf("%v already has inline body", n)
if myimportpath != "runtime" || (tbase != types.Types[tbase.Etype] && tbase != types.Bytetype && tbase != types.Runetype && tbase != types.Errortype) { // int, float, etc
// named types from other files are defined only by those files
if tbase.Sym != nil && tbase.Sym.Pkg != localpkg {
+ if i, ok := typeSymIdx[tbase]; ok {
+ lsym.Pkg = tbase.Sym.Pkg.Prefix
+ if t != tbase {
+ lsym.SymIdx = int32(i[1])
+ } else {
+ lsym.SymIdx = int32(i[0])
+ }
+ lsym.Set(obj.AttrIndexed, true)
+ }
return lsym
}
// TODO(mdempsky): Investigate whether this can happen.
// DwarfFiles [...]string
//
// SymbolDefs [...]struct {
-// Name string
-// ABI uint16
-// Type uint8
-// Flag uint8
-// Size uint32
+// Name string
+// ABI uint16
+// Type uint8
+// Flag uint8
+// Flag2 uint8
+// Size uint32
// }
// Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions
// ... // same as SymbolDefs
// ... // same as SymbolDefs
// }
//
+// RefFlags [...]struct { // referenced symbol flags
+// Sym symRef
+// Flag uint8
+// Flag2 uint8
+// }
+//
// Hash64 [...][8]byte
// Hash [...][N]byte
//
BlkHasheddef
BlkNonpkgdef
BlkNonpkgref
+ BlkRefFlags
BlkHash64
BlkHash
BlkRelocIdx
// for testing
func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
+// Referenced symbol flags.
+//
+// Serialized format:
+// RefFlags struct {
+// Sym symRef
+// Flag uint8
+// Flag2 uint8
+// }
+type RefFlags [RefFlagsSize]byte
+
+const RefFlagsSize = 8 + 1 + 1
+
+func (r *RefFlags) Sym() SymRef {
+ return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
+}
+func (r *RefFlags) Flag() uint8 { return r[8] }
+func (r *RefFlags) Flag2() uint8 { return r[9] }
+
+func (r *RefFlags) SetSym(x SymRef) {
+ binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
+ binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
+}
+func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
+func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
+
+func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
+
// Referenced symbol name.
//
// Serialized format:
return (*Sym)(unsafe.Pointer(&r.b[off]))
}
+// NRefFlags returns the number of referenced symbol flags.
+func (r *Reader) NRefFlags() int {
+ return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
+}
+
+// RefFlags returns a pointer to the i-th referenced symbol flags.
+// Note: here i is not a local symbol index, just a counter.
+func (r *Reader) RefFlags(i int) *RefFlags {
+ off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
+ return (*RefFlags)(unsafe.Pointer(&r.b[off]))
+}
+
// Hash64 returns the i-th short hashed symbol's hash.
// Note: here i is the index of short hashed symbols, not all symbols
// (unlike other accessors).
w.Sym(s)
}
+ // Referenced package symbol flags
+ h.Offsets[goobj2.BlkRefFlags] = w.Offset()
+ w.refFlags()
+
// Hashes
h.Offsets[goobj2.BlkHash64] = w.Offset()
for _, s := range ctxt.hashed64defs {
}
}
+// Emits flags of referenced indexed symbols.
+func (w *writer) refFlags() {
+ seen := make(map[*LSym]bool)
+ w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
+ switch rs.PkgIdx {
+ case goobj2.PkgIdxNone, goobj2.PkgIdxHashed64, goobj2.PkgIdxHashed, goobj2.PkgIdxBuiltin, goobj2.PkgIdxSelf: // not an external indexed reference
+ return
+ case goobj2.PkgIdxInvalid:
+ panic("unindexed symbol reference")
+ }
+ if seen[rs] {
+ return
+ }
+ seen[rs] = true
+ symref := makeSymRef(rs)
+ flag2 := uint8(0)
+ if rs.UsedInIface() {
+ flag2 |= goobj2.SymFlagUsedInIface
+ }
+ if flag2 == 0 {
+ return // no need to write zero flags
+ }
+ var o goobj2.RefFlags
+ o.SetSym(symref)
+ o.SetFlag2(flag2)
+ o.Write(w.Writer)
+ })
+}
+
// Emits names of referenced indexed symbols, used by tools (objdump, nm)
// only.
func (w *writer) refNames() {
- seen := make(map[goobj2.SymRef]bool)
+ seen := make(map[*LSym]bool)
w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
switch rs.PkgIdx {
case goobj2.PkgIdxNone, goobj2.PkgIdxHashed64, goobj2.PkgIdxHashed, goobj2.PkgIdxBuiltin, goobj2.PkgIdxSelf: // not an external indexed reference
case goobj2.PkgIdxInvalid:
panic("unindexed symbol reference")
}
- symref := makeSymRef(rs)
- if seen[symref] {
+ if seen[rs] {
return
}
- seen[symref] = true
+ seen[rs] = true
+ symref := makeSymRef(rs)
var o goobj2.RefName
o.SetSym(symref)
o.SetName(rs.Name, w.Writer)
}
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
+ // load non-package refs
ndef := uint32(r.NAlldef())
needNameExpansion := r.NeedNameExpansion()
for i, n := uint32(0), uint32(r.NNonpkgref()); i < n; i++ {
l.SetAttrUsedInIface(gi, true)
}
}
+
+ // load flags of package refs
+ for i, n := 0, r.NRefFlags(); i < n; i++ {
+ rf := r.RefFlags(i)
+ gi := l.resolve(r, rf.Sym())
+ if rf.Flag2()&goobj2.SymFlagUsedInIface != 0 {
+ l.SetAttrUsedInIface(gi, true)
+ }
+ }
}
func abiToVer(abi uint16, localSymVersion int) int {