aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-01-16 12:42:46 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-01-16 12:42:46 -0500
commit4cbeb87e83135e0a1ecbfb90170761ad6e5adb7a (patch)
treeb95b6e7a7723280c7f9ae7be17ff748f4f2cfaa0 /src
parentc7591736b4ae3aed90f6980b4cb23a4dab21d925 (diff)
downloadzig-4cbeb87e83135e0a1ecbfb90170761ad6e5adb7a.tar.gz
zig-4cbeb87e83135e0a1ecbfb90170761ad6e5adb7a.zip
fix handling of const values for 2d arrays
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp5
-rw-r--r--src/codegen.cpp33
-rw-r--r--src/ir.cpp9
3 files changed, 36 insertions, 11 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index bd322d114c..e9c2118f68 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -81,6 +81,11 @@ struct ConstArrayValue {
// This will be the same as `len` from the type, but we duplicate the information
// in the constant value so that pointers pointing to arrays can see this size.
size_t size;
+ // If the data for this array is supposed to be contained in a different constant
+ // value, we link to the parent here. This way getting a pointer to this constant
+ // value can return a pointer into the parent data structure.
+ ConstExprValue *parent_array;
+ size_t parent_array_index;
};
enum ConstPtrSpecial {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index ebaa1b4c07..35039b9418 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2412,6 +2412,25 @@ 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;
+ }
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(usize->type_ref),
+ LLVMConstInt(usize->type_ref, 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);
@@ -2554,7 +2573,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
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;
- TypeTableEntry *usize = g->builtin_types.entry_usize;
if (base_ptr) {
if (index == SIZE_MAX) {
render_const_val(g, base_ptr);
@@ -2568,25 +2586,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
assert(array_const_val->type->id == TypeTableEntryIdArray);
if (array_const_val->type->zero_bits) {
// make this a null pointer
- TypeTableEntry *usize_type = g->builtin_types.entry_usize;
- const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize_type->type_ref),
+ 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;
}
- render_const_val(g, array_const_val);
- render_const_val_global(g, array_const_val);
- LLVMValueRef indices[] = {
- LLVMConstNull(usize->type_ref),
- LLVMConstInt(usize->type_ref, index, false),
- };
- LLVMValueRef uncasted_ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);
+ 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;
diff --git a/src/ir.cpp b/src/ir.cpp
index 60c5f8b85c..98d56de989 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -8314,7 +8314,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
return ira->codegen->builtin_types.entry_invalid;
bool safety_check_on = elem_ptr_instruction->safety_check_on;
- if (casted_elem_index->value.special != ConstValSpecialRuntime) {
+ if (instr_is_comptime(casted_elem_index)) {
uint64_t index = casted_elem_index->value.data.x_bignum.data.x_uint;
if (array_type->id == TypeTableEntryIdArray) {
uint64_t array_len = array_type->data.array.len;
@@ -9923,6 +9923,13 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
if (const_val.special == ConstValSpecialStatic) {
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var);
*out_val = const_val;
+ for (size_t i = 0; i < elem_count; i += 1) {
+ ConstExprValue *elem_val = &out_val->data.x_array.elements[i];
+ if (elem_val->type->id == TypeTableEntryIdArray) {
+ elem_val->data.x_array.parent_array = out_val;
+ elem_val->data.x_array.parent_array_index = i;
+ }
+ }
return fixed_size_array_type;
}