Commit 916a96fb72

Andrew Kelley <superjoe30@gmail.com>
2017-02-07 07:50:10
variables, memcpy, and memset all get alignment
See #37
1 parent 573f3f8
src/analyze.cpp
@@ -2973,60 +2973,6 @@ bool type_has_bits(TypeTableEntry *type_entry) {
     return !type_entry->zero_bits;
 }
 
-static TypeTableEntry *first_struct_field_type(TypeTableEntry *type_entry) {
-    assert(type_entry->id == TypeTableEntryIdStruct);
-    for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
-        TypeStructField *tsf = &type_entry->data.structure.fields[i];
-        if (tsf->gen_index == 0) {
-            return tsf->type_entry;
-        }
-    }
-    zig_unreachable();
-}
-
-static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) {
-    assert(type_has_bits(type_entry));
-    switch (type_entry->id) {
-        case TypeTableEntryIdInvalid:
-        case TypeTableEntryIdNumLitFloat:
-        case TypeTableEntryIdNumLitInt:
-        case TypeTableEntryIdUndefLit:
-        case TypeTableEntryIdNullLit:
-        case TypeTableEntryIdUnreachable:
-        case TypeTableEntryIdMetaType:
-        case TypeTableEntryIdVoid:
-        case TypeTableEntryIdNamespace:
-        case TypeTableEntryIdBlock:
-        case TypeTableEntryIdBoundFn:
-        case TypeTableEntryIdVar:
-        case TypeTableEntryIdArgTuple:
-            zig_unreachable();
-        case TypeTableEntryIdArray:
-            return type_of_first_thing_in_memory(type_entry->data.array.child_type);
-        case TypeTableEntryIdStruct:
-            return type_of_first_thing_in_memory(first_struct_field_type(type_entry));
-        case TypeTableEntryIdUnion:
-            zig_panic("TODO");
-        case TypeTableEntryIdMaybe:
-            return type_of_first_thing_in_memory(type_entry->data.maybe.child_type);
-        case TypeTableEntryIdErrorUnion:
-            return type_of_first_thing_in_memory(type_entry->data.error.child_type);
-        case TypeTableEntryIdTypeDecl:
-            return type_of_first_thing_in_memory(type_entry->data.type_decl.canonical_type);
-        case TypeTableEntryIdEnum:
-            return type_entry->data.enumeration.tag_type;
-        case TypeTableEntryIdPureError:
-        case TypeTableEntryIdFn:
-        case TypeTableEntryIdBool:
-        case TypeTableEntryIdInt:
-        case TypeTableEntryIdFloat:
-        case TypeTableEntryIdPointer:
-        case TypeTableEntryIdEnumTag:
-            return type_entry;
-    }
-    zig_unreachable();
-}
-
 bool type_requires_comptime(TypeTableEntry *type_entry) {
     switch (get_underlying_type(type_entry)->id) {
         case TypeTableEntryIdInvalid:
@@ -3063,11 +3009,6 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
     zig_unreachable();
 }
 
-uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
-    TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);
-    return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
-}
-
 void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
     const_val->special = ConstValSpecialStatic;
     const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
src/analyze.hpp
@@ -38,7 +38,6 @@ void find_libc_lib_path(CodeGen *g);
 
 TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
 bool type_has_bits(TypeTableEntry *type_entry);
-uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
 
 
 ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
src/codegen.cpp
@@ -682,6 +682,33 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
     }
 }
 
+static bool is_array_of_at_least_n_bytes(CodeGen *g, TypeTableEntry *type_entry, uint32_t n) {
+    if (type_entry->id != TypeTableEntryIdArray)
+        return false;
+
+    TypeTableEntry *child_type = type_entry->data.array.child_type;
+    if (child_type->id != TypeTableEntryIdInt)
+        return false;
+
+    if (child_type != g->builtin_types.entry_u8)
+        return false;
+
+    if (type_entry->data.array.len < n)
+        return false;
+
+    return true;
+}
+
+static uint32_t get_type_alignment(CodeGen *g, TypeTableEntry *type_entry) {
+    uint32_t alignment = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, type_entry->type_ref);
+    uint32_t dbl_ptr_bytes = g->pointer_size_bytes * 2;
+    if (is_array_of_at_least_n_bytes(g, type_entry, dbl_ptr_bytes)) {
+        return (alignment < dbl_ptr_bytes) ? dbl_ptr_bytes : alignment;
+    } else {
+        return alignment;
+    }
+}
+
 static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,
         TypeTableEntry *type_entry)
 {
@@ -697,7 +724,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
 
     TypeTableEntry *usize = g->builtin_types.entry_usize;
     uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
-    uint64_t align_bytes = get_memcpy_align(g, type_entry);
+    uint64_t align_bytes = get_type_alignment(g, type_entry);
     assert(size_bytes > 0);
     assert(align_bytes > 0);
 
@@ -1308,7 +1335,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
         if (!ignore_uninit && want_safe) {
             TypeTableEntry *usize = g->builtin_types.entry_usize;
             uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value.type->type_ref);
-            uint64_t align_bytes = get_memcpy_align(g, var->value.type);
+            uint64_t align_bytes = get_type_alignment(g, var->value.type);
 
             // memset uninitialized memory to 0xa
             LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
@@ -2748,6 +2775,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
         LLVMSetLinkage(global_value, LLVMInternalLinkage);
         LLVMSetGlobalConstant(global_value, true);
         LLVMSetUnnamedAddr(global_value, true);
+        LLVMSetAlignment(global_value, get_type_alignment(g, const_val->type));
 
         const_val->llvm_global = global_value;
     }
@@ -2882,6 +2910,12 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini
         type_entry->di_type, is_local_to_unit, init_val);
 }
 
+static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name) {
+    LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
+    LLVMSetAlignment(result, get_type_alignment(g, type_entry));
+    return result;
+}
+
 static void do_code_gen(CodeGen *g) {
     assert(!g->errors.length);
 
@@ -2938,9 +2972,8 @@ static void do_code_gen(CodeGen *g) {
             if (tld_var->section_name) {
                 LLVMSetSection(global_value, buf_ptr(tld_var->section_name));
             }
-            if (tld_var->alignment) {
-                LLVMSetAlignment(global_value, tld_var->alignment);
-            }
+            LLVMSetAlignment(global_value, tld_var->alignment ?
+                    tld_var->alignment : get_type_alignment(g, var->value.type));
 
             // TODO debug info for function pointers
             if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {
@@ -3114,7 +3147,7 @@ static void do_code_gen(CodeGen *g) {
             } else {
                 zig_unreachable();
             }
-            *slot = LLVMBuildAlloca(g->builder, slot_type->type_ref, "");
+            *slot = build_alloca(g, slot_type, "");
         }
 
         ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
@@ -3132,11 +3165,7 @@ static void do_code_gen(CodeGen *g) {
                 continue;
 
             if (var->src_arg_index == SIZE_MAX) {
-                var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name));
-
-
-                unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref);
-                LLVMSetAlignment(var->value_ref, align_bytes);
+                var->value_ref = build_alloca(g, var->value.type, buf_ptr(&var->name));
 
                 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
                         buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
@@ -3150,9 +3179,7 @@ static void do_code_gen(CodeGen *g) {
                     var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
                 } else {
                     gen_type = var->value.type;
-                    var->value_ref = LLVMBuildAlloca(g->builder, var->value.type->type_ref, buf_ptr(&var->name));
-                    unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref);
-                    LLVMSetAlignment(var->value_ref, align_bytes);
+                    var->value_ref = build_alloca(g, var->value.type, buf_ptr(&var->name));
                 }
                 if (var->decl_node) {
                     var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),