runtime: redefine _type to abi.Type; add rtype for methods.

Change-Id: I1c478b704d84811caa209006c657dda82d9c4cf9
Reviewed-on: https://go-review.googlesource.com/c/go/+/488435
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
David Chase 2023-04-24 15:45:33 -04:00
parent 48f8c5c037
commit a2838ec5f2
19 changed files with 76 additions and 75 deletions

View File

@ -1802,7 +1802,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
// Needed by the prettyprinter code for interface inspection. // Needed by the prettyprinter code for interface inspection.
for _, typ := range []string{ for _, typ := range []string{
"type:runtime._type", "type:internal/abi.Type",
"type:internal/abi.ArrayType", "type:internal/abi.ArrayType",
"type:internal/abi.ChanType", "type:internal/abi.ChanType",
"type:runtime.functype", "type:runtime.functype",

View File

@ -56,7 +56,7 @@ func TestRuntimeTypesPresent(t *testing.T) {
} }
want := map[string]bool{ want := map[string]bool{
"runtime._type": true, "internal/abi.Type": true,
"internal/abi.ArrayType": true, "internal/abi.ArrayType": true,
"internal/abi.ChanType": true, "internal/abi.ChanType": true,
"runtime.functype": true, "runtime.functype": true,

View File

@ -279,8 +279,7 @@ const Ptr = Pointer
// to describe a non-defined type with no methods. // to describe a non-defined type with no methods.
type uncommonType = abi.UncommonType type uncommonType = abi.UncommonType
// rtype is the common implementation of most values. // rtype is a wrapper that allows us to define exactly the type.Reflect methods.
// It is embedded in other struct types.
type rtype struct { type rtype struct {
t *abi.Type t *abi.Type
} }

View File

@ -106,7 +106,7 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr {
// typehash, but we want to report the topmost type in // typehash, but we want to report the topmost type in
// the error text (e.g. in a struct with a field of slice type // the error text (e.g. in a struct with a field of slice type
// we want to report the struct, not the slice). // we want to report the struct, not the slice).
panic(errorString("hash of unhashable type " + t.string())) panic(errorString("hash of unhashable type " + toRType(t).string()))
} }
if isDirectIface(t) { if isDirectIface(t) {
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0) return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
@ -123,7 +123,7 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
} }
if t.Equal == nil { if t.Equal == nil {
// See comment in interhash above. // See comment in interhash above.
panic(errorString("hash of unhashable type " + t.string())) panic(errorString("hash of unhashable type " + toRType(t).string()))
} }
if isDirectIface(t) { if isDirectIface(t) {
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0) return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
@ -174,7 +174,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
case kindArray: case kindArray:
a := (*arraytype)(unsafe.Pointer(t)) a := (*arraytype)(unsafe.Pointer(t))
for i := uintptr(0); i < a.Len; i++ { for i := uintptr(0); i < a.Len; i++ {
h = typehash(toType(a.Elem), add(p, i*a.Elem.Size_), h) h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
} }
return h return h
case kindStruct: case kindStruct:
@ -189,7 +189,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
default: default:
// Should never happen, as typehash should only be called // Should never happen, as typehash should only be called
// with comparable types. // with comparable types.
panic(errorString("hash of unhashable type " + t.string())) panic(errorString("hash of unhashable type " + toRType(t).string()))
} }
} }
@ -247,7 +247,7 @@ func efaceeq(t *_type, x, y unsafe.Pointer) bool {
} }
eq := t.Equal eq := t.Equal
if eq == nil { if eq == nil {
panic(errorString("comparing uncomparable type " + t.string())) panic(errorString("comparing uncomparable type " + toRType(t).string()))
} }
if isDirectIface(t) { if isDirectIface(t) {
// Direct interface types are ptr, chan, map, func, and single-element structs/arrays thereof. // Direct interface types are ptr, chan, map, func, and single-element structs/arrays thereof.
@ -264,7 +264,7 @@ func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
t := tab._type t := tab._type
eq := t.Equal eq := t.Equal
if eq == nil { if eq == nil {
panic(errorString("comparing uncomparable type " + t.string())) panic(errorString("comparing uncomparable type " + toRType(t).string()))
} }
if isDirectIface(t) { if isDirectIface(t) {
// See comment in efaceeq. // See comment in efaceeq.

View File

@ -466,11 +466,11 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
if at.Len != 1 { if at.Len != 1 {
throw("can't happen") throw("can't happen")
} }
cgoCheckArg(toType(at.Elem), p, at.Elem.Kind_&kindDirectIface == 0, top, msg) cgoCheckArg(at.Elem, p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
return return
} }
for i := uintptr(0); i < at.Len; i++ { for i := uintptr(0); i < at.Len; i++ {
cgoCheckArg(toType(at.Elem), p, true, top, msg) cgoCheckArg(at.Elem, p, true, top, msg)
p = add(p, at.Elem.Size_) p = add(p, at.Elem.Size_)
} }
case kindChan, kindMap: case kindChan, kindMap:

View File

@ -249,7 +249,7 @@ func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
at := (*arraytype)(unsafe.Pointer(typ)) at := (*arraytype)(unsafe.Pointer(typ))
for i := uintptr(0); i < at.Len; i++ { for i := uintptr(0); i < at.Len; i++ {
if off < at.Elem.Size_ { if off < at.Elem.Size_ {
cgoCheckUsingType(toType(at.Elem), src, off, size) cgoCheckUsingType(at.Elem, src, off, size)
} }
src = add(src, at.Elem.Size_) src = add(src, at.Elem.Size_)
skipped := off skipped := off

View File

@ -104,11 +104,11 @@ func makechan(t *chantype, size int) *hchan {
default: default:
// Elements contain pointers. // Elements contain pointers.
c = new(hchan) c = new(hchan)
c.buf = mallocgc(mem, toType(elem), true) c.buf = mallocgc(mem, elem, true)
} }
c.elemsize = uint16(elem.Size_) c.elemsize = uint16(elem.Size_)
c.elemtype = toType(elem) c.elemtype = elem
c.dataqsiz = uint(size) c.dataqsiz = uint(size)
lockInit(&c.lock, lockRankHchan) lockInit(&c.lock, lockRankHchan)

View File

@ -30,18 +30,18 @@ func (*TypeAssertionError) RuntimeError() {}
func (e *TypeAssertionError) Error() string { func (e *TypeAssertionError) Error() string {
inter := "interface" inter := "interface"
if e._interface != nil { if e._interface != nil {
inter = e._interface.string() inter = toRType(e._interface).string()
} }
as := e.asserted.string() as := toRType(e.asserted).string()
if e.concrete == nil { if e.concrete == nil {
return "interface conversion: " + inter + " is nil, not " + as return "interface conversion: " + inter + " is nil, not " + as
} }
cs := e.concrete.string() cs := toRType(e.concrete).string()
if e.missingMethod == "" { if e.missingMethod == "" {
msg := "interface conversion: " + inter + " is " + cs + ", not " + as msg := "interface conversion: " + inter + " is " + cs + ", not " + as
if cs == as { if cs == as {
// provide slightly clearer error message // provide slightly clearer error message
if e.concrete.pkgpath() != e.asserted.pkgpath() { if toRType(e.concrete).pkgpath() != toRType(e.asserted).pkgpath() {
msg += " (types from different packages)" msg += " (types from different packages)"
} else { } else {
msg += " (types from different scopes)" msg += " (types from different scopes)"
@ -256,7 +256,7 @@ func printany(i any) {
func printanycustomtype(i any) { func printanycustomtype(i any) {
eface := efaceOf(&i) eface := efaceOf(&i)
typestring := eface._type.string() typestring := toRType(eface._type).string()
switch eface._type.Kind_ { switch eface._type.Kind_ {
case kindString: case kindString:

View File

@ -194,11 +194,12 @@ func dumptype(t *_type) {
dumpint(tagType) dumpint(tagType)
dumpint(uint64(uintptr(unsafe.Pointer(t)))) dumpint(uint64(uintptr(unsafe.Pointer(t))))
dumpint(uint64(t.Size_)) dumpint(uint64(t.Size_))
if x := t.uncommon(); x == nil || t.nameOff(x.PkgPath).name() == "" { rt := toRType(t)
dumpstr(t.string()) if x := t.Uncommon(); x == nil || rt.nameOff(x.PkgPath).name() == "" {
dumpstr(rt.string())
} else { } else {
pkgpath := t.nameOff(x.PkgPath).name() pkgpath := rt.nameOff(x.PkgPath).name()
name := t.name() name := rt.name()
dumpint(uint64(uintptr(len(pkgpath)) + 1 + uintptr(len(name)))) dumpint(uint64(uintptr(len(pkgpath)) + 1 + uintptr(len(name))))
dwrite(unsafe.Pointer(unsafe.StringData(pkgpath)), uintptr(len(pkgpath))) dwrite(unsafe.Pointer(unsafe.StringData(pkgpath)), uintptr(len(pkgpath)))
dwritebyte('.') dwritebyte('.')

View File

@ -41,7 +41,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
if canfail { if canfail {
return nil return nil
} }
name := inter.typ.nameOff(inter.mhdr[0].Name) name := toRType(&inter.typ).nameOff(inter.mhdr[0].Name)
panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()}) panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
} }
@ -192,7 +192,7 @@ func (t *itabTableType) add(m *itab) {
func (m *itab) init() string { func (m *itab) init() string {
inter := m.inter inter := m.inter
typ := m._type typ := m._type
x := typ.uncommon() x := typ.Uncommon()
// both inter and typ have method sorted by name, // both inter and typ have method sorted by name,
// and interface names are unique, // and interface names are unique,
@ -207,8 +207,8 @@ func (m *itab) init() string {
imethods: imethods:
for k := 0; k < ni; k++ { for k := 0; k < ni; k++ {
i := &inter.mhdr[k] i := &inter.mhdr[k]
itype := inter.typ.typeOff(i.Typ) itype := toRType(&inter.typ).typeOff(i.Typ)
name := inter.typ.nameOff(i.Name) name := toRType(&inter.typ).nameOff(i.Name)
iname := name.name() iname := name.name()
ipkg := name.pkgPath() ipkg := name.pkgPath()
if ipkg == "" { if ipkg == "" {
@ -216,15 +216,16 @@ imethods:
} }
for ; j < nt; j++ { for ; j < nt; j++ {
t := &xmhdr[j] t := &xmhdr[j]
tname := typ.nameOff(t.Name) rtyp := toRType(typ)
if typ.typeOff(t.Mtyp) == itype && tname.name() == iname { tname := rtyp.nameOff(t.Name)
if rtyp.typeOff(t.Mtyp) == itype && tname.name() == iname {
pkgPath := tname.pkgPath() pkgPath := tname.pkgPath()
if pkgPath == "" { if pkgPath == "" {
pkgPath = typ.nameOff(x.PkgPath).name() pkgPath = rtyp.nameOff(x.PkgPath).name()
} }
if tname.isExported() || pkgPath == ipkg { if tname.isExported() || pkgPath == ipkg {
if m != nil { if m != nil {
ifn := typ.textOff(t.Ifn) ifn := rtyp.textOff(t.Ifn)
if k == 0 { if k == 0 {
fun0 = ifn // we'll set m.fun[0] at the end fun0 = ifn // we'll set m.fun[0] at the end
} else { } else {

View File

@ -155,7 +155,7 @@ import (
// anywhere in the bulk barrier or memmove. // anywhere in the bulk barrier or memmove.
// //
//go:nosplit //go:nosplit
func typedmemmove(typ *_type, dst, src unsafe.Pointer) { func typedmemmove(typ *abi.Type, dst, src unsafe.Pointer) {
if dst == src { if dst == src {
return return
} }

View File

@ -683,11 +683,11 @@ func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) {
throw("runtime: typeBitsBulkBarrier without type") throw("runtime: typeBitsBulkBarrier without type")
} }
if typ.Size_ != size { if typ.Size_ != size {
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " of size ", typ.Size_, " but memory size", size) println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " of size ", typ.Size_, " but memory size", size)
throw("runtime: invalid typeBitsBulkBarrier") throw("runtime: invalid typeBitsBulkBarrier")
} }
if typ.Kind_&kindGCProg != 0 { if typ.Kind_&kindGCProg != 0 {
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " with GC prog") println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " with GC prog")
throw("runtime: invalid typeBitsBulkBarrier") throw("runtime: invalid typeBitsBulkBarrier")
} }
if !writeBarrier.needed { if !writeBarrier.needed {

View File

@ -372,7 +372,7 @@ func SetFinalizer(obj any, finalizer any) {
throw("runtime.SetFinalizer: first argument is nil") throw("runtime.SetFinalizer: first argument is nil")
} }
if etyp.Kind_&kindMask != kindPtr { if etyp.Kind_&kindMask != kindPtr {
throw("runtime.SetFinalizer: first argument is " + etyp.string() + ", not pointer") throw("runtime.SetFinalizer: first argument is " + toRType(etyp).string() + ", not pointer")
} }
ot := (*ptrtype)(unsafe.Pointer(etyp)) ot := (*ptrtype)(unsafe.Pointer(etyp))
if ot.elem == nil { if ot.elem == nil {
@ -431,14 +431,14 @@ func SetFinalizer(obj any, finalizer any) {
} }
if ftyp.Kind_&kindMask != kindFunc { if ftyp.Kind_&kindMask != kindFunc {
throw("runtime.SetFinalizer: second argument is " + ftyp.string() + ", not a function") throw("runtime.SetFinalizer: second argument is " + toRType(ftyp).string() + ", not a function")
} }
ft := (*functype)(unsafe.Pointer(ftyp)) ft := (*functype)(unsafe.Pointer(ftyp))
if ft.dotdotdot() { if ft.dotdotdot() {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string() + " because dotdotdot") throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string() + " because dotdotdot")
} }
if ft.inCount != 1 { if ft.inCount != 1 {
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string()) throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
} }
fint := ft.in()[0] fint := ft.in()[0]
switch { switch {
@ -446,7 +446,7 @@ func SetFinalizer(obj any, finalizer any) {
// ok - same type // ok - same type
goto okarg goto okarg
case fint.Kind_&kindMask == kindPtr: case fint.Kind_&kindMask == kindPtr:
if (fint.uncommon() == nil || etyp.uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem { if (fint.Uncommon() == nil || etyp.Uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
// ok - not same type, but both pointers, // ok - not same type, but both pointers,
// one or the other is unnamed, and same element type, so assignable. // one or the other is unnamed, and same element type, so assignable.
goto okarg goto okarg
@ -461,7 +461,7 @@ func SetFinalizer(obj any, finalizer any) {
goto okarg goto okarg
} }
} }
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string()) throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
okarg: okarg:
// compute size needed for return parameters // compute size needed for return parameters
nret := uintptr(0) nret := uintptr(0)

View File

@ -1230,7 +1230,7 @@ func tracealloc(p unsafe.Pointer, size uintptr, typ *_type) {
if typ == nil { if typ == nil {
print("tracealloc(", p, ", ", hex(size), ")\n") print("tracealloc(", p, ", ", hex(size), ")\n")
} else { } else {
print("tracealloc(", p, ", ", hex(size), ", ", typ.string(), ")\n") print("tracealloc(", p, ", ", hex(size), ", ", toRType(typ).string(), ")\n")
} }
if gp.m.curg == nil || gp == gp.m.curg { if gp.m.curg == nil || gp == gp.m.curg {
goroutineheader(gp) goroutineheader(gp)

View File

@ -573,7 +573,7 @@ func preprintpanics(p *_panic) {
case string: case string:
throw(text + ": " + r) throw(text + ": " + r)
default: default:
throw(text + ": type " + efaceOf(&r)._type.string()) throw(text + ": type " + toRType(efaceOf(&r)._type).string())
} }
}() }()
for p != nil { for p != nil {

View File

@ -79,7 +79,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]any, initTasks []*ini
syms = make(map[string]any, len(md.ptab)) syms = make(map[string]any, len(md.ptab))
for _, ptab := range md.ptab { for _, ptab := range md.ptab {
symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name) symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ) t := toRType((*_type)(unsafe.Pointer(md.types))).typeOff(ptab.typ) // TODO can this stack of conversions be simpler?
var val any var val any
valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val)) valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
(*valp)[0] = unsafe.Pointer(t) (*valp)[0] = unsafe.Pointer(t)

View File

@ -608,14 +608,14 @@ func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointe
// //
//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff //go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off))) return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
} }
// reflect_resolveTextOff resolves a function pointer offset from a base type. // reflect_resolveTextOff resolves a function pointer offset from a base type.
// //
//go:linkname reflect_resolveTextOff reflect.resolveTextOff //go:linkname reflect_resolveTextOff reflect.resolveTextOff
func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return (*_type)(rtype).textOff(textOff(off)) return toRType((*_type)(rtype)).textOff(textOff(off))
} }
@ -630,7 +630,7 @@ func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Po
// //
//go:linkname reflectlite_resolveTypeOff internal/reflectlite.resolveTypeOff //go:linkname reflectlite_resolveTypeOff internal/reflectlite.resolveTypeOff
func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off))) return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
} }
// reflect_addReflectOff adds a pointer to the reflection offset lookup map. // reflect_addReflectOff adds a pointer to the reflection offset lookup map.

View File

@ -200,7 +200,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
} }
// Pointer-sized types such as maps and channels are currently // Pointer-sized types such as maps and channels are currently
// not supported. // not supported.
panic("compileCallabck: type " + t.string() + " is currently not supported for use in system callbacks") panic("compileCallback: type " + toRType(t).string() + " is currently not supported for use in system callbacks")
} }
// assignReg attempts to assign a single register for an // assignReg attempts to assign a single register for an

View File

@ -15,15 +15,14 @@ type nameOff = abi.NameOff
type typeOff = abi.TypeOff type typeOff = abi.TypeOff
type textOff = abi.TextOff type textOff = abi.TextOff
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize, type _type = abi.Type
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype. // rtype is a wrapper that allows us to define additional methods.
// ../internal/reflectlite/type.go:/^type.rtype. type rtype struct {
type _type struct { *abi.Type // embedding is okay here (unlike reflect) because none of this is public
abi.Type
} }
func (t *_type) string() string { func (t rtype) string() string {
s := t.nameOff(t.Str).name() s := t.nameOff(t.Str).name()
if t.TFlag&abi.TFlagExtraStar != 0 { if t.TFlag&abi.TFlagExtraStar != 0 {
return s[1:] return s[1:]
@ -31,11 +30,11 @@ func (t *_type) string() string {
return s return s
} }
func (t *_type) uncommon() *uncommontype { func (t rtype) uncommon() *uncommontype {
return t.Uncommon() return t.Uncommon()
} }
func (t *_type) name() string { func (t rtype) name() string {
if t.TFlag&abi.TFlagNamed == 0 { if t.TFlag&abi.TFlagNamed == 0 {
return "" return ""
} }
@ -58,16 +57,16 @@ func (t *_type) name() string {
// available. This is not the same as the reflect package's PkgPath // available. This is not the same as the reflect package's PkgPath
// method, in that it returns the package path for struct and interface // method, in that it returns the package path for struct and interface
// types, not just named types. // types, not just named types.
func (t *_type) pkgpath() string { func (t rtype) pkgpath() string {
if u := t.uncommon(); u != nil { if u := t.uncommon(); u != nil {
return t.nameOff(u.PkgPath).name() return t.nameOff(u.PkgPath).name()
} }
switch t.Kind_ & kindMask { switch t.Kind_ & kindMask {
case kindStruct: case kindStruct:
st := (*structtype)(unsafe.Pointer(t)) st := (*structtype)(unsafe.Pointer(t.Type))
return st.pkgPath.name() return st.pkgPath.name()
case kindInterface: case kindInterface:
it := (*interfacetype)(unsafe.Pointer(t)) it := (*interfacetype)(unsafe.Pointer(t.Type))
return it.pkgpath.name() return it.pkgpath.name()
} }
return "" return ""
@ -137,8 +136,8 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
return name{(*byte)(res)} return name{(*byte)(res)}
} }
func (t *_type) nameOff(off nameOff) name { func (t rtype) nameOff(off nameOff) name {
return resolveNameOff(unsafe.Pointer(t), off) return resolveNameOff(unsafe.Pointer(t.Type), off)
} }
func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type { func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
@ -179,17 +178,17 @@ func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
return (*_type)(unsafe.Pointer(res)) return (*_type)(unsafe.Pointer(res))
} }
func (t *_type) typeOff(off typeOff) *_type { func (t rtype) typeOff(off typeOff) *_type {
return resolveTypeOff(unsafe.Pointer(t), off) return resolveTypeOff(unsafe.Pointer(t.Type), off)
} }
func (t *_type) textOff(off textOff) unsafe.Pointer { func (t rtype) textOff(off textOff) unsafe.Pointer {
if off == -1 { if off == -1 {
// -1 is the sentinel value for unreachable code. // -1 is the sentinel value for unreachable code.
// See cmd/link/internal/ld/data.go:relocsym. // See cmd/link/internal/ld/data.go:relocsym.
return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod)) return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod))
} }
base := uintptr(unsafe.Pointer(t)) base := uintptr(unsafe.Pointer(t.Type))
var md *moduledata var md *moduledata
for next := &firstmoduledata; next != nil; next = next.next { for next := &firstmoduledata; next != nil; next = next.next {
if base >= next.types && base < next.etypes { if base >= next.types && base < next.etypes {
@ -440,8 +439,8 @@ type _typePair struct {
t2 *_type t2 *_type
} }
func toType(t *abi.Type) *_type { func toRType(t *abi.Type) rtype {
return (*_type)(unsafe.Pointer(t)) return rtype{t}
} }
// typesEqual reports whether two types are equal. // typesEqual reports whether two types are equal.
@ -474,17 +473,18 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
if kind != v.Kind_&kindMask { if kind != v.Kind_&kindMask {
return false return false
} }
if t.string() != v.string() { rt, rv := toRType(t), toRType(v)
if rt.string() != rv.string() {
return false return false
} }
ut := t.uncommon() ut := t.Uncommon()
uv := v.uncommon() uv := v.Uncommon()
if ut != nil || uv != nil { if ut != nil || uv != nil {
if ut == nil || uv == nil { if ut == nil || uv == nil {
return false return false
} }
pkgpatht := t.nameOff(ut.PkgPath).name() pkgpatht := rt.nameOff(ut.PkgPath).name()
pkgpathv := v.nameOff(uv.PkgPath).name() pkgpathv := rv.nameOff(uv.PkgPath).name()
if pkgpatht != pkgpathv { if pkgpatht != pkgpathv {
return false return false
} }
@ -498,11 +498,11 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
case kindArray: case kindArray:
at := (*arraytype)(unsafe.Pointer(t)) at := (*arraytype)(unsafe.Pointer(t))
av := (*arraytype)(unsafe.Pointer(v)) av := (*arraytype)(unsafe.Pointer(v))
return typesEqual(toType(at.Elem), toType(av.Elem), seen) && at.Len == av.Len return typesEqual(at.Elem, av.Elem, seen) && at.Len == av.Len
case kindChan: case kindChan:
ct := (*chantype)(unsafe.Pointer(t)) ct := (*chantype)(unsafe.Pointer(t))
cv := (*chantype)(unsafe.Pointer(v)) cv := (*chantype)(unsafe.Pointer(v))
return ct.Dir == cv.Dir && typesEqual(toType(ct.Elem), toType(cv.Elem), seen) return ct.Dir == cv.Dir && typesEqual(ct.Elem, cv.Elem, seen)
case kindFunc: case kindFunc:
ft := (*functype)(unsafe.Pointer(t)) ft := (*functype)(unsafe.Pointer(t))
fv := (*functype)(unsafe.Pointer(v)) fv := (*functype)(unsafe.Pointer(v))