| ... | @@ -88,7 +88,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -88,7 +88,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 88 | g->exported_symbol_names.init(8); | 88 | g->exported_symbol_names.init(8); |
| 89 | g->external_prototypes.init(8); | 89 | g->external_prototypes.init(8); |
| 90 | g->string_literals_table.init(16); | 90 | g->string_literals_table.init(16); |
| 91 | g->workaround_struct_gep_table.init(8); | | |
| 92 | g->is_test_build = false; | 91 | g->is_test_build = false; |
| 93 | g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); | 92 | g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); |
| 94 | buf_resize(&g->global_asm, 0); | 93 | buf_resize(&g->global_asm, 0); |
| ... | @@ -2782,52 +2781,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2782,52 +2781,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2782 | } | 2781 | } |
| 2783 | } | 2782 | } |
| 2784 | | 2783 | |
| 2785 | static LLVMValueRef get_workaround_struct_gep_fn_val(CodeGen *g, LLVMTypeRef struct_ptr_type, uint32_t index) { | | |
| 2786 | WorkaroundStructGEPId hash_id = {struct_ptr_type, index}; | | |
| 2787 | auto existing_entry = g->workaround_struct_gep_table.maybe_get(hash_id); | | |
| 2788 | if (existing_entry) | | |
| 2789 | return existing_entry->value; | | |
| 2790 | | | |
| 2791 | LLVMTypeRef arg_types[] = { | | |
| 2792 | struct_ptr_type, | | |
| 2793 | }; | | |
| 2794 | LLVMTypeRef result_type = LLVMStructGetTypeAtIndex(LLVMGetElementType(struct_ptr_type), index); | | |
| 2795 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(result_type, 0), arg_types, 1, false); | | |
| 2796 | | | |
| 2797 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_workaround_llvm_struct_gep"), false); | | |
| 2798 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | | |
| 2799 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | | |
| 2800 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | | |
| 2801 | addLLVMFnAttr(fn_val, "nounwind"); | | |
| 2802 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | | |
| 2803 | | | |
| 2804 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | | |
| 2805 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | | |
| 2806 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | | |
| 2807 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | | |
| 2808 | ZigLLVMClearCurrentDebugLocation(g->builder); | | |
| 2809 | | | |
| 2810 | LLVMValueRef result = LLVMBuildStructGEP(g->builder, LLVMGetParam(fn_val, 0), index, ""); | | |
| 2811 | LLVMBuildRet(g->builder, result); | | |
| 2812 | | | |
| 2813 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | | |
| 2814 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | | |
| 2815 | | | |
| 2816 | g->workaround_struct_gep_table.put(hash_id, fn_val); | | |
| 2817 | return fn_val; | | |
| 2818 | } | | |
| 2819 | | | |
| 2820 | static LLVMValueRef gen_workaround_struct_gep(CodeGen *g, LLVMValueRef struct_ptr, uint32_t field_index) { | | |
| 2821 | if (g->cur_workaround_gep_on) { | | |
| 2822 | // We need to generate a normal StructGEP but due to llvm bugs we have to workaround it by | | |
| 2823 | // putting the GEP in a function call | | |
| 2824 | LLVMValueRef fn_val = get_workaround_struct_gep_fn_val(g, LLVMTypeOf(struct_ptr), field_index); | | |
| 2825 | return LLVMBuildCall(g->builder, fn_val, &struct_ptr, 1, ""); | | |
| 2826 | } else { | | |
| 2827 | return LLVMBuildStructGEP(g->builder, struct_ptr, field_index, ""); | | |
| 2828 | } | | |
| 2829 | } | | |
| 2830 | | | |
| 2831 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, | 2784 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, |
| 2832 | IrInstructionStructFieldPtr *instruction) | 2785 | IrInstructionStructFieldPtr *instruction) |
| 2833 | { | 2786 | { |
| ... | @@ -2846,7 +2799,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa | ... | @@ -2846,7 +2799,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 2846 | } | 2799 | } |
| 2847 | | 2800 | |
| 2848 | assert(field->gen_index != SIZE_MAX); | 2801 | assert(field->gen_index != SIZE_MAX); |
| 2849 | return gen_workaround_struct_gep(g, struct_ptr, field->gen_index); | 2802 | return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); |
| 2850 | } | 2803 | } |
| 2851 | | 2804 | |
| 2852 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, | 2805 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, |
| ... | @@ -3702,7 +3655,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3702,7 +3655,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 3702 | | 3655 | |
| 3703 | LLVMValueRef err_val; | 3656 | LLVMValueRef err_val; |
| 3704 | if (type_has_bits(payload_type)) { | 3657 | if (type_has_bits(payload_type)) { |
| 3705 | LLVMValueRef err_val_ptr = gen_workaround_struct_gep(g, err_union_handle, err_union_err_index); | 3658 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3706 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3659 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3707 | } else { | 3660 | } else { |
| 3708 | err_val = err_union_handle; | 3661 | err_val = err_union_handle; |
| ... | @@ -3721,12 +3674,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab | ... | @@ -3721,12 +3674,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 3721 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | 3674 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 3722 | | 3675 | |
| 3723 | if (type_has_bits(payload_type)) { | 3676 | if (type_has_bits(payload_type)) { |
| 3724 | LLVMValueRef err_val_ptr; | 3677 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3725 | if (g->cur_workaround_gep_on) { | | |
| 3726 | err_val_ptr = gen_workaround_struct_gep(g, err_union_handle, err_union_err_index); | | |
| 3727 | } else { | | |
| 3728 | err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | | |
| 3729 | } | | |
| 3730 | return gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3678 | return gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3731 | } else { | 3679 | } else { |
| 3732 | return err_union_handle; | 3680 | return err_union_handle; |
| ... | @@ -3748,7 +3696,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu | ... | @@ -3748,7 +3696,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3748 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { | 3696 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { |
| 3749 | LLVMValueRef err_val; | 3697 | LLVMValueRef err_val; |
| 3750 | if (type_has_bits(payload_type)) { | 3698 | if (type_has_bits(payload_type)) { |
| 3751 | LLVMValueRef err_val_ptr = gen_workaround_struct_gep(g, err_union_handle, err_union_err_index); | 3699 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3752 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3700 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3753 | } else { | 3701 | } else { |
| 3754 | err_val = err_union_handle; | 3702 | err_val = err_union_handle; |
| ... | @@ -3766,11 +3714,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu | ... | @@ -3766,11 +3714,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3766 | } | 3714 | } |
| 3767 | | 3715 | |
| 3768 | if (type_has_bits(payload_type)) { | 3716 | if (type_has_bits(payload_type)) { |
| 3769 | if (g->cur_workaround_gep_on) { | 3717 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); |
| 3770 | return gen_workaround_struct_gep(g, err_union_handle, err_union_payload_index); | | |
| 3771 | } else { | | |
| 3772 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); | | |
| 3773 | } | | |
| 3774 | } else { | 3718 | } else { |
| 3775 | return nullptr; | 3719 | return nullptr; |
| 3776 | } | 3720 | } |
| ... | @@ -3990,7 +3934,6 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I | ... | @@ -3990,7 +3934,6 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I |
| 3990 | coro_id, | 3934 | coro_id, |
| 3991 | coro_mem_ptr, | 3935 | coro_mem_ptr, |
| 3992 | }; | 3936 | }; |
| 3993 | g->cur_workaround_gep_on = false; | | |
| 3994 | return LLVMBuildCall(g->builder, get_coro_begin_fn_val(g), params, 2, ""); | 3937 | return LLVMBuildCall(g->builder, get_coro_begin_fn_val(g), params, 2, ""); |
| 3995 | } | 3938 | } |
| 3996 | | 3939 | |
| ... | @@ -5130,7 +5073,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -5130,7 +5073,6 @@ static void do_code_gen(CodeGen *g) { |
| 5130 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); | 5073 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); |
| 5131 | g->cur_fn = fn_table_entry; | 5074 | g->cur_fn = fn_table_entry; |
| 5132 | g->cur_fn_val = fn; | 5075 | g->cur_fn_val = fn; |
| 5133 | g->cur_workaround_gep_on = fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | | |
| 5134 | TypeTableEntry *return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; | 5076 | TypeTableEntry *return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; |
| 5135 | if (handle_is_ptr(return_type)) { | 5077 | if (handle_is_ptr(return_type)) { |
| 5136 | g->cur_ret_ptr = LLVMGetParam(fn, 0); | 5078 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |