compiler: fix deferred calls to exported functions

Previously using defer with an exported function generated an invalid function call due to differences between TinyGo's calling convention and the C calling convention.
This commit is contained in:
Jaden Weiss
2020-02-26 15:54:00 -05:00
committed by Ayke
parent 4dfc289ae5
commit 6896b0014b
3 changed files with 17 additions and 5 deletions
+9 -5
View File
@@ -295,12 +295,16 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
forwardParams = append(forwardParams, forwardParam)
}
// Add the context parameter. We know it is ignored by the receiving
// function, but we have to pass one anyway.
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
// Plain TinyGo functions add some extra parameters to implement async functionality and function recievers.
// These parameters should not be supplied when calling into an external C/ASM function.
if !callback.IsExported() {
// Add the context parameter. We know it is ignored by the receiving
// function, but we have to pass one anyway.
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
// Parent coroutine handle.
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
// Parent coroutine handle.
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
}
// Call real function.
c.createCall(callback.LLVMFn, forwardParams, "")
+7
View File
@@ -72,6 +72,8 @@ func hello(n int) {
}
func testDefer() {
defer exportedDefer()
i := 1
defer deferred("...run as defer", i)
i++
@@ -98,6 +100,11 @@ func deferred(msg string, i int) {
println(msg, i)
}
//go:export __exportedDefer
func exportedDefer() {
println("...exported defer")
}
func testBound(f func() string) {
println("bound method:", f())
}
+1
View File
@@ -4,6 +4,7 @@ Thing.Print: foo arg: bar
...run as defer 3
...run closure deferred: 4
...run as defer 1
...exported defer
loop 3
loop 2
loop 1