diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/compiler.go | 2 | ||||
-rw-r--r-- | compiler/interface.go | 34 | ||||
-rw-r--r-- | compiler/testdata/interface.ll | 17 |
3 files changed, 29 insertions, 24 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go index 0afa20daf..c6e577fd6 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -23,7 +23,7 @@ import ( // Version of the compiler pacakge. Must be incremented each time the compiler // package changes in a way that affects the generated LLVM module. // This version is independent of the TinyGo version number. -const Version = 8 // last change: don't use runtime.typecodeID in func lowering +const Version = 9 // last change: implement reflect.New() func init() { llvm.InitializeAllTargets() diff --git a/compiler/interface.go b/compiler/interface.go index 8b3988a12..eda7e3653 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -46,6 +46,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { var references llvm.Value var length int64 var methodSet llvm.Value + var ptrTo llvm.Value switch typ := typ.(type) { case *types.Named: references = c.getTypeCode(typ.Underlying()) @@ -69,22 +70,25 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { if _, ok := typ.Underlying().(*types.Interface); !ok { methodSet = c.getTypeMethodSet(typ) } - if !references.IsNil() || length != 0 || !methodSet.IsNil() { - // Set the 'references' field of the runtime.typecodeID struct. - globalValue := llvm.ConstNull(global.Type().ElementType()) - if !references.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0}) - } - if length != 0 { - lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false) - globalValue = llvm.ConstInsertValue(globalValue, lengthValue, []uint32{1}) - } - if !methodSet.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, methodSet, []uint32{2}) - } - global.SetInitializer(globalValue) - global.SetLinkage(llvm.LinkOnceODRLinkage) + if _, ok := typ.Underlying().(*types.Pointer); !ok { + ptrTo = c.getTypeCode(types.NewPointer(typ)) + } + globalValue := llvm.ConstNull(global.Type().ElementType()) + if !references.IsNil() { + globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0}) + } + if length != 0 { + lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false) + globalValue = llvm.ConstInsertValue(globalValue, lengthValue, []uint32{1}) + } + if !methodSet.IsNil() { + globalValue = llvm.ConstInsertValue(globalValue, methodSet, []uint32{2}) + } + if !ptrTo.IsNil() { + globalValue = llvm.ConstInsertValue(globalValue, ptrTo, []uint32{3}) } + global.SetInitializer(globalValue) + global.SetLinkage(llvm.LinkOnceODRLinkage) global.SetGlobalConstant(true) } return global diff --git a/compiler/testdata/interface.ll b/compiler/testdata/interface.ll index e5aa7eef1..1414db8c3 100644 --- a/compiler/testdata/interface.ll +++ b/compiler/testdata/interface.ll @@ -3,20 +3,21 @@ source_filename = "interface.go" target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128" target triple = "i686--linux" -%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo* } +%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID* } %runtime.interfaceMethodInfo = type { i8*, i32 } %runtime._interface = type { i32, i8* } %runtime._string = type { i8*, i32 } -@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID zeroinitializer -@"reflect/types.type:pointer:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i32 0, %runtime.interfaceMethodInfo* null } -@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null } -@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null } -@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{Error() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null } +@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* null, i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:basic:int" } +@"reflect/types.type:pointer:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null } +@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null } +@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:named:error" } +@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{Error() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" } @"func Error() string" = external constant i8 @"reflect/types.interface:interface{Error() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"func Error() string"] -@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null } -@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{String() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null } +@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null } +@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{String:func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* null } +@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* bitcast ([1 x i8*]* @"reflect/types.interface:interface{String() string}$interface" to %runtime.typecodeID*), i32 0, %runtime.interfaceMethodInfo* null, %runtime.typecodeID* @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" } @"func String() string" = external constant i8 @"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"func String() string"] @"reflect/types.typeid:basic:int" = external constant i8 |