aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-11 13:13:45 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-11 13:13:45 -0500
commit39287d7346436a87ce785866befa77351bf2fc85 (patch)
tree0c3e20f4bd3c0dea8f42486177f88f49b71be09c /src/codegen.cpp
parent12049aa43b154f75445e616c2699aaff017d8228 (diff)
downloadzig-39287d7346436a87ce785866befa77351bf2fc85.tar.gz
zig-39287d7346436a87ce785866befa77351bf2fc85.zip
rework compile-time known pointer values
See #257
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp131
1 files changed, 94 insertions, 37 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 828dba3b64..e56c3b7de2 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2527,17 +2527,29 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
}
}
-static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
- ConstExprValue *parent_array = array_const_val->data.x_array.parent_array;
- LLVMValueRef base_ptr;
- if (parent_array) {
- size_t parent_array_index = array_const_val->data.x_array.parent_array_index;
- base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);
- } else {
- render_const_val(g, array_const_val);
- render_const_val_global(g, array_const_val, "");
- base_ptr = array_const_val->llvm_global;
+static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
+static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
+
+static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
+ switch (parent->id) {
+ case ConstParentIdNone:
+ render_const_val(g, val);
+ render_const_val_global(g, val, "");
+ return val->llvm_global;
+ case ConstParentIdStruct:
+ return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
+ parent->data.p_struct.field_index);
+ case ConstParentIdArray:
+ return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
+ parent->data.p_array.elem_index);
}
+ zig_unreachable();
+}
+
+static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
+ ConstParent *parent = &array_const_val->data.x_array.parent;
+ LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
+
TypeTableEntry *usize = g->builtin_types.entry_usize;
LLVMValueRef indices[] = {
LLVMConstNull(usize->type_ref),
@@ -2546,6 +2558,19 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
}
+static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
+ ConstParent *parent = &struct_const_val->data.x_struct.parent;
+ LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
+
+ TypeTableEntry *u32 = g->builtin_types.entry_u32;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(u32->type_ref),
+ LLVMConstInt(u32->type_ref, field_index, false),
+ };
+ return LLVMConstInBoundsGEP(base_ptr, indices, 2);
+}
+
+
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
TypeTableEntry *canon_type = get_underlying_type(const_val->type);
assert(!canon_type->zero_bits);
@@ -2684,38 +2709,70 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
case TypeTableEntryIdPointer:
{
render_const_val_global(g, const_val, "");
- size_t index = const_val->data.x_ptr.index;
- ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
- if (base_ptr) {
- if (index == SIZE_MAX) {
- render_const_val(g, base_ptr);
- render_const_val_global(g, base_ptr, "");
- ConstExprValue *other_val = base_ptr;
- const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->llvm_value;
- } else {
- ConstExprValue *array_const_val = base_ptr;
- assert(array_const_val->type->id == TypeTableEntryIdArray);
- if (array_const_val->type->zero_bits) {
- // make this a null pointer
+ switch (const_val->data.x_ptr.special) {
+ case ConstPtrSpecialInvalid:
+ zig_unreachable();
+ case ConstPtrSpecialRef:
+ {
+ ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
+ render_const_val(g, pointee);
+ render_const_val_global(g, pointee, "");
+ ConstExprValue *other_val = pointee;
+ const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->llvm_value;
+ }
+ case ConstPtrSpecialBaseArray:
+ {
+ ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
+ size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
+ assert(array_const_val->type->id == TypeTableEntryIdArray);
+ if (array_const_val->type->zero_bits) {
+ // make this a null pointer
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->llvm_value;
+ }
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
+ elem_index);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->llvm_value = ptr_val;
+ render_const_val_global(g, const_val, "");
+ return ptr_val;
+ }
+ case ConstPtrSpecialBaseStruct:
+ {
+ ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
+ assert(struct_const_val->type->id == TypeTableEntryIdStruct);
+ if (struct_const_val->type->zero_bits) {
+ // make this a null pointer
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->llvm_value;
+ }
+ size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
+ size_t gen_field_index =
+ struct_const_val->type->data.structure.fields[src_field_index].gen_index;
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
+ gen_field_index);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->llvm_value = ptr_val;
+ render_const_val_global(g, const_val, "");
+ return ptr_val;
+ }
+ case ConstPtrSpecialHardCodedAddr:
+ {
+ uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
TypeTableEntry *usize = g->builtin_types.entry_usize;
- const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
const_val->type->type_ref);
render_const_val_global(g, const_val, "");
return const_val->llvm_value;
}
- LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);
- LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
- const_val->llvm_value = ptr_val;
- render_const_val_global(g, const_val, "");
- return ptr_val;
- }
- } else {
- TypeTableEntry *usize = g->builtin_types.entry_usize;
- const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->llvm_value;
}
}
case TypeTableEntryIdErrorUnion: