add struct size and field offsets to reflect data
Этот коммит содержится в:
родитель
36bd66a858
коммит
4c0fbbfc7f
3 изменённых файлов: 17 добавлений и 26 удалений
|
@ -205,6 +205,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||||
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
||||||
|
types.NewVar(token.NoPos, nil, "size", types.Typ[types.Uint32]),
|
||||||
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
||||||
)
|
)
|
||||||
|
@ -306,16 +307,21 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||||
}
|
}
|
||||||
pkgPathPtr := c.pkgPathPtr(pkgpath)
|
pkgPathPtr := c.pkgPathPtr(pkgpath)
|
||||||
|
|
||||||
|
llvmStructType := c.getLLVMType(typ)
|
||||||
|
size := c.targetData.TypeStoreSize(llvmStructType)
|
||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods
|
llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods
|
||||||
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
||||||
pkgPathPtr,
|
pkgPathPtr,
|
||||||
|
llvm.ConstInt(c.ctx.Int32Type(), uint64(size), false), // size
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields
|
llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields
|
||||||
}
|
}
|
||||||
structFieldType := c.getLLVMRuntimeType("structField")
|
structFieldType := c.getLLVMRuntimeType("structField")
|
||||||
|
|
||||||
var fields []llvm.Value
|
var fields []llvm.Value
|
||||||
for i := 0; i < typ.NumFields(); i++ {
|
for i := 0; i < typ.NumFields(); i++ {
|
||||||
field := typ.Field(i)
|
field := typ.Field(i)
|
||||||
|
offset := c.targetData.ElementOffset(llvmStructType, i)
|
||||||
var flags uint8
|
var flags uint8
|
||||||
if field.Anonymous() {
|
if field.Anonymous() {
|
||||||
flags |= structFieldFlagAnonymous
|
flags |= structFieldFlagAnonymous
|
||||||
|
@ -346,6 +352,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||||
fieldType := c.getTypeCode(field.Type())
|
fieldType := c.getTypeCode(field.Type())
|
||||||
fields = append(fields, llvm.ConstNamedStruct(structFieldType, []llvm.Value{
|
fields = append(fields, llvm.ConstNamedStruct(structFieldType, []llvm.Value{
|
||||||
fieldType,
|
fieldType,
|
||||||
|
llvm.ConstInt(c.ctx.Int32Type(), uint64(offset), false),
|
||||||
llvm.ConstGEP(dataGlobal.GlobalValueType(), dataGlobal, []llvm.Value{
|
llvm.ConstGEP(dataGlobal.GlobalValueType(), dataGlobal, []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
// meta uint8
|
// meta uint8
|
||||||
// nmethods uint16
|
// nmethods uint16
|
||||||
// ptrTo *typeStruct
|
// ptrTo *typeStruct
|
||||||
|
// size uint32
|
||||||
// pkgpath *byte // package path; null terminated
|
// pkgpath *byte // package path; null terminated
|
||||||
// numField uint16
|
// numField uint16
|
||||||
// fields [...]structField // the remaining fields are all of type structField
|
// fields [...]structField // the remaining fields are all of type structField
|
||||||
|
@ -455,12 +456,14 @@ type structType struct {
|
||||||
numMethod uint16
|
numMethod uint16
|
||||||
ptrTo *rawType
|
ptrTo *rawType
|
||||||
pkgpath *byte
|
pkgpath *byte
|
||||||
|
size uint32
|
||||||
numField uint16
|
numField uint16
|
||||||
fields [1]structField // the remaining fields are all of type structField
|
fields [1]structField // the remaining fields are all of type structField
|
||||||
}
|
}
|
||||||
|
|
||||||
type structField struct {
|
type structField struct {
|
||||||
fieldType *rawType
|
fieldType *rawType
|
||||||
|
offset uint32
|
||||||
data unsafe.Pointer // various bits of information, packed in a byte array
|
data unsafe.Pointer // various bits of information, packed in a byte array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,18 +672,8 @@ func (t *rawType) rawField(n int) rawStructField {
|
||||||
// This offset could have been stored directly in the array (to make the
|
// This offset could have been stored directly in the array (to make the
|
||||||
// lookup faster), but by calculating it on-the-fly a bit of storage can be
|
// lookup faster), but by calculating it on-the-fly a bit of storage can be
|
||||||
// saved.
|
// saved.
|
||||||
field := &descriptor.fields[0]
|
field := (*structField)(unsafe.Add(unsafe.Pointer(&descriptor.fields[0]), uintptr(n)*unsafe.Sizeof(structField{})))
|
||||||
var offset uintptr = 0
|
offset := uintptr(field.offset)
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
offset += field.fieldType.Size()
|
|
||||||
|
|
||||||
// Increment pointer to the next field.
|
|
||||||
field = (*structField)(unsafe.Add(unsafe.Pointer(field), unsafe.Sizeof(structField{})))
|
|
||||||
|
|
||||||
// Align the offset for the next field.
|
|
||||||
offset = align(offset, uintptr(field.fieldType.Align()))
|
|
||||||
}
|
|
||||||
|
|
||||||
data := field.data
|
data := field.data
|
||||||
|
|
||||||
// Read some flags of this field, like whether the field is an embedded
|
// Read some flags of this field, like whether the field is an embedded
|
||||||
|
@ -726,7 +719,6 @@ func (t *rawType) rawFieldByName(n string) (rawStructField, []int, bool) {
|
||||||
// Also calculate field offset.
|
// Also calculate field offset.
|
||||||
|
|
||||||
descriptor := (*structType)(unsafe.Pointer(ll.t.underlying()))
|
descriptor := (*structType)(unsafe.Pointer(ll.t.underlying()))
|
||||||
var offset uintptr
|
|
||||||
field := &descriptor.fields[0]
|
field := &descriptor.fields[0]
|
||||||
|
|
||||||
for i := uint16(0); i < descriptor.numField; i++ {
|
for i := uint16(0); i < descriptor.numField; i++ {
|
||||||
|
@ -740,6 +732,7 @@ func (t *rawType) rawFieldByName(n string) (rawStructField, []int, bool) {
|
||||||
name := readStringZ(data)
|
name := readStringZ(data)
|
||||||
data = unsafe.Add(data, len(name))
|
data = unsafe.Add(data, len(name))
|
||||||
if name == n {
|
if name == n {
|
||||||
|
offset := uintptr(field.offset)
|
||||||
found = append(found, result{
|
found = append(found, result{
|
||||||
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
|
rawStructFieldFromPointer(descriptor, field.fieldType, data, flagsByte, name, offset),
|
||||||
append(ll.index, int(i)),
|
append(ll.index, int(i)),
|
||||||
|
@ -759,16 +752,10 @@ func (t *rawType) rawFieldByName(n string) (rawStructField, []int, bool) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += field.fieldType.Size()
|
|
||||||
|
|
||||||
// update offset/field pointer if there *is* a next field
|
// update offset/field pointer if there *is* a next field
|
||||||
if i < descriptor.numField-1 {
|
if i < descriptor.numField-1 {
|
||||||
|
|
||||||
// Increment pointer to the next field.
|
// Increment pointer to the next field.
|
||||||
field = (*structField)(unsafe.Add(unsafe.Pointer(field), unsafe.Sizeof(structField{})))
|
field = (*structField)(unsafe.Add(unsafe.Pointer(field), unsafe.Sizeof(structField{})))
|
||||||
|
|
||||||
// Align the offset for the next field.
|
|
||||||
offset = align(offset, uintptr(field.fieldType.Align()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -860,12 +847,8 @@ func (t *rawType) Size() uintptr {
|
||||||
case Array:
|
case Array:
|
||||||
return t.elem().Size() * uintptr(t.Len())
|
return t.elem().Size() * uintptr(t.Len())
|
||||||
case Struct:
|
case Struct:
|
||||||
numField := t.NumField()
|
u := t.underlying()
|
||||||
if numField == 0 {
|
return uintptr((*structType)(unsafe.Pointer(u)).size)
|
||||||
return 0
|
|
||||||
}
|
|
||||||
lastField := t.rawField(numField - 1)
|
|
||||||
return align(lastField.Offset+lastField.Type.Size(), uintptr(t.Align()))
|
|
||||||
default:
|
default:
|
||||||
panic("unimplemented: size of type")
|
panic("unimplemented: size of type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ func interfaceTypeAssert(ok bool) {
|
||||||
|
|
||||||
type structField struct {
|
type structField struct {
|
||||||
typecode unsafe.Pointer // type of this struct field
|
typecode unsafe.Pointer // type of this struct field
|
||||||
|
offset uint32
|
||||||
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
|
data *uint8 // pointer to byte array containing name, tag, and 'embedded' flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче