Skip to content

Commit 6896b00

Browse files
niaowaykevl
authored andcommitted
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.
1 parent 4dfc289 commit 6896b00

File tree

3 files changed

+18
-6
lines changed

3 files changed

+18
-6
lines changed

compiler/defer.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,16 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
295295
forwardParams = append(forwardParams, forwardParam)
296296
}
297297

298-
// Add the context parameter. We know it is ignored by the receiving
299-
// function, but we have to pass one anyway.
300-
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
301-
302-
// Parent coroutine handle.
303-
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
298+
// Plain TinyGo functions add some extra parameters to implement async functionality and function recievers.
299+
// These parameters should not be supplied when calling into an external C/ASM function.
300+
if !callback.IsExported() {
301+
// Add the context parameter. We know it is ignored by the receiving
302+
// function, but we have to pass one anyway.
303+
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
304+
305+
// Parent coroutine handle.
306+
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
307+
}
304308

305309
// Call real function.
306310
c.createCall(callback.LLVMFn, forwardParams, "")

testdata/calls.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ func hello(n int) {
7272
}
7373

7474
func testDefer() {
75+
defer exportedDefer()
76+
7577
i := 1
7678
defer deferred("...run as defer", i)
7779
i++
@@ -98,6 +100,11 @@ func deferred(msg string, i int) {
98100
println(msg, i)
99101
}
100102

103+
//go:export __exportedDefer
104+
func exportedDefer() {
105+
println("...exported defer")
106+
}
107+
101108
func testBound(f func() string) {
102109
println("bound method:", f())
103110
}

testdata/calls.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Thing.Print: foo arg: bar
44
...run as defer 3
55
...run closure deferred: 4
66
...run as defer 1
7+
...exported defer
78
loop 3
89
loop 2
910
loop 1

0 commit comments

Comments
 (0)