authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-07 01:50:10-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-07 01:50:10-05:00
log916a96fb724aab03be0e0a1bbaef6de8cc6c305c
treea4b7298e786f92c3fc51e4374e52f7032f9cab83
parent573f3f8d487dfd1f56ab71b96ad23af1a2d4162e

variables, memcpy, and memset all get alignment

See #37

3 files changed, 41 insertions(+), 74 deletions(-)

src/analyze.cpp-59
...@@ -2973,60 +2973,6 @@ bool type_has_bits(TypeTableEntry *type_entry) {...@@ -2973,60 +2973,6 @@ bool type_has_bits(TypeTableEntry *type_entry) {
2973 return !type_entry->zero_bits;2973 return !type_entry->zero_bits;
2974}2974}
29752975
2976static TypeTableEntry *first_struct_field_type(TypeTableEntry *type_entry) {
2977 assert(type_entry->id == TypeTableEntryIdStruct);
2978 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
2979 TypeStructField *tsf = &type_entry->data.structure.fields[i];
2980 if (tsf->gen_index == 0) {
2981 return tsf->type_entry;
2982 }
2983 }
2984 zig_unreachable();
2985}
2986
2987static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) {
2988 assert(type_has_bits(type_entry));
2989 switch (type_entry->id) {
2990 case TypeTableEntryIdInvalid:
2991 case TypeTableEntryIdNumLitFloat:
2992 case TypeTableEntryIdNumLitInt:
2993 case TypeTableEntryIdUndefLit:
2994 case TypeTableEntryIdNullLit:
2995 case TypeTableEntryIdUnreachable:
2996 case TypeTableEntryIdMetaType:
2997 case TypeTableEntryIdVoid:
2998 case TypeTableEntryIdNamespace:
2999 case TypeTableEntryIdBlock:
3000 case TypeTableEntryIdBoundFn:
3001 case TypeTableEntryIdVar:
3002 case TypeTableEntryIdArgTuple:
3003 zig_unreachable();
3004 case TypeTableEntryIdArray:
3005 return type_of_first_thing_in_memory(type_entry->data.array.child_type);
3006 case TypeTableEntryIdStruct:
3007 return type_of_first_thing_in_memory(first_struct_field_type(type_entry));
3008 case TypeTableEntryIdUnion:
3009 zig_panic("TODO");
3010 case TypeTableEntryIdMaybe:
3011 return type_of_first_thing_in_memory(type_entry->data.maybe.child_type);
3012 case TypeTableEntryIdErrorUnion:
3013 return type_of_first_thing_in_memory(type_entry->data.error.child_type);
3014 case TypeTableEntryIdTypeDecl:
3015 return type_of_first_thing_in_memory(type_entry->data.type_decl.canonical_type);
3016 case TypeTableEntryIdEnum:
3017 return type_entry->data.enumeration.tag_type;
3018 case TypeTableEntryIdPureError:
3019 case TypeTableEntryIdFn:
3020 case TypeTableEntryIdBool:
3021 case TypeTableEntryIdInt:
3022 case TypeTableEntryIdFloat:
3023 case TypeTableEntryIdPointer:
3024 case TypeTableEntryIdEnumTag:
3025 return type_entry;
3026 }
3027 zig_unreachable();
3028}
3029
3030bool type_requires_comptime(TypeTableEntry *type_entry) {2976bool type_requires_comptime(TypeTableEntry *type_entry) {
3031 switch (get_underlying_type(type_entry)->id) {2977 switch (get_underlying_type(type_entry)->id) {
3032 case TypeTableEntryIdInvalid:2978 case TypeTableEntryIdInvalid:
...@@ -3063,11 +3009,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {...@@ -3063,11 +3009,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
3063 zig_unreachable();3009 zig_unreachable();
3064}3010}
30653011
3066uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
3067 TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);
3068 return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
3069}
3070
3071void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {3012void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3072 const_val->special = ConstValSpecialStatic;3013 const_val->special = ConstValSpecialStatic;
3073 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));3014 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
src/analyze.hpp-1
...@@ -38,7 +38,6 @@ void find_libc_lib_path(CodeGen *g);...@@ -38,7 +38,6 @@ void find_libc_lib_path(CodeGen *g);
3838
39TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);39TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
40bool type_has_bits(TypeTableEntry *type_entry);40bool type_has_bits(TypeTableEntry *type_entry);
41uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
4241
4342
44ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,43ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
src/codegen.cpp+41-14
...@@ -682,6 +682,33 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {...@@ -682,6 +682,33 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
682 }682 }
683}683}
684684
685static 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
702static 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
685static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,712static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,
686 TypeTableEntry *type_entry)713 TypeTableEntry *type_entry)
687{714{
...@@ -697,7 +724,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef...@@ -697,7 +724,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
697724
698 TypeTableEntry *usize = g->builtin_types.entry_usize;725 TypeTableEntry *usize = g->builtin_types.entry_usize;
699 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);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 assert(size_bytes > 0);728 assert(size_bytes > 0);
702 assert(align_bytes > 0);729 assert(align_bytes > 0);
703730
...@@ -1308,7 +1335,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -1308,7 +1335,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
1308 if (!ignore_uninit && want_safe) {1335 if (!ignore_uninit && want_safe) {
1309 TypeTableEntry *usize = g->builtin_types.entry_usize;1336 TypeTableEntry *usize = g->builtin_types.entry_usize;
1310 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value.type->type_ref);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);
13121339
1313 // memset uninitialized memory to 0xa1340 // memset uninitialized memory to 0xa
1314 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);1341 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
...@@ -2748,6 +2775,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const...@@ -2748,6 +2775,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
2748 LLVMSetLinkage(global_value, LLVMInternalLinkage);2775 LLVMSetLinkage(global_value, LLVMInternalLinkage);
2749 LLVMSetGlobalConstant(global_value, true);2776 LLVMSetGlobalConstant(global_value, true);
2750 LLVMSetUnnamedAddr(global_value, true);2777 LLVMSetUnnamedAddr(global_value, true);
2778 LLVMSetAlignment(global_value, get_type_alignment(g, const_val->type));
27512779
2752 const_val->llvm_global = global_value;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,6 +2910,12 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini
2882 type_entry->di_type, is_local_to_unit, init_val);2910 type_entry->di_type, is_local_to_unit, init_val);
2883}2911}
28842912
2913static 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
2885static void do_code_gen(CodeGen *g) {2919static void do_code_gen(CodeGen *g) {
2886 assert(!g->errors.length);2920 assert(!g->errors.length);
28872921
...@@ -2938,9 +2972,8 @@ static void do_code_gen(CodeGen *g) {...@@ -2938,9 +2972,8 @@ static void do_code_gen(CodeGen *g) {
2938 if (tld_var->section_name) {2972 if (tld_var->section_name) {
2939 LLVMSetSection(global_value, buf_ptr(tld_var->section_name));2973 LLVMSetSection(global_value, buf_ptr(tld_var->section_name));
2940 }2974 }
2941 if (tld_var->alignment) {2975 LLVMSetAlignment(global_value, tld_var->alignment ?
2942 LLVMSetAlignment(global_value, tld_var->alignment);2976 tld_var->alignment : get_type_alignment(g, var->value.type));
2943 }
29442977
2945 // TODO debug info for function pointers2978 // TODO debug info for function pointers
2946 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {2979 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {
...@@ -3114,7 +3147,7 @@ static void do_code_gen(CodeGen *g) {...@@ -3114,7 +3147,7 @@ static void do_code_gen(CodeGen *g) {
3114 } else {3147 } else {
3115 zig_unreachable();3148 zig_unreachable();
3116 }3149 }
3117 *slot = LLVMBuildAlloca(g->builder, slot_type->type_ref, "");3150 *slot = build_alloca(g, slot_type, "");
3118 }3151 }
31193152
3120 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);3153 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
...@@ -3132,11 +3165,7 @@ static void do_code_gen(CodeGen *g) {...@@ -3132,11 +3165,7 @@ static void do_code_gen(CodeGen *g) {
3132 continue;3165 continue;
31333166
3134 if (var->src_arg_index == SIZE_MAX) {3167 if (var->src_arg_index == SIZE_MAX) {
3135 var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name));3168 var->value_ref = build_alloca(g, var->value.type, 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);
31403169
3141 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),3170 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
3142 buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,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,9 +3179,7 @@ static void do_code_gen(CodeGen *g) {
3150 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);3179 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
3151 } else {3180 } else {
3152 gen_type = var->value.type;3181 gen_type = var->value.type;
3153 var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name));3182 var->value_ref = build_alloca(g, var->value.type, 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);
3156 }3183 }
3157 if (var->decl_node) {3184 if (var->decl_node) {
3158 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),3185 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),