| author | |
| committer | |
| log | 8205253b2b660791ff074b7cb09b8f11bfe924dc |
| tree | 1b6c2bcd23ea540966c7a804af09108647b163d9 |
| parent | 8bc3fae1cf055e33e01e0cbbbbc67f307f60b95b |
3 files changed, 70 insertions(+), 9 deletions(-)
src/analyze.cpp+26-4| ... | ... | @@ -233,8 +233,7 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| 233 | 233 | } |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, | |
| 237 | TypeTableEntry *child_type, uint64_t array_size) | |
| 236 | static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) | |
| 238 | 237 | { |
| 239 | 238 | auto existing_entry = child_type->arrays_by_size.maybe_get(array_size); |
| 240 | 239 | if (existing_entry) { |
| ... | ... | @@ -1389,6 +1388,29 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry |
| 1389 | 1388 | } |
| 1390 | 1389 | } |
| 1391 | 1390 | return container_type; |
| 1391 | } else if (container_type->id == TypeTableEntryIdStruct && | |
| 1392 | container_type->data.structure.is_unknown_size_array && | |
| 1393 | kind == ContainerInitKindArray) | |
| 1394 | { | |
| 1395 | int elem_count = container_init_expr->entries.length; | |
| 1396 | ||
| 1397 | TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry; | |
| 1398 | assert(pointer_type->id == TypeTableEntryIdPointer); | |
| 1399 | TypeTableEntry *child_type = pointer_type->data.pointer.child_type; | |
| 1400 | ||
| 1401 | for (int i = 0; i < elem_count; i += 1) { | |
| 1402 | AstNode *elem_node = container_init_expr->entries.at(i); | |
| 1403 | analyze_expression(g, import, context, child_type, elem_node); | |
| 1404 | } | |
| 1405 | ||
| 1406 | TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count); | |
| 1407 | ||
| 1408 | StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; | |
| 1409 | codegen->type_entry = fixed_size_array_type; | |
| 1410 | codegen->source_node = node; | |
| 1411 | context->struct_val_expr_alloca_list.append(codegen); | |
| 1412 | ||
| 1413 | return fixed_size_array_type; | |
| 1392 | 1414 | } else if (container_type->id == TypeTableEntryIdArray) { |
| 1393 | 1415 | zig_panic("TODO array container init"); |
| 1394 | 1416 | return container_type; |
| ... | ... | @@ -2151,7 +2173,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, |
| 2151 | 2173 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 2152 | 2174 | if (const_val->ok) { |
| 2153 | 2175 | return resolve_expr_const_val_as_type(g, node, |
| 2154 | get_array_type(g, import, child_type, const_val->data.x_uint)); | |
| 2176 | get_array_type(g, child_type, const_val->data.x_uint)); | |
| 2155 | 2177 | } else { |
| 2156 | 2178 | add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression")); |
| 2157 | 2179 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -2986,7 +3008,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2986 | 3008 | if (node->data.string_literal.c) { |
| 2987 | 3009 | return_type = g->builtin_types.entry_c_string_literal; |
| 2988 | 3010 | } else { |
| 2989 | return_type = get_array_type(g, import, g->builtin_types.entry_u8, | |
| 3011 | return_type = get_array_type(g, g->builtin_types.entry_u8, | |
| 2990 | 3012 | buf_len(&node->data.string_literal.buf)); |
| 2991 | 3013 | } |
| 2992 | 3014 | break; |
src/codegen.cpp+25-5| ... | ... | @@ -1132,7 +1132,8 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu |
| 1132 | 1132 | { |
| 1133 | 1133 | assert(type_entry->id == TypeTableEntryIdStruct || |
| 1134 | 1134 | type_entry->id == TypeTableEntryIdMaybe || |
| 1135 | (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0)); | |
| 1135 | (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) || | |
| 1136 | type_entry->id == TypeTableEntryIdArray); | |
| 1136 | 1137 | |
| 1137 | 1138 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 1138 | 1139 | |
| ... | ... | @@ -1157,11 +1158,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b |
| 1157 | 1158 | { |
| 1158 | 1159 | if (op1_type->id == TypeTableEntryIdStruct || |
| 1159 | 1160 | (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) || |
| 1160 | op1_type->id == TypeTableEntryIdMaybe) | |
| 1161 | op1_type->id == TypeTableEntryIdMaybe || | |
| 1162 | op1_type->id == TypeTableEntryIdArray) | |
| 1161 | 1163 | { |
| 1162 | assert(op2_type->id == TypeTableEntryIdStruct || | |
| 1163 | (op2_type->id == TypeTableEntryIdEnum && op2_type->data.enumeration.gen_field_count != 0) || | |
| 1164 | op2_type->id == TypeTableEntryIdMaybe); | |
| 1165 | 1164 | assert(op1_type == op2_type); |
| 1166 | 1165 | assert(bin_op == BinOpTypeAssign); |
| 1167 | 1166 | |
| ... | ... | @@ -1633,6 +1632,27 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { |
| 1633 | 1632 | } else if (type_entry->id == TypeTableEntryIdVoid) { |
| 1634 | 1633 | assert(node->data.container_init_expr.entries.length == 0); |
| 1635 | 1634 | return nullptr; |
| 1635 | } else if (type_entry->id == TypeTableEntryIdArray) { | |
| 1636 | StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr; | |
| 1637 | LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr; | |
| 1638 | ||
| 1639 | int field_count = type_entry->data.array.len; | |
| 1640 | assert(field_count == node->data.container_init_expr.entries.length); | |
| 1641 | ||
| 1642 | for (int i = 0; i < field_count; i += 1) { | |
| 1643 | AstNode *field_node = node->data.container_init_expr.entries.at(i); | |
| 1644 | LLVMValueRef elem_val = gen_expr(g, field_node); | |
| 1645 | ||
| 1646 | LLVMValueRef indices[] = { | |
| 1647 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | |
| 1648 | LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false), | |
| 1649 | }; | |
| 1650 | add_debug_source_node(g, field_node); | |
| 1651 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); | |
| 1652 | LLVMBuildStore(g->builder, elem_val, elem_ptr); | |
| 1653 | } | |
| 1654 | ||
| 1655 | return tmp_array_ptr; | |
| 1636 | 1656 | } else { |
| 1637 | 1657 | zig_unreachable(); |
| 1638 | 1658 | } |
test/run_tests.cpp+19| ... | ... | @@ -1102,6 +1102,25 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 1102 | 1102 | return 0; |
| 1103 | 1103 | } |
| 1104 | 1104 | )SOURCE", "OK\n"); |
| 1105 | ||
| 1106 | add_simple_case("array literal", R"SOURCE( | |
| 1107 | import "std.zig"; | |
| 1108 | ||
| 1109 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1110 | const HEX_MULT = []u16{4096, 256, 16, 1}; | |
| 1111 | ||
| 1112 | if (HEX_MULT.len != 4) { | |
| 1113 | print_str("BAD\n"); | |
| 1114 | } | |
| 1115 | ||
| 1116 | if (HEX_MULT[1] != 256) { | |
| 1117 | print_str("BAD\n"); | |
| 1118 | } | |
| 1119 | ||
| 1120 | print_str("OK\n"); | |
| 1121 | return 0; | |
| 1122 | } | |
| 1123 | )SOURCE", "OK\n"); | |
| 1105 | 1124 | } |
| 1106 | 1125 | |
| 1107 | 1126 |