authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-18 04:34:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-18 04:34:26-07:00
logf0a43cfda9bcfcbefb24cac3ef01c5c745022c58
tree6e1ad0d4b16713078f40bf235aebbef09f8b196d
parent826c7f06a3cebdf15d88e5228e705974b215bcd4

fix nested arrays


3 files changed, 87 insertions(+), 29 deletions(-)

src/analyze.cpp+39-16
...@@ -235,17 +235,53 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui...@@ -235,17 +235,53 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui
235 }235 }
236}236}
237237
238static void unknown_size_array_type_common_init(CodeGen *g, TypeTableEntry *child_type,
239 bool is_const, TypeTableEntry *entry)
240{
241 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
242
243 unsigned element_count = 2;
244 entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
245 entry->align_in_bits = g->pointer_size_bytes * 8;
246 entry->data.structure.is_packed = false;
247 entry->data.structure.is_unknown_size_array = true;
248 entry->data.structure.field_count = element_count;
249 entry->data.structure.fields = allocate<TypeStructField>(element_count);
250 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
251 entry->data.structure.fields[0].type_entry = pointer_type;
252 entry->data.structure.fields[0].src_index = 0;
253 entry->data.structure.fields[0].gen_index = 0;
254 entry->data.structure.fields[1].name = buf_create_from_str("len");
255 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
256 entry->data.structure.fields[1].src_index = 1;
257 entry->data.structure.fields[1].gen_index = 1;
258}
259
238static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {260static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
239 assert(child_type->id != TypeTableEntryIdInvalid);261 assert(child_type->id != TypeTableEntryIdInvalid);
240 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];262 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
263
241 if (*parent_pointer) {264 if (*parent_pointer) {
242 return *parent_pointer;265 return *parent_pointer;
266 } else if (is_const) {
267 TypeTableEntry *var_peer = get_unknown_size_array_type(g, child_type, false);
268 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
269
270 buf_resize(&entry->name, 0);
271 buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name));
272
273 unknown_size_array_type_common_init(g, child_type, is_const, entry);
274
275 entry->type_ref = var_peer->type_ref;
276 entry->di_type = var_peer->di_type;
277
278 *parent_pointer = entry;
279 return entry;
243 } else {280 } else {
244 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);281 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
245282
246 const char *const_str = is_const ? "const " : "";
247 buf_resize(&entry->name, 0);283 buf_resize(&entry->name, 0);
248 buf_appendf(&entry->name, "[]%s%s", const_str, buf_ptr(&child_type->name));284 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
249 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));285 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
250286
251 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);287 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
...@@ -257,20 +293,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c...@@ -257,20 +293,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
257 };293 };
258 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);294 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
259295
260 entry->size_in_bits = g->pointer_size_bytes * 2 * 8;296 unknown_size_array_type_common_init(g, child_type, is_const, entry);
261 entry->align_in_bits = g->pointer_size_bytes * 8;
262 entry->data.structure.is_packed = false;
263 entry->data.structure.is_unknown_size_array = true;
264 entry->data.structure.field_count = element_count;
265 entry->data.structure.fields = allocate<TypeStructField>(element_count);
266 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
267 entry->data.structure.fields[0].type_entry = pointer_type;
268 entry->data.structure.fields[0].src_index = 0;
269 entry->data.structure.fields[0].gen_index = 0;
270 entry->data.structure.fields[1].name = buf_create_from_str("len");
271 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
272 entry->data.structure.fields[1].src_index = 1;
273 entry->data.structure.fields[1].gen_index = 1;
274297
275 LLVMZigDIType *di_element_types[] = {298 LLVMZigDIType *di_element_types[] = {
276 pointer_type->di_type,299 pointer_type->di_type,
src/codegen.cpp+33-13
...@@ -150,6 +150,13 @@ static TypeTableEntry *get_expr_type(AstNode *node) {...@@ -150,6 +150,13 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
150 return expr->type_entry;150 return expr->type_entry;
151}151}
152152
153static bool handle_is_ptr(TypeTableEntry *type_entry) {
154 return type_entry->id == TypeTableEntryIdStruct ||
155 (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
156 type_entry->id == TypeTableEntryIdMaybe ||
157 type_entry->id == TypeTableEntryIdArray;
158}
159
153static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,160static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
154 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)161 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
155{162{
...@@ -681,12 +688,27 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -681,12 +688,27 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
681 }688 }
682}689}
683690
691
684static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {692static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
685 assert(node->type == NodeTypeArrayAccessExpr);693 assert(node->type == NodeTypeArrayAccessExpr);
686694
687 LLVMValueRef ptr = gen_array_ptr(g, node);695 LLVMValueRef ptr = gen_array_ptr(g, node);
696 TypeTableEntry *child_type;
697 TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
698 if (array_type->id == TypeTableEntryIdPointer) {
699 child_type = array_type->data.pointer.child_type;
700 } else if (array_type->id == TypeTableEntryIdStruct) {
701 assert(array_type->data.structure.is_unknown_size_array);
702 TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
703 assert(child_ptr_type->id == TypeTableEntryIdPointer);
704 child_type = child_ptr_type->data.pointer.child_type;
705 } else if (array_type->id == TypeTableEntryIdArray) {
706 child_type = array_type->data.array.child_type;
707 } else {
708 zig_unreachable();
709 }
688710
689 if (is_lvalue || !ptr) {711 if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
690 return ptr;712 return ptr;
691 } else {713 } else {
692 add_debug_source_node(g, node);714 add_debug_source_node(g, node);
...@@ -1142,10 +1164,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -1142,10 +1164,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
1142static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,1164static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,
1143 TypeTableEntry *type_entry)1165 TypeTableEntry *type_entry)
1144{1166{
1145 assert(type_entry->id == TypeTableEntryIdStruct ||1167 assert(handle_is_ptr(type_entry));
1146 type_entry->id == TypeTableEntryIdMaybe ||
1147 (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
1148 type_entry->id == TypeTableEntryIdArray);
11491168
1150 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);1169 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
11511170
...@@ -1168,11 +1187,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -1168,11 +1187,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
1168 LLVMValueRef target_ref, LLVMValueRef value,1187 LLVMValueRef target_ref, LLVMValueRef value,
1169 TypeTableEntry *op1_type, TypeTableEntry *op2_type)1188 TypeTableEntry *op1_type, TypeTableEntry *op2_type)
1170{1189{
1171 if (op1_type->id == TypeTableEntryIdStruct ||1190 if (handle_is_ptr(op1_type)) {
1172 (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) ||
1173 op1_type->id == TypeTableEntryIdMaybe ||
1174 op1_type->id == TypeTableEntryIdArray)
1175 {
1176 assert(op1_type == op2_type);1191 assert(op1_type == op2_type);
1177 assert(bin_op == BinOpTypeAssign);1192 assert(bin_op == BinOpTypeAssign);
11781193
...@@ -1632,8 +1647,10 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {...@@ -1632,8 +1647,10 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
16321647
1633 add_debug_source_node(g, field_node);1648 add_debug_source_node(g, field_node);
1634 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");1649 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
1635 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);1650 AstNode *expr_node = field_node->data.struct_val_field.expr;
1636 LLVMBuildStore(g->builder, value, field_ptr);1651 LLVMValueRef value = gen_expr(g, expr_node);
1652 gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value,
1653 type_struct_field->type_entry, get_expr_type(expr_node));
1637 }1654 }
16381655
1639 return tmp_struct_ptr;1656 return tmp_struct_ptr;
...@@ -1651,6 +1668,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {...@@ -1651,6 +1668,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
1651 int field_count = type_entry->data.array.len;1668 int field_count = type_entry->data.array.len;
1652 assert(field_count == node->data.container_init_expr.entries.length);1669 assert(field_count == node->data.container_init_expr.entries.length);
16531670
1671 TypeTableEntry *child_type = type_entry->data.array.child_type;
1672
1654 for (int i = 0; i < field_count; i += 1) {1673 for (int i = 0; i < field_count; i += 1) {
1655 AstNode *field_node = node->data.container_init_expr.entries.at(i);1674 AstNode *field_node = node->data.container_init_expr.entries.at(i);
1656 LLVMValueRef elem_val = gen_expr(g, field_node);1675 LLVMValueRef elem_val = gen_expr(g, field_node);
...@@ -1661,7 +1680,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {...@@ -1661,7 +1680,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
1661 };1680 };
1662 add_debug_source_node(g, field_node);1681 add_debug_source_node(g, field_node);
1663 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");1682 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
1664 LLVMBuildStore(g->builder, elem_val, elem_ptr);1683 gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
1684 child_type, get_expr_type(field_node));
1665 }1685 }
16661686
1667 return tmp_array_ptr;1687 return tmp_array_ptr;
test/run_tests.cpp+15
...@@ -1121,6 +1121,21 @@ pub fn main(args: [][]u8) i32 => {...@@ -1121,6 +1121,21 @@ pub fn main(args: [][]u8) i32 => {
1121 return 0;1121 return 0;
1122}1122}
1123 )SOURCE", "OK\n");1123 )SOURCE", "OK\n");
1124
1125 add_simple_case("nested arrays", R"SOURCE(
1126import "std.zig";
1127
1128pub fn main(args: [][]u8) i32 => {
1129 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
1130 var i: @typeof(array_of_strings.len) = 0;
1131 while (i < array_of_strings.len) {
1132 print_str(array_of_strings[i]);
1133 print_str("\n");
1134 i += 1;
1135 }
1136 return 0;
1137}
1138 )SOURCE", "hello\nthis\nis\nmy\nthing\n");
1124}1139}
11251140
11261141