authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 18:05:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 18:05:22-07:00
log1158bc3eadd8127301f96ecb9bcbb04cf04156b8
tree8887fad0da5bc92e1098268ce9efe8617d950f67
parent7bd9c8238626998f8016086762483114e5c58f70

support statically initialized structs


4 files changed, 80 insertions(+), 34 deletions(-)

src/all_types.hpp+7-1
......@@ -45,6 +45,10 @@ struct ConstEnumValue {
4545 ConstExprValue *payload;
4646};
4747
48struct ConstStructValue {
49 ConstExprValue **fields;
50};
51
4852struct ConstExprValue {
4953 bool ok; // true if constant expression evalution worked
5054 bool depends_on_compile_var;
......@@ -56,6 +60,7 @@ struct ConstExprValue {
5660 TypeTableEntry *x_type;
5761 ConstExprValue *x_maybe;
5862 ConstEnumValue x_enum;
63 ConstStructValue x_struct;
5964 } data;
6065};
6166
......@@ -721,7 +726,8 @@ struct TypeStructField {
721726struct TypeTableEntryStruct {
722727 AstNode *decl_node;
723728 bool is_packed;
724 uint32_t field_count;
729 uint32_t src_field_count;
730 uint32_t gen_field_count;
725731 TypeStructField *fields;
726732 uint64_t size_bytes;
727733 bool is_invalid; // true if any fields are invalid
src/analyze.cpp+29-20
......@@ -34,6 +34,8 @@ static AstNode *first_executing_node(AstNode *node) {
3434 return first_executing_node(node->data.field_access_expr.struct_expr);
3535 case NodeTypeSwitchRange:
3636 return first_executing_node(node->data.switch_range.start);
37 case NodeTypeContainerInitExpr:
38 return first_executing_node(node->data.container_init_expr.type);
3739 case NodeTypeRoot:
3840 case NodeTypeRootExportDecl:
3941 case NodeTypeFnProto:
......@@ -69,7 +71,6 @@ static AstNode *first_executing_node(AstNode *node) {
6971 case NodeTypeForExpr:
7072 case NodeTypeSwitchExpr:
7173 case NodeTypeSwitchProng:
72 case NodeTypeContainerInitExpr:
7374 case NodeTypeArrayType:
7475 return node;
7576 }
......@@ -303,7 +304,8 @@ static void unknown_size_array_type_common_init(CodeGen *g, TypeTableEntry *chil
303304 entry->align_in_bits = g->pointer_size_bytes * 8;
304305 entry->data.structure.is_packed = false;
305306 entry->data.structure.is_unknown_size_array = true;
306 entry->data.structure.field_count = element_count;
307 entry->data.structure.src_field_count = element_count;
308 entry->data.structure.gen_field_count = element_count;
307309 entry->data.structure.fields = allocate<TypeStructField>(element_count);
308310 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
309311 entry->data.structure.fields[0].type_entry = pointer_type;
......@@ -764,7 +766,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
764766
765767 int field_count = decl_node->data.struct_decl.fields.length;
766768
767 struct_type->data.structure.field_count = field_count;
769 struct_type->data.structure.src_field_count = field_count;
768770 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
769771
770772 // we possibly allocate too much here since gen_field_count can be lower than field_count.
......@@ -823,6 +825,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
823825 }
824826 struct_type->data.structure.embedded_in_current = false;
825827
828 struct_type->data.structure.gen_field_count = gen_field_index;
829
826830 if (!struct_type->data.structure.is_invalid) {
827831
828832 LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_index, false);
......@@ -1083,6 +1087,9 @@ static void add_global_const_expr(CodeGen *g, Expr *expr) {
10831087}
10841088
10851089static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) {
1090 if (other_type->id == TypeTableEntryIdInvalid) {
1091 return false;
1092 }
10861093 Expr *expr = get_resolved_expr(literal_node);
10871094 ConstExprValue *const_val = &expr->const_val;
10881095 assert(const_val->ok);
......@@ -1438,16 +1445,6 @@ static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
14381445 return nullptr;
14391446}
14401447
1441static TypeStructField *get_struct_field(TypeTableEntry *struct_type, Buf *name) {
1442 for (uint32_t i = 0; i < struct_type->data.structure.field_count; i += 1) {
1443 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
1444 if (buf_eql_buf(type_struct_field->name, name)) {
1445 return type_struct_field;
1446 }
1447 }
1448 return nullptr;
1449}
1450
14511448static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
14521449 AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name)
14531450{
......@@ -1484,12 +1481,11 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
14841481 return enum_type;
14851482}
14861483
1487static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name, int *index) {
1484static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
14881485 assert(type_entry->id == TypeTableEntryIdStruct);
1489 for (uint32_t i = 0; i < type_entry->data.structure.field_count; i += 1) {
1486 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
14901487 TypeStructField *field = &type_entry->data.structure.fields[i];
14911488 if (buf_eql_buf(field->name, name)) {
1492 *index = i;
14931489 return field;
14941490 }
14951491 }
......@@ -1530,16 +1526,18 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
15301526
15311527
15321528 int expr_field_count = container_init_expr->entries.length;
1533 int actual_field_count = container_type->data.structure.field_count;
1529 int actual_field_count = container_type->data.structure.src_field_count;
15341530
15351531 int *field_use_counts = allocate<int>(actual_field_count);
1532 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
1533 const_val->ok = true;
1534 const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
15361535 for (int i = 0; i < expr_field_count; i += 1) {
15371536 AstNode *val_field_node = container_init_expr->entries.at(i);
15381537 assert(val_field_node->type == NodeTypeStructValueField);
15391538
1540 int field_index;
15411539 TypeStructField *type_field = find_struct_type_field(container_type,
1542 &val_field_node->data.struct_val_field.name, &field_index);
1540 &val_field_node->data.struct_val_field.name);
15431541
15441542 if (!type_field) {
15451543 add_node_error(g, val_field_node,
......@@ -1548,6 +1546,7 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
15481546 continue;
15491547 }
15501548
1549 int field_index = type_field->src_index;
15511550 field_use_counts[field_index] += 1;
15521551 if (field_use_counts[field_index] > 1) {
15531552 add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
......@@ -1558,6 +1557,16 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
15581557
15591558 analyze_expression(g, import, context, type_field->type_entry,
15601559 val_field_node->data.struct_val_field.expr);
1560
1561 if (const_val->ok) {
1562 ConstExprValue *field_val =
1563 &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
1564 if (field_val->ok) {
1565 const_val->data.x_struct.fields[field_index] = field_val;
1566 } else {
1567 const_val->ok = false;
1568 }
1569 }
15611570 }
15621571
15631572 for (int i = 0; i < actual_field_count; i += 1) {
......@@ -1634,7 +1643,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
16341643 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
16351644 struct_type : struct_type->data.pointer.child_type;
16361645
1637 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);
1646 node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
16381647 if (node->data.field_access_expr.type_struct_field) {
16391648 return node->data.field_access_expr.type_struct_field->type_entry;
16401649 } else {
src/codegen.cpp+26-13
......@@ -1527,13 +1527,13 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
15271527 if (type_entry->id == TypeTableEntryIdStruct) {
15281528 assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
15291529
1530 int field_count = type_entry->data.structure.field_count;
1531 assert(field_count == node->data.container_init_expr.entries.length);
1530 int src_field_count = type_entry->data.structure.src_field_count;
1531 assert(src_field_count == node->data.container_init_expr.entries.length);
15321532
15331533 StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
15341534 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
15351535
1536 for (int i = 0; i < field_count; i += 1) {
1536 for (int i = 0; i < src_field_count; i += 1) {
15371537 AstNode *field_node = node->data.container_init_expr.entries.at(i);
15381538 assert(field_node->type == NodeTypeStructValueField);
15391539 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
......@@ -2109,7 +2109,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
21092109 };
21102110 return LLVMConstStruct(fields, 2, false);
21112111 } else if (type_entry->id == TypeTableEntryIdStruct) {
2112 zig_panic("TODO");
2112 LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
2113 for (int i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
2114 TypeStructField *type_struct_field = &type_entry->data.structure.fields[i];
2115 fields[type_struct_field->gen_index] = gen_const_val(g, type_struct_field->type_entry,
2116 const_val->data.x_struct.fields[i]);
2117 }
2118 return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);
21132119 } else if (type_entry->id == TypeTableEntryIdArray) {
21142120 zig_panic("TODO");
21152121 } else if (type_entry->id == TypeTableEntryIdEnum) {
......@@ -2142,10 +2148,10 @@ static void gen_const_globals(CodeGen *g) {
21422148 TypeTableEntry *type_entry = expr->type_entry;
21432149
21442150 if (handle_is_ptr(type_entry)) {
2145 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_entry->type_ref, "");
2146 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
21472151 LLVMValueRef init_val = gen_const_val(g, type_entry, const_val);
2152 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
21482153 LLVMSetInitializer(global_value, init_val);
2154 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
21492155 LLVMSetGlobalConstant(global_value, true);
21502156 LLVMSetUnnamedAddr(global_value, true);
21512157 expr->const_llvm_val = global_value;
......@@ -2171,15 +2177,22 @@ static void do_code_gen(CodeGen *g) {
21712177 }
21722178
21732179 // TODO if the global is exported, set external linkage
2174 LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, "");
2175 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
2176
2177 if (var->is_const) {
2178 LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
2179 LLVMSetInitializer(global_value, init_val);
2180 LLVMValueRef init_val;
2181
2182 assert(var->decl_node);
2183 assert(var->decl_node->type == NodeTypeVariableDeclaration);
2184 AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
2185 if (expr_node) {
2186 Expr *expr = get_resolved_expr(expr_node);
2187 ConstExprValue *const_val = &expr->const_val;
2188 assert(const_val->ok);
2189 TypeTableEntry *type_entry = expr->type_entry;
2190 init_val = gen_const_val(g, type_entry, const_val);
21802191 } else {
2181 LLVMSetInitializer(global_value, LLVMConstNull(var->type->type_ref));
2192 init_val = LLVMConstNull(var->type->type_ref);
21822193 }
2194 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
2195 LLVMSetInitializer(global_value, init_val);
21832196 LLVMSetGlobalConstant(global_value, var->is_const);
21842197 LLVMSetUnnamedAddr(global_value, true);
21852198
test/run_tests.cpp+18
......@@ -1226,6 +1226,24 @@ pub fn main(args: [][]u8) i32 => {
12261226}
12271227 )SOURCE", "OK\n");
12281228
1229 add_simple_case("statically initialized struct", R"SOURCE(
1230import "std.zig";
1231struct Foo {
1232 x: i32,
1233 y: bool,
1234}
1235var foo = Foo { .x = 13, .y = true, };
1236pub fn main(args: [][]u8) i32 => {
1237 foo.x += 1;
1238 if (foo.x != 14) {
1239 print_str("BAD\n");
1240 }
1241
1242 print_str("OK\n");
1243 return 0;
1244}
1245 )SOURCE", "OK\n");
1246
12291247}
12301248
12311249