add missing return pointer restore for regular coroutine tail calls
This fixes an issue where a normal suspending call followed by a plain tail call would result in the tail return value being written to the return pointer of the normal suspending call. This is fixed by saving the return pointer at the start of the function and restoring it before initiating a plain tail call.
Этот коммит содержится в:
родитель
c20328472b
коммит
d424b3d7ea
2 изменённых файлов: 11 добавлений и 5 удалений
1
Makefile
1
Makefile
|
@ -188,6 +188,7 @@ tinygo-test:
|
|||
$(TINYGO) test encoding/base32
|
||||
$(TINYGO) test encoding/hex
|
||||
$(TINYGO) test hash/fnv
|
||||
$(TINYGO) test hash/crc64
|
||||
$(TINYGO) test math
|
||||
$(TINYGO) test text/scanner
|
||||
$(TINYGO) test unicode/utf8
|
||||
|
|
|
@ -735,10 +735,10 @@ func (c *coroutineLoweringPass) lowerFuncCoro(fn *asyncFunc) {
|
|||
task := c.builder.CreateCall(c.current, []llvm.Value{llvm.Undef(c.i8ptr), fn.rawTask}, "task")
|
||||
parentState := c.builder.CreateCall(c.setState, []llvm.Value{task, coroState, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "task.state.parent")
|
||||
// Get return pointer if needed.
|
||||
var retPtr llvm.Value
|
||||
if fn.hasValueStoreReturn() {
|
||||
retPtr = c.builder.CreateCall(c.getRetPtr, []llvm.Value{task, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "task.retPtr")
|
||||
retPtr = c.builder.CreateBitCast(retPtr, llvm.PointerType(fn.fn.Type().ElementType().ReturnType(), 0), "task.retPtr.bitcast")
|
||||
var retPtrRaw, retPtr llvm.Value
|
||||
if returnType.TypeKind() != llvm.VoidTypeKind {
|
||||
retPtrRaw = c.builder.CreateCall(c.getRetPtr, []llvm.Value{task, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "task.retPtr")
|
||||
retPtr = c.builder.CreateBitCast(retPtrRaw, llvm.PointerType(fn.fn.Type().ElementType().ReturnType(), 0), "task.retPtr.bitcast")
|
||||
}
|
||||
|
||||
// Build suspend block.
|
||||
|
@ -802,8 +802,13 @@ func (c *coroutineLoweringPass) lowerFuncCoro(fn *asyncFunc) {
|
|||
|
||||
// Resume caller.
|
||||
c.builder.CreateCall(c.returnTo, []llvm.Value{task, parentState, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "")
|
||||
case returnVoidTail, returnTail, returnDeadTail:
|
||||
case returnVoidTail, returnDeadTail:
|
||||
// Nothing to do.
|
||||
case returnTail:
|
||||
c.builder.SetInsertPointBefore(call)
|
||||
|
||||
// Restore the return pointer so that the caller can store into it.
|
||||
c.builder.CreateCall(c.setRetPtr, []llvm.Value{task, retPtrRaw, llvm.Undef(c.i8ptr), llvm.Undef(c.i8ptr)}, "")
|
||||
case returnAlternateTail:
|
||||
c.builder.SetInsertPointBefore(call)
|
||||
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче