| ... | ... | @@ -4232,31 +4232,40 @@ static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode |
| 4232 | 4232 | { |
| 4233 | 4233 | if (modifier == CallModifierNoAsync) |
| 4234 | 4234 | return ErrorNone; |
| 4235 | | if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified) |
| 4236 | | return ErrorNone; |
| 4237 | | if (callee->anal_state == FnAnalStateReady) { |
| 4238 | | analyze_fn_body(g, callee); |
| 4239 | | if (callee->anal_state == FnAnalStateInvalid) { |
| 4240 | | return ErrorSemanticAnalyzeFail; |
| 4241 | | } |
| 4235 | bool callee_is_async = false; |
| 4236 | switch (callee->type_entry->data.fn.fn_type_id.cc) { |
| 4237 | case CallingConventionUnspecified: |
| 4238 | break; |
| 4239 | case CallingConventionAsync: |
| 4240 | callee_is_async = true; |
| 4241 | break; |
| 4242 | default: |
| 4243 | return ErrorNone; |
| 4242 | 4244 | } |
| 4243 | | bool callee_is_async; |
| 4244 | | if (callee->anal_state == FnAnalStateComplete) { |
| 4245 | | analyze_fn_async(g, callee, true); |
| 4246 | | if (callee->anal_state == FnAnalStateInvalid) { |
| 4247 | | return ErrorSemanticAnalyzeFail; |
| 4245 | if (!callee_is_async) { |
| 4246 | if (callee->anal_state == FnAnalStateReady) { |
| 4247 | analyze_fn_body(g, callee); |
| 4248 | if (callee->anal_state == FnAnalStateInvalid) { |
| 4249 | return ErrorSemanticAnalyzeFail; |
| 4250 | } |
| 4248 | 4251 | } |
| 4249 | | callee_is_async = fn_is_async(callee); |
| 4250 | | } else { |
| 4251 | | // If it's already been determined, use that value. Otherwise |
| 4252 | | // assume non-async, emit an error later if it turned out to be async. |
| 4253 | | if (callee->inferred_async_node == nullptr || |
| 4254 | | callee->inferred_async_node == inferred_async_checking) |
| 4255 | | { |
| 4256 | | callee->assumed_non_async = call_node; |
| 4257 | | callee_is_async = false; |
| 4252 | if (callee->anal_state == FnAnalStateComplete) { |
| 4253 | analyze_fn_async(g, callee, true); |
| 4254 | if (callee->anal_state == FnAnalStateInvalid) { |
| 4255 | return ErrorSemanticAnalyzeFail; |
| 4256 | } |
| 4257 | callee_is_async = fn_is_async(callee); |
| 4258 | 4258 | } else { |
| 4259 | | callee_is_async = callee->inferred_async_node != inferred_async_none; |
| 4259 | // If it's already been determined, use that value. Otherwise |
| 4260 | // assume non-async, emit an error later if it turned out to be async. |
| 4261 | if (callee->inferred_async_node == nullptr || |
| 4262 | callee->inferred_async_node == inferred_async_checking) |
| 4263 | { |
| 4264 | callee->assumed_non_async = call_node; |
| 4265 | callee_is_async = false; |
| 4266 | } else { |
| 4267 | callee_is_async = callee->inferred_async_node != inferred_async_none; |
| 4268 | } |
| 4260 | 4269 | } |
| 4261 | 4270 | } |
| 4262 | 4271 | if (callee_is_async) { |
| ... | ... | @@ -4333,6 +4342,8 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { |
| 4333 | 4342 | } |
| 4334 | 4343 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 4335 | 4344 | IrInstructionAwaitGen *await = fn->await_list.at(i); |
| 4345 | // TODO If this is a noasync await, it doesn't count |
| 4346 | // https://github.com/ziglang/zig/issues/3157 |
| 4336 | 4347 | switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, |
| 4337 | 4348 | CallModifierNone)) |
| 4338 | 4349 | { |
| ... | ... | @@ -5771,15 +5782,39 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { |
| 5771 | 5782 | if (!fn_is_async(callee)) |
| 5772 | 5783 | continue; |
| 5773 | 5784 | |
| 5774 | | IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); |
| 5775 | | alloca_gen->base.id = IrInstructionIdAllocaGen; |
| 5776 | | alloca_gen->base.source_node = call->base.source_node; |
| 5777 | | alloca_gen->base.scope = call->base.scope; |
| 5778 | | alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false); |
| 5779 | | alloca_gen->base.ref_count = 1; |
| 5780 | | alloca_gen->name_hint = ""; |
| 5781 | | fn->alloca_gen_list.append(alloca_gen); |
| 5782 | | call->frame_result_loc = &alloca_gen->base; |
| 5785 | call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn, |
| 5786 | callee_frame_type, ""); |
| 5787 | } |
| 5788 | // Since this frame is async, an await might represent a suspend point, and |
| 5789 | // therefore need to spill. |
| 5790 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 5791 | IrInstructionAwaitGen *await = fn->await_list.at(i); |
| 5792 | // TODO If this is a noasync await, it doesn't need to spill |
| 5793 | // https://github.com/ziglang/zig/issues/3157 |
| 5794 | if (await->result_loc != nullptr) { |
| 5795 | // If there's a result location, that is the spill |
| 5796 | continue; |
| 5797 | } |
| 5798 | if (!type_has_bits(await->base.value.type)) |
| 5799 | continue; |
| 5800 | if (await->base.value.special != ConstValSpecialRuntime) |
| 5801 | continue; |
| 5802 | if (await->base.ref_count == 0) |
| 5803 | continue; |
| 5804 | if (await->target_fn != nullptr) { |
| 5805 | // we might not need to suspend |
| 5806 | analyze_fn_async(g, await->target_fn, false); |
| 5807 | if (await->target_fn->anal_state == FnAnalStateInvalid) { |
| 5808 | frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid; |
| 5809 | return ErrorSemanticAnalyzeFail; |
| 5810 | } |
| 5811 | if (!fn_is_async(await->target_fn)) { |
| 5812 | // This await does not represent a suspend point. No spill needed. |
| 5813 | continue; |
| 5814 | } |
| 5815 | } |
| 5816 | await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn, |
| 5817 | await->base.value.type, ""); |
| 5783 | 5818 | } |
| 5784 | 5819 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 5785 | 5820 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); |
| ... | ... | @@ -8505,3 +8540,18 @@ void src_assert(bool ok, AstNode *source_node) { |
| 8505 | 8540 | const char *msg = "assertion failed. This is a bug in the Zig compiler."; |
| 8506 | 8541 | stage2_panic(msg, strlen(msg)); |
| 8507 | 8542 | } |
| 8543 | |
| 8544 | IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, |
| 8545 | ZigType *var_type, const char *name_hint) |
| 8546 | { |
| 8547 | IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); |
| 8548 | alloca_gen->base.id = IrInstructionIdAllocaGen; |
| 8549 | alloca_gen->base.source_node = source_node; |
| 8550 | alloca_gen->base.scope = scope; |
| 8551 | alloca_gen->base.value.type = get_pointer_to_type(g, var_type, false); |
| 8552 | alloca_gen->base.ref_count = 1; |
| 8553 | alloca_gen->name_hint = name_hint; |
| 8554 | fn->alloca_gen_list.append(alloca_gen); |
| 8555 | return &alloca_gen->base; |
| 8556 | } |
| 8557 | |