compiler,reflect: adjust struct layout for type info

Этот коммит содержится в:
Damian Gryski 2023-03-13 14:31:52 -07:00 коммит произвёл Ron Evans
родитель 0d65b4dd26
коммит f2cc98caa5
4 изменённых файлов: 53 добавлений и 44 удалений

Просмотреть файл

@ -135,40 +135,43 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
) )
case *types.Named: case *types.Named:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
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, "underlying", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
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, "name", types.NewArray(types.Typ[types.Int8], 1+int64(len(typ.Obj().Name())))), types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], 1+int64(len(typ.Obj().Name())))),
) )
case *types.Chan, *types.Slice: case *types.Chan, *types.Slice:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
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, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
) )
case *types.Pointer: case *types.Pointer:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
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, "elementType", types.Typ[types.UnsafePointer]),
) )
case *types.Array: case *types.Array:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
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, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]), types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
) )
case *types.Map: case *types.Map:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
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, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
types.NewVar(token.NoPos, nil, "keyType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "keyType", types.Typ[types.UnsafePointer]),
) )
case *types.Struct: case *types.Struct:
typeFieldTypes = append(typeFieldTypes, typeFieldTypes = append(typeFieldTypes,
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
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, "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()))),
) )
case *types.Interface: case *types.Interface:
@ -207,39 +210,43 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
} }
pkgPathPtr := c.pkgPathPtr(pkgpath) pkgPathPtr := c.pkgPathPtr(pkgpath)
typeFields = []llvm.Value{ typeFields = []llvm.Value{
llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods
c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Underlying()), // underlying c.getTypeCode(typ.Underlying()), // underlying
llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods pkgPathPtr, // pkgpath pointer
pkgPathPtr, // pkgpath pointer c.ctx.ConstString(name+"\x00", false), // name
c.ctx.ConstString(name+"\x00", false), // name
} }
metabyte |= 1 << 5 // "named" flag metabyte |= 1 << 5 // "named" flag
case *types.Chan: case *types.Chan:
typeFields = []llvm.Value{ typeFields = []llvm.Value{
c.getTypeCode(types.NewPointer(typ)), // ptrTo llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
c.getTypeCode(typ.Elem()), // elementType c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Elem()), // elementType
} }
case *types.Slice: case *types.Slice:
typeFields = []llvm.Value{ typeFields = []llvm.Value{
c.getTypeCode(types.NewPointer(typ)), // ptrTo llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
c.getTypeCode(typ.Elem()), // elementType c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Elem()), // elementType
} }
case *types.Pointer: case *types.Pointer:
typeFields = []llvm.Value{ typeFields = []llvm.Value{
c.getTypeCode(typ.Elem()),
llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods
c.getTypeCode(typ.Elem()),
} }
case *types.Array: case *types.Array:
typeFields = []llvm.Value{ typeFields = []llvm.Value{
llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Elem()), // elementType c.getTypeCode(typ.Elem()), // elementType
llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length
} }
case *types.Map: case *types.Map:
typeFields = []llvm.Value{ typeFields = []llvm.Value{
c.getTypeCode(types.NewPointer(typ)), // ptrTo llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
c.getTypeCode(typ.Elem()), // elem c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Key()), // key c.getTypeCode(typ.Elem()), // elem
c.getTypeCode(typ.Key()), // key
} }
case *types.Struct: case *types.Struct:
var pkgpath string var pkgpath string
@ -251,10 +258,10 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
pkgPathPtr := c.pkgPathPtr(pkgpath) pkgPathPtr := c.pkgPathPtr(pkgpath)
typeFields = []llvm.Value{ typeFields = []llvm.Value{
llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields 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.Int16Type(), uint64(typ.NumFields()), false), // numFields
} }
structFieldType := c.getLLVMRuntimeType("structField") structFieldType := c.getLLVMRuntimeType("structField")
var fields []llvm.Value var fields []llvm.Value

2
compiler/testdata/gc.ll предоставленный
Просмотреть файл

@ -22,7 +22,7 @@ target triple = "wasm32-unknown-wasi"
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " } @"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" } @"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 16, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4 @"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 16, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:basic:complex128", i16 0 }, align 4 @"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:basic:complex128" }, align 4
declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0 declare noalias nonnull ptr @runtime.alloc(i32, ptr, ptr) #0

10
compiler/testdata/interface.ll предоставленный
Просмотреть файл

@ -7,13 +7,13 @@ target triple = "wasm32-unknown-wasi"
%runtime._string = type { ptr, i32 } %runtime._string = type { ptr, i32 }
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 2, ptr @"reflect/types.type:pointer:basic:int" }, align 4 @"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 2, ptr @"reflect/types.type:pointer:basic:int" }, align 4
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:basic:int", i16 0 }, align 4 @"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:basic:int" }, align 4
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:named:error", i16 0 }, align 4 @"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:named:error" }, align 4
@"reflect/types.type:named:error" = linkonce_odr constant { i8, ptr, ptr, i16, ptr, [6 x i8] } { i8 52, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i16 1, ptr @"reflect/types.type.pkgpath.empty", [6 x i8] c"error\00" }, align 4 @"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [6 x i8] } { i8 52, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [6 x i8] c"error\00" }, align 4
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1 @"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4 @"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i16 0 }, align 4 @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}", i16 0 }, align 4 @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }, align 4 @"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }, align 4
@"reflect/types.typeid:basic:int" = external constant i8 @"reflect/types.typeid:basic:int" = external constant i8

Просмотреть файл

@ -14,34 +14,33 @@
// - basic types (Bool..UnsafePointer): // - basic types (Bool..UnsafePointer):
// meta uint8 // actually: kind + flags // meta uint8 // actually: kind + flags
// ptrTo *typeStruct // ptrTo *typeStruct
// - named types (see elemType):
// meta uint8
// ptrTo *typeStruct
// underlying *typeStruct // the underlying, non-named type
// - channels and slices (see elemType): // - channels and slices (see elemType):
// meta uint8 // meta uint8
// nmethods uint16 (0)
// ptrTo *typeStruct // ptrTo *typeStruct
// elementType *typeStruct // the type that you get with .Elem() // elementType *typeStruct // the type that you get with .Elem()
// - pointer types (see ptrType, this doesn't include chan, map, etc): // - pointer types (see ptrType, this doesn't include chan, map, etc):
// meta uint8 // meta uint8
// elementType *typeStruct
// nmethods uint16 // nmethods uint16
// elementType *typeStruct
// - array types (see arrayType) // - array types (see arrayType)
// meta uint8 // meta uint8
// nmethods uint16 (0)
// ptrTo *typeStruct // ptrTo *typeStruct
// elem *typeStruct // element type of the array // elem *typeStruct // element type of the array
// arrayLen uintptr // length of the array (this is part of the type) // arrayLen uintptr // length of the array (this is part of the type)
// - map types (this is still missing the key and element types) // - map types (this is still missing the key and element types)
// meta uint8 // meta uint8
// nmethods uint16 (0)
// ptrTo *typeStruct // ptrTo *typeStruct
// elem *typeStruct // elem *typeStruct
// key *typeStruct // key *typeStruct
// - struct types (see structType): // - struct types (see structType):
// meta uint8 // meta uint8
// numField uint16
// nmethods uint16 // nmethods uint16
// ptrTo *typeStruct // ptrTo *typeStruct
// pkgpath *byte // pkgpath *byte // package path; null terminated
// numField uint16
// fields [...]structField // the remaining fields are all of type structField // fields [...]structField // the remaining fields are all of type structField
// - interface types (this is missing the interface methods): // - interface types (this is missing the interface methods):
// meta uint8 // meta uint8
@ -51,11 +50,11 @@
// ptrTo *typeStruct // ptrTo *typeStruct
// - named types // - named types
// meta uint8 // meta uint8
// nmethods uint16 // number of methods
// ptrTo *typeStruct // ptrTo *typeStruct
// elem *typeStruct // underlying type // elem *typeStruct // underlying type
// nmethods uint16 // number of methods // pkgpath *byte // pkgpath; null terminated
// pkg *byte // pkgpath // name [1]byte // actual name; null terminated
// name [1]byte // actual name; length nlem
// //
// The type struct is essentially a union of all the above types. Which it is, // The type struct is essentially a union of all the above types. Which it is,
// can be determined by looking at the meta byte. // can be determined by looking at the meta byte.
@ -406,35 +405,38 @@ type rawType struct {
// pointer because it doesn't have ptrTo). // pointer because it doesn't have ptrTo).
type elemType struct { type elemType struct {
rawType rawType
ptrTo *rawType numMethod uint16
elem *rawType ptrTo *rawType
elem *rawType
} }
type ptrType struct { type ptrType struct {
rawType rawType
elem *rawType
numMethod uint16 numMethod uint16
elem *rawType
} }
type arrayType struct { type arrayType struct {
rawType rawType
ptrTo *rawType numMethod uint16
elem *rawType ptrTo *rawType
arrayLen uintptr elem *rawType
arrayLen uintptr
} }
type mapType struct { type mapType struct {
rawType rawType
ptrTo *rawType numMethod uint16
elem *rawType ptrTo *rawType
key *rawType elem *rawType
key *rawType
} }
type namedType struct { type namedType struct {
rawType rawType
numMethod uint16
ptrTo *rawType ptrTo *rawType
elem *rawType elem *rawType
numMethod uint16
pkg *byte pkg *byte
name [1]byte name [1]byte
} }
@ -448,10 +450,10 @@ type namedType struct {
// checker. // checker.
type structType struct { type structType struct {
rawType rawType
numField uint16
numMethod uint16 numMethod uint16
ptrTo *rawType ptrTo *rawType
pkgpath *byte pkgpath *byte
numField uint16
fields [1]structField // the remaining fields are all of type structField fields [1]structField // the remaining fields are all of type structField
} }