diff --git a/compiler/interface.go b/compiler/interface.go index 5eb939d1..a0667be1 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -112,10 +112,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { typeFieldTypes = append(typeFieldTypes, 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, "pkglen", types.Typ[types.Uintptr]), types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]), - types.NewVar(token.NoPos, nil, "len", types.Typ[types.Uintptr]), - types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], 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: typeFieldTypes = append(typeFieldTypes, @@ -183,7 +181,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { pkgpathName = "reflect/types.type.pkgpath:" + pkgpath } - pkgpathInitializer := c.ctx.ConstString(pkgpath, false) + pkgpathInitializer := c.ctx.ConstString(pkgpath+"\x00", false) pkgpathGlobal := llvm.AddGlobal(c.mod, pkgpathInitializer.Type(), pkgpathName) pkgpathGlobal.SetInitializer(pkgpathInitializer) pkgpathGlobal.SetAlignment(1) @@ -196,12 +194,10 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { }) typeFields = []llvm.Value{ - c.getTypeCode(types.NewPointer(typ)), // ptrTo - c.getTypeCode(typ.Underlying()), // underlying - llvm.ConstInt(c.uintptrType, uint64(len(pkgpath)), false), // pkgpath length - pkgpathPtr, // pkgpath pointer - llvm.ConstInt(c.uintptrType, uint64(len(name)), false), // length - c.ctx.ConstString(name, false), // name + c.getTypeCode(types.NewPointer(typ)), // ptrTo + c.getTypeCode(typ.Underlying()), // underlying + pkgpathPtr, // pkgpath pointer + c.ctx.ConstString(name+"\x00", false), // name } metabyte |= 1 << 5 // "named" flag case *types.Chan: diff --git a/compiler/testdata/interface.ll b/compiler/testdata/interface.ll index aa816a03..cb04c11c 100644 --- a/compiler/testdata/interface.ll +++ b/compiler/testdata/interface.ll @@ -9,8 +9,8 @@ target triple = "wasm32-unknown-wasi" @"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 } { i8 21, ptr @"reflect/types.type:basic:int" }, align 4 @"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, ptr } { i8 21, ptr @"reflect/types.type:named:error" }, align 4 -@"reflect/types.type:named:error" = linkonce_odr constant { i8, ptr, ptr, i32, ptr, i32, [5 x i8] } { i8 52, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr @"reflect/types.type.pkgpath.empty", i32 5, [5 x i8] c"error" }, align 4 -@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [0 x i8] zeroinitializer, align 1 +@"reflect/types.type:named:error" = linkonce_odr constant { i8, ptr, ptr, ptr, [6 x i8] } { i8 52, 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 } { i8 21, 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 } { i8 21, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4 diff --git a/src/reflect/type.go b/src/reflect/type.go index dd8c9a79..44879dae 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -50,9 +50,7 @@ // meta uint8 // ptrTo *typeStruct // elem *typeStruct // underlying type -// plen uintptr // length of pkgpath // pkg *byte // pkgpath -// nlem uintptr // length of name // name [1]byte // actual name; length nlem // // The type struct is essentially a union of all the above types. Which it is, @@ -430,9 +428,7 @@ type namedType struct { rawType ptrTo *rawType elem *rawType - plen uintptr pkg *byte - nlen uintptr name [1]byte } @@ -896,10 +892,25 @@ func (t *rawType) NumMethod() int { panic("unimplemented: (reflect.Type).NumMethod()") } +// Read and return a null terminated string starting from data. +func readStringZ(data unsafe.Pointer) string { + start := data + var len uintptr + for *(*byte)(data) != 0 { + len++ + data = unsafe.Add(data, 1) // C: data++ + } + + return *(*string)(unsafe.Pointer(&stringHeader{ + data: start, + len: len, + })) +} + func (t *rawType) Name() string { if t.isNamed() { ntype := (*namedType)(unsafe.Pointer(t)) - return unsafe.String(&ntype.name[0], ntype.nlen) + return readStringZ(unsafe.Pointer(&ntype.name[0])) } return t.Kind().String() @@ -924,7 +935,7 @@ func (t rawType) MethodByName(name string) (Method, bool) { func (t *rawType) PkgPath() string { if t.isNamed() { ntype := (*namedType)(unsafe.Pointer(t)) - return unsafe.String(ntype.pkg, ntype.plen) + return readStringZ(unsafe.Pointer(ntype.pkg)) } return ""