authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-10 22:59:00-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-10 22:59:00-04:00
logc9b2210fcf58d9e99851ad2a6a1219c997cf0d82
treeb4976b37d6a29279abf003ffff47fe58707db169
parent7101e583d6a752fa1145c13c6e1a58f36bd35f2d
signaturelock-open Commit is signed but in an unrecognized format.

async function calls re-use frame buffers

See #3069

2 files changed, 33 insertions(+), 3 deletions(-)

src/analyze.cpp+21-2
...@@ -2538,6 +2538,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2538,6 +2538,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2538 enum_type->data.enumeration.resolve_loop_flag = false;2538 enum_type->data.enumeration.resolve_loop_flag = false;
2539 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;2539 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
25402540
2541 occupied_tag_values.deinit();
2542
2541 return ErrorNone;2543 return ErrorNone;
2542}2544}
25432545
...@@ -5878,6 +5880,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5878,6 +5880,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5878 fn->err_code_spill = &alloca_gen->base;5880 fn->err_code_spill = &alloca_gen->base;
5879 }5881 }
58805882
5883 ZigType *largest_call_frame_type = nullptr;
5884 // Later we'll change this to be largest_call_frame_type instead of void.
5885 IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
5886 fn, g->builtin_types.entry_void, "@async_call_frame");
5887
5881 for (size_t i = 0; i < fn->call_list.length; i += 1) {5888 for (size_t i = 0; i < fn->call_list.length; i += 1) {
5882 IrInstructionCallGen *call = fn->call_list.at(i);5889 IrInstructionCallGen *call = fn->call_list.at(i);
5883 if (call->new_stack != nullptr) {5890 if (call->new_stack != nullptr) {
...@@ -5921,9 +5928,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5921,9 +5928,21 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
59215928
5922 mark_suspension_point(call->base.scope);5929 mark_suspension_point(call->base.scope);
59235930
5924 call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn,5931 if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
5925 callee_frame_type, "");5932 return err;
5933 }
5934 if (largest_call_frame_type == nullptr ||
5935 callee_frame_type->abi_size > largest_call_frame_type->abi_size)
5936 {
5937 largest_call_frame_type = callee_frame_type;
5938 }
5939
5940 call->frame_result_loc = all_calls_alloca;
5926 }5941 }
5942 if (largest_call_frame_type != nullptr) {
5943 all_calls_alloca->value.type = get_pointer_to_type(g, largest_call_frame_type, false);
5944 }
5945
5927 // Since this frame is async, an await might represent a suspend point, and5946 // Since this frame is async, an await might represent a suspend point, and
5928 // therefore need to spill. It also needs to mark expr scopes as having to spill.5947 // therefore need to spill. It also needs to mark expr scopes as having to spill.
5929 // For example: foo() + await z5948 // For example: foo() + await z
src/codegen.cpp+12-1
...@@ -3863,6 +3863,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3863,6 +3863,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3863 ZigList<ZigType *> gen_param_types = {};3863 ZigList<ZigType *> gen_param_types = {};
3864 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;3864 LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr;
3865 LLVMValueRef zero = LLVMConstNull(usize_type_ref);3865 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
3866 LLVMValueRef frame_result_loc_uncasted = nullptr;
3866 LLVMValueRef frame_result_loc;3867 LLVMValueRef frame_result_loc;
3867 LLVMValueRef awaiter_init_val;3868 LLVMValueRef awaiter_init_val;
3868 LLVMValueRef ret_ptr;3869 LLVMValueRef ret_ptr;
...@@ -3871,7 +3872,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3871,7 +3872,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3871 if (instruction->modifier == CallModifierAsync) {3872 if (instruction->modifier == CallModifierAsync) {
3872 frame_result_loc = result_loc;3873 frame_result_loc = result_loc;
3873 } else {3874 } else {
3874 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);3875 frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc);
3876 src_assert(instruction->fn_entry != nullptr, instruction->base.source_node);
3877 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
3878 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
3875 }3879 }
3876 } else {3880 } else {
3877 if (instruction->new_stack->value.type->id == ZigTypeIdPointer &&3881 if (instruction->new_stack->value.type->id == ZigTypeIdPointer &&
...@@ -4138,6 +4142,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4138,6 +4142,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4138 }4142 }
4139 }4143 }
41404144
4145 if (frame_result_loc_uncasted != nullptr && instruction->fn_entry != nullptr) {
4146 // Instead of a spill, we do the bitcast again. The uncasted LLVM IR instruction will
4147 // be an Alloca from the entry block, so it does not need to be spilled.
4148 frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted,
4149 LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), "");
4150 }
4151
4141 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");4152 LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
4142 return LLVMBuildLoad(g->builder, result_ptr, "");4153 return LLVMBuildLoad(g->builder, result_ptr, "");
4143 }4154 }