authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-04 18:57:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-04 18:58:14-04:00
logfbf21efd24bf812e0fd52a5917708a4c45f05b5e
tree96aeb27f9a24d57b477c763073b2f2198df2a05c
parent042914de75f7ccf520fb2058372cc3f255ccfecb
signature Commit is signed but in an unrecognized format.

simpler, less memory intensive suspend/resume implementation


4 files changed, 62 insertions(+), 92 deletions(-)

src/all_types.hpp+5-11
......@@ -1386,7 +1386,6 @@ struct ZigFn {
13861386
13871387 ZigList<IrInstructionAllocaGen *> alloca_gen_list;
13881388 ZigList<ZigVar *> variable_list;
1389 ZigList<IrBasicBlock *> resume_blocks;
13901389
13911390 Buf *section_name;
13921391 AstNode *set_alignstack_node;
......@@ -1719,6 +1718,7 @@ struct CodeGen {
17191718 LLVMValueRef cur_async_resume_index_ptr;
17201719 LLVMValueRef cur_async_awaiter_ptr;
17211720 LLVMBasicBlockRef cur_preamble_llvm_block;
1721 size_t cur_resume_block_count;
17221722 LLVMValueRef cur_err_ret_trace_val_arg;
17231723 LLVMValueRef cur_err_ret_trace_val_stack;
17241724 LLVMValueRef memcpy_fn_val;
......@@ -2114,7 +2114,6 @@ struct ScopeRuntime {
21142114struct ScopeSuspend {
21152115 Scope base;
21162116
2117 IrBasicBlock *resume_block;
21182117 bool reported_err;
21192118};
21202119
......@@ -2169,8 +2168,6 @@ struct IrBasicBlock {
21692168 size_t ref_count;
21702169 // index into the basic block list
21712170 size_t index;
2172 // for async functions, the resume index which corresponds to this block
2173 size_t resume_index;
21742171 LLVMBasicBlockRef llvm_block;
21752172 LLVMBasicBlockRef llvm_exit_block;
21762173 // The instruction that referenced this basic block and caused us to
......@@ -2354,7 +2351,7 @@ enum IrInstructionId {
23542351 IrInstructionIdPtrOfArrayToSlice,
23552352 IrInstructionIdUnionInitNamedField,
23562353 IrInstructionIdSuspendBegin,
2357 IrInstructionIdSuspendBr,
2354 IrInstructionIdSuspendFinish,
23582355 IrInstructionIdAwait,
23592356 IrInstructionIdCoroResume,
23602357};
......@@ -3600,13 +3597,13 @@ struct IrInstructionPtrOfArrayToSlice {
36003597struct IrInstructionSuspendBegin {
36013598 IrInstruction base;
36023599
3603 IrBasicBlock *resume_block;
3600 LLVMBasicBlockRef resume_bb;
36043601};
36053602
3606struct IrInstructionSuspendBr {
3603struct IrInstructionSuspendFinish {
36073604 IrInstruction base;
36083605
3609 IrBasicBlock *resume_block;
3606 IrInstructionSuspendBegin *begin;
36103607};
36113608
36123609struct IrInstructionAwait {
......@@ -3710,9 +3707,6 @@ static const size_t coro_resume_index = 1;
37103707static const size_t coro_awaiter_index = 2;
37113708static const size_t coro_arg_start = 3;
37123709
3713// one for the Entry block, resume blocks are indexed after that.
3714static const size_t coro_extra_resume_block_count = 1;
3715
37163710// TODO call graph analysis to find out what this number needs to be for every function
37173711// MUST BE A POWER OF TWO.
37183712static const size_t stack_trace_ptr_count = 32;
src/codegen.cpp+25-29
......@@ -3661,8 +3661,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
36613661 ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true);
36623662
36633663 LLVMBasicBlockRef call_bb = LLVMAppendBasicBlock(g->cur_fn_val, "CallResume");
3664 size_t new_block_index = g->cur_fn->resume_blocks.length + coro_extra_resume_block_count;
3665 g->cur_fn->resume_blocks.append(nullptr);
3664 size_t new_block_index = g->cur_resume_block_count;
3665 g->cur_resume_block_count += 1;
36663666 LLVMValueRef new_block_index_val = LLVMConstInt(usize_type_ref, new_block_index, false);
36673667 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, call_bb);
36683668
......@@ -5153,15 +5153,22 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable
51535153 IrInstructionSuspendBegin *instruction)
51545154{
51555155 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5156 LLVMValueRef new_resume_index = LLVMConstInt(usize_type_ref, instruction->resume_block->resume_index, false);
5157 LLVMBuildStore(g->builder, new_resume_index, g->cur_async_resume_index_ptr);
5156 instruction->resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, "SuspendResume");
5157 size_t new_block_index = g->cur_resume_block_count;
5158 g->cur_resume_block_count += 1;
5159 LLVMValueRef new_block_index_val = LLVMConstInt(usize_type_ref, new_block_index, false);
5160 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, instruction->resume_bb);
5161 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);
51585162 return nullptr;
51595163}
51605164
5161static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,
5162 IrInstructionSuspendBr *instruction)
5165static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executable,
5166 IrInstructionSuspendFinish *instruction)
51635167{
51645168 LLVMBuildRetVoid(g->builder);
5169
5170 LLVMPositionBuilderAtEnd(g->builder, instruction->begin->resume_bb);
5171 render_async_var_decls(g, instruction->base.scope);
51655172 return nullptr;
51665173}
51675174
......@@ -5173,8 +5180,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
51735180
51745181 // Prepare to be suspended
51755182 LLVMBasicBlockRef resume_bb = LLVMAppendBasicBlock(g->cur_fn_val, "AwaitResume");
5176 size_t new_block_index = g->cur_fn->resume_blocks.length + coro_extra_resume_block_count;
5177 g->cur_fn->resume_blocks.append(nullptr);
5183 size_t new_block_index = g->cur_resume_block_count;
5184 g->cur_resume_block_count += 1;
51785185 LLVMValueRef new_block_index_val = LLVMConstInt(usize_type_ref, new_block_index, false);
51795186 LLVMAddCase(g->cur_async_switch_instr, new_block_index_val, resume_bb);
51805187 LLVMBuildStore(g->builder, new_block_index_val, g->cur_async_resume_index_ptr);
......@@ -5534,8 +5541,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
55345541 return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction);
55355542 case IrInstructionIdSuspendBegin:
55365543 return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction);
5537 case IrInstructionIdSuspendBr:
5538 return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
5544 case IrInstructionIdSuspendFinish:
5545 return ir_render_suspend_finish(g, executable, (IrInstructionSuspendFinish *)instruction);
55395546 case IrInstructionIdCoroResume:
55405547 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
55415548 case IrInstructionIdFrameSizeGen:
......@@ -5552,19 +5559,10 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
55525559 IrExecutable *executable = &fn_entry->analyzed_executable;
55535560 assert(executable->basic_block_list.length > 0);
55545561
5555 if (fn_is_async(fn_entry)) {
5556 IrBasicBlock *entry_block = executable->basic_block_list.at(0);
5557 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
5558 render_async_var_decls(g, entry_block->instruction_list.at(0)->scope);
5559 }
5560
55615562 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
55625563 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
55635564 assert(current_block->llvm_block);
55645565 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
5565 if (current_block->resume_index != 0) {
5566 render_async_var_decls(g, current_block->instruction_list.at(0)->scope);
5567 }
55685566 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
55695567 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
55705568 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
......@@ -6757,6 +6755,8 @@ static void do_code_gen(CodeGen *g) {
67576755 }
67586756
67596757 if (is_async) {
6758 g->cur_resume_block_count = 0;
6759
67606760 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
67616761 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);
67626762 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);
......@@ -6777,19 +6777,15 @@ static void do_code_gen(CodeGen *g) {
67776777 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, "");
67786778 g->cur_async_resume_index_ptr = resume_index_ptr;
67796779 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
6780 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block,
6781 fn_table_entry->resume_blocks.length + coro_extra_resume_block_count);
6780 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4);
67826781 g->cur_async_switch_instr = switch_instr;
67836782
67846783 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
6785 LLVMAddCase(switch_instr, zero, executable->basic_block_list.at(0)->llvm_block);
6786
6787 for (size_t resume_i = 0; resume_i < fn_table_entry->resume_blocks.length; resume_i += 1) {
6788 IrBasicBlock *resume_block = fn_table_entry->resume_blocks.at(resume_i);
6789 LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_block->resume_index, false);
6790 LLVMAddCase(switch_instr, case_value, resume_block->llvm_block);
6791 }
6792
6784 IrBasicBlock *entry_block = executable->basic_block_list.at(0);
6785 LLVMAddCase(switch_instr, zero, entry_block->llvm_block);
6786 g->cur_resume_block_count += 1;
6787 LLVMPositionBuilderAtEnd(g->builder, entry_block->llvm_block);
6788 render_async_var_decls(g, entry_block->instruction_list.at(0)->scope);
67936789 } else {
67946790 // create debug variable declarations for parameters
67956791 // rely on the first variables in the variable_list being parameters.
src/ir.cpp+28-46
......@@ -1049,8 +1049,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBegin *)
10491049 return IrInstructionIdSuspendBegin;
10501050}
10511051
1052static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) {
1053 return IrInstructionIdSuspendBr;
1052static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendFinish *) {
1053 return IrInstructionIdSuspendFinish;
10541054}
10551055
10561056static constexpr IrInstructionId ir_instruction_id(IrInstructionAwait *) {
......@@ -3260,25 +3260,21 @@ static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *s
32603260 return &instruction->base;
32613261}
32623262
3263static IrInstruction *ir_build_suspend_begin(IrBuilder *irb, Scope *scope, AstNode *source_node,
3264 IrBasicBlock *resume_block)
3265{
3263static IrInstructionSuspendBegin *ir_build_suspend_begin(IrBuilder *irb, Scope *scope, AstNode *source_node) {
32663264 IrInstructionSuspendBegin *instruction = ir_build_instruction<IrInstructionSuspendBegin>(irb, scope, source_node);
32673265 instruction->base.value.type = irb->codegen->builtin_types.entry_void;
3268 instruction->resume_block = resume_block;
3269
3270 ir_ref_bb(resume_block);
32713266
3272 return &instruction->base;
3267 return instruction;
32733268}
32743269
3275static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode *source_node,
3276 IrBasicBlock *resume_block)
3270static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstNode *source_node,
3271 IrInstructionSuspendBegin *begin)
32773272{
3278 IrInstructionSuspendBr *instruction = ir_build_instruction<IrInstructionSuspendBr>(irb, scope, source_node);
3279 instruction->resume_block = resume_block;
3273 IrInstructionSuspendFinish *instruction = ir_build_instruction<IrInstructionSuspendFinish>(irb, scope, source_node);
3274 instruction->base.value.type = irb->codegen->builtin_types.entry_void;
3275 instruction->begin = begin;
32803276
3281 ir_ref_bb(resume_block);
3277 ir_ref_instruction(&begin->base, irb->current_basic_block);
32823278
32833279 return &instruction->base;
32843280}
......@@ -7890,22 +7886,15 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
78907886 return irb->codegen->invalid_instruction;
78917887 }
78927888
7893 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
7894
7895 ir_build_suspend_begin(irb, parent_scope, node, resume_block);
7889 IrInstructionSuspendBegin *begin = ir_build_suspend_begin(irb, parent_scope, node);
78967890 if (node->data.suspend.block != nullptr) {
7897 Scope *child_scope;
78987891 ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
7899 suspend_scope->resume_block = resume_block;
7900 child_scope = &suspend_scope->base;
7892 Scope *child_scope = &suspend_scope->base;
79017893 IrInstruction *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
79027894 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
79037895 }
79047896
7905 IrInstruction *result = ir_build_suspend_br(irb, parent_scope, node, resume_block);
7906 result->value.type = irb->codegen->builtin_types.entry_void;
7907 ir_set_cursor_at_end_and_append_block(irb, resume_block);
7908 return result;
7897 return ir_build_suspend_finish(irb, parent_scope, node, begin);
79097898}
79107899
79117900static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
......@@ -24458,35 +24447,28 @@ static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *i
2445824447}
2445924448
2446024449static IrInstruction *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, IrInstructionSuspendBegin *instruction) {
24461 IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, instruction->resume_block, &instruction->base);
24462 if (new_bb == nullptr)
24463 return ir_unreach_error(ira);
24464 return ir_build_suspend_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, new_bb);
24450 IrInstructionSuspendBegin *result = ir_build_suspend_begin(&ira->new_irb, instruction->base.scope,
24451 instruction->base.source_node);
24452 return &result->base;
2446524453}
2446624454
24467static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstructionSuspendBr *instruction) {
24468 IrBasicBlock *old_dest_block = instruction->resume_block;
24469
24470 IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &instruction->base);
24471 if (new_bb == nullptr)
24472 return ir_unreach_error(ira);
24455static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira,
24456 IrInstructionSuspendFinish *instruction)
24457{
24458 IrInstruction *begin_base = instruction->begin->base.child;
24459 if (type_is_invalid(begin_base->value.type))
24460 return ira->codegen->invalid_instruction;
24461 ir_assert(begin_base->id == IrInstructionIdSuspendBegin, &instruction->base);
24462 IrInstructionSuspendBegin *begin = reinterpret_cast<IrInstructionSuspendBegin *>(begin_base);
2447324463
2447424464 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
2447524465 ir_assert(fn_entry != nullptr, &instruction->base);
2447624466
24477 new_bb->resume_index = fn_entry->resume_blocks.length + coro_extra_resume_block_count;
24478
24479 fn_entry->resume_blocks.append(new_bb);
2448024467 if (fn_entry->inferred_async_node == nullptr) {
2448124468 fn_entry->inferred_async_node = instruction->base.source_node;
2448224469 }
2448324470
24484 ir_push_resume_block(ira, old_dest_block);
24485
24486 IrInstruction *result = ir_build_suspend_br(&ira->new_irb,
24487 instruction->base.scope, instruction->base.source_node, new_bb);
24488 result->value.type = ira->codegen->builtin_types.entry_unreachable;
24489 return ir_finish_anal(ira, result);
24471 return ir_build_suspend_finish(&ira->new_irb, instruction->base.scope, instruction->base.source_node, begin);
2449024472}
2449124473
2449224474static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwait *instruction) {
......@@ -24847,8 +24829,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2484724829 return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction);
2484824830 case IrInstructionIdSuspendBegin:
2484924831 return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction);
24850 case IrInstructionIdSuspendBr:
24851 return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction);
24832 case IrInstructionIdSuspendFinish:
24833 return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction);
2485224834 case IrInstructionIdCoroResume:
2485324835 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
2485424836 case IrInstructionIdAwait:
......@@ -24986,7 +24968,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2498624968 case IrInstructionIdVectorToArray:
2498724969 case IrInstructionIdResetResult:
2498824970 case IrInstructionIdSuspendBegin:
24989 case IrInstructionIdSuspendBr:
24971 case IrInstructionIdSuspendFinish:
2499024972 case IrInstructionIdCoroResume:
2499124973 case IrInstructionIdAwait:
2499224974 return true;
src/ir_print.cpp+4-6
......@@ -1534,10 +1534,8 @@ static void ir_print_suspend_begin(IrPrint *irp, IrInstructionSuspendBegin *inst
15341534 fprintf(irp->f, "@suspendBegin()");
15351535}
15361536
1537static void ir_print_suspend_br(IrPrint *irp, IrInstructionSuspendBr *instruction) {
1538 fprintf(irp->f, "@suspendBr(");
1539 ir_print_other_block(irp, instruction->resume_block);
1540 fprintf(irp->f, ")");
1537static void ir_print_suspend_finish(IrPrint *irp, IrInstructionSuspendFinish *instruction) {
1538 fprintf(irp->f, "@suspendFinish()");
15411539}
15421540
15431541static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) {
......@@ -2025,8 +2023,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
20252023 case IrInstructionIdSuspendBegin:
20262024 ir_print_suspend_begin(irp, (IrInstructionSuspendBegin *)instruction);
20272025 break;
2028 case IrInstructionIdSuspendBr:
2029 ir_print_suspend_br(irp, (IrInstructionSuspendBr *)instruction);
2026 case IrInstructionIdSuspendFinish:
2027 ir_print_suspend_finish(irp, (IrInstructionSuspendFinish *)instruction);
20302028 break;
20312029 case IrInstructionIdCoroResume:
20322030 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);