| author | |
| committer | |
| log | 026aebf2ea567c15eebf9ddb9180f7d0e2ec7a9d |
| tree | e01512d7d9883706d207fd701c0b89165f431880 |
| parent | d24345386274e3abcbcc676fe65bda127c06ce8e |
this one doesn't work either6 files changed, 222 insertions(+), 51 deletions(-)
src/all_types.hpp+9| ... | @@ -1634,6 +1634,7 @@ struct CodeGen { | ... | @@ -1634,6 +1634,7 @@ struct CodeGen { |
| 1634 | LLVMValueRef coro_free_fn_val; | 1634 | LLVMValueRef coro_free_fn_val; |
| 1635 | LLVMValueRef coro_resume_fn_val; | 1635 | LLVMValueRef coro_resume_fn_val; |
| 1636 | LLVMValueRef coro_save_fn_val; | 1636 | LLVMValueRef coro_save_fn_val; |
| 1637 | LLVMValueRef coro_alloc_helper_fn_val; | ||
| 1637 | bool error_during_imports; | 1638 | bool error_during_imports; |
| 1638 | 1639 | ||
| 1639 | const char **clang_argv; | 1640 | const char **clang_argv; |
| ... | @@ -2004,6 +2005,7 @@ enum IrInstructionId { | ... | @@ -2004,6 +2005,7 @@ enum IrInstructionId { |
| 2004 | IrInstructionIdCoroFree, | 2005 | IrInstructionIdCoroFree, |
| 2005 | IrInstructionIdCoroResume, | 2006 | IrInstructionIdCoroResume, |
| 2006 | IrInstructionIdCoroSave, | 2007 | IrInstructionIdCoroSave, |
| 2008 | IrInstructionIdCoroAllocHelper, | ||
| 2007 | }; | 2009 | }; |
| 2008 | 2010 | ||
| 2009 | struct IrInstruction { | 2011 | struct IrInstruction { |
| ... | @@ -2913,6 +2915,13 @@ struct IrInstructionCoroSave { | ... | @@ -2913,6 +2915,13 @@ struct IrInstructionCoroSave { |
| 2913 | IrInstruction *coro_handle; | 2915 | IrInstruction *coro_handle; |
| 2914 | }; | 2916 | }; |
| 2915 | 2917 | ||
| 2918 | struct IrInstructionCoroAllocHelper { | ||
| 2919 | IrInstruction base; | ||
| 2920 | |||
| 2921 | IrInstruction *alloc_fn; | ||
| 2922 | IrInstruction *coro_size; | ||
| 2923 | }; | ||
| 2924 | |||
| 2916 | static const size_t slice_ptr_index = 0; | 2925 | static const size_t slice_ptr_index = 0; |
| 2917 | static const size_t slice_len_index = 1; | 2926 | static const size_t slice_len_index = 1; |
| 2918 | 2927 |
src/analyze.cpp+7-3| ... | @@ -1001,9 +1001,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -1001,9 +1001,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1001 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && | 1001 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && |
| 1002 | handle_is_ptr(fn_type_id->return_type); | 1002 | handle_is_ptr(fn_type_id->return_type); |
| 1003 | bool is_async = fn_type_id->cc == CallingConventionAsync; | 1003 | bool is_async = fn_type_id->cc == CallingConventionAsync; |
| 1004 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && | 1004 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); |
| 1005 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || | ||
| 1006 | fn_type_id->return_type->id == TypeTableEntryIdErrorSet); | ||
| 1007 | // +1 for maybe making the first argument the return value | 1005 | // +1 for maybe making the first argument the return value |
| 1008 | // +1 for maybe first argument the error return trace | 1006 | // +1 for maybe first argument the error return trace |
| 1009 | // +2 for maybe arguments async allocator and error code pointer | 1007 | // +2 for maybe arguments async allocator and error code pointer |
| ... | @@ -5795,3 +5793,9 @@ bool type_is_global_error_set(TypeTableEntry *err_set_type) { | ... | @@ -5795,3 +5793,9 @@ bool type_is_global_error_set(TypeTableEntry *err_set_type) { |
| 5795 | uint32_t get_coro_frame_align_bytes(CodeGen *g) { | 5793 | uint32_t get_coro_frame_align_bytes(CodeGen *g) { |
| 5796 | return g->pointer_size_bytes * 2; | 5794 | return g->pointer_size_bytes * 2; |
| 5797 | } | 5795 | } |
| 5796 | |||
| 5797 | bool fn_type_can_fail(FnTypeId *fn_type_id) { | ||
| 5798 | TypeTableEntry *return_type = fn_type_id->return_type; | ||
| 5799 | return return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdErrorSet || | ||
| 5800 | fn_type_id->cc == CallingConventionAsync; | ||
| 5801 | } |
src/analyze.hpp+1| ... | @@ -192,5 +192,6 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry); | ... | @@ -192,5 +192,6 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry); |
| 192 | TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry); | 192 | TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry); |
| 193 | 193 | ||
| 194 | uint32_t get_coro_frame_align_bytes(CodeGen *g); | 194 | uint32_t get_coro_frame_align_bytes(CodeGen *g); |
| 195 | bool fn_type_can_fail(FnTypeId *fn_type_id); | ||
| 195 | 196 | ||
| 196 | #endif | 197 | #endif |
src/codegen.cpp+141-14| ... | @@ -412,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e | ... | @@ -412,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e |
| 412 | return UINT32_MAX; | 412 | return UINT32_MAX; |
| 413 | } | 413 | } |
| 414 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | 414 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 415 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | 415 | if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) { |
| 416 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) { | ||
| 417 | return UINT32_MAX; | 416 | return UINT32_MAX; |
| 418 | } | 417 | } |
| 418 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | ||
| 419 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); | 419 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); |
| 420 | return first_arg_ret ? 1 : 0; | 420 | return first_arg_ret ? 1 : 0; |
| 421 | } | 421 | } |
| ... | @@ -2662,21 +2662,23 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2662,21 +2662,23 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2662 | } | 2662 | } |
| 2663 | } | 2663 | } |
| 2664 | 2664 | ||
| 2665 | static bool get_prefix_arg_err_ret_stack(CodeGen *g, TypeTableEntry *src_return_type) { | 2665 | static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) { |
| 2666 | return g->have_err_ret_tracing && | 2666 | return g->have_err_ret_tracing && |
| 2667 | (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet); | 2667 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || |
| 2668 | fn_type_id->return_type->id == TypeTableEntryIdErrorSet || | ||
| 2669 | fn_type_id->cc == CallingConventionAsync); | ||
| 2668 | } | 2670 | } |
| 2669 | 2671 | ||
| 2670 | static size_t get_async_allocator_arg_index(CodeGen *g, TypeTableEntry *src_return_type) { | 2672 | static size_t get_async_allocator_arg_index(CodeGen *g, FnTypeId *fn_type_id) { |
| 2671 | // 0 1 2 3 | 2673 | // 0 1 2 3 |
| 2672 | // err_ret_stack allocator_ptr err_code other_args... | 2674 | // err_ret_stack allocator_ptr err_code other_args... |
| 2673 | return get_prefix_arg_err_ret_stack(g, src_return_type) ? 1 : 0; | 2675 | return get_prefix_arg_err_ret_stack(g, fn_type_id) ? 1 : 0; |
| 2674 | } | 2676 | } |
| 2675 | 2677 | ||
| 2676 | static size_t get_async_err_code_arg_index(CodeGen *g, TypeTableEntry *src_return_type) { | 2678 | static size_t get_async_err_code_arg_index(CodeGen *g, FnTypeId *fn_type_id) { |
| 2677 | // 0 1 2 3 | 2679 | // 0 1 2 3 |
| 2678 | // err_ret_stack allocator_ptr err_code other_args... | 2680 | // err_ret_stack allocator_ptr err_code other_args... |
| 2679 | return 1 + get_async_allocator_arg_index(g, src_return_type); | 2681 | return 1 + get_async_allocator_arg_index(g, fn_type_id); |
| 2680 | } | 2682 | } |
| 2681 | 2683 | ||
| 2682 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { | 2684 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { |
| ... | @@ -2698,7 +2700,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2698,7 +2700,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2698 | 2700 | ||
| 2699 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) && | 2701 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) && |
| 2700 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc); | 2702 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc); |
| 2701 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, src_return_type); | 2703 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id); |
| 2702 | // +2 for the async args | 2704 | // +2 for the async args |
| 2703 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2; | 2705 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2; |
| 2704 | bool is_var_args = fn_type_id->is_var_args; | 2706 | bool is_var_args = fn_type_id->is_var_args; |
| ... | @@ -2717,7 +2719,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2717,7 +2719,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2717 | gen_param_index += 1; | 2719 | gen_param_index += 1; |
| 2718 | 2720 | ||
| 2719 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); | 2721 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); |
| 2720 | LLVMBuildStore(g->builder, LLVMConstNull(g->builtin_types.entry_global_error_set->type_ref), err_val_ptr); | ||
| 2721 | gen_param_values[gen_param_index] = err_val_ptr; | 2722 | gen_param_values[gen_param_index] = err_val_ptr; |
| 2722 | gen_param_index += 1; | 2723 | gen_param_index += 1; |
| 2723 | } | 2724 | } |
| ... | @@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns |
| 3293 | static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable, | 3294 | static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable, |
| 3294 | IrInstructionGetImplicitAllocator *instruction) | 3295 | IrInstructionGetImplicitAllocator *instruction) |
| 3295 | { | 3296 | { |
| 3296 | TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; | 3297 | size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); |
| 3297 | size_t allocator_arg_index = get_async_allocator_arg_index(g, src_return_type); | ||
| 3298 | return LLVMGetParam(g->cur_fn_val, allocator_arg_index); | 3298 | return LLVMGetParam(g->cur_fn_val, allocator_arg_index); |
| 3299 | } | 3299 | } |
| 3300 | 3300 | ||
| ... | @@ -3926,8 +3926,7 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I | ... | @@ -3926,8 +3926,7 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I |
| 3926 | static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable, | 3926 | static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable, |
| 3927 | IrInstructionCoroAllocFail *instruction) | 3927 | IrInstructionCoroAllocFail *instruction) |
| 3928 | { | 3928 | { |
| 3929 | TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; | 3929 | size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); |
| 3930 | size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, src_return_type); | ||
| 3931 | LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index); | 3930 | LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index); |
| 3932 | LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val); | 3931 | LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val); |
| 3933 | LLVMBuildStore(g->builder, err_code, err_code_ptr_val); | 3932 | LLVMBuildStore(g->builder, err_code, err_code_ptr_val); |
| ... | @@ -3985,6 +3984,132 @@ static LLVMValueRef ir_render_coro_save(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -3985,6 +3984,132 @@ static LLVMValueRef ir_render_coro_save(CodeGen *g, IrExecutable *executable, Ir |
| 3985 | return LLVMBuildCall(g->builder, get_coro_save_fn_val(g), &coro_handle, 1, ""); | 3984 | return LLVMBuildCall(g->builder, get_coro_save_fn_val(g), &coro_handle, 1, ""); |
| 3986 | } | 3985 | } |
| 3987 | 3986 | ||
| 3987 | static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_fn_type_ref, TypeTableEntry *fn_type) { | ||
| 3988 | if (g->coro_alloc_helper_fn_val != nullptr) | ||
| 3989 | return g->coro_alloc_fn_val; | ||
| 3990 | |||
| 3991 | assert(fn_type->id == TypeTableEntryIdFn); | ||
| 3992 | |||
| 3993 | TypeTableEntry *ptr_to_err_code_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); | ||
| 3994 | |||
| 3995 | LLVMTypeRef alloc_raw_fn_type_ref = LLVMGetElementType(alloc_fn_type_ref); | ||
| 3996 | LLVMTypeRef *alloc_fn_arg_types = allocate<LLVMTypeRef>(LLVMCountParamTypes(alloc_raw_fn_type_ref)); | ||
| 3997 | LLVMGetParamTypes(alloc_raw_fn_type_ref, alloc_fn_arg_types); | ||
| 3998 | |||
| 3999 | ZigList<LLVMTypeRef> arg_types = {}; | ||
| 4000 | arg_types.append(alloc_fn_type_ref); | ||
| 4001 | if (g->have_err_ret_tracing) { | ||
| 4002 | arg_types.append(alloc_fn_arg_types[1]); | ||
| 4003 | } | ||
| 4004 | arg_types.append(alloc_fn_arg_types[g->have_err_ret_tracing ? 2 : 1]); | ||
| 4005 | arg_types.append(ptr_to_err_code_type->type_ref); | ||
| 4006 | arg_types.append(g->builtin_types.entry_usize->type_ref); | ||
| 4007 | |||
| 4008 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), | ||
| 4009 | arg_types.items, arg_types.length, false); | ||
| 4010 | |||
| 4011 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_coro_alloc_helper"), false); | ||
| 4012 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | ||
| 4013 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | ||
| 4014 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | ||
| 4015 | addLLVMFnAttr(fn_val, "nounwind"); | ||
| 4016 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | ||
| 4017 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); | ||
| 4018 | |||
| 4019 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | ||
| 4020 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | ||
| 4021 | FnTableEntry *prev_cur_fn = g->cur_fn; | ||
| 4022 | LLVMValueRef prev_cur_fn_val = g->cur_fn_val; | ||
| 4023 | |||
| 4024 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | ||
| 4025 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | ||
| 4026 | ZigLLVMClearCurrentDebugLocation(g->builder); | ||
| 4027 | g->cur_fn = nullptr; | ||
| 4028 | g->cur_fn_val = fn_val; | ||
| 4029 | |||
| 4030 | LLVMValueRef sret_ptr = LLVMBuildAlloca(g->builder, LLVMGetElementType(alloc_fn_arg_types[0]), ""); | ||
| 4031 | |||
| 4032 | size_t next_arg = 0; | ||
| 4033 | LLVMValueRef alloc_fn_val = LLVMGetParam(fn_val, next_arg); | ||
| 4034 | next_arg += 1; | ||
| 4035 | |||
| 4036 | LLVMValueRef stack_trace_val; | ||
| 4037 | if (g->have_err_ret_tracing) { | ||
| 4038 | stack_trace_val = LLVMGetParam(fn_val, next_arg); | ||
| 4039 | next_arg += 1; | ||
| 4040 | } | ||
| 4041 | |||
| 4042 | LLVMValueRef allocator_val = LLVMGetParam(fn_val, next_arg); | ||
| 4043 | next_arg += 1; | ||
| 4044 | LLVMValueRef err_code_ptr = LLVMGetParam(fn_val, next_arg); | ||
| 4045 | next_arg += 1; | ||
| 4046 | LLVMValueRef coro_size = LLVMGetParam(fn_val, next_arg); | ||
| 4047 | next_arg += 1; | ||
| 4048 | LLVMValueRef alignment_val = LLVMConstInt(g->builtin_types.entry_u29->type_ref, | ||
| 4049 | 2 * g->pointer_size_bytes, false); | ||
| 4050 | |||
| 4051 | ZigList<LLVMValueRef> args = {}; | ||
| 4052 | args.append(sret_ptr); | ||
| 4053 | if (g->have_err_ret_tracing) { | ||
| 4054 | args.append(stack_trace_val); | ||
| 4055 | } | ||
| 4056 | args.append(allocator_val); | ||
| 4057 | args.append(coro_size); | ||
| 4058 | args.append(alignment_val); | ||
| 4059 | ZigLLVMBuildCall(g->builder, alloc_fn_val, args.items, args.length, | ||
| 4060 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | ||
| 4061 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_err_index, ""); | ||
| 4062 | LLVMValueRef err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); | ||
| 4063 | LLVMBuildStore(g->builder, err_val, err_code_ptr); | ||
| 4064 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, LLVMConstNull(LLVMTypeOf(err_val)), ""); | ||
| 4065 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(fn_val, "AllocOk"); | ||
| 4066 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(fn_val, "AllocFail"); | ||
| 4067 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 4068 | |||
| 4069 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 4070 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, ""); | ||
| 4071 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); | ||
| 4072 | TypeTableEntry *slice_type = get_slice_type(g, u8_ptr_type); | ||
| 4073 | size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 4074 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, ""); | ||
| 4075 | LLVMValueRef ptr_val = LLVMBuildLoad(g->builder, ptr_field_ptr, ""); | ||
| 4076 | LLVMBuildRet(g->builder, ptr_val); | ||
| 4077 | |||
| 4078 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 4079 | LLVMBuildRet(g->builder, LLVMConstNull(LLVMPointerType(LLVMInt8Type(), 0))); | ||
| 4080 | |||
| 4081 | g->cur_fn = prev_cur_fn; | ||
| 4082 | g->cur_fn_val = prev_cur_fn_val; | ||
| 4083 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | ||
| 4084 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | ||
| 4085 | |||
| 4086 | g->coro_alloc_helper_fn_val = fn_val; | ||
| 4087 | return fn_val; | ||
| 4088 | } | ||
| 4089 | |||
| 4090 | static LLVMValueRef ir_render_coro_alloc_helper(CodeGen *g, IrExecutable *executable, | ||
| 4091 | IrInstructionCoroAllocHelper *instruction) | ||
| 4092 | { | ||
| 4093 | LLVMValueRef alloc_fn = ir_llvm_value(g, instruction->alloc_fn); | ||
| 4094 | LLVMValueRef coro_size = ir_llvm_value(g, instruction->coro_size); | ||
| 4095 | LLVMValueRef fn_val = get_coro_alloc_helper_fn_val(g, LLVMTypeOf(alloc_fn), instruction->alloc_fn->value.type); | ||
| 4096 | size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); | ||
| 4097 | size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); | ||
| 4098 | |||
| 4099 | ZigList<LLVMValueRef> params = {}; | ||
| 4100 | params.append(alloc_fn); | ||
| 4101 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, g->cur_fn); | ||
| 4102 | if (err_ret_trace_arg_index != UINT32_MAX) { | ||
| 4103 | params.append(LLVMGetParam(g->cur_fn_val, err_ret_trace_arg_index)); | ||
| 4104 | } | ||
| 4105 | params.append(LLVMGetParam(g->cur_fn_val, allocator_arg_index)); | ||
| 4106 | params.append(LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index)); | ||
| 4107 | params.append(coro_size); | ||
| 4108 | |||
| 4109 | return ZigLLVMBuildCall(g->builder, fn_val, params.items, params.length, | ||
| 4110 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | ||
| 4111 | } | ||
| 4112 | |||
| 3988 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | 4113 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 3989 | AstNode *source_node = instruction->source_node; | 4114 | AstNode *source_node = instruction->source_node; |
| 3990 | Scope *scope = instruction->scope; | 4115 | Scope *scope = instruction->scope; |
| ... | @@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 4190 | return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); | 4315 | return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); |
| 4191 | case IrInstructionIdCoroSave: | 4316 | case IrInstructionIdCoroSave: |
| 4192 | return ir_render_coro_save(g, executable, (IrInstructionCoroSave *)instruction); | 4317 | return ir_render_coro_save(g, executable, (IrInstructionCoroSave *)instruction); |
| 4318 | case IrInstructionIdCoroAllocHelper: | ||
| 4319 | return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction); | ||
| 4193 | } | 4320 | } |
| 4194 | zig_unreachable(); | 4321 | zig_unreachable(); |
| 4195 | } | 4322 | } |
src/ir.cpp+53-34| ... | @@ -695,6 +695,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) { | ... | @@ -695,6 +695,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) { |
| 695 | return IrInstructionIdCoroSave; | 695 | return IrInstructionIdCoroSave; |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocHelper *) { | ||
| 699 | return IrInstructionIdCoroAllocHelper; | ||
| 700 | } | ||
| 701 | |||
| 698 | template<typename T> | 702 | template<typename T> |
| 699 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 703 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 700 | T *special_instruction = allocate<T>(1); | 704 | T *special_instruction = allocate<T>(1); |
| ... | @@ -829,14 +833,6 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -829,14 +833,6 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode |
| 829 | return &const_instruction->base; | 833 | return &const_instruction->base; |
| 830 | } | 834 | } |
| 831 | 835 | ||
| 832 | static IrInstruction *ir_build_const_u29(IrBuilder *irb, Scope *scope, AstNode *source_node, uint32_t value) { | ||
| 833 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); | ||
| 834 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_u29; | ||
| 835 | const_instruction->base.value.special = ConstValSpecialStatic; | ||
| 836 | bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value); | ||
| 837 | return &const_instruction->base; | ||
| 838 | } | ||
| 839 | |||
| 840 | static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) { | 836 | static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) { |
| 841 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); | 837 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 842 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8; | 838 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8; |
| ... | @@ -2600,6 +2596,19 @@ static IrInstruction *ir_build_coro_save(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -2600,6 +2596,19 @@ static IrInstruction *ir_build_coro_save(IrBuilder *irb, Scope *scope, AstNode * |
| 2600 | return &instruction->base; | 2596 | return &instruction->base; |
| 2601 | } | 2597 | } |
| 2602 | 2598 | ||
| 2599 | static IrInstruction *ir_build_coro_alloc_helper(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2600 | IrInstruction *alloc_fn, IrInstruction *coro_size) | ||
| 2601 | { | ||
| 2602 | IrInstructionCoroAllocHelper *instruction = ir_build_instruction<IrInstructionCoroAllocHelper>(irb, scope, source_node); | ||
| 2603 | instruction->alloc_fn = alloc_fn; | ||
| 2604 | instruction->coro_size = coro_size; | ||
| 2605 | |||
| 2606 | ir_ref_instruction(alloc_fn, irb->current_basic_block); | ||
| 2607 | ir_ref_instruction(coro_size, irb->current_basic_block); | ||
| 2608 | |||
| 2609 | return &instruction->base; | ||
| 2610 | } | ||
| 2611 | |||
| 2603 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2612 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2604 | results[ReturnKindUnconditional] = 0; | 2613 | results[ReturnKindUnconditional] = 0; |
| 2605 | results[ReturnKindError] = 0; | 2614 | results[ReturnKindError] = 0; |
| ... | @@ -6074,10 +6083,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6074,10 +6083,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6074 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | 6083 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 6075 | IrInstruction *u8_ptr_type; | 6084 | IrInstruction *u8_ptr_type; |
| 6076 | IrInstruction *const_bool_false; | 6085 | IrInstruction *const_bool_false; |
| 6077 | IrInstruction *coro_unwrapped_mem_ptr; | 6086 | IrInstruction *coro_size; |
| 6078 | IrInstruction *coro_id; | 6087 | IrInstruction *coro_id; |
| 6079 | IrInstruction *coro_promise_ptr; | 6088 | IrInstruction *coro_promise_ptr; |
| 6080 | IrInstruction *coro_result_field_ptr; | 6089 | IrInstruction *coro_result_field_ptr; |
| 6090 | IrInstruction *coro_mem_ptr; | ||
| 6081 | TypeTableEntry *return_type; | 6091 | TypeTableEntry *return_type; |
| 6082 | Buf *result_ptr_field_name; | 6092 | Buf *result_ptr_field_name; |
| 6083 | if (is_async) { | 6093 | if (is_async) { |
| ... | @@ -6095,39 +6105,25 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6095,39 +6105,25 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6095 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); | 6105 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 6096 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr); | 6106 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr); |
| 6097 | coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr); | 6107 | coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr); |
| 6098 | IrInstruction *coro_size = ir_build_coro_size(irb, scope, node); | 6108 | coro_size = ir_build_coro_size(irb, scope, node); |
| 6099 | irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node); | 6109 | irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node); |
| 6100 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); | 6110 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 6101 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, | 6111 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6102 | alloc_field_name); | 6112 | alloc_field_name); |
| 6103 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); | 6113 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); |
| 6104 | IrInstruction *alignment = ir_build_const_u29(irb, scope, node, | 6114 | IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size); |
| 6105 | get_coro_frame_align_bytes(irb->codegen)); | 6115 | IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr); |
| 6106 | size_t arg_count = 3; | ||
| 6107 | IrInstruction **args = allocate<IrInstruction *>(arg_count); | ||
| 6108 | args[0] = irb->exec->implicit_allocator_ptr; // self | ||
| 6109 | args[1] = coro_size; // byte_count | ||
| 6110 | args[2] = alignment; // alignment | ||
| 6111 | IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false, | ||
| 6112 | FnInlineAuto, false, nullptr); | ||
| 6113 | IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false); | ||
| 6114 | IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result); | ||
| 6115 | IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError"); | 6116 | IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError"); |
| 6116 | IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk"); | 6117 | IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk"); |
| 6117 | ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, const_bool_false); | 6118 | ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false); |
| 6118 | 6119 | ||
| 6119 | ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); | 6120 | ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); |
| 6120 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr); | 6121 | IrInstruction *undef = ir_build_const_undefined(irb, scope, node); |
| 6121 | ir_build_coro_alloc_fail(irb, scope, node, err_val); | 6122 | ir_build_return(irb, scope, node, undef); |
| 6122 | 6123 | ||
| 6123 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); | 6124 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| 6124 | coro_unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false); | 6125 | coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr); |
| 6125 | Buf *ptr_field_name = buf_create_from_str("ptr"); | 6126 | irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr); |
| 6126 | IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, coro_unwrapped_mem_ptr, | ||
| 6127 | ptr_field_name); | ||
| 6128 | IrInstruction *coro_mem = ir_build_load_ptr(irb, scope, node, coro_mem_ptr_field); | ||
| 6129 | |||
| 6130 | irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem); | ||
| 6131 | 6127 | ||
| 6132 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); | 6128 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); |
| 6133 | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, | 6129 | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| ... | @@ -6207,10 +6203,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6207,10 +6203,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6207 | IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, | 6203 | IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6208 | free_field_name); | 6204 | free_field_name); |
| 6209 | IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr); | 6205 | IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr); |
| 6206 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); | ||
| 6207 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); | ||
| 6208 | IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false); | ||
| 6210 | size_t arg_count = 2; | 6209 | size_t arg_count = 2; |
| 6211 | IrInstruction **args = allocate<IrInstruction *>(arg_count); | 6210 | IrInstruction **args = allocate<IrInstruction *>(arg_count); |
| 6212 | args[0] = irb->exec->implicit_allocator_ptr; // self | 6211 | args[0] = irb->exec->implicit_allocator_ptr; // self |
| 6213 | args[1] = ir_build_load_ptr(irb, scope, node, coro_unwrapped_mem_ptr); // old_mem | 6212 | args[1] = mem_slice; // old_mem |
| 6214 | ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); | 6213 | ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); |
| 6215 | 6214 | ||
| 6216 | IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume"); | 6215 | IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume"); |
| ... | @@ -11844,7 +11843,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -11844,7 +11843,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11844 | } | 11843 | } |
| 11845 | 11844 | ||
| 11846 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | 11845 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; |
| 11847 | if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) { | 11846 | if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) { |
| 11848 | parent_fn_entry->calls_errorable_function = true; | 11847 | parent_fn_entry->calls_errorable_function = true; |
| 11849 | } | 11848 | } |
| 11850 | 11849 | ||
| ... | @@ -11870,7 +11869,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -11870,7 +11869,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 11870 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); | 11869 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 11871 | assert(fn_type_id->return_type != nullptr); | 11870 | assert(fn_type_id->return_type != nullptr); |
| 11872 | assert(parent_fn_entry != nullptr); | 11871 | assert(parent_fn_entry != nullptr); |
| 11873 | if (fn_type_id->return_type->id == TypeTableEntryIdErrorSet || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) { | 11872 | if (fn_type_can_fail(fn_type_id)) { |
| 11874 | parent_fn_entry->calls_errorable_function = true; | 11873 | parent_fn_entry->calls_errorable_function = true; |
| 11875 | } | 11874 | } |
| 11876 | 11875 | ||
| ... | @@ -17274,6 +17273,23 @@ static TypeTableEntry *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstru | ... | @@ -17274,6 +17273,23 @@ static TypeTableEntry *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstru |
| 17274 | return result->value.type; | 17273 | return result->value.type; |
| 17275 | } | 17274 | } |
| 17276 | 17275 | ||
| 17276 | static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) { | ||
| 17277 | IrInstruction *alloc_fn = instruction->alloc_fn->other; | ||
| 17278 | if (type_is_invalid(alloc_fn->value.type)) | ||
| 17279 | return ira->codegen->builtin_types.entry_invalid; | ||
| 17280 | |||
| 17281 | IrInstruction *coro_size = instruction->coro_size->other; | ||
| 17282 | if (type_is_invalid(coro_size->value.type)) | ||
| 17283 | return ira->codegen->builtin_types.entry_invalid; | ||
| 17284 | |||
| 17285 | IrInstruction *result = ir_build_coro_alloc_helper(&ira->new_irb, instruction->base.scope, | ||
| 17286 | instruction->base.source_node, alloc_fn, coro_size); | ||
| 17287 | ir_link_new_instruction(result, &instruction->base); | ||
| 17288 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false); | ||
| 17289 | result->value.type = get_maybe_type(ira->codegen, u8_ptr_type); | ||
| 17290 | return result->value.type; | ||
| 17291 | } | ||
| 17292 | |||
| 17277 | 17293 | ||
| 17278 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 17294 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 17279 | switch (instruction->id) { | 17295 | switch (instruction->id) { |
| ... | @@ -17501,6 +17517,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -17501,6 +17517,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 17501 | return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction); | 17517 | return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction); |
| 17502 | case IrInstructionIdCoroSave: | 17518 | case IrInstructionIdCoroSave: |
| 17503 | return ir_analyze_instruction_coro_save(ira, (IrInstructionCoroSave *)instruction); | 17519 | return ir_analyze_instruction_coro_save(ira, (IrInstructionCoroSave *)instruction); |
| 17520 | case IrInstructionIdCoroAllocHelper: | ||
| 17521 | return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction); | ||
| 17504 | } | 17522 | } |
| 17505 | zig_unreachable(); | 17523 | zig_unreachable(); |
| 17506 | } | 17524 | } |
| ... | @@ -17624,6 +17642,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -17624,6 +17642,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 17624 | case IrInstructionIdCoroEnd: | 17642 | case IrInstructionIdCoroEnd: |
| 17625 | case IrInstructionIdCoroResume: | 17643 | case IrInstructionIdCoroResume: |
| 17626 | case IrInstructionIdCoroSave: | 17644 | case IrInstructionIdCoroSave: |
| 17645 | case IrInstructionIdCoroAllocHelper: | ||
| 17627 | return true; | 17646 | return true; |
| 17628 | 17647 | ||
| 17629 | case IrInstructionIdPhi: | 17648 | case IrInstructionIdPhi: |
src/ir_print.cpp+11| ... | @@ -1096,6 +1096,14 @@ static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction) | ... | @@ -1096,6 +1096,14 @@ static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction) |
| 1096 | fprintf(irp->f, ")"); | 1096 | fprintf(irp->f, ")"); |
| 1097 | } | 1097 | } |
| 1098 | 1098 | ||
| 1099 | static void ir_print_coro_alloc_helper(IrPrint *irp, IrInstructionCoroAllocHelper *instruction) { | ||
| 1100 | fprintf(irp->f, "@coroAllocHelper("); | ||
| 1101 | ir_print_other_instruction(irp, instruction->alloc_fn); | ||
| 1102 | fprintf(irp->f, ","); | ||
| 1103 | ir_print_other_instruction(irp, instruction->coro_size); | ||
| 1104 | fprintf(irp->f, ")"); | ||
| 1105 | } | ||
| 1106 | |||
| 1099 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1107 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1100 | ir_print_prefix(irp, instruction); | 1108 | ir_print_prefix(irp, instruction); |
| 1101 | switch (instruction->id) { | 1109 | switch (instruction->id) { |
| ... | @@ -1452,6 +1460,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1452,6 +1460,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1452 | case IrInstructionIdCoroSave: | 1460 | case IrInstructionIdCoroSave: |
| 1453 | ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction); | 1461 | ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction); |
| 1454 | break; | 1462 | break; |
| 1463 | case IrInstructionIdCoroAllocHelper: | ||
| 1464 | ir_print_coro_alloc_helper(irp, (IrInstructionCoroAllocHelper *)instruction); | ||
| 1465 | break; | ||
| 1455 | } | 1466 | } |
| 1456 | fprintf(irp->f, "\n"); | 1467 | fprintf(irp->f, "\n"); |
| 1457 | } | 1468 | } |