Commit 72805fd66e

Andrew Kelley <andrew@ziglang.org>
2020-02-15 20:16:12
fix taking address of temporary async frame
1 parent 652efe3
Changed files (2)
src
test
stage1
behavior
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;
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();
+}