| 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 | 1634 | LLVMValueRef coro_free_fn_val; |
| 1635 | 1635 | LLVMValueRef coro_resume_fn_val; |
| 1636 | 1636 | LLVMValueRef coro_save_fn_val; |
| 1637 | LLVMValueRef coro_alloc_helper_fn_val; | |
| 1637 | 1638 | bool error_during_imports; |
| 1638 | 1639 | |
| 1639 | 1640 | const char **clang_argv; |
| ... | ... | @@ -2004,6 +2005,7 @@ enum IrInstructionId { |
| 2004 | 2005 | IrInstructionIdCoroFree, |
| 2005 | 2006 | IrInstructionIdCoroResume, |
| 2006 | 2007 | IrInstructionIdCoroSave, |
| 2008 | IrInstructionIdCoroAllocHelper, | |
| 2007 | 2009 | }; |
| 2008 | 2010 | |
| 2009 | 2011 | struct IrInstruction { |
| ... | ... | @@ -2913,6 +2915,13 @@ struct IrInstructionCoroSave { |
| 2913 | 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 | 2925 | static const size_t slice_ptr_index = 0; |
| 2917 | 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 | 1001 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && |
| 1002 | 1002 | handle_is_ptr(fn_type_id->return_type); |
| 1003 | 1003 | bool is_async = fn_type_id->cc == CallingConventionAsync; |
| 1004 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && | |
| 1005 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || | |
| 1006 | fn_type_id->return_type->id == TypeTableEntryIdErrorSet); | |
| 1004 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); | |
| 1007 | 1005 | // +1 for maybe making the first argument the return value |
| 1008 | 1006 | // +1 for maybe first argument the error return trace |
| 1009 | 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 | 5793 | uint32_t get_coro_frame_align_bytes(CodeGen *g) { |
| 5796 | 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 | 192 | TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry); |
| 193 | 193 | |
| 194 | 194 | uint32_t get_coro_frame_align_bytes(CodeGen *g); |
| 195 | bool fn_type_can_fail(FnTypeId *fn_type_id); | |
| 195 | 196 | |
| 196 | 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 | 412 | return UINT32_MAX; |
| 413 | 413 | } |
| 414 | 414 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 415 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | |
| 416 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) { | |
| 415 | if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) { | |
| 417 | 416 | return UINT32_MAX; |
| 418 | 417 | } |
| 418 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | |
| 419 | 419 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); |
| 420 | 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 | 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 | 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 | 2673 | // 0 1 2 3 |
| 2672 | 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 | 2679 | // 0 1 2 3 |
| 2678 | 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 | 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 | 2700 | |
| 2699 | 2701 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) && |
| 2700 | 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 | 2704 | // +2 for the async args |
| 2703 | 2705 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2; |
| 2704 | 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 | 2719 | gen_param_index += 1; |
| 2718 | 2720 | |
| 2719 | 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 | 2722 | gen_param_values[gen_param_index] = err_val_ptr; |
| 2722 | 2723 | gen_param_index += 1; |
| 2723 | 2724 | } |
| ... | ... | @@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns |
| 3293 | 3294 | static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable, |
| 3294 | 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, src_return_type); | |
| 3297 | size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id); | |
| 3298 | 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 | 3926 | static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable, |
| 3927 | 3927 | IrInstructionCoroAllocFail *instruction) |
| 3928 | 3928 | { |
| 3929 | TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; | |
| 3930 | size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, src_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); | |
| 3931 | 3930 | LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index); |
| 3932 | 3931 | LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val); |
| 3933 | 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 | 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 | 4113 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 3989 | 4114 | AstNode *source_node = instruction->source_node; |
| 3990 | 4115 | Scope *scope = instruction->scope; |
| ... | ... | @@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 4190 | 4315 | return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); |
| 4191 | 4316 | case IrInstructionIdCoroSave: |
| 4192 | 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 | 4321 | zig_unreachable(); |
| 4195 | 4322 | } |
src/ir.cpp+53-34| ... | ... | @@ -695,6 +695,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) { |
| 695 | 695 | return IrInstructionIdCoroSave; |
| 696 | 696 | } |
| 697 | 697 | |
| 698 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocHelper *) { | |
| 699 | return IrInstructionIdCoroAllocHelper; | |
| 700 | } | |
| 701 | ||
| 698 | 702 | template<typename T> |
| 699 | 703 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 700 | 704 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -829,14 +833,6 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode |
| 829 | 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 | 836 | static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) { |
| 841 | 837 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 842 | 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 | 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 | 2612 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2604 | 2613 | results[ReturnKindUnconditional] = 0; |
| 2605 | 2614 | results[ReturnKindError] = 0; |
| ... | ... | @@ -6074,10 +6083,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6074 | 6083 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 6075 | 6084 | IrInstruction *u8_ptr_type; |
| 6076 | 6085 | IrInstruction *const_bool_false; |
| 6077 | IrInstruction *coro_unwrapped_mem_ptr; | |
| 6086 | IrInstruction *coro_size; | |
| 6078 | 6087 | IrInstruction *coro_id; |
| 6079 | 6088 | IrInstruction *coro_promise_ptr; |
| 6080 | 6089 | IrInstruction *coro_result_field_ptr; |
| 6090 | IrInstruction *coro_mem_ptr; | |
| 6081 | 6091 | TypeTableEntry *return_type; |
| 6082 | 6092 | Buf *result_ptr_field_name; |
| 6083 | 6093 | if (is_async) { |
| ... | ... | @@ -6095,39 +6105,25 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6095 | 6105 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 6096 | 6106 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr); |
| 6097 | 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 | 6109 | irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node); |
| 6100 | 6110 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 6101 | 6111 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6102 | 6112 | alloc_field_name); |
| 6103 | 6113 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); |
| 6104 | IrInstruction *alignment = ir_build_const_u29(irb, scope, node, | |
| 6105 | get_coro_frame_align_bytes(irb->codegen)); | |
| 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); | |
| 6114 | IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size); | |
| 6115 | IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr); | |
| 6115 | 6116 | IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError"); |
| 6116 | 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 | 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 | ir_build_coro_alloc_fail(irb, scope, node, err_val); | |
| 6121 | IrInstruction *undef = ir_build_const_undefined(irb, scope, node); | |
| 6122 | ir_build_return(irb, scope, node, undef); | |
| 6122 | 6123 | |
| 6123 | 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 | Buf *ptr_field_name = buf_create_from_str("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); | |
| 6125 | coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr); | |
| 6126 | irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr); | |
| 6131 | 6127 | |
| 6132 | 6128 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); |
| 6133 | 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 | 6203 | IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr, |
| 6208 | 6204 | free_field_name); |
| 6209 | 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 | 6209 | size_t arg_count = 2; |
| 6211 | 6210 | IrInstruction **args = allocate<IrInstruction *>(arg_count); |
| 6212 | 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 | 6213 | ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr); |
| 6215 | 6214 | |
| 6216 | 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 | 11843 | } |
| 11845 | 11844 | |
| 11846 | 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 | 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 | 11869 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 11871 | 11870 | assert(fn_type_id->return_type != nullptr); |
| 11872 | 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 | 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 | 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 | 17294 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 17279 | 17295 | switch (instruction->id) { |
| ... | ... | @@ -17501,6 +17517,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 17501 | 17517 | return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction); |
| 17502 | 17518 | case IrInstructionIdCoroSave: |
| 17503 | 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 | 17523 | zig_unreachable(); |
| 17506 | 17524 | } |
| ... | ... | @@ -17624,6 +17642,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 17624 | 17642 | case IrInstructionIdCoroEnd: |
| 17625 | 17643 | case IrInstructionIdCoroResume: |
| 17626 | 17644 | case IrInstructionIdCoroSave: |
| 17645 | case IrInstructionIdCoroAllocHelper: | |
| 17627 | 17646 | return true; |
| 17628 | 17647 | |
| 17629 | 17648 | case IrInstructionIdPhi: |
src/ir_print.cpp+11| ... | ... | @@ -1096,6 +1096,14 @@ static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction) |
| 1096 | 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 | 1107 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1100 | 1108 | ir_print_prefix(irp, instruction); |
| 1101 | 1109 | switch (instruction->id) { |
| ... | ... | @@ -1452,6 +1460,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1452 | 1460 | case IrInstructionIdCoroSave: |
| 1453 | 1461 | ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction); |
| 1454 | 1462 | break; |
| 1463 | case IrInstructionIdCoroAllocHelper: | |
| 1464 | ir_print_coro_alloc_helper(irp, (IrInstructionCoroAllocHelper *)instruction); | |
| 1465 | break; | |
| 1455 | 1466 | } |
| 1456 | 1467 | fprintf(irp->f, "\n"); |
| 1457 | 1468 | } |