zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 72805fd66e732e29637872f540371c30cb9f8b27 (tree)
parent 652efe38b40af8c2a98756e71c9e98fe339d059d
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sat, 15 Feb 2020 14:16:12 -0500

fix taking address of temporary async frame

Diffstat:
Msrc/codegen.cpp | 8+++++++-
Mtest/stage1/behavior/async_fn.zig | 29+++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -5018,6 +5018,12 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns if (!type_has_bits(instruction->base.value->type)) { return nullptr; } + if (instruction->operand->id == IrInstGenIdCall) { + IrInstGenCall *call = reinterpret_cast<IrInstGenCall *>(instruction->operand); + if (call->result_loc != nullptr) { + return ir_llvm_value(g, call->result_loc); + } + } LLVMValueRef value = ir_llvm_value(g, instruction->operand); if (handle_is_ptr(instruction->operand->value->type)) { return value; @@ -6533,7 +6539,7 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { set_debug_location(g, instruction); } instruction->llvm_value = ir_render_instruction(g, executable, instruction); - if (instruction->spill != nullptr) { + if (instruction->spill != nullptr && instruction->llvm_value != nullptr) { LLVMValueRef spill_ptr = ir_llvm_value(g, instruction->spill); gen_assign_raw(g, spill_ptr, instruction->spill->value->type, instruction->llvm_value); instruction->llvm_value = nullptr; diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig @@ -1481,3 +1481,32 @@ test "handle defer interfering with return value spill" { }; S.doTheTest(); } + +test "take address of temporary async frame" { + const S = struct { + var global_frame: anyframe = undefined; + var finished = false; + + fn doTheTest() void { + _ = async asyncDoTheTest(); + resume global_frame; + expect(finished); + } + + fn asyncDoTheTest() void { + expect(finishIt(&async foo(10)) == 1245); + finished = true; + } + + fn foo(arg: i32) i32 { + global_frame = @frame(); + suspend; + return arg + 1234; + } + + fn finishIt(frame: anyframe->i32) i32 { + return (await frame) + 1; + } + }; + S.doTheTest(); +}