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.
Этот коммит содержится в:
родитель
4dfc289ae5
коммит
6896b0014b
3 изменённых файлов: 17 добавлений и 5 удалений
|
@ -295,12 +295,16 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
||||||
forwardParams = append(forwardParams, forwardParam)
|
forwardParams = append(forwardParams, forwardParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the context parameter. We know it is ignored by the receiving
|
// Plain TinyGo functions add some extra parameters to implement async functionality and function recievers.
|
||||||
// function, but we have to pass one anyway.
|
// These parameters should not be supplied when calling into an external C/ASM function.
|
||||||
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
|
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.
|
// Parent coroutine handle.
|
||||||
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
|
forwardParams = append(forwardParams, llvm.Undef(c.i8ptrType))
|
||||||
|
}
|
||||||
|
|
||||||
// Call real function.
|
// Call real function.
|
||||||
c.createCall(callback.LLVMFn, forwardParams, "")
|
c.createCall(callback.LLVMFn, forwardParams, "")
|
||||||
|
|
7
testdata/calls.go
предоставленный
7
testdata/calls.go
предоставленный
|
@ -72,6 +72,8 @@ func hello(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDefer() {
|
func testDefer() {
|
||||||
|
defer exportedDefer()
|
||||||
|
|
||||||
i := 1
|
i := 1
|
||||||
defer deferred("...run as defer", i)
|
defer deferred("...run as defer", i)
|
||||||
i++
|
i++
|
||||||
|
@ -98,6 +100,11 @@ func deferred(msg string, i int) {
|
||||||
println(msg, i)
|
println(msg, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:export __exportedDefer
|
||||||
|
func exportedDefer() {
|
||||||
|
println("...exported defer")
|
||||||
|
}
|
||||||
|
|
||||||
func testBound(f func() string) {
|
func testBound(f func() string) {
|
||||||
println("bound method:", f())
|
println("bound method:", f())
|
||||||
}
|
}
|
||||||
|
|
1
testdata/calls.txt
предоставленный
1
testdata/calls.txt
предоставленный
|
@ -4,6 +4,7 @@ Thing.Print: foo arg: bar
|
||||||
...run as defer 3
|
...run as defer 3
|
||||||
...run closure deferred: 4
|
...run closure deferred: 4
|
||||||
...run as defer 1
|
...run as defer 1
|
||||||
|
...exported defer
|
||||||
loop 3
|
loop 3
|
||||||
loop 2
|
loop 2
|
||||||
loop 1
|
loop 1
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче