Commit f7721ac37c

Andrew Kelley <andrew@ziglang.org>
2019-09-09 18:15:39
implement spilling when returning error union async function call
closes #3190
1 parent 2482bdf
Changed files (2)
src
test
stage1
behavior
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, "");
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;
+}
+