mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-12 15:03:41 +00:00
compiler: decouple func lowering from interface type codes
There is no good reason for func values to refer to interface type codes. The only thing they need is a stable identifier for function signatures, which is easily created as a new kind of globals. Decoupling makes it easier to change interface related code.
This commit is contained in:
committed by
Ron Evans
parent
8383552552
commit
57271d7eaa
@@ -53,15 +53,14 @@ func LowerFuncValues(mod llvm.Module) {
|
||||
uintptrType := ctx.IntType(llvm.NewTargetData(mod.DataLayout()).PointerSize() * 8)
|
||||
|
||||
// Find all func values used in the program with their signatures.
|
||||
funcValueWithSignaturePtr := llvm.PointerType(mod.GetTypeByName("runtime.funcValueWithSignature"), 0)
|
||||
signatures := map[string]*funcSignatureInfo{}
|
||||
for global := mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
||||
var sig, funcVal llvm.Value
|
||||
switch {
|
||||
case global.Type() == funcValueWithSignaturePtr:
|
||||
case strings.HasSuffix(global.Name(), "$withSignature"):
|
||||
sig = llvm.ConstExtractValue(global.Initializer(), []uint32{1})
|
||||
funcVal = global
|
||||
case strings.HasPrefix(global.Name(), "reflect/types.type:func:{"):
|
||||
case strings.HasPrefix(global.Name(), "reflect/types.funcid:func:{"):
|
||||
sig = global
|
||||
default:
|
||||
continue
|
||||
@@ -202,6 +201,12 @@ func LowerFuncValues(mod llvm.Module) {
|
||||
}
|
||||
getFuncPtrCall.EraseFromParentAsInstruction()
|
||||
}
|
||||
|
||||
// Clean up all globals used before func lowering.
|
||||
for _, obj := range info.funcValueWithSignatures {
|
||||
obj.EraseFromParentAsGlobal()
|
||||
}
|
||||
info.sig.EraseFromParentAsGlobal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,11 +132,11 @@ func LowerInterrupts(mod llvm.Module, sizeLevel int) []error {
|
||||
errs = append(errs, errorAt(global, "internal error: expected a global for func lowering"))
|
||||
continue
|
||||
}
|
||||
initializer := global.Initializer()
|
||||
if initializer.Type() != mod.GetTypeByName("runtime.funcValueWithSignature") {
|
||||
errs = append(errs, errorAt(global, "internal error: func lowering global has unexpected type"))
|
||||
if !strings.HasSuffix(global.Name(), "$withSignature") {
|
||||
errs = append(errs, errorAt(global, "internal error: func lowering global has unexpected name: "+global.Name()))
|
||||
continue
|
||||
}
|
||||
initializer := global.Initializer()
|
||||
ptrtoint := llvm.ConstExtractValue(initializer, []uint32{0})
|
||||
if ptrtoint.IsAConstantExpr().IsNil() || ptrtoint.Opcode() != llvm.PtrToInt {
|
||||
errs = append(errs, errorAt(global, "internal error: func lowering global has unexpected func ptr type"))
|
||||
|
||||
Vendored
+12
-13
@@ -1,18 +1,17 @@
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32 }
|
||||
%runtime.funcValueWithSignature = type { i32, %runtime.typecodeID* }
|
||||
%runtime.funcValueWithSignature = type { i32, i8* }
|
||||
|
||||
@"reflect/types.type:func:{basic:uint8}{}" = external constant %runtime.typecodeID
|
||||
@"reflect/types.type:func:{basic:int}{}" = external constant %runtime.typecodeID
|
||||
@"reflect/types.type:func:{}{basic:uint32}" = external constant %runtime.typecodeID
|
||||
@"func1Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func1Uint8 to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:uint8}{}" }
|
||||
@"func2Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func2Uint8 to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:uint8}{}" }
|
||||
@"main$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}" }
|
||||
@"main$2$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}" }
|
||||
@"reflect/types.funcid:func:{basic:uint8}{}" = external constant i8
|
||||
@"reflect/types.funcid:func:{basic:int}{}" = external constant i8
|
||||
@"reflect/types.funcid:func:{}{basic:uint32}" = external constant i8
|
||||
@"func1Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func1Uint8 to i32), i8* @"reflect/types.funcid:func:{basic:uint8}{}" }
|
||||
@"func2Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func2Uint8 to i32), i8* @"reflect/types.funcid:func:{basic:uint8}{}" }
|
||||
@"main$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" }
|
||||
@"main$2$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), i8* @"reflect/types.funcid:func:{basic:int}{}" }
|
||||
|
||||
declare i32 @runtime.getFuncPtr(i8*, i32, %runtime.typecodeID*, i8*, i8*)
|
||||
declare i32 @runtime.getFuncPtr(i8*, i32, i8*, i8*, i8*)
|
||||
|
||||
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
|
||||
|
||||
@@ -30,7 +29,7 @@ declare void @func2Uint8(i8, i8*, i8*)
|
||||
; This means that this should unconditionally nil panic.
|
||||
define i32 @runFuncNone(i8*, i32, i8* %context, i8* %parentHandle) {
|
||||
entry:
|
||||
%2 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, %runtime.typecodeID* @"reflect/types.type:func:{}{basic:uint32}", i8* undef, i8* null)
|
||||
%2 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, i8* @"reflect/types.funcid:func:{}{basic:uint32}", i8* undef, i8* null)
|
||||
%3 = inttoptr i32 %2 to i32 (i8*, i8*)*
|
||||
%4 = icmp eq i32 (i8*, i8*)* %3, null
|
||||
br i1 %4, label %fpcall.nil, label %fpcall.next
|
||||
@@ -49,7 +48,7 @@ fpcall.next:
|
||||
; func value is nil). This call will thus be lowered to a switch statement.
|
||||
define void @runFunc2(i8*, i32, i8, i8* %context, i8* %parentHandle) {
|
||||
entry:
|
||||
%3 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, %runtime.typecodeID* @"reflect/types.type:func:{basic:uint8}{}", i8* undef, i8* null)
|
||||
%3 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, i8* @"reflect/types.funcid:func:{basic:uint8}{}", i8* undef, i8* null)
|
||||
%4 = inttoptr i32 %3 to void (i8, i8*, i8*)*
|
||||
%5 = icmp eq void (i8, i8*, i8*)* %4, null
|
||||
br i1 %5, label %fpcall.nil, label %fpcall.next
|
||||
@@ -66,7 +65,7 @@ fpcall.next:
|
||||
; Special case for internal/task.start.
|
||||
define void @sleepFuncValue(i8*, i32, i8* nocapture readnone %context, i8* nocapture readnone %parentHandle) {
|
||||
entry:
|
||||
%2 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}", i8* undef, i8* null)
|
||||
%2 = call i32 @runtime.getFuncPtr(i8* %0, i32 %1, i8* @"reflect/types.funcid:func:{basic:int}{}", i8* undef, i8* null)
|
||||
call void @"internal/task.start"(i32 %2, i8* null, i32 undef, i8* undef, i8* null)
|
||||
ret void
|
||||
}
|
||||
|
||||
+1
-12
@@ -1,18 +1,7 @@
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32 }
|
||||
%runtime.funcValueWithSignature = type { i32, %runtime.typecodeID* }
|
||||
|
||||
@"reflect/types.type:func:{basic:uint8}{}" = external constant %runtime.typecodeID
|
||||
@"reflect/types.type:func:{basic:int}{}" = external constant %runtime.typecodeID
|
||||
@"reflect/types.type:func:{}{basic:uint32}" = external constant %runtime.typecodeID
|
||||
@"func1Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func1Uint8 to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:uint8}{}" }
|
||||
@"func2Uint8$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i8, i8*, i8*)* @func2Uint8 to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:uint8}{}" }
|
||||
@"main$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}" }
|
||||
@"main$2$withSignature" = constant %runtime.funcValueWithSignature { i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), %runtime.typecodeID* @"reflect/types.type:func:{basic:int}{}" }
|
||||
|
||||
declare i32 @runtime.getFuncPtr(i8*, i32, %runtime.typecodeID*, i8*, i8*)
|
||||
declare i32 @runtime.getFuncPtr(i8*, i32, i8*, i8*, i8*)
|
||||
|
||||
declare void @"internal/task.start"(i32, i8*, i32, i8*, i8*)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user