aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-11-17 04:00:02 -0500
committerAndrew Kelley <superjoe30@gmail.com>2016-11-17 04:00:02 -0500
commit62d0d88b56b909cf9f9f7a78a8222acd0f37b6cb (patch)
treec61b610a3c43bad96f28cc46385f2843c2dd2633 /src/codegen.cpp
parenta55555c99e9bcc1424c8650ab44570caf593bcdc (diff)
downloadzig-62d0d88b56b909cf9f9f7a78a8222acd0f37b6cb.tar.gz
zig-62d0d88b56b909cf9f9f7a78a8222acd0f37b6cb.zip
IR: pointers to constants don't copy data
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp150
1 files changed, 69 insertions, 81 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 8fe4191754..e1c9091587 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -226,7 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
g->linker_rdynamic = rdynamic;
}
-static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
+static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
+static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
static void set_debug_source_node(CodeGen *g, AstNode *node) {
assert(node->block_context);
@@ -862,11 +863,17 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
if (!type_has_bits(instruction->type_entry))
return nullptr;
if (!instruction->llvm_value) {
- assert(instruction->static_value.ok);
+ assert(instruction->static_value.special != ConstValSpecialRuntime);
assert(instruction->type_entry);
- instruction->llvm_value = gen_const_val(g, instruction->type_entry, &instruction->static_value);
+ render_const_val(g, instruction->type_entry, &instruction->static_value);
+ instruction->llvm_value = instruction->static_value.llvm_value;
assert(instruction->llvm_value);
}
+ if (instruction->static_value.special != ConstValSpecialRuntime) {
+ if (instruction->type_entry->id == TypeTableEntryIdPointer) {
+ return LLVMBuildLoad(g->builder, instruction->static_value.llvm_global, "");
+ }
+ }
return instruction->llvm_value;
}
@@ -1401,9 +1408,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
bool want_zeroes = false;
ConstExprValue *const_val = &init_value->static_value;
- if (!const_val->ok || const_val->special == ConstValSpecialOther)
+ if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
have_init_expr = true;
- if (const_val->ok && const_val->special == ConstValSpecialZeroes)
+ if (const_val->special == ConstValSpecialZeroes)
want_zeroes = true;
if (have_init_expr) {
@@ -1740,14 +1747,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
}
static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
- assert(const_val->ok);
-
switch (const_val->special) {
+ case ConstValSpecialRuntime:
+ zig_unreachable();
case ConstValSpecialUndef:
return LLVMGetUndef(type_entry->type_ref);
case ConstValSpecialZeroes:
return LLVMConstNull(type_entry->type_ref);
- case ConstValSpecialOther:
+ case ConstValSpecialStatic:
break;
}
@@ -1814,7 +1821,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
continue;
}
fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,
- const_val->data.x_struct.fields[i]);
+ &const_val->data.x_struct.fields[i]);
}
return LLVMConstNamedStruct(type_entry->type_ref, fields,
type_entry->data.structure.gen_field_count);
@@ -1829,8 +1836,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
uint64_t len = type_entry->data.array.len;
LLVMValueRef *values = allocate<LLVMValueRef>(len);
for (uint64_t i = 0; i < len; i += 1) {
- ConstExprValue *field_value = const_val->data.x_array.fields[i];
- values[i] = gen_const_val(g, child_type, field_value);
+ ConstExprValue *elem_value = &const_val->data.x_array.elements[i];
+ values[i] = gen_const_val(g, child_type, elem_value);
}
return LLVMConstArray(child_type->type_ref, values, len);
}
@@ -1878,29 +1885,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
case TypeTableEntryIdPointer:
{
TypeTableEntry *child_type = type_entry->data.pointer.child_type;
- size_t len = const_val->data.x_ptr.len;
- LLVMValueRef target_val;
- if (len == 1) {
- target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);
- } else if (len > 1) {
- LLVMValueRef *values = allocate<LLVMValueRef>(len);
- for (size_t i = 0; i < len; i += 1) {
- values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]);
- }
- target_val = LLVMConstArray(child_type->type_ref, values, len);
- } else {
- return LLVMGetUndef(type_entry->type_ref);
- }
- LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), "");
- LLVMSetInitializer(global_value, target_val);
- LLVMSetLinkage(global_value, LLVMPrivateLinkage);
- LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const);
- LLVMSetUnnamedAddr(global_value, true);
-
- if (len > 1) {
- return LLVMConstBitCast(global_value, type_entry->type_ref);
+
+ render_const_val_global(g, type_entry, const_val);
+ size_t index = const_val->data.x_ptr.index;
+ if (index == SIZE_MAX) {
+ render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);
+ render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);
+ return const_val->data.x_ptr.base_ptr->llvm_global;
} else {
- return global_value;
+ ConstExprValue *array_const_val = const_val->data.x_ptr.base_ptr;
+ TypeTableEntry *array_type = get_array_type(g, child_type,
+ array_const_val->data.x_array.size);
+ render_const_val(g, array_type, array_const_val);
+ render_const_val_global(g, array_type, array_const_val);
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(usize->type_ref),
+ LLVMConstInt(usize->type_ref, index, false),
+ };
+ LLVMValueRef ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);
+ return ptr_val;
}
}
case TypeTableEntryIdErrorUnion:
@@ -1945,27 +1949,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
zig_unreachable();
}
-static void gen_const_globals(CodeGen *g) {
- for (size_t i = 0; i < g->global_const_list.length; i += 1) {
- AstNode *expr_node = g->global_const_list.at(i);
- Expr *expr = get_resolved_expr(expr_node);
- ConstExprValue *const_val = &expr->const_val;
- assert(const_val->ok);
- TypeTableEntry *type_entry = expr->type_entry;
-
- if (handle_is_ptr(type_entry)) {
- LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);
- LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
- LLVMSetInitializer(global_value, init_val);
- LLVMSetLinkage(global_value, LLVMPrivateLinkage);
- LLVMSetGlobalConstant(global_value, true);
- LLVMSetUnnamedAddr(global_value, true);
- expr->const_llvm_val = global_value;
- } else {
- expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
- }
- assert(expr->const_llvm_val);
+static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
+ if (!const_val->llvm_value)
+ const_val->llvm_value = gen_const_val(g, type_entry, const_val);
+
+ if (const_val->llvm_global)
+ LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
+}
+
+static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
+ if (!const_val->llvm_global) {
+ LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, "");
+ LLVMSetLinkage(global_value, LLVMInternalLinkage);
+ LLVMSetGlobalConstant(global_value, true);
+ LLVMSetUnnamedAddr(global_value, true);
+
+ const_val->llvm_global = global_value;
}
+
+ if (const_val->llvm_value)
+ LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
}
static void delete_unused_builtin_fns(CodeGen *g) {
@@ -2096,9 +2099,6 @@ static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
delete_unused_builtin_fns(g);
-
-
- gen_const_globals(g);
generate_error_name_table(g);
// Generate module level variables
@@ -2107,8 +2107,8 @@ static void do_code_gen(CodeGen *g) {
if (var->type->id == TypeTableEntryIdNumLitFloat) {
// Generate debug info for it but that's it.
- ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
- assert(const_val->ok);
+ ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
+ assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *var_type = g->builtin_types.entry_f64;
LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);
gen_global_var(g, var, init_val, var_type);
@@ -2117,8 +2117,8 @@ static void do_code_gen(CodeGen *g) {
if (var->type->id == TypeTableEntryIdNumLitInt) {
// Generate debug info for it but that's it.
- ConstExprValue *const_val = &get_resolved_expr(var->val_node)->const_val;
- assert(const_val->ok);
+ ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value;
+ assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
g->builtin_types.entry_isize : g->builtin_types.entry_usize;
LLVMValueRef init_val = LLVMConstInt(var_type->type_ref,
@@ -2143,25 +2143,13 @@ static void do_code_gen(CodeGen *g) {
LLVMSetLinkage(global_value, LLVMExternalLinkage);
} else {
AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
- LLVMValueRef init_val;
- if (expr_node) {
- Expr *expr = get_resolved_expr(expr_node);
- ConstExprValue *const_val = &expr->const_val;
- assert(const_val->ok);
- TypeTableEntry *type_entry = expr->type_entry;
- init_val = gen_const_val(g, type_entry, const_val);
- } else {
- init_val = LLVMConstNull(var->type->type_ref);
- }
-
- global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name));
- LLVMSetInitializer(global_value, init_val);
- LLVMSetLinkage(global_value, LLVMInternalLinkage);
- LLVMSetUnnamedAddr(global_value, true);
-
+ IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
+ render_const_val(g, instruction->type_entry, &instruction->static_value);
+ render_const_val_global(g, instruction->type_entry, &instruction->static_value);
+ global_value = instruction->static_value.llvm_global;
// TODO debug info for function pointers
if (var->gen_is_const && var->type->id != TypeTableEntryIdFn) {
- gen_global_var(g, var, init_val, var->type);
+ gen_global_var(g, var, instruction->static_value.llvm_value, var->type);
}
}
@@ -3282,11 +3270,11 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
Expr *expr = get_resolved_expr(type_node);
- assert(expr->type_entry);
- assert(expr->type_entry->id == TypeTableEntryIdMetaType);
+ assert(expr->instruction->type_entry);
+ assert(expr->instruction->type_entry->id == TypeTableEntryIdMetaType);
- ConstExprValue *const_val = &expr->const_val;
- assert(const_val->ok);
+ ConstExprValue *const_val = &expr->instruction->static_value;
+ assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *type_entry = const_val->data.x_type;