| ... | @@ -4232,31 +4232,40 @@ static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode | ... | @@ -4232,31 +4232,40 @@ static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode |
| 4232 | { | 4232 | { |
| 4233 | if (modifier == CallModifierNoAsync) | 4233 | if (modifier == CallModifierNoAsync) |
| 4234 | return ErrorNone; | 4234 | return ErrorNone; |
| 4235 | if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified) | 4235 | bool callee_is_async = false; |
| 4236 | return ErrorNone; | 4236 | switch (callee->type_entry->data.fn.fn_type_id.cc) { |
| 4237 | if (callee->anal_state == FnAnalStateReady) { | 4237 | case CallingConventionUnspecified: |
| 4238 | analyze_fn_body(g, callee); | 4238 | break; |
| 4239 | if (callee->anal_state == FnAnalStateInvalid) { | 4239 | case CallingConventionAsync: |
| 4240 | return ErrorSemanticAnalyzeFail; | 4240 | callee_is_async = true; |
| 4241 | } | 4241 | break; |
| | 4242 | default: |
| | 4243 | return ErrorNone; |
| 4242 | } | 4244 | } |
| 4243 | bool callee_is_async; | 4245 | if (!callee_is_async) { |
| 4244 | if (callee->anal_state == FnAnalStateComplete) { | 4246 | if (callee->anal_state == FnAnalStateReady) { |
| 4245 | analyze_fn_async(g, callee, true); | 4247 | analyze_fn_body(g, callee); |
| 4246 | if (callee->anal_state == FnAnalStateInvalid) { | 4248 | if (callee->anal_state == FnAnalStateInvalid) { |
| 4247 | return ErrorSemanticAnalyzeFail; | 4249 | return ErrorSemanticAnalyzeFail; |
| | 4250 | } |
| 4248 | } | 4251 | } |
| 4249 | callee_is_async = fn_is_async(callee); | 4252 | if (callee->anal_state == FnAnalStateComplete) { |
| 4250 | } else { | 4253 | analyze_fn_async(g, callee, true); |
| 4251 | // If it's already been determined, use that value. Otherwise | 4254 | if (callee->anal_state == FnAnalStateInvalid) { |
| 4252 | // assume non-async, emit an error later if it turned out to be async. | 4255 | return ErrorSemanticAnalyzeFail; |
| 4253 | if (callee->inferred_async_node == nullptr || | 4256 | } |
| 4254 | callee->inferred_async_node == inferred_async_checking) | 4257 | callee_is_async = fn_is_async(callee); |
| 4255 | { | | |
| 4256 | callee->assumed_non_async = call_node; | | |
| 4257 | callee_is_async = false; | | |
| 4258 | } else { | 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 | if (callee_is_async) { | 4271 | if (callee_is_async) { |
| ... | @@ -4333,6 +4342,8 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { | ... | @@ -4333,6 +4342,8 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { |
| 4333 | } | 4342 | } |
| 4334 | for (size_t i = 0; i < fn->await_list.length; i += 1) { | 4343 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 4335 | IrInstructionAwaitGen *await = fn->await_list.at(i); | 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 | switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, | 4347 | switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, |
| 4337 | CallModifierNone)) | 4348 | CallModifierNone)) |
| 4338 | { | 4349 | { |
| ... | @@ -5771,15 +5782,39 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5771,15 +5782,39 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { |
| 5771 | if (!fn_is_async(callee)) | 5782 | if (!fn_is_async(callee)) |
| 5772 | continue; | 5783 | continue; |
| 5773 | | 5784 | |
| 5774 | IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); | 5785 | call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn, |
| 5775 | alloca_gen->base.id = IrInstructionIdAllocaGen; | 5786 | callee_frame_type, ""); |
| 5776 | alloca_gen->base.source_node = call->base.source_node; | 5787 | } |
| 5777 | alloca_gen->base.scope = call->base.scope; | 5788 | // Since this frame is async, an await might represent a suspend point, and |
| 5778 | alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false); | 5789 | // therefore need to spill. |
| 5779 | alloca_gen->base.ref_count = 1; | 5790 | for (size_t i = 0; i < fn->await_list.length; i += 1) { |
| 5780 | alloca_gen->name_hint = ""; | 5791 | IrInstructionAwaitGen *await = fn->await_list.at(i); |
| 5781 | fn->alloca_gen_list.append(alloca_gen); | 5792 | // TODO If this is a noasync await, it doesn't need to spill |
| 5782 | call->frame_result_loc = &alloca_gen->base; | 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 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 5819 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 5785 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); | 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,3 +8540,18 @@ void src_assert(bool ok, AstNode *source_node) { |
| 8505 | const char *msg = "assertion failed. This is a bug in the Zig compiler."; | 8540 | const char *msg = "assertion failed. This is a bug in the Zig compiler."; |
| 8506 | stage2_panic(msg, strlen(msg)); | 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 | |