1
0
mirror of https://github.com/golang/go synced 2024-11-17 00:34:48 -07:00

cmd/compile: generate itabs using rttype mechanism

Change-Id: I9a85704c57e978c8c6303b21da3e4627d3446f3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/549455
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Keith Randall 2023-12-12 21:03:09 -08:00
parent e0ee5b1afa
commit 977803e796
2 changed files with 37 additions and 10 deletions

View File

@ -1331,20 +1331,25 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
// _ [4]byte
// fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
// }
o := objw.SymPtr(lsym, 0, writeType(iface), 0)
o = objw.SymPtr(lsym, o, writeType(typ), 0)
o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash
o += 4 // skip unused field
c := rttype.NewCursor(lsym, 0, rttype.ITab)
c.Field("Inter").WritePtr(writeType(iface))
c.Field("Type").WritePtr(writeType(typ))
c.Field("Hash").WriteUint32(types.TypeHash(typ)) // copy of type hash
var delta int64
c = c.Field("Fun")
if !completeItab {
// If typ doesn't implement iface, make method entries be zero.
o = objw.Uintptr(lsym, o, 0)
entries = entries[:0]
}
for _, fn := range entries {
o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
c.Elem(0).WriteUintptr(0)
} else {
var a rttype.ArrayCursor
a, delta = c.ModifyArray(len(entries))
for i, fn := range entries {
a.Elem(i).WritePtrWeak(fn) // method pointer for each method
}
}
// Nothing writes static itabs, so they are read only.
objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
objw.Global(lsym, int32(rttype.ITab.Size()+delta), int16(obj.DUPOK|obj.RODATA))
lsym.Set(obj.AttrContentAddressable, true)
}

View File

@ -42,6 +42,9 @@ var UncommonType *types.Type
var InterfaceSwitch *types.Type
var TypeAssert *types.Type
// Interface tables (itabs)
var ITab *types.Type
func Init() {
// Note: this has to be called explicitly instead of being
// an init function so it runs after the types package has
@ -64,6 +67,8 @@ func Init() {
InterfaceSwitch = fromReflect(reflect.TypeOf(abi.InterfaceSwitch{}))
TypeAssert = fromReflect(reflect.TypeOf(abi.TypeAssert{}))
ITab = fromReflect(reflect.TypeOf(abi.ITab{}))
// Make sure abi functions are correct. These functions are used
// by the linker which doesn't have the ability to do type layout,
// so we check the functions it uses here.
@ -154,6 +159,12 @@ func (c Cursor) WritePtr(target *obj.LSym) {
objw.SymPtr(c.lsym, int(c.offset), target, 0)
}
}
func (c Cursor) WritePtrWeak(target *obj.LSym) {
if c.typ.Kind() != types.TUINTPTR {
base.Fatalf("can't write ptr, it has kind %s", c.typ.Kind())
}
objw.SymPtrWeak(c.lsym, int(c.offset), target, 0)
}
func (c Cursor) WriteUintptr(val uint64) {
if c.typ.Kind() != types.TUINTPTR {
base.Fatalf("can't write uintptr, it has kind %s", c.typ.Kind())
@ -250,6 +261,17 @@ func (c Cursor) Field(name string) Cursor {
return Cursor{}
}
func (c Cursor) Elem(i int64) Cursor {
if c.typ.Kind() != types.TARRAY {
base.Fatalf("can't call Elem on non-array %v", c.typ)
}
if i < 0 || i >= c.typ.NumElem() {
base.Fatalf("element access out of bounds [%d] in [0:%d]", i, c.typ.NumElem())
}
elem := c.typ.Elem()
return Cursor{lsym: c.lsym, offset: c.offset + i*elem.Size(), typ: elem}
}
type ArrayCursor struct {
c Cursor // cursor pointing at first element
n int // number of elements