aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-07 01:50:10 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-07 01:50:10 -0500
commit916a96fb724aab03be0e0a1bbaef6de8cc6c305c (patch)
treea4b7298e786f92c3fc51e4374e52f7032f9cab83 /src/codegen.cpp
parent573f3f8d487dfd1f56ab71b96ad23af1a2d4162e (diff)
downloadzig-916a96fb724aab03be0e0a1bbaef6de8cc6c305c.tar.gz
zig-916a96fb724aab03be0e0a1bbaef6de8cc6c305c.zip
variables, memcpy, and memset all get alignment
See #37
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp55
1 files changed, 41 insertions, 14 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 292aa22566..a7ed6cd704 100644
--- a/src/codegen.cpp
+++ b/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),