diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-08-14 12:52:20 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-08-14 12:52:20 -0400 |
| commit | 64c293f8a4ce5fcbb506c32b989a88d982f005ce (patch) | |
| tree | d3f8332a227ddd4a316bd08ca93ba1d8624b4b6a /src/analyze.cpp | |
| parent | f3f838cc016fd8190a9bba46fa495fbc27325492 (diff) | |
| download | zig-64c293f8a4ce5fcbb506c32b989a88d982f005ce.tar.gz zig-64c293f8a4ce5fcbb506c32b989a88d982f005ce.zip | |
codegen for async call of blocking function
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index 64d6059da4..1b6de6e7df 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3831,7 +3831,7 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { } // This function resolves functions being inferred async. -static void analyze_fn_async(CodeGen *g, ZigFn *fn) { +static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { if (fn->inferred_async_node == inferred_async_checking) { // TODO call graph cycle detected, disallow the recursion fn->inferred_async_node = inferred_async_none; @@ -3841,7 +3841,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) { return; } if (fn->inferred_async_node != nullptr) { - resolve_async_fn_frame(g, fn); + if (resolve_frame) { + resolve_async_fn_frame(g, fn); + } return; } fn->inferred_async_node = inferred_async_checking; @@ -3870,7 +3872,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) { } } assert(callee->anal_state == FnAnalStateComplete); - analyze_fn_async(g, callee); + analyze_fn_async(g, callee, true); if (callee->anal_state == FnAnalStateInvalid) { fn->anal_state = FnAnalStateInvalid; return; @@ -3886,7 +3888,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) { fn->anal_state = FnAnalStateInvalid; return; } - resolve_async_fn_frame(g, fn); + if (resolve_frame) { + resolve_async_fn_frame(g, fn); + } return; } } @@ -4141,7 +4145,7 @@ void semantic_analyze(CodeGen *g) { // second pass over functions for detecting async for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index); - analyze_fn_async(g, fn_entry); + analyze_fn_async(g, fn_entry, true); } } @@ -5212,6 +5216,36 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { return ErrorSemanticAnalyzeFail; } } + analyze_fn_async(g, fn, false); + if (fn->anal_state == FnAnalStateInvalid) + return ErrorSemanticAnalyzeFail; + + if (!fn_is_async(fn)) { + ZigType *fn_type = fn->type_entry; + FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; + ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); + + // label (grep this): [fn_frame_struct_layout] + ZigList<SrcField> fields = {}; + + fields.append({"@fn_ptr", g->builtin_types.entry_usize, 0}); + fields.append({"@resume_index", g->builtin_types.entry_usize, 0}); + fields.append({"@awaiter", g->builtin_types.entry_usize, 0}); + fields.append({"@prev_val", g->builtin_types.entry_usize, 0}); + + fields.append({"@result_ptr_callee", ptr_return_type, 0}); + fields.append({"@result_ptr_awaiter", ptr_return_type, 0}); + fields.append({"@result", fn_type_id->return_type, 0}); + + frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name), + fields.items, fields.length, target_fn_align(g->zig_target)); + frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size; + frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align; + frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits; + + return ErrorNone; + } + ZigType *fn_type = get_async_fn_type(g, fn->type_entry); if (fn->analyzed_executable.need_err_code_spill) { @@ -5252,7 +5286,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid; return ErrorSemanticAnalyzeFail; } - analyze_fn_async(g, callee); + analyze_fn_async(g, callee, true); if (!fn_is_async(callee)) continue; @@ -5268,6 +5302,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { fn->alloca_gen_list.append(alloca_gen); call->frame_result_loc = &alloca_gen->base; } + FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; + ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); // label (grep this): [fn_frame_struct_layout] ZigList<SrcField> fields = {}; @@ -5277,9 +5313,6 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { fields.append({"@awaiter", g->builtin_types.entry_usize, 0}); fields.append({"@prev_val", g->builtin_types.entry_usize, 0}); - FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; - ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); - fields.append({"@result_ptr_callee", ptr_return_type, 0}); fields.append({"@result_ptr_awaiter", ptr_return_type, 0}); fields.append({"@result", fn_type_id->return_type, 0}); @@ -7651,7 +7684,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { } static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) { - resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type); + ZigType *passed_frame_type = fn_is_async(frame_type->data.frame.fn) ? frame_type : nullptr; + resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, passed_frame_type); frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type; frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type; } |
