diff --git a/src/analyze.cpp b/src/analyze.cpp index 9fa5409c1..fe943ec69 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -233,8 +233,7 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { } } -static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, - TypeTableEntry *child_type, uint64_t array_size) +static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) { auto existing_entry = child_type->arrays_by_size.maybe_get(array_size); if (existing_entry) { @@ -1389,6 +1388,29 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry } } return container_type; + } else if (container_type->id == TypeTableEntryIdStruct && + container_type->data.structure.is_unknown_size_array && + kind == ContainerInitKindArray) + { + int elem_count = container_init_expr->entries.length; + + TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry; + assert(pointer_type->id == TypeTableEntryIdPointer); + TypeTableEntry *child_type = pointer_type->data.pointer.child_type; + + for (int i = 0; i < elem_count; i += 1) { + AstNode *elem_node = container_init_expr->entries.at(i); + analyze_expression(g, import, context, child_type, elem_node); + } + + TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count); + + StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; + codegen->type_entry = fixed_size_array_type; + codegen->source_node = node; + context->struct_val_expr_alloca_list.append(codegen); + + return fixed_size_array_type; } else if (container_type->id == TypeTableEntryIdArray) { zig_panic("TODO array container init"); return container_type; @@ -2151,7 +2173,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; if (const_val->ok) { return resolve_expr_const_val_as_type(g, node, - get_array_type(g, import, child_type, const_val->data.x_uint)); + get_array_type(g, child_type, const_val->data.x_uint)); } else { add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression")); return g->builtin_types.entry_invalid; @@ -2986,7 +3008,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, if (node->data.string_literal.c) { return_type = g->builtin_types.entry_c_string_literal; } else { - return_type = get_array_type(g, import, g->builtin_types.entry_u8, + return_type = get_array_type(g, g->builtin_types.entry_u8, buf_len(&node->data.string_literal.buf)); } break; diff --git a/src/codegen.cpp b/src/codegen.cpp index d9d22d52a..fd5f048ff 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1132,7 +1132,8 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu { assert(type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdMaybe || - (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0)); + (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) || + type_entry->id == TypeTableEntryIdArray); LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); @@ -1157,11 +1158,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b { if (op1_type->id == TypeTableEntryIdStruct || (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) || - op1_type->id == TypeTableEntryIdMaybe) + op1_type->id == TypeTableEntryIdMaybe || + op1_type->id == TypeTableEntryIdArray) { - assert(op2_type->id == TypeTableEntryIdStruct || - (op2_type->id == TypeTableEntryIdEnum && op2_type->data.enumeration.gen_field_count != 0) || - op2_type->id == TypeTableEntryIdMaybe); assert(op1_type == op2_type); assert(bin_op == BinOpTypeAssign); @@ -1633,6 +1632,27 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { } else if (type_entry->id == TypeTableEntryIdVoid) { assert(node->data.container_init_expr.entries.length == 0); return nullptr; + } else if (type_entry->id == TypeTableEntryIdArray) { + StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr; + LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr; + + int field_count = type_entry->data.array.len; + assert(field_count == node->data.container_init_expr.entries.length); + + for (int i = 0; i < field_count; i += 1) { + AstNode *field_node = node->data.container_init_expr.entries.at(i); + LLVMValueRef elem_val = gen_expr(g, field_node); + + LLVMValueRef indices[] = { + LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false), + }; + add_debug_source_node(g, field_node); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); + LLVMBuildStore(g->builder, elem_val, elem_ptr); + } + + return tmp_array_ptr; } else { zig_unreachable(); } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 0c6669b8c..d61246344 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1102,6 +1102,25 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { return 0; } )SOURCE", "OK\n"); + + add_simple_case("array literal", R"SOURCE( +import "std.zig"; + +pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { + const HEX_MULT = []u16{4096, 256, 16, 1}; + + if (HEX_MULT.len != 4) { + print_str("BAD\n"); + } + + if (HEX_MULT[1] != 256) { + print_str("BAD\n"); + } + + print_str("OK\n"); + return 0; +} + )SOURCE", "OK\n"); }