commit f7721ac37cbb38c2f27d51f91eab776c5aca9767 (tree)
parent 2482bdf22b77bdee718167da5390157cc792dced
Author: Andrew Kelley <andrew@ziglang.org>
Date: Mon, 9 Sep 2019 12:15:39 -0400
implement spilling when returning error union async function call
closes #3190
Diffstat:
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git 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
@@ -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;
+}
+