| ... | ... | @@ -88,7 +88,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 88 | 88 | g->exported_symbol_names.init(8); |
| 89 | 89 | g->external_prototypes.init(8); |
| 90 | 90 | g->string_literals_table.init(16); |
| 91 | | g->workaround_struct_gep_table.init(8); |
| 92 | 91 | g->is_test_build = false; |
| 93 | 92 | g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); |
| 94 | 93 | buf_resize(&g->global_asm, 0); |
| ... | ... | @@ -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 | 2784 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, |
| 2832 | 2785 | IrInstructionStructFieldPtr *instruction) |
| 2833 | 2786 | { |
| ... | ... | @@ -2846,7 +2799,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 2846 | 2799 | } |
| 2847 | 2800 | |
| 2848 | 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 | 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 | 3655 | |
| 3703 | 3656 | LLVMValueRef err_val; |
| 3704 | 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 | 3659 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3707 | 3660 | } else { |
| 3708 | 3661 | err_val = err_union_handle; |
| ... | ... | @@ -3721,12 +3674,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 3721 | 3674 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 3722 | 3675 | |
| 3723 | 3676 | if (type_has_bits(payload_type)) { |
| 3724 | | LLVMValueRef err_val_ptr; |
| 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 | | } |
| 3677 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3730 | 3678 | return gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3731 | 3679 | } else { |
| 3732 | 3680 | return err_union_handle; |
| ... | ... | @@ -3748,7 +3696,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3748 | 3696 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { |
| 3749 | 3697 | LLVMValueRef err_val; |
| 3750 | 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 | 3700 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3753 | 3701 | } else { |
| 3754 | 3702 | err_val = err_union_handle; |
| ... | ... | @@ -3766,11 +3714,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3766 | 3714 | } |
| 3767 | 3715 | |
| 3768 | 3716 | if (type_has_bits(payload_type)) { |
| 3769 | | if (g->cur_workaround_gep_on) { |
| 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 | | } |
| 3717 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); |
| 3774 | 3718 | } else { |
| 3775 | 3719 | return nullptr; |
| 3776 | 3720 | } |
| ... | ... | @@ -3990,7 +3934,6 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I |
| 3990 | 3934 | coro_id, |
| 3991 | 3935 | coro_mem_ptr, |
| 3992 | 3936 | }; |
| 3993 | | g->cur_workaround_gep_on = false; |
| 3994 | 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 | 5073 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); |
| 5131 | 5074 | g->cur_fn = fn_table_entry; |
| 5132 | 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 | 5076 | TypeTableEntry *return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; |
| 5135 | 5077 | if (handle_is_ptr(return_type)) { |
| 5136 | 5078 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |