| ... | ... | @@ -603,6 +603,24 @@ static LLVMValueRef get_floor_ceil_fn(CodeGen *g, TypeTableEntry *type_entry, Zi |
| 603 | 603 | return fn_val; |
| 604 | 604 | } |
| 605 | 605 | |
| 606 | static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, |
| 607 | uint32_t alignment, bool is_volatile) |
| 608 | { |
| 609 | LLVMValueRef instruction = LLVMBuildStore(g->builder, value, ptr); |
| 610 | if (is_volatile) LLVMSetVolatile(instruction, true); |
| 611 | if (alignment == 0) { |
| 612 | LLVMSetAlignment(instruction, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(value))); |
| 613 | } else { |
| 614 | LLVMSetAlignment(instruction, alignment); |
| 615 | } |
| 616 | return instruction; |
| 617 | } |
| 618 | |
| 619 | static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, TypeTableEntry *ptr_type) { |
| 620 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 621 | return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile); |
| 622 | } |
| 623 | |
| 606 | 624 | static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile, |
| 607 | 625 | const char *name) |
| 608 | 626 | { |
| ... | ... | @@ -617,6 +635,7 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig |
| 617 | 635 | } |
| 618 | 636 | |
| 619 | 637 | static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type, const char *name) { |
| 638 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 620 | 639 | return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name); |
| 621 | 640 | } |
| 622 | 641 | |
| ... | ... | @@ -789,6 +808,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 789 | 808 | for (; i < err_buf_len; i += 1) { |
| 790 | 809 | err_buf_vals[i] = LLVMGetUndef(LLVMInt8Type()); |
| 791 | 810 | } |
| 811 | uint32_t u8_align_bytes = get_abi_alignment(g, g->builtin_types.entry_u8); |
| 792 | 812 | LLVMValueRef init_value = LLVMConstArray(LLVMInt8Type(), err_buf_vals, err_buf_len); |
| 793 | 813 | Buf *global_name = get_mangled_name(g, buf_create_from_str("__zig_panic_buf"), false); |
| 794 | 814 | LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_value), buf_ptr(global_name)); |
| ... | ... | @@ -796,7 +816,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 796 | 816 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 797 | 817 | LLVMSetGlobalConstant(global_value, false); |
| 798 | 818 | LLVMSetUnnamedAddr(global_value, true); |
| 799 | | LLVMSetAlignment(global_value, get_abi_alignment(g, g->builtin_types.entry_u8)); |
| 819 | LLVMSetAlignment(global_value, u8_align_bytes); |
| 800 | 820 | |
| 801 | 821 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 802 | 822 | LLVMValueRef full_buf_ptr_indices[] = { |
| ... | ... | @@ -851,7 +871,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 851 | 871 | offset_buf_ptr, // dest pointer |
| 852 | 872 | err_name_ptr, // source pointer |
| 853 | 873 | err_name_len, // size bytes |
| 854 | | LLVMConstInt(LLVMInt32Type(), 1, false), // align bytes |
| 874 | LLVMConstInt(LLVMInt32Type(), u8_align_bytes, false), // align bytes |
| 855 | 875 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| 856 | 876 | }; |
| 857 | 877 | |
| ... | ... | @@ -1089,9 +1109,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry |
| 1089 | 1109 | |
| 1090 | 1110 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 1091 | 1111 | if (unaligned_bit_count == 0) { |
| 1092 | | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); |
| 1093 | | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); |
| 1094 | | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1112 | gen_store(g, value, ptr, ptr_type); |
| 1095 | 1113 | return nullptr; |
| 1096 | 1114 | } |
| 1097 | 1115 | |
| ... | ... | @@ -1112,9 +1130,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry |
| 1112 | 1130 | LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, ""); |
| 1113 | 1131 | LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); |
| 1114 | 1132 | |
| 1115 | | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr); |
| 1116 | | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); |
| 1117 | | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1133 | gen_store(g, ored_value, ptr, ptr_type); |
| 1118 | 1134 | return nullptr; |
| 1119 | 1135 | } |
| 1120 | 1136 | |
| ... | ... | @@ -1673,7 +1689,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 1673 | 1689 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); |
| 1674 | 1690 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 1675 | 1691 | (unsigned)wanted_ptr_index, ""); |
| 1676 | | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 1692 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); |
| 1677 | 1693 | |
| 1678 | 1694 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); |
| 1679 | 1695 | LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); |
| ... | ... | @@ -1706,7 +1722,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 1706 | 1722 | |
| 1707 | 1723 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 1708 | 1724 | (unsigned)wanted_len_index, ""); |
| 1709 | | LLVMBuildStore(g->builder, new_len, dest_len_ptr); |
| 1725 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); |
| 1710 | 1726 | |
| 1711 | 1727 | |
| 1712 | 1728 | return cast_instruction->tmp_ptr; |
| ... | ... | @@ -1726,14 +1742,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 1726 | 1742 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 1727 | 1743 | (unsigned)wanted_ptr_index, ""); |
| 1728 | 1744 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); |
| 1729 | | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 1745 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); |
| 1730 | 1746 | |
| 1731 | 1747 | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 1732 | 1748 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 1733 | 1749 | (unsigned)wanted_len_index, ""); |
| 1734 | 1750 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 1735 | 1751 | actual_type->data.array.len / type_size(g, wanted_child_type), false); |
| 1736 | | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 1752 | gen_store_untyped(g, len_val, len_ptr, 0, false); |
| 1737 | 1753 | |
| 1738 | 1754 | return cast_instruction->tmp_ptr; |
| 1739 | 1755 | } |
| ... | ... | @@ -2542,7 +2558,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru |
| 2542 | 2558 | return value; |
| 2543 | 2559 | } else { |
| 2544 | 2560 | assert(instruction->tmp_ptr); |
| 2545 | | LLVMBuildStore(g->builder, value, instruction->tmp_ptr); |
| 2561 | gen_store_untyped(g, value, instruction->tmp_ptr, 0, false); |
| 2546 | 2562 | return instruction->tmp_ptr; |
| 2547 | 2563 | } |
| 2548 | 2564 | } |
| ... | ... | @@ -2828,11 +2844,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 2828 | 2844 | start_val, |
| 2829 | 2845 | }; |
| 2830 | 2846 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); |
| 2831 | | LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr); |
| 2847 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 2832 | 2848 | |
| 2833 | 2849 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 2834 | 2850 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 2835 | | LLVMBuildStore(g->builder, len_value, len_field_ptr); |
| 2851 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); |
| 2836 | 2852 | |
| 2837 | 2853 | return tmp_struct_ptr; |
| 2838 | 2854 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| ... | ... | @@ -2845,11 +2861,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 2845 | 2861 | |
| 2846 | 2862 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, ""); |
| 2847 | 2863 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); |
| 2848 | | LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr); |
| 2864 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 2849 | 2865 | |
| 2850 | 2866 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 2851 | 2867 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 2852 | | LLVMBuildStore(g->builder, len_value, len_field_ptr); |
| 2868 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); |
| 2853 | 2869 | |
| 2854 | 2870 | return tmp_struct_ptr; |
| 2855 | 2871 | } else if (array_type->id == TypeTableEntryIdStruct) { |
| ... | ... | @@ -2888,11 +2904,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 2888 | 2904 | LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); |
| 2889 | 2905 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, ""); |
| 2890 | 2906 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, (unsigned)len_index, ""); |
| 2891 | | LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr); |
| 2907 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 2892 | 2908 | |
| 2893 | 2909 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, ""); |
| 2894 | 2910 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 2895 | | LLVMBuildStore(g->builder, len_value, len_field_ptr); |
| 2911 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); |
| 2896 | 2912 | |
| 2897 | 2913 | return tmp_struct_ptr; |
| 2898 | 2914 | } else { |
| ... | ... | @@ -2979,7 +2995,7 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp |
| 2979 | 2995 | } |
| 2980 | 2996 | LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, op1, orig_val, ""); |
| 2981 | 2997 | |
| 2982 | | LLVMBuildStore(g->builder, result, ptr_result); |
| 2998 | gen_store(g, result, ptr_result, instruction->result_ptr->value.type); |
| 2983 | 2999 | |
| 2984 | 3000 | return overflow_bit; |
| 2985 | 3001 | } |
| ... | ... | @@ -3017,7 +3033,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, |
| 3017 | 3033 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); |
| 3018 | 3034 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); |
| 3019 | 3035 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); |
| 3020 | | LLVMBuildStore(g->builder, result, ptr_result); |
| 3036 | gen_store(g, result, ptr_result, instruction->result_ptr->value.type); |
| 3021 | 3037 | |
| 3022 | 3038 | return overflow_bit; |
| 3023 | 3039 | } |
| ... | ... | @@ -3114,7 +3130,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I |
| 3114 | 3130 | // child_type and instruction->value->value.type may differ by constness |
| 3115 | 3131 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); |
| 3116 | 3132 | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, ""); |
| 3117 | | LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr); |
| 3133 | gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false); |
| 3118 | 3134 | |
| 3119 | 3135 | return instruction->tmp_ptr; |
| 3120 | 3136 | } |
| ... | ... | @@ -3133,7 +3149,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable |
| 3133 | 3149 | assert(instruction->tmp_ptr); |
| 3134 | 3150 | |
| 3135 | 3151 | LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); |
| 3136 | | LLVMBuildStore(g->builder, err_val, err_tag_ptr); |
| 3152 | gen_store_untyped(g, err_val, err_tag_ptr, 0, false); |
| 3137 | 3153 | |
| 3138 | 3154 | return instruction->tmp_ptr; |
| 3139 | 3155 | } |
| ... | ... | @@ -3155,7 +3171,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa |
| 3155 | 3171 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); |
| 3156 | 3172 | |
| 3157 | 3173 | LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); |
| 3158 | | LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr); |
| 3174 | gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); |
| 3159 | 3175 | |
| 3160 | 3176 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, ""); |
| 3161 | 3177 | gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, child_type, false), payload_val); |
| ... | ... | @@ -3190,7 +3206,7 @@ static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, Ir |
| 3190 | 3206 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; |
| 3191 | 3207 | |
| 3192 | 3208 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, enum_type->data.enumeration.gen_tag_index, ""); |
| 3193 | | LLVMBuildStore(g->builder, tag_value, tag_field_ptr); |
| 3209 | gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); |
| 3194 | 3210 | |
| 3195 | 3211 | TypeTableEntry *union_val_type = instruction->field->type_entry; |
| 3196 | 3212 | if (type_has_bits(union_val_type)) { |
| ... | ... | @@ -4318,7 +4334,8 @@ static void do_code_gen(CodeGen *g) { |
| 4318 | 4334 | |
| 4319 | 4335 | if (!handle_is_ptr(variable->value->type)) { |
| 4320 | 4336 | clear_debug_source_node(g); |
| 4321 | | LLVMBuildStore(g->builder, LLVMGetParam(fn, (unsigned)variable->gen_arg_index), variable->value_ref); |
| 4337 | gen_store_untyped(g, LLVMGetParam(fn, (unsigned)variable->gen_arg_index), variable->value_ref, |
| 4338 | variable->align_bytes, false); |
| 4322 | 4339 | } |
| 4323 | 4340 | |
| 4324 | 4341 | if (variable->decl_node) { |