authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-08 13:45:31-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-08 13:45:31-05:00
log884804dbc3a066fde06da769994554efe09febd6
treeba1c1340830ca852ad74eb4399528b4d311f485a
parentc48831512b017202aa8797b72b11eb6993c9428e
signaturelock-open Commit is signed but in an unrecognized format.

fix async runtime function call resolves target fn frame


2 files changed, 34 insertions(+), 7 deletions(-)

src/codegen.cpp+10-6
...@@ -4092,6 +4092,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4092,6 +4092,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
4092 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;4092 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
4093 LLVMValueRef zero = LLVMConstNull(usize_type_ref);4093 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
4094 bool need_frame_ptr_ptr_spill = false;4094 bool need_frame_ptr_ptr_spill = false;
4095 ZigType *anyframe_type = nullptr;
4095 LLVMValueRef frame_result_loc_uncasted = nullptr;4096 LLVMValueRef frame_result_loc_uncasted = nullptr;
4096 LLVMValueRef frame_result_loc;4097 LLVMValueRef frame_result_loc;
4097 LLVMValueRef awaiter_init_val;4098 LLVMValueRef awaiter_init_val;
...@@ -4134,7 +4135,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4134,7 +4135,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
4134 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");4135 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
4135 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");4136 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
4136 if (instruction->fn_entry == nullptr) {4137 if (instruction->fn_entry == nullptr) {
4137 ZigType *anyframe_type = get_any_frame_type(g, src_return_type);4138 anyframe_type = get_any_frame_type(g, src_return_type);
4138 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");4139 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");
4139 } else {4140 } else {
4140 ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry);4141 ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry);
...@@ -4416,11 +4417,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4416,11 +4417,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
4416 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");4417 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
4417 frame_result_loc_uncasted = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");4418 frame_result_loc_uncasted = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
4418 }4419 }
4419 if (frame_result_loc_uncasted != nullptr && instruction->fn_entry != nullptr) {4420 if (frame_result_loc_uncasted != nullptr) {
4420 // Instead of a spill, we do the bitcast again. The uncasted LLVM IR instruction will4421 if (instruction->fn_entry != nullptr) {
4421 // be an Alloca from the entry block, so it does not need to be spilled.4422 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
4422 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,4423 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
4423 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");4424 } else {
4425 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
4426 get_llvm_type(g, anyframe_type), "");
4427 }
4424 }4428 }
44254429
4426 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");4430 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
test/stage1/behavior/async_fn.zig+24-1
...@@ -1372,7 +1372,7 @@ test "async function passed align(16) arg after align(8) arg" {...@@ -1372,7 +1372,7 @@ test "async function passed align(16) arg after align(8) arg" {
1372 expect(S.global_int == 99);1372 expect(S.global_int == 99);
1373}1373}
13741374
1375test "async function call resolves target fn frame" {1375test "async function call resolves target fn frame, comptime func" {
1376 const S = struct {1376 const S = struct {
1377 var global_frame: anyframe = undefined;1377 var global_frame: anyframe = undefined;
1378 var global_int: i32 = 9;1378 var global_int: i32 = 9;
...@@ -1393,3 +1393,26 @@ test "async function call resolves target fn frame" {...@@ -1393,3 +1393,26 @@ test "async function call resolves target fn frame" {
1393 resume S.global_frame;1393 resume S.global_frame;
1394 expect(S.global_int == 10);1394 expect(S.global_int == 10);
1395}1395}
1396
1397test "async function call resolves target fn frame, runtime func" {
1398 const S = struct {
1399 var global_frame: anyframe = undefined;
1400 var global_int: i32 = 9;
1401
1402 fn foo() anyerror!void {
1403 const stack_size = 1000;
1404 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1405 var func: async fn () anyerror!void = bar;
1406 return await @asyncCall(&stack_frame, {}, func);
1407 }
1408
1409 fn bar() anyerror!void {
1410 global_frame = @frame();
1411 suspend;
1412 global_int += 1;
1413 }
1414 };
1415 _ = async S.foo();
1416 resume S.global_frame;
1417 expect(S.global_int == 10);
1418}