| ... | ... | @@ -682,6 +682,33 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) { |
| 682 | 682 | } |
| 683 | 683 | } |
| 684 | 684 | |
| 685 | static bool is_array_of_at_least_n_bytes(CodeGen *g, TypeTableEntry *type_entry, uint32_t n) { |
| 686 | if (type_entry->id != TypeTableEntryIdArray) |
| 687 | return false; |
| 688 | |
| 689 | TypeTableEntry *child_type = type_entry->data.array.child_type; |
| 690 | if (child_type->id != TypeTableEntryIdInt) |
| 691 | return false; |
| 692 | |
| 693 | if (child_type != g->builtin_types.entry_u8) |
| 694 | return false; |
| 695 | |
| 696 | if (type_entry->data.array.len < n) |
| 697 | return false; |
| 698 | |
| 699 | return true; |
| 700 | } |
| 701 | |
| 702 | static uint32_t get_type_alignment(CodeGen *g, TypeTableEntry *type_entry) { |
| 703 | uint32_t alignment = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, type_entry->type_ref); |
| 704 | uint32_t dbl_ptr_bytes = g->pointer_size_bytes * 2; |
| 705 | if (is_array_of_at_least_n_bytes(g, type_entry, dbl_ptr_bytes)) { |
| 706 | return (alignment < dbl_ptr_bytes) ? dbl_ptr_bytes : alignment; |
| 707 | } else { |
| 708 | return alignment; |
| 709 | } |
| 710 | } |
| 711 | |
| 685 | 712 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest, |
| 686 | 713 | TypeTableEntry *type_entry) |
| 687 | 714 | { |
| ... | ... | @@ -697,7 +724,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef |
| 697 | 724 | |
| 698 | 725 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 699 | 726 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); |
| 700 | | uint64_t align_bytes = get_memcpy_align(g, type_entry); |
| 727 | uint64_t align_bytes = get_type_alignment(g, type_entry); |
| 701 | 728 | assert(size_bytes > 0); |
| 702 | 729 | assert(align_bytes > 0); |
| 703 | 730 | |
| ... | ... | @@ -1308,7 +1335,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 1308 | 1335 | if (!ignore_uninit && want_safe) { |
| 1309 | 1336 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 1310 | 1337 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value.type->type_ref); |
| 1311 | | uint64_t align_bytes = get_memcpy_align(g, var->value.type); |
| 1338 | uint64_t align_bytes = get_type_alignment(g, var->value.type); |
| 1312 | 1339 | |
| 1313 | 1340 | // memset uninitialized memory to 0xa |
| 1314 | 1341 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| ... | ... | @@ -2748,6 +2775,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const |
| 2748 | 2775 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 2749 | 2776 | LLVMSetGlobalConstant(global_value, true); |
| 2750 | 2777 | LLVMSetUnnamedAddr(global_value, true); |
| 2778 | LLVMSetAlignment(global_value, get_type_alignment(g, const_val->type)); |
| 2751 | 2779 | |
| 2752 | 2780 | const_val->llvm_global = global_value; |
| 2753 | 2781 | } |
| ... | ... | @@ -2882,6 +2910,12 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini |
| 2882 | 2910 | type_entry->di_type, is_local_to_unit, init_val); |
| 2883 | 2911 | } |
| 2884 | 2912 | |
| 2913 | static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name) { |
| 2914 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); |
| 2915 | LLVMSetAlignment(result, get_type_alignment(g, type_entry)); |
| 2916 | return result; |
| 2917 | } |
| 2918 | |
| 2885 | 2919 | static void do_code_gen(CodeGen *g) { |
| 2886 | 2920 | assert(!g->errors.length); |
| 2887 | 2921 | |
| ... | ... | @@ -2938,9 +2972,8 @@ static void do_code_gen(CodeGen *g) { |
| 2938 | 2972 | if (tld_var->section_name) { |
| 2939 | 2973 | LLVMSetSection(global_value, buf_ptr(tld_var->section_name)); |
| 2940 | 2974 | } |
| 2941 | | if (tld_var->alignment) { |
| 2942 | | LLVMSetAlignment(global_value, tld_var->alignment); |
| 2943 | | } |
| 2975 | LLVMSetAlignment(global_value, tld_var->alignment ? |
| 2976 | tld_var->alignment : get_type_alignment(g, var->value.type)); |
| 2944 | 2977 | |
| 2945 | 2978 | // TODO debug info for function pointers |
| 2946 | 2979 | if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) { |
| ... | ... | @@ -3114,7 +3147,7 @@ static void do_code_gen(CodeGen *g) { |
| 3114 | 3147 | } else { |
| 3115 | 3148 | zig_unreachable(); |
| 3116 | 3149 | } |
| 3117 | | *slot = LLVMBuildAlloca(g->builder, slot_type->type_ref, ""); |
| 3150 | *slot = build_alloca(g, slot_type, ""); |
| 3118 | 3151 | } |
| 3119 | 3152 | |
| 3120 | 3153 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| ... | ... | @@ -3132,11 +3165,7 @@ static void do_code_gen(CodeGen *g) { |
| 3132 | 3165 | continue; |
| 3133 | 3166 | |
| 3134 | 3167 | if (var->src_arg_index == SIZE_MAX) { |
| 3135 | | var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name)); |
| 3136 | | |
| 3137 | | |
| 3138 | | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref); |
| 3139 | | LLVMSetAlignment(var->value_ref, align_bytes); |
| 3168 | var->value_ref = build_alloca(g, var->value.type, buf_ptr(&var->name)); |
| 3140 | 3169 | |
| 3141 | 3170 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 3142 | 3171 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, |
| ... | ... | @@ -3150,9 +3179,7 @@ static void do_code_gen(CodeGen *g) { |
| 3150 | 3179 | var->value_ref = LLVMGetParam(fn, var->gen_arg_index); |
| 3151 | 3180 | } else { |
| 3152 | 3181 | gen_type = var->value.type; |
| 3153 | | var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name)); |
| 3154 | | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref); |
| 3155 | | LLVMSetAlignment(var->value_ref, align_bytes); |
| 3182 | var->value_ref = build_alloca(g, var->value.type, buf_ptr(&var->name)); |
| 3156 | 3183 | } |
| 3157 | 3184 | if (var->decl_node) { |
| 3158 | 3185 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |