authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 18:56:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 18:56:50-07:00
logb147ff5b60ebb32ec5a3c1f6da82601201d5ad9a
treeeca6659ef15bba8d0a4cff2706b3119be0bf3e2c
parent4d7835e21a28fbfeca5202332c52cb47340941d5

fix codegen for void struct fields


4 files changed, 66 insertions(+), 27 deletions(-)

src/all_types.hpp+3-2
...@@ -315,7 +315,6 @@ struct AstNodeFieldAccessExpr {...@@ -315,7 +315,6 @@ struct AstNodeFieldAccessExpr {
315 Buf field_name;315 Buf field_name;
316316
317 // populated by semantic analyzer317 // populated by semantic analyzer
318 int field_index;
319 TypeStructField *type_struct_field;318 TypeStructField *type_struct_field;
320 Expr resolved_expr;319 Expr resolved_expr;
321};320};
...@@ -527,7 +526,7 @@ struct AstNodeStructValueField {...@@ -527,7 +526,7 @@ struct AstNodeStructValueField {
527 AstNode *expr;526 AstNode *expr;
528527
529 // populated by semantic analyzer528 // populated by semantic analyzer
530 int index;529 TypeStructField *type_struct_field;
531};530};
532531
533struct AstNodeStructValueExpr {532struct AstNodeStructValueExpr {
...@@ -678,6 +677,8 @@ struct TypeTableEntryArray {...@@ -678,6 +677,8 @@ struct TypeTableEntryArray {
678struct TypeStructField {677struct TypeStructField {
679 Buf *name;678 Buf *name;
680 TypeTableEntry *type_entry;679 TypeTableEntry *type_entry;
680 int src_index;
681 int gen_index;
681};682};
682683
683struct TypeTableEntryStruct {684struct TypeTableEntryStruct {
src/analyze.cpp+30-20
...@@ -273,8 +273,12 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry...@@ -273,8 +273,12 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
273 entry->data.structure.fields = allocate<TypeStructField>(element_count);273 entry->data.structure.fields = allocate<TypeStructField>(element_count);
274 entry->data.structure.fields[0].name = buf_create_from_str("ptr");274 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
275 entry->data.structure.fields[0].type_entry = pointer_type;275 entry->data.structure.fields[0].type_entry = pointer_type;
276 entry->data.structure.fields[0].src_index = 0;
277 entry->data.structure.fields[0].gen_index = 0;
276 entry->data.structure.fields[1].name = buf_create_from_str("len");278 entry->data.structure.fields[1].name = buf_create_from_str("len");
277 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;279 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
280 entry->data.structure.fields[1].src_index = 1;
281 entry->data.structure.fields[1].gen_index = 1;
278282
279 LLVMZigDIType *di_element_types[] = {283 LLVMZigDIType *di_element_types[] = {
280 pointer_type->di_type,284 pointer_type->di_type,
...@@ -632,7 +636,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_...@@ -632,7 +636,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_
632 }636 }
633}637}
634638
635static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) {639static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) {
636 assert(struct_type->id == TypeTableEntryIdStruct);640 assert(struct_type->id == TypeTableEntryIdStruct);
637641
638 AstNode *decl_node = struct_type->data.structure.decl_node;642 AstNode *decl_node = struct_type->data.structure.decl_node;
...@@ -655,9 +659,12 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -655,9 +659,12 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
655 assert(struct_type->di_type);659 assert(struct_type->di_type);
656660
657 int field_count = decl_node->data.struct_decl.fields.length;661 int field_count = decl_node->data.struct_decl.fields.length;
662
658 struct_type->data.structure.field_count = field_count;663 struct_type->data.structure.field_count = field_count;
659 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);664 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
660665
666 // we possibly allocate too much here since gen_field_count can be lower than field_count.
667 // the only problem is potential wasted space though.
661 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);668 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
662 LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);669 LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);
663670
...@@ -665,33 +672,40 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -665,33 +672,40 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
665 uint64_t first_field_align_in_bits = 0;672 uint64_t first_field_align_in_bits = 0;
666 uint64_t offset_in_bits = 0;673 uint64_t offset_in_bits = 0;
667674
668 // this field should be set to true only during the recursive calls to resolve_struct_type675 // this field should be set to true only during the recursive calls to resolve_container_type
669 struct_type->data.structure.embedded_in_current = true;676 struct_type->data.structure.embedded_in_current = true;
670677
678 int gen_field_index = 0;
671 for (int i = 0; i < field_count; i += 1) {679 for (int i = 0; i < field_count; i += 1) {
672 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);680 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
673 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];681 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
674 type_struct_field->name = &field_node->data.struct_field.name;682 type_struct_field->name = &field_node->data.struct_field.name;
675 type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type,683 type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type,
676 import, import->block_context, false);684 import, import->block_context, false);
685 type_struct_field->src_index = i;
686 type_struct_field->gen_index = -1;
677687
678 if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) {688 if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) {
679 resolve_struct_type(g, import, type_struct_field->type_entry);689 resolve_container_type(g, import, type_struct_field->type_entry);
680 } else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {690 } else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
681 struct_type->data.structure.is_invalid = true;691 struct_type->data.structure.is_invalid = true;
682 continue;692 continue;
693 } else if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
694 continue;
683 }695 }
684696
685 di_element_types[i] = LLVMZigCreateDebugMemberType(g->dbuilder,697 type_struct_field->gen_index = gen_field_index;
698
699 di_element_types[gen_field_index] = LLVMZigCreateDebugMemberType(g->dbuilder,
686 LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),700 LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
687 import->di_file, field_node->line + 1,701 import->di_file, field_node->line + 1,
688 type_struct_field->type_entry->size_in_bits,702 type_struct_field->type_entry->size_in_bits,
689 type_struct_field->type_entry->align_in_bits,703 type_struct_field->type_entry->align_in_bits,
690 offset_in_bits, 0, type_struct_field->type_entry->di_type);704 offset_in_bits, 0, type_struct_field->type_entry->di_type);
691705
692 element_types[i] = type_struct_field->type_entry->type_ref;706 element_types[gen_field_index] = type_struct_field->type_entry->type_ref;
693 assert(di_element_types[i]);707 assert(di_element_types[gen_field_index]);
694 assert(element_types[i]);708 assert(element_types[gen_field_index]);
695709
696 total_size_in_bits += type_struct_field->type_entry->size_in_bits;710 total_size_in_bits += type_struct_field->type_entry->size_in_bits;
697 if (first_field_align_in_bits == 0) {711 if (first_field_align_in_bits == 0) {
...@@ -699,12 +713,13 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -699,12 +713,13 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
699 }713 }
700 offset_in_bits += type_struct_field->type_entry->size_in_bits;714 offset_in_bits += type_struct_field->type_entry->size_in_bits;
701715
716 gen_field_index += 1;
702 }717 }
703 struct_type->data.structure.embedded_in_current = false;718 struct_type->data.structure.embedded_in_current = false;
704719
705 if (!struct_type->data.structure.is_invalid) {720 if (!struct_type->data.structure.is_invalid) {
706721
707 LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false);722 LLVMStructSetBody(struct_type->type_ref, element_types, gen_field_index, false);
708723
709 struct_type->align_in_bits = first_field_align_in_bits;724 struct_type->align_in_bits = first_field_align_in_bits;
710 struct_type->size_in_bits = total_size_in_bits;725 struct_type->size_in_bits = total_size_in_bits;
...@@ -713,7 +728,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -713,7 +728,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
713 LLVMZigFileToScope(import->di_file),728 LLVMZigFileToScope(import->di_file),
714 buf_ptr(&decl_node->data.struct_decl.name),729 buf_ptr(&decl_node->data.struct_decl.name),
715 import->di_file, decl_node->line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0,730 import->di_file, decl_node->line + 1, struct_type->size_in_bits, struct_type->align_in_bits, 0,
716 nullptr, di_element_types, field_count, 0, nullptr, "");731 nullptr, di_element_types, gen_field_index, 0, nullptr, "");
717732
718 LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);733 LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
719 struct_type->di_type = replacement_di_type;734 struct_type->di_type = replacement_di_type;
...@@ -888,7 +903,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -888,7 +903,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
888 {903 {
889 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;904 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
890905
891 resolve_struct_type(g, import, type_entry);906 resolve_container_type(g, import, type_entry);
892907
893 // struct member fns will get resolved independently908 // struct member fns will get resolved independently
894 break;909 break;
...@@ -1262,17 +1277,14 @@ TypeTableEntry *find_container(BlockContext *context, Buf *name) {...@@ -1262,17 +1277,14 @@ TypeTableEntry *find_container(BlockContext *context, Buf *name) {
1262 return nullptr;1277 return nullptr;
1263}1278}
12641279
1265static void get_struct_field(TypeTableEntry *struct_type, Buf *name, TypeStructField **out_tsf, int *out_i) {1280static TypeStructField *get_struct_field(TypeTableEntry *struct_type, Buf *name) {
1266 for (int i = 0; i < struct_type->data.structure.field_count; i += 1) {1281 for (int i = 0; i < struct_type->data.structure.field_count; i += 1) {
1267 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];1282 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
1268 if (buf_eql_buf(type_struct_field->name, name)) {1283 if (buf_eql_buf(type_struct_field->name, name)) {
1269 *out_tsf = type_struct_field;1284 return type_struct_field;
1270 *out_i = i;
1271 return;
1272 }1285 }
1273 }1286 }
1274 *out_tsf = nullptr;1287 return nullptr;
1275 *out_i = -1;
1276}1288}
12771289
1278static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1290static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -1293,9 +1305,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1293,9 +1305,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
1293 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?1305 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
1294 struct_type : struct_type->data.pointer.child_type;1306 struct_type : struct_type->data.pointer.child_type;
12951307
1296 get_struct_field(bare_struct_type, field_name,1308 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);
1297 &node->data.field_access_expr.type_struct_field,
1298 &node->data.field_access_expr.field_index);
1299 if (node->data.field_access_expr.type_struct_field) {1309 if (node->data.field_access_expr.type_struct_field) {
1300 return_type = node->data.field_access_expr.type_struct_field->type_entry;1310 return_type = node->data.field_access_expr.type_struct_field->type_entry;
1301 } else {1311 } else {
...@@ -1885,7 +1895,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp...@@ -1885,7 +1895,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
1885 continue;1895 continue;
1886 }1896 }
18871897
1888 val_field_node->data.struct_val_field.index = field_index;1898 val_field_node->data.struct_val_field.type_struct_field = type_field;
18891899
1890 analyze_expression(g, import, context, type_field->type_entry,1900 analyze_expression(g, import, context, type_field->type_entry,
1891 val_field_node->data.struct_val_field.expr);1901 val_field_node->data.struct_val_field.expr);
src/codegen.cpp+8-5
...@@ -412,12 +412,13 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -412,12 +412,13 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
412 assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);412 assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
413 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);413 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);
414414
415 assert(node->data.field_access_expr.field_index >= 0);415 int gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
416 assert(gen_field_index >= 0);
416417
417 *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;418 *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
418419
419 add_debug_source_node(g, node);420 add_debug_source_node(g, node);
420 return LLVMBuildStructGEP(g->builder, struct_ptr, node->data.field_access_expr.field_index, "");421 return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
421}422}
422423
423static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {424static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
...@@ -1419,12 +1420,14 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {...@@ -1419,12 +1420,14 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
1419 for (int i = 0; i < field_count; i += 1) {1420 for (int i = 0; i < field_count; i += 1) {
1420 AstNode *field_node = node->data.struct_val_expr.fields.at(i);1421 AstNode *field_node = node->data.struct_val_expr.fields.at(i);
1421 assert(field_node->type == NodeTypeStructValueField);1422 assert(field_node->type == NodeTypeStructValueField);
1422 int index = field_node->data.struct_val_field.index;1423 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
1423 TypeStructField *type_struct_field = &type_entry->data.structure.fields[index];1424 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
1425 continue;
1426 }
1424 assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));1427 assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
14251428
1426 add_debug_source_node(g, field_node);1429 add_debug_source_node(g, field_node);
1427 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, index, "");1430 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
1428 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);1431 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);
1429 LLVMBuildStore(g->builder, value, field_ptr);1432 LLVMBuildStore(g->builder, value, field_ptr);
1430 }1433 }
test/run_tests.cpp+25
...@@ -326,6 +326,31 @@ fn void_fun(a : i32, b : void, c : i32) {...@@ -326,6 +326,31 @@ fn void_fun(a : i32, b : void, c : i32) {
326}326}
327 )SOURCE", "OK\n");327 )SOURCE", "OK\n");
328328
329 add_simple_case("void struct fields", R"SOURCE(
330use "std.zig";
331struct Foo {
332 a : void,
333 b : i32,
334 c : void,
335}
336pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
337 const foo = Foo {
338 .a = void,
339 .b = 1,
340 .c = void,
341 };
342 if (foo.b != 1) {
343 print_str("BAD\n");
344 }
345 if (#sizeof(Foo) != 4) {
346 print_str("BAD\n");
347 }
348 print_str("OK\n");
349 return 0;
350}
351
352 )SOURCE", "OK\n");
353
329 add_simple_case("mutable local variables", R"SOURCE(354 add_simple_case("mutable local variables", R"SOURCE(
330use "std.zig";355use "std.zig";
331356