authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-07 22:48:31-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-07 22:48:31-05:00
log877f39d2270a648fac2dda048bf972b7cc9a1430
tree7ad7440d1e8721d7859b3b7f0a986afb3e7cb11e
parent39ee1f4b97053cdc080ddf3562cefc6bed2071a8
signaturelock-open Commit is signed but in an unrecognized format.

fix async function call resolves target fn frame


2 files changed, 35 insertions(+), 2 deletions(-)

src/codegen.cpp+13-2
...@@ -4059,6 +4059,8 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV...@@ -4059,6 +4059,8 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV
4059}4059}
40604060
4061static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrInstGenCall *instruction) {4061static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrInstGenCall *instruction) {
4062 Error err;
4063
4062 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;4064 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
40634065
4064 LLVMValueRef fn_val;4066 LLVMValueRef fn_val;
...@@ -4089,6 +4091,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4089,6 +4091,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
4089 ZigList<ZigType *> gen_param_types = {};4091 ZigList<ZigType *> gen_param_types = {};
4090 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;
4091 LLVMValueRef zero = LLVMConstNull(usize_type_ref);4093 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
4094 bool need_frame_ptr_ptr_spill = false;
4092 LLVMValueRef frame_result_loc_uncasted = nullptr;4095 LLVMValueRef frame_result_loc_uncasted = nullptr;
4093 LLVMValueRef frame_result_loc;4096 LLVMValueRef frame_result_loc;
4094 LLVMValueRef awaiter_init_val;4097 LLVMValueRef awaiter_init_val;
...@@ -4127,14 +4130,17 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4127,14 +4130,17 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
41274130
4128 LLVMPositionBuilderAtEnd(g->builder, ok_block);4131 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4129 }4132 }
4133 need_frame_ptr_ptr_spill = true;
4130 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");4134 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
4131 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");4135 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
4132 if (instruction->fn_entry == nullptr) {4136 if (instruction->fn_entry == nullptr) {
4133 ZigType *anyframe_type = get_any_frame_type(g, src_return_type);4137 ZigType *anyframe_type = get_any_frame_type(g, src_return_type);
4134 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");4138 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");
4135 } else {4139 } else {
4136 ZigType *ptr_frame_type = get_pointer_to_type(g,4140 ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry);
4137 get_fn_frame_type(g, instruction->fn_entry), false);4141 if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull)))
4142 codegen_report_errors_and_exit(g);
4143 ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false);
4138 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,4144 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,
4139 get_llvm_type(g, ptr_frame_type), "");4145 get_llvm_type(g, ptr_frame_type), "");
4140 }4146 }
...@@ -4405,6 +4411,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn...@@ -4405,6 +4411,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn
4405 }4411 }
4406 }4412 }
44074413
4414 if (need_frame_ptr_ptr_spill) {
4415 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
4416 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 }
4408 if (frame_result_loc_uncasted != nullptr && instruction->fn_entry != nullptr) {4419 if (frame_result_loc_uncasted != nullptr && instruction->fn_entry != nullptr) {
4409 // Instead of a spill, we do the bitcast again. The uncasted LLVM IR instruction will4420 // Instead of a spill, we do the bitcast again. The uncasted LLVM IR instruction will
4410 // be an Alloca from the entry block, so it does not need to be spilled.4421 // be an Alloca from the entry block, so it does not need to be spilled.
test/stage1/behavior/async_fn.zig+22
...@@ -1371,3 +1371,25 @@ test "async function passed align(16) arg after align(8) arg" {...@@ -1371,3 +1371,25 @@ test "async function passed align(16) arg after align(8) arg" {
1371 resume S.global_frame;1371 resume S.global_frame;
1372 expect(S.global_int == 99);1372 expect(S.global_int == 99);
1373}1373}
1374
1375test "async function call resolves target fn frame" {
1376 const S = struct {
1377 var global_frame: anyframe = undefined;
1378 var global_int: i32 = 9;
1379
1380 fn foo() anyerror!void {
1381 const stack_size = 1000;
1382 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1383 return await @asyncCall(&stack_frame, {}, bar);
1384 }
1385
1386 fn bar() anyerror!void {
1387 global_frame = @frame();
1388 suspend;
1389 global_int += 1;
1390 }
1391 };
1392 _ = async S.foo();
1393 resume S.global_frame;
1394 expect(S.global_int == 10);
1395}