From f7721ac37cbb38c2f27d51f91eab776c5aca9767 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 12:15:39 -0400 Subject: [PATCH] implement spilling when returning error union async function call closes #3190 --- src/codegen.cpp | 10 ++++++++-- test/stage1/behavior/async_fn.zig | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b590995c92..0533cc85b5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4122,8 +4122,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr if (!type_has_bits(src_return_type)) return nullptr; - if (result_loc != nullptr) - return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + if (result_loc != nullptr) { + if (instruction->result_loc->id == IrInstructionIdReturnPtr) { + instruction->base.spill = nullptr; + return g->cur_ret_ptr; + } else { + return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + } + } LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); return LLVMBuildLoad(g->builder, result_ptr, ""); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index b8a7196ed6..3ee728f8a5 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1178,3 +1178,26 @@ test "suspend in for loop" { S.doTheTest(); } +test "correctly spill when returning the error union result of another async fn" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + expect((atest() catch unreachable) == 1234); + } + + fn atest() !i32 { + return fallible1(); + } + + fn fallible1() anyerror!i32 { + suspend { + global_frame = @frame(); + } + return 1234; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; +} +