| author | |
| committer | |
| log | 22428a75462e01877181501801dce4c090a87e9c |
| tree | 36affbe0da86d106bd7f6f4091dfb6e95fe461cc |
| parent | b9d1d45dfd0f704bc762732c23aa2844f1d14e8d |
| signature | Commit is signed but in an unrecognized format. |
6 files changed, 187 insertions(+), 57 deletions(-)
src/all_types.hpp+11-2| ... | ... | @@ -74,6 +74,7 @@ struct IrExecutable { |
| 74 | 74 | bool invalid; |
| 75 | 75 | bool is_inline; |
| 76 | 76 | bool is_generic_instantiation; |
| 77 | bool need_err_code_spill; | |
| 77 | 78 | }; |
| 78 | 79 | |
| 79 | 80 | enum OutType { |
| ... | ... | @@ -1384,6 +1385,7 @@ struct ZigFn { |
| 1384 | 1385 | size_t prealloc_backward_branch_quota; |
| 1385 | 1386 | AstNode **param_source_nodes; |
| 1386 | 1387 | Buf **param_names; |
| 1388 | IrInstruction *err_code_spill; | |
| 1387 | 1389 | |
| 1388 | 1390 | AstNode *fn_no_inline_set_node; |
| 1389 | 1391 | AstNode *fn_static_eval_set_node; |
| ... | ... | @@ -2366,7 +2368,8 @@ enum IrInstructionId { |
| 2366 | 2368 | IrInstructionIdAwaitGen, |
| 2367 | 2369 | IrInstructionIdCoroResume, |
| 2368 | 2370 | IrInstructionIdTestCancelRequested, |
| 2369 | IrInstructionIdSpill, | |
| 2371 | IrInstructionIdSpillBegin, | |
| 2372 | IrInstructionIdSpillEnd, | |
| 2370 | 2373 | }; |
| 2371 | 2374 | |
| 2372 | 2375 | struct IrInstruction { |
| ... | ... | @@ -3649,13 +3652,19 @@ enum SpillId { |
| 3649 | 3652 | SpillIdRetErrCode, |
| 3650 | 3653 | }; |
| 3651 | 3654 | |
| 3652 | struct IrInstructionSpill { | |
| 3655 | struct IrInstructionSpillBegin { | |
| 3653 | 3656 | IrInstruction base; |
| 3654 | 3657 | |
| 3655 | 3658 | SpillId spill_id; |
| 3656 | 3659 | IrInstruction *operand; |
| 3657 | 3660 | }; |
| 3658 | 3661 | |
| 3662 | struct IrInstructionSpillEnd { | |
| 3663 | IrInstruction base; | |
| 3664 | ||
| 3665 | IrInstructionSpillBegin *begin; | |
| 3666 | }; | |
| 3667 | ||
| 3659 | 3668 | enum ResultLocId { |
| 3660 | 3669 | ResultLocIdInvalid, |
| 3661 | 3670 | ResultLocIdNone, |
src/analyze.cpp+12| ... | ... | @@ -5190,6 +5190,18 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5190 | 5190 | } |
| 5191 | 5191 | ZigType *fn_type = get_async_fn_type(g, fn->type_entry); |
| 5192 | 5192 | |
| 5193 | if (fn->analyzed_executable.need_err_code_spill) { | |
| 5194 | IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); | |
| 5195 | alloca_gen->base.id = IrInstructionIdAllocaGen; | |
| 5196 | alloca_gen->base.source_node = fn->proto_node; | |
| 5197 | alloca_gen->base.scope = fn->child_scope; | |
| 5198 | alloca_gen->base.value.type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); | |
| 5199 | alloca_gen->base.ref_count = 1; | |
| 5200 | alloca_gen->name_hint = ""; | |
| 5201 | fn->alloca_gen_list.append(alloca_gen); | |
| 5202 | fn->err_code_spill = &alloca_gen->base; | |
| 5203 | } | |
| 5204 | ||
| 5193 | 5205 | for (size_t i = 0; i < fn->call_list.length; i += 1) { |
| 5194 | 5206 | IrInstructionCallGen *call = fn->call_list.at(i); |
| 5195 | 5207 | ZigFn *callee = call->fn_entry; |
src/codegen.cpp+44-31| ... | ... | @@ -2274,16 +2274,16 @@ static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMV |
| 2274 | 2274 | static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2275 | 2275 | IrInstructionReturnBegin *instruction) |
| 2276 | 2276 | { |
| 2277 | bool ret_type_has_bits = instruction->operand != nullptr && | |
| 2278 | type_has_bits(instruction->operand->value.type); | |
| 2279 | ||
| 2277 | ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value.type : nullptr; | |
| 2278 | bool operand_has_bits = (operand_type != nullptr) && type_has_bits(operand_type); | |
| 2280 | 2279 | if (!fn_is_async(g->cur_fn)) { |
| 2281 | return ret_type_has_bits ? ir_llvm_value(g, instruction->operand) : nullptr; | |
| 2280 | return operand_has_bits ? ir_llvm_value(g, instruction->operand) : nullptr; | |
| 2282 | 2281 | } |
| 2283 | 2282 | |
| 2283 | ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; | |
| 2284 | bool ret_type_has_bits = type_has_bits(ret_type); | |
| 2284 | 2285 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2285 | 2286 | |
| 2286 | ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr; | |
| 2287 | 2287 | if (ret_type_has_bits && !handle_is_ptr(ret_type)) { |
| 2288 | 2288 | // It's a scalar, so it didn't get written to the result ptr. Do that before the atomic rmw. |
| 2289 | 2289 | LLVMBuildStore(g->builder, ir_llvm_value(g, instruction->operand), g->cur_ret_ptr); |
| ... | ... | @@ -2333,11 +2333,11 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2333 | 2333 | g->cur_is_after_return = true; |
| 2334 | 2334 | LLVMBuildStore(g->builder, g->cur_async_prev_val, g->cur_async_prev_val_field_ptr); |
| 2335 | 2335 | |
| 2336 | if (!ret_type_has_bits) { | |
| 2336 | if (!operand_has_bits) { | |
| 2337 | 2337 | return nullptr; |
| 2338 | 2338 | } |
| 2339 | 2339 | |
| 2340 | return get_handle_value(g, g->cur_ret_ptr, ret_type, get_pointer_to_type(g, ret_type, true)); | |
| 2340 | return get_handle_value(g, g->cur_ret_ptr, operand_type, get_pointer_to_type(g, operand_type, true)); | |
| 2341 | 2341 | } |
| 2342 | 2342 | |
| 2343 | 2343 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) { |
| ... | ... | @@ -5113,18 +5113,6 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 5113 | 5113 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); |
| 5114 | 5114 | } |
| 5115 | 5115 | |
| 5116 | static LLVMValueRef gen_unwrap_err_code(CodeGen *g, LLVMValueRef err_union_ptr, ZigType *ptr_type) { | |
| 5117 | ZigType *err_union_type = ptr_type->data.pointer.child_type; | |
| 5118 | ZigType *payload_type = err_union_type->data.error_union.payload_type; | |
| 5119 | if (!type_has_bits(payload_type)) { | |
| 5120 | return err_union_ptr; | |
| 5121 | } else { | |
| 5122 | // TODO assign undef to the payload | |
| 5123 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | |
| 5124 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | |
| 5125 | } | |
| 5126 | } | |
| 5127 | ||
| 5128 | 5116 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, |
| 5129 | 5117 | IrInstructionUnwrapErrCode *instruction) |
| 5130 | 5118 | { |
| ... | ... | @@ -5133,8 +5121,16 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 5133 | 5121 | |
| 5134 | 5122 | ZigType *ptr_type = instruction->err_union_ptr->value.type; |
| 5135 | 5123 | assert(ptr_type->id == ZigTypeIdPointer); |
| 5124 | ZigType *err_union_type = ptr_type->data.pointer.child_type; | |
| 5125 | ZigType *payload_type = err_union_type->data.error_union.payload_type; | |
| 5136 | 5126 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union_ptr); |
| 5137 | return gen_unwrap_err_code(g, err_union_ptr, ptr_type); | |
| 5127 | if (!type_has_bits(payload_type)) { | |
| 5128 | return err_union_ptr; | |
| 5129 | } else { | |
| 5130 | // TODO assign undef to the payload | |
| 5131 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | |
| 5132 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | |
| 5133 | } | |
| 5138 | 5134 | } |
| 5139 | 5135 | |
| 5140 | 5136 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -5615,21 +5611,36 @@ static LLVMValueRef ir_render_test_cancel_requested(CodeGen *g, IrExecutable *ex |
| 5615 | 5611 | } |
| 5616 | 5612 | } |
| 5617 | 5613 | |
| 5618 | static LLVMValueRef ir_render_spill(CodeGen *g, IrExecutable *executable, IrInstructionSpill *instruction) { | |
| 5614 | static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable, | |
| 5615 | IrInstructionSpillBegin *instruction) | |
| 5616 | { | |
| 5619 | 5617 | if (!fn_is_async(g->cur_fn)) |
| 5620 | return ir_llvm_value(g, instruction->operand); | |
| 5618 | return nullptr; | |
| 5621 | 5619 | |
| 5622 | 5620 | switch (instruction->spill_id) { |
| 5623 | 5621 | case SpillIdInvalid: |
| 5624 | 5622 | zig_unreachable(); |
| 5625 | 5623 | case SpillIdRetErrCode: { |
| 5626 | LLVMValueRef ret_ptr = LLVMBuildLoad(g->builder, g->cur_ret_ptr, ""); | |
| 5627 | ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; | |
| 5628 | if (ret_type->id == ZigTypeIdErrorUnion) { | |
| 5629 | return gen_unwrap_err_code(g, ret_ptr, get_pointer_to_type(g, ret_type, true)); | |
| 5630 | } else { | |
| 5631 | zig_unreachable(); | |
| 5632 | } | |
| 5624 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); | |
| 5625 | LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill); | |
| 5626 | LLVMBuildStore(g->builder, operand, ptr); | |
| 5627 | return nullptr; | |
| 5628 | } | |
| 5629 | ||
| 5630 | } | |
| 5631 | zig_unreachable(); | |
| 5632 | } | |
| 5633 | ||
| 5634 | static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, IrInstructionSpillEnd *instruction) { | |
| 5635 | if (!fn_is_async(g->cur_fn)) | |
| 5636 | return ir_llvm_value(g, instruction->begin->operand); | |
| 5637 | ||
| 5638 | switch (instruction->begin->spill_id) { | |
| 5639 | case SpillIdInvalid: | |
| 5640 | zig_unreachable(); | |
| 5641 | case SpillIdRetErrCode: { | |
| 5642 | LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill); | |
| 5643 | return LLVMBuildLoad(g->builder, ptr, ""); | |
| 5633 | 5644 | } |
| 5634 | 5645 | |
| 5635 | 5646 | } |
| ... | ... | @@ -5891,8 +5902,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5891 | 5902 | return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction); |
| 5892 | 5903 | case IrInstructionIdTestCancelRequested: |
| 5893 | 5904 | return ir_render_test_cancel_requested(g, executable, (IrInstructionTestCancelRequested *)instruction); |
| 5894 | case IrInstructionIdSpill: | |
| 5895 | return ir_render_spill(g, executable, (IrInstructionSpill *)instruction); | |
| 5905 | case IrInstructionIdSpillBegin: | |
| 5906 | return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction); | |
| 5907 | case IrInstructionIdSpillEnd: | |
| 5908 | return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction); | |
| 5896 | 5909 | } |
| 5897 | 5910 | zig_unreachable(); |
| 5898 | 5911 | } |
src/ir.cpp+77-20| ... | ... | @@ -1066,8 +1066,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelReques |
| 1066 | 1066 | return IrInstructionIdTestCancelRequested; |
| 1067 | 1067 | } |
| 1068 | 1068 | |
| 1069 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSpill *) { | |
| 1070 | return IrInstructionIdSpill; | |
| 1069 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillBegin *) { | |
| 1070 | return IrInstructionIdSpillBegin; | |
| 1071 | } | |
| 1072 | ||
| 1073 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) { | |
| 1074 | return IrInstructionIdSpillEnd; | |
| 1071 | 1075 | } |
| 1072 | 1076 | |
| 1073 | 1077 | template<typename T> |
| ... | ... | @@ -3336,15 +3340,28 @@ static IrInstruction *ir_build_test_cancel_requested(IrBuilder *irb, Scope *scop |
| 3336 | 3340 | return &instruction->base; |
| 3337 | 3341 | } |
| 3338 | 3342 | |
| 3339 | static IrInstruction *ir_build_spill(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3343 | static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3340 | 3344 | IrInstruction *operand, SpillId spill_id) |
| 3341 | 3345 | { |
| 3342 | IrInstructionSpill *instruction = ir_build_instruction<IrInstructionSpill>(irb, scope, source_node); | |
| 3346 | IrInstructionSpillBegin *instruction = ir_build_instruction<IrInstructionSpillBegin>(irb, scope, source_node); | |
| 3347 | instruction->base.value.special = ConstValSpecialStatic; | |
| 3348 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; | |
| 3343 | 3349 | instruction->operand = operand; |
| 3344 | 3350 | instruction->spill_id = spill_id; |
| 3345 | 3351 | |
| 3346 | 3352 | ir_ref_instruction(operand, irb->current_basic_block); |
| 3347 | 3353 | |
| 3354 | return instruction; | |
| 3355 | } | |
| 3356 | ||
| 3357 | static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3358 | IrInstructionSpillBegin *begin) | |
| 3359 | { | |
| 3360 | IrInstructionSpillEnd *instruction = ir_build_instruction<IrInstructionSpillEnd>(irb, scope, source_node); | |
| 3361 | instruction->begin = begin; | |
| 3362 | ||
| 3363 | ir_ref_instruction(&begin->base, irb->current_basic_block); | |
| 3364 | ||
| 3348 | 3365 | return &instruction->base; |
| 3349 | 3366 | } |
| 3350 | 3367 | |
| ... | ... | @@ -3602,14 +3619,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3602 | 3619 | IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); |
| 3603 | 3620 | IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); |
| 3604 | 3621 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val)); |
| 3605 | err_val = ir_build_return_begin(irb, scope, node, err_val); | |
| 3622 | IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val, | |
| 3623 | SpillIdRetErrCode); | |
| 3624 | ir_build_return_begin(irb, scope, node, err_val); | |
| 3625 | err_val = ir_build_spill_end(irb, scope, node, spill_begin); | |
| 3626 | ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1); | |
| 3627 | result_loc_ret->base.id = ResultLocIdReturn; | |
| 3628 | ir_build_reset_result(irb, scope, node, &result_loc_ret->base); | |
| 3629 | ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); | |
| 3606 | 3630 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) { |
| 3607 | ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1); | |
| 3608 | result_loc_ret->base.id = ResultLocIdReturn; | |
| 3609 | ir_build_reset_result(irb, scope, node, &result_loc_ret->base); | |
| 3610 | err_val = ir_build_spill(irb, scope, node, err_val, SpillIdRetErrCode); | |
| 3611 | ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); | |
| 3612 | ||
| 3613 | 3631 | if (irb->codegen->have_err_ret_tracing && !should_inline) { |
| 3614 | 3632 | ir_build_save_err_ret_addr(irb, scope, node); |
| 3615 | 3633 | } |
| ... | ... | @@ -12778,8 +12796,21 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 12778 | 12796 | return ir_finish_anal(ira, result); |
| 12779 | 12797 | } |
| 12780 | 12798 | |
| 12799 | // This cast might have been already done from IrInstructionReturnBegin but it also | |
| 12800 | // might not have, in the case of `try`. | |
| 12801 | IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); | |
| 12802 | if (type_is_invalid(casted_operand->value.type)) { | |
| 12803 | AstNode *source_node = ira->explicit_return_type_source_node; | |
| 12804 | if (source_node != nullptr) { | |
| 12805 | ErrorMsg *msg = ira->codegen->errors.last(); | |
| 12806 | add_error_note(ira->codegen, msg, source_node, | |
| 12807 | buf_sprintf("return type declared here")); | |
| 12808 | } | |
| 12809 | return ir_unreach_error(ira); | |
| 12810 | } | |
| 12811 | ||
| 12781 | 12812 | IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, |
| 12782 | instruction->base.source_node, operand); | |
| 12813 | instruction->base.source_node, casted_operand); | |
| 12783 | 12814 | result->value.type = ira->codegen->builtin_types.entry_unreachable; |
| 12784 | 12815 | return ir_finish_anal(ira, result); |
| 12785 | 12816 | } |
| ... | ... | @@ -24742,15 +24773,38 @@ static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ir |
| 24742 | 24773 | return ir_build_test_cancel_requested(&ira->new_irb, instruction->base.scope, instruction->base.source_node); |
| 24743 | 24774 | } |
| 24744 | 24775 | |
| 24745 | static IrInstruction *ir_analyze_instruction_spill(IrAnalyze *ira, IrInstructionSpill *instruction) { | |
| 24776 | static IrInstruction *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstructionSpillBegin *instruction) { | |
| 24777 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) | |
| 24778 | return ir_const_void(ira, &instruction->base); | |
| 24779 | ||
| 24746 | 24780 | IrInstruction *operand = instruction->operand->child; |
| 24747 | 24781 | if (type_is_invalid(operand->value.type)) |
| 24748 | 24782 | return ira->codegen->invalid_instruction; |
| 24749 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) { | |
| 24783 | ||
| 24784 | if (!type_has_bits(operand->value.type)) | |
| 24785 | return ir_const_void(ira, &instruction->base); | |
| 24786 | ||
| 24787 | ir_assert(instruction->spill_id == SpillIdRetErrCode, &instruction->base); | |
| 24788 | ira->new_irb.exec->need_err_code_spill = true; | |
| 24789 | ||
| 24790 | IrInstructionSpillBegin *result = ir_build_spill_begin(&ira->new_irb, instruction->base.scope, | |
| 24791 | instruction->base.source_node, operand, instruction->spill_id); | |
| 24792 | return &result->base; | |
| 24793 | } | |
| 24794 | ||
| 24795 | static IrInstruction *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstructionSpillEnd *instruction) { | |
| 24796 | IrInstruction *operand = instruction->begin->operand->child; | |
| 24797 | if (type_is_invalid(operand->value.type)) | |
| 24798 | return ira->codegen->invalid_instruction; | |
| 24799 | ||
| 24800 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope) || !type_has_bits(operand->value.type)) | |
| 24750 | 24801 | return operand; |
| 24751 | } | |
| 24752 | IrInstruction *result = ir_build_spill(&ira->new_irb, instruction->base.scope, instruction->base.source_node, | |
| 24753 | operand, instruction->spill_id); | |
| 24802 | ||
| 24803 | ir_assert(instruction->begin->base.child->id == IrInstructionIdSpillBegin, &instruction->base); | |
| 24804 | IrInstructionSpillBegin *begin = reinterpret_cast<IrInstructionSpillBegin *>(instruction->begin->base.child); | |
| 24805 | ||
| 24806 | IrInstruction *result = ir_build_spill_end(&ira->new_irb, instruction->base.scope, | |
| 24807 | instruction->base.source_node, begin); | |
| 24754 | 24808 | result->value.type = operand->value.type; |
| 24755 | 24809 | return result; |
| 24756 | 24810 | } |
| ... | ... | @@ -25054,8 +25108,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 25054 | 25108 | return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction); |
| 25055 | 25109 | case IrInstructionIdTestCancelRequested: |
| 25056 | 25110 | return ir_analyze_instruction_test_cancel_requested(ira, (IrInstructionTestCancelRequested *)instruction); |
| 25057 | case IrInstructionIdSpill: | |
| 25058 | return ir_analyze_instruction_spill(ira, (IrInstructionSpill *)instruction); | |
| 25111 | case IrInstructionIdSpillBegin: | |
| 25112 | return ir_analyze_instruction_spill_begin(ira, (IrInstructionSpillBegin *)instruction); | |
| 25113 | case IrInstructionIdSpillEnd: | |
| 25114 | return ir_analyze_instruction_spill_end(ira, (IrInstructionSpillEnd *)instruction); | |
| 25059 | 25115 | } |
| 25060 | 25116 | zig_unreachable(); |
| 25061 | 25117 | } |
| ... | ... | @@ -25193,6 +25249,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25193 | 25249 | case IrInstructionIdCoroResume: |
| 25194 | 25250 | case IrInstructionIdAwaitSrc: |
| 25195 | 25251 | case IrInstructionIdAwaitGen: |
| 25252 | case IrInstructionIdSpillBegin: | |
| 25196 | 25253 | return true; |
| 25197 | 25254 | |
| 25198 | 25255 | case IrInstructionIdPhi: |
| ... | ... | @@ -25291,7 +25348,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25291 | 25348 | case IrInstructionIdAllocaSrc: |
| 25292 | 25349 | case IrInstructionIdAllocaGen: |
| 25293 | 25350 | case IrInstructionIdTestCancelRequested: |
| 25294 | case IrInstructionIdSpill: | |
| 25351 | case IrInstructionIdSpillEnd: | |
| 25295 | 25352 | return false; |
| 25296 | 25353 | |
| 25297 | 25354 | case IrInstructionIdAsm: |
src/ir_print.cpp+13-4| ... | ... | @@ -1554,12 +1554,18 @@ static void ir_print_test_cancel_requested(IrPrint *irp, IrInstructionTestCancel |
| 1554 | 1554 | fprintf(irp->f, "@testCancelRequested()"); |
| 1555 | 1555 | } |
| 1556 | 1556 | |
| 1557 | static void ir_print_spill(IrPrint *irp, IrInstructionSpill *instruction) { | |
| 1558 | fprintf(irp->f, "@spill("); | |
| 1557 | static void ir_print_spill_begin(IrPrint *irp, IrInstructionSpillBegin *instruction) { | |
| 1558 | fprintf(irp->f, "@spillBegin("); | |
| 1559 | 1559 | ir_print_other_instruction(irp, instruction->operand); |
| 1560 | 1560 | fprintf(irp->f, ")"); |
| 1561 | 1561 | } |
| 1562 | 1562 | |
| 1563 | static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) { | |
| 1564 | fprintf(irp->f, "@spillEnd("); | |
| 1565 | ir_print_other_instruction(irp, &instruction->begin->base); | |
| 1566 | fprintf(irp->f, ")"); | |
| 1567 | } | |
| 1568 | ||
| 1563 | 1569 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1564 | 1570 | ir_print_prefix(irp, instruction); |
| 1565 | 1571 | switch (instruction->id) { |
| ... | ... | @@ -2045,8 +2051,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 2045 | 2051 | case IrInstructionIdTestCancelRequested: |
| 2046 | 2052 | ir_print_test_cancel_requested(irp, (IrInstructionTestCancelRequested *)instruction); |
| 2047 | 2053 | break; |
| 2048 | case IrInstructionIdSpill: | |
| 2049 | ir_print_spill(irp, (IrInstructionSpill *)instruction); | |
| 2054 | case IrInstructionIdSpillBegin: | |
| 2055 | ir_print_spill_begin(irp, (IrInstructionSpillBegin *)instruction); | |
| 2056 | break; | |
| 2057 | case IrInstructionIdSpillEnd: | |
| 2058 | ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction); | |
| 2050 | 2059 | break; |
| 2051 | 2060 | } |
| 2052 | 2061 | fprintf(irp->f, "\n"); |
test/stage1/behavior/coroutines.zig+30| ... | ... | @@ -642,3 +642,33 @@ test "combining try with errdefer cancel" { |
| 642 | 642 | }; |
| 643 | 643 | S.doTheTest(); |
| 644 | 644 | } |
| 645 | ||
| 646 | test "try in an async function with error union and non-zero-bit payload" { | |
| 647 | const S = struct { | |
| 648 | var frame: anyframe = undefined; | |
| 649 | var ok = false; | |
| 650 | ||
| 651 | fn doTheTest() void { | |
| 652 | _ = async amain(); | |
| 653 | resume frame; | |
| 654 | expect(ok); | |
| 655 | } | |
| 656 | ||
| 657 | fn amain() void { | |
| 658 | std.testing.expectError(error.Bad, theProblem()); | |
| 659 | ok = true; | |
| 660 | } | |
| 661 | ||
| 662 | fn theProblem() ![]u8 { | |
| 663 | frame = @frame(); | |
| 664 | suspend; | |
| 665 | const result = try other(); | |
| 666 | return result; | |
| 667 | } | |
| 668 | ||
| 669 | fn other() ![]u8 { | |
| 670 | return error.Bad; | |
| 671 | } | |
| 672 | }; | |
| 673 | S.doTheTest(); | |
| 674 | } |