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 {
315315 Buf field_name;
316316
317317 // populated by semantic analyzer
318 int field_index;
319318 TypeStructField *type_struct_field;
320319 Expr resolved_expr;
321320};
......@@ -527,7 +526,7 @@ struct AstNodeStructValueField {
527526 AstNode *expr;
528527
529528 // populated by semantic analyzer
530 int index;
529 TypeStructField *type_struct_field;
531530};
532531
533532struct AstNodeStructValueExpr {
......@@ -678,6 +677,8 @@ struct TypeTableEntryArray {
678677struct TypeStructField {
679678 Buf *name;
680679 TypeTableEntry *type_entry;
680 int src_index;
681 int gen_index;
681682};
682683
683684struct TypeTableEntryStruct {
src/analyze.cpp+30-20
......@@ -273,8 +273,12 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
273273 entry->data.structure.fields = allocate<TypeStructField>(element_count);
274274 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
275275 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;
276278 entry->data.structure.fields[1].name = buf_create_from_str("len");
277279 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
279283 LLVMZigDIType *di_element_types[] = {
280284 pointer_type->di_type,
......@@ -632,7 +636,7 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_
632636 }
633637}
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) {
636640 assert(struct_type->id == TypeTableEntryIdStruct);
637641
638642 AstNode *decl_node = struct_type->data.structure.decl_node;
......@@ -655,9 +659,12 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
655659 assert(struct_type->di_type);
656660
657661 int field_count = decl_node->data.struct_decl.fields.length;
662
658663 struct_type->data.structure.field_count = field_count;
659664 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.
661668 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count);
662669 LLVMZigDIType **di_element_types = allocate<LLVMZigDIType*>(field_count);
663670
......@@ -665,33 +672,40 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
665672 uint64_t first_field_align_in_bits = 0;
666673 uint64_t offset_in_bits = 0;
667674
668 // this field should be set to true only during the recursive calls to resolve_struct_type
675 // this field should be set to true only during the recursive calls to resolve_container_type
669676 struct_type->data.structure.embedded_in_current = true;
670677
678 int gen_field_index = 0;
671679 for (int i = 0; i < field_count; i += 1) {
672680 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
673681 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
674682 type_struct_field->name = &field_node->data.struct_field.name;
675683 type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type,
676684 import, import->block_context, false);
685 type_struct_field->src_index = i;
686 type_struct_field->gen_index = -1;
677687
678688 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);
680690 } else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) {
681691 struct_type->data.structure.is_invalid = true;
682692 continue;
693 } else if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
694 continue;
683695 }
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,
686700 LLVMZigTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name),
687701 import->di_file, field_node->line + 1,
688702 type_struct_field->type_entry->size_in_bits,
689703 type_struct_field->type_entry->align_in_bits,
690704 offset_in_bits, 0, type_struct_field->type_entry->di_type);
691705
692 element_types[i] = type_struct_field->type_entry->type_ref;
693 assert(di_element_types[i]);
694 assert(element_types[i]);
706 element_types[gen_field_index] = type_struct_field->type_entry->type_ref;
707 assert(di_element_types[gen_field_index]);
708 assert(element_types[gen_field_index]);
695709
696710 total_size_in_bits += type_struct_field->type_entry->size_in_bits;
697711 if (first_field_align_in_bits == 0) {
......@@ -699,12 +713,13 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
699713 }
700714 offset_in_bits += type_struct_field->type_entry->size_in_bits;
701715
716 gen_field_index += 1;
702717 }
703718 struct_type->data.structure.embedded_in_current = false;
704719
705720 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
709724 struct_type->align_in_bits = first_field_align_in_bits;
710725 struct_type->size_in_bits = total_size_in_bits;
......@@ -713,7 +728,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
713728 LLVMZigFileToScope(import->di_file),
714729 buf_ptr(&decl_node->data.struct_decl.name),
715730 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
718733 LLVMZigReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type);
719734 struct_type->di_type = replacement_di_type;
......@@ -888,7 +903,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
888903 {
889904 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
893908 // struct member fns will get resolved independently
894909 break;
......@@ -1262,17 +1277,14 @@ TypeTableEntry *find_container(BlockContext *context, Buf *name) {
12621277 return nullptr;
12631278}
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) {
12661281 for (int i = 0; i < struct_type->data.structure.field_count; i += 1) {
12671282 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
12681283 if (buf_eql_buf(type_struct_field->name, name)) {
1269 *out_tsf = type_struct_field;
1270 *out_i = i;
1271 return;
1284 return type_struct_field;
12721285 }
12731286 }
1274 *out_tsf = nullptr;
1275 *out_i = -1;
1287 return nullptr;
12761288}
12771289
12781290static 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
12931305 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
12941306 struct_type : struct_type->data.pointer.child_type;
12951307
1296 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);
1308 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);
12991309 if (node->data.field_access_expr.type_struct_field) {
13001310 return_type = node->data.field_access_expr.type_struct_field->type_entry;
13011311 } else {
......@@ -1885,7 +1895,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp
18851895 continue;
18861896 }
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
18901900 analyze_expression(g, import, context, type_field->type_entry,
18911901 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
412412 assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
413413 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
417418 *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
418419
419420 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, "");
421422}
422423
423424static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
......@@ -1419,12 +1420,14 @@ static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
14191420 for (int i = 0; i < field_count; i += 1) {
14201421 AstNode *field_node = node->data.struct_val_expr.fields.at(i);
14211422 assert(field_node->type == NodeTypeStructValueField);
1422 int index = field_node->data.struct_val_field.index;
1423 TypeStructField *type_struct_field = &type_entry->data.structure.fields[index];
1423 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
1424 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
1425 continue;
1426 }
14241427 assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
14251428
14261429 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, "");
14281431 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);
14291432 LLVMBuildStore(g->builder, value, field_ptr);
14301433 }
test/run_tests.cpp+25
......@@ -326,6 +326,31 @@ fn void_fun(a : i32, b : void, c : i32) {
326326}
327327 )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
329354 add_simple_case("mutable local variables", R"SOURCE(
330355use "std.zig";
331356