Skip to content

Commit

Permalink
implement spilling when returning error union async function call
Browse files Browse the repository at this point in the history
closes #3190
  • Loading branch information
andrewrk committed Sep 9, 2019
1 parent 2482bdf commit f7721ac
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, "");
Expand Down
23 changes: 23 additions & 0 deletions test/stage1/behavior/async_fn.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit f7721ac

Please sign in to comment.