From f2cc98caa57846ecdbcc35f61d13fa6a1d6ea2e9 Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Mon, 13 Mar 2023 14:31:52 -0700 Subject: [PATCH] compiler,reflect: adjust struct layout for type info --- compiler/interface.go | 41 ++++++++++++++++++------------- compiler/testdata/gc.ll | 2 +- compiler/testdata/interface.ll | 10 ++++---- src/reflect/type.go | 44 ++++++++++++++++++---------------- 4 files changed, 53 insertions(+), 44 deletions(-) diff --git a/compiler/interface.go b/compiler/interface.go index 128844c0..bc2cbf33 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -135,40 +135,43 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { ) case *types.Named: 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, "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, "name", types.NewArray(types.Typ[types.Int8], 1+int64(len(typ.Obj().Name())))), ) case *types.Chan, *types.Slice: 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, "elementType", types.Typ[types.UnsafePointer]), ) case *types.Pointer: 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, "elementType", types.Typ[types.UnsafePointer]), ) case *types.Array: 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, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]), ) case *types.Map: 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, "elementType", types.Typ[types.UnsafePointer]), types.NewVar(token.NoPos, nil, "keyType", types.Typ[types.UnsafePointer]), ) case *types.Struct: 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, "ptrTo", 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()))), ) case *types.Interface: @@ -207,39 +210,43 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { } pkgPathPtr := c.pkgPathPtr(pkgpath) typeFields = []llvm.Value{ + llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(typ.Underlying()), // underlying - llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods - pkgPathPtr, // pkgpath pointer - c.ctx.ConstString(name+"\x00", false), // name + pkgPathPtr, // pkgpath pointer + c.ctx.ConstString(name+"\x00", false), // name } metabyte |= 1 << 5 // "named" flag case *types.Chan: typeFields = []llvm.Value{ - c.getTypeCode(types.NewPointer(typ)), // ptrTo - c.getTypeCode(typ.Elem()), // elementType + llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods + c.getTypeCode(types.NewPointer(typ)), // ptrTo + c.getTypeCode(typ.Elem()), // elementType } case *types.Slice: typeFields = []llvm.Value{ - c.getTypeCode(types.NewPointer(typ)), // ptrTo - c.getTypeCode(typ.Elem()), // elementType + llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods + c.getTypeCode(types.NewPointer(typ)), // ptrTo + c.getTypeCode(typ.Elem()), // elementType } case *types.Pointer: typeFields = []llvm.Value{ - c.getTypeCode(typ.Elem()), llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods + c.getTypeCode(typ.Elem()), } case *types.Array: typeFields = []llvm.Value{ + llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods c.getTypeCode(types.NewPointer(typ)), // ptrTo c.getTypeCode(typ.Elem()), // elementType llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false), // length } case *types.Map: typeFields = []llvm.Value{ - c.getTypeCode(types.NewPointer(typ)), // ptrTo - c.getTypeCode(typ.Elem()), // elem - c.getTypeCode(typ.Key()), // key + llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods + c.getTypeCode(types.NewPointer(typ)), // ptrTo + c.getTypeCode(typ.Elem()), // elem + c.getTypeCode(typ.Key()), // key } case *types.Struct: var pkgpath string @@ -251,10 +258,10 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { pkgPathPtr := c.pkgPathPtr(pkgpath) typeFields = []llvm.Value{ - llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields - llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods - c.getTypeCode(types.NewPointer(typ)), // ptrTo + llvm.ConstInt(c.ctx.Int16Type(), uint64(ms.Len()), false), // numMethods + c.getTypeCode(types.NewPointer(typ)), // ptrTo pkgPathPtr, + llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields } structFieldType := c.getLLVMRuntimeType("structField") var fields []llvm.Value diff --git a/compiler/testdata/gc.ll b/compiler/testdata/gc.ll index 492f9d57..160f8690 100644 --- a/compiler/testdata/gc.ll +++ b/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-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: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 diff --git a/compiler/testdata/interface.ll b/compiler/testdata/interface.ll index a619b62f..4322b554 100644 --- a/compiler/testdata/interface.ll +++ b/compiler/testdata/interface.ll @@ -7,13 +7,13 @@ target triple = "wasm32-unknown-wasi" %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: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:named:error" = linkonce_odr constant { i8, ptr, i16 } { i8 21, ptr @"reflect/types.type:named:error", i16 0 }, 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: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, i16, ptr } { i8 21, i16 0, ptr @"reflect/types.type:named:error" }, 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: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:{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:{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, 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.typeid:basic:int" = external constant i8 diff --git a/src/reflect/type.go b/src/reflect/type.go index db09fb43..79ca6e5f 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -14,34 +14,33 @@ // - basic types (Bool..UnsafePointer): // meta uint8 // actually: kind + flags // ptrTo *typeStruct -// - named types (see elemType): -// meta uint8 -// ptrTo *typeStruct -// underlying *typeStruct // the underlying, non-named type // - channels and slices (see elemType): // meta uint8 +// nmethods uint16 (0) // ptrTo *typeStruct // elementType *typeStruct // the type that you get with .Elem() // - pointer types (see ptrType, this doesn't include chan, map, etc): // meta uint8 -// elementType *typeStruct // nmethods uint16 +// elementType *typeStruct // - array types (see arrayType) // meta uint8 +// nmethods uint16 (0) // ptrTo *typeStruct // elem *typeStruct // element type of the array // arrayLen uintptr // length of the array (this is part of the type) // - map types (this is still missing the key and element types) // meta uint8 +// nmethods uint16 (0) // ptrTo *typeStruct // elem *typeStruct // key *typeStruct // - struct types (see structType): // meta uint8 -// numField uint16 // nmethods uint16 // ptrTo *typeStruct -// pkgpath *byte +// pkgpath *byte // package path; null terminated +// numField uint16 // fields [...]structField // the remaining fields are all of type structField // - interface types (this is missing the interface methods): // meta uint8 @@ -51,11 +50,11 @@ // ptrTo *typeStruct // - named types // meta uint8 +// nmethods uint16 // number of methods // ptrTo *typeStruct // elem *typeStruct // underlying type -// nmethods uint16 // number of methods -// pkg *byte // pkgpath -// name [1]byte // actual name; length nlem +// pkgpath *byte // pkgpath; null terminated +// name [1]byte // actual name; null terminated // // The type struct is essentially a union of all the above types. Which it is, // can be determined by looking at the meta byte. @@ -406,35 +405,38 @@ type rawType struct { // pointer because it doesn't have ptrTo). type elemType struct { rawType - ptrTo *rawType - elem *rawType + numMethod uint16 + ptrTo *rawType + elem *rawType } type ptrType struct { rawType - elem *rawType numMethod uint16 + elem *rawType } type arrayType struct { rawType - ptrTo *rawType - elem *rawType - arrayLen uintptr + numMethod uint16 + ptrTo *rawType + elem *rawType + arrayLen uintptr } type mapType struct { rawType - ptrTo *rawType - elem *rawType - key *rawType + numMethod uint16 + ptrTo *rawType + elem *rawType + key *rawType } type namedType struct { rawType + numMethod uint16 ptrTo *rawType elem *rawType - numMethod uint16 pkg *byte name [1]byte } @@ -448,10 +450,10 @@ type namedType struct { // checker. type structType struct { rawType - numField uint16 numMethod uint16 ptrTo *rawType pkgpath *byte + numField uint16 fields [1]structField // the remaining fields are all of type structField }