| ... | @@ -36,6 +36,7 @@ struct Context { | ... | @@ -36,6 +36,7 @@ struct Context { |
| 36 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table; | 36 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table; |
| 37 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table; | 37 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table; |
| 38 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table; | 38 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_type_table; |
| | 39 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> struct_decl_table; |
| 39 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table; | 40 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table; |
| 40 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; | 41 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; |
| 41 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; | 42 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| ... | @@ -51,6 +52,7 @@ static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, con | ... | @@ -51,6 +52,7 @@ static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, con |
| 51 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table); | 52 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table); |
| 52 | | 53 | |
| 53 | static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl); | 54 | static TypeTableEntry *resolve_qual_type(Context *c, QualType qt, const Decl *decl); |
| | 55 | static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl); |
| 54 | | 56 | |
| 55 | | 57 | |
| 56 | __attribute__ ((format (printf, 3, 4))) | 58 | __attribute__ ((format (printf, 3, 4))) |
| ... | @@ -79,12 +81,17 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...) | ... | @@ -79,12 +81,17 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...) |
| 79 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); | 81 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 80 | } | 82 | } |
| 81 | | 83 | |
| | 84 | static uint32_t get_next_node_index(Context *c) { |
| | 85 | uint32_t result = c->codegen->next_node_index; |
| | 86 | c->codegen->next_node_index += 1; |
| | 87 | return result; |
| | 88 | } |
| | 89 | |
| 82 | static AstNode *create_node(Context *c, NodeType type) { | 90 | static AstNode *create_node(Context *c, NodeType type) { |
| 83 | AstNode *node = allocate<AstNode>(1); | 91 | AstNode *node = allocate<AstNode>(1); |
| 84 | node->type = type; | 92 | node->type = type; |
| 85 | node->owner = c->import; | 93 | node->owner = c->import; |
| 86 | node->create_index = c->codegen->next_node_index; | 94 | node->create_index = get_next_node_index(c); |
| 87 | c->codegen->next_node_index += 1; | | |
| 88 | return node; | 95 | return node; |
| 89 | } | 96 | } |
| 90 | | 97 | |
| ... | @@ -437,18 +444,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const | ... | @@ -437,18 +444,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 437 | case Type::Record: | 444 | case Type::Record: |
| 438 | { | 445 | { |
| 439 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | 446 | const RecordType *record_ty = static_cast<const RecordType*>(ty); |
| 440 | Buf *record_name = buf_create_from_str(decl_name(record_ty->getDecl())); | 447 | return resolve_record_decl(c, record_ty->getDecl()); |
| 441 | if (buf_len(record_name) == 0) { | | |
| 442 | emit_warning(c, decl, "unhandled anonymous struct"); | | |
| 443 | return c->codegen->builtin_types.entry_invalid; | | |
| 444 | } | | |
| 445 | | | |
| 446 | auto entry = type_table->maybe_get(record_name); | | |
| 447 | if (!entry) { | | |
| 448 | return c->codegen->builtin_types.entry_invalid; | | |
| 449 | } | | |
| 450 | | | |
| 451 | return entry->value; | | |
| 452 | } | 448 | } |
| 453 | case Type::Enum: | 449 | case Type::Enum: |
| 454 | { | 450 | { |
| ... | @@ -754,47 +750,39 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { | ... | @@ -754,47 +750,39 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) { |
| 754 | | 750 | |
| 755 | } | 751 | } |
| 756 | | 752 | |
| 757 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | 753 | static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl) { |
| 758 | const char *raw_name = decl_name(record_decl); | 754 | const char *raw_name = decl_name(record_decl); |
| 759 | | 755 | |
| 760 | // we have no interest in top level anonymous structs since they're | | |
| 761 | // not exposing anything. | | |
| 762 | if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) { | | |
| 763 | return; | | |
| 764 | } | | |
| 765 | | | |
| 766 | if (!record_decl->isStruct()) { | 756 | if (!record_decl->isStruct()) { |
| 767 | emit_warning(c, record_decl, "skipping record %s, not a struct", raw_name); | 757 | emit_warning(c, record_decl, "skipping record %s, not a struct", raw_name); |
| 768 | return; | 758 | return c->codegen->builtin_types.entry_invalid; |
| 769 | } | 759 | } |
| 770 | | 760 | |
| 771 | Buf *bare_name = buf_create_from_str(raw_name); | 761 | Buf *bare_name; |
| 772 | Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); | 762 | if (record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0) { |
| | 763 | bare_name = buf_sprintf("anon_$%" PRIu32, get_next_node_index(c)); |
| | 764 | } else { |
| | 765 | bare_name = buf_create_from_str(raw_name); |
| 773 | | 766 | |
| 774 | if (c->struct_type_table.maybe_get(bare_name)) { | 767 | auto existing_entry = c->struct_type_table.maybe_get(bare_name); |
| 775 | // we've already seen it | 768 | if (existing_entry) { |
| 776 | return; | 769 | return existing_entry->value; |
| | 770 | } |
| 777 | } | 771 | } |
| 778 | | 772 | |
| 779 | RecordDecl *record_def = record_decl->getDefinition(); | 773 | Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); |
| 780 | if (!record_def) { | | |
| 781 | TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(full_type_name), | | |
| 782 | c->codegen->builtin_types.entry_u8); | | |
| 783 | c->struct_type_table.put(bare_name, typedecl_type); | | |
| 784 | | 774 | |
| 785 | // this is a type that we can point to but that's it, such as `struct Foo;`. | | |
| 786 | add_typedef_node(c, typedecl_type); | | |
| 787 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); | | |
| 788 | return; | | |
| 789 | } | | |
| 790 | | 775 | |
| 791 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, | 776 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, |
| 792 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); | 777 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); |
| 793 | | 778 | |
| 794 | c->struct_type_table.put(bare_name, struct_type); | 779 | c->struct_type_table.put(bare_name, struct_type); |
| 795 | // make an alias without the "struct_" prefix. this will get emitted at the | 780 | |
| 796 | // end if it doesn't conflict with anything else | 781 | RecordDecl *record_def = record_decl->getDefinition(); |
| 797 | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); | 782 | if (!record_def) { |
| | 783 | return struct_type; |
| | 784 | } |
| | 785 | |
| 798 | | 786 | |
| 799 | // count fields and validate | 787 | // count fields and validate |
| 800 | uint32_t field_count = 0; | 788 | uint32_t field_count = 0; |
| ... | @@ -805,8 +793,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -805,8 +793,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 805 | const FieldDecl *field_decl = *it; | 793 | const FieldDecl *field_decl = *it; |
| 806 | | 794 | |
| 807 | if (field_decl->isBitField()) { | 795 | if (field_decl->isBitField()) { |
| 808 | emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name)); | 796 | emit_warning(c, field_decl, "struct %s demoted to typedef - has bitfield\n", buf_ptr(bare_name)); |
| 809 | return; | 797 | return struct_type; |
| 810 | } | 798 | } |
| 811 | } | 799 | } |
| 812 | | 800 | |
| ... | @@ -837,8 +825,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -837,8 +825,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 837 | type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl); | 825 | type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl); |
| 838 | | 826 | |
| 839 | if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) { | 827 | if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) { |
| 840 | emit_warning(c, field_decl, "skipping struct %s - unresolved type\n", buf_ptr(bare_name)); | 828 | emit_warning(c, field_decl, "struct %s demoted to typedef - unresolved type\n", buf_ptr(bare_name)); |
| 841 | return; | 829 | return struct_type; |
| 842 | } | 830 | } |
| 843 | | 831 | |
| 844 | di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder, | 832 | di_element_types[i] = LLVMZigCreateDebugMemberType(c->codegen->dbuilder, |
| ... | @@ -878,25 +866,52 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { | ... | @@ -878,25 +866,52 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 878 | LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); | 866 | LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); |
| 879 | struct_type->di_type = replacement_di_type; | 867 | struct_type->di_type = replacement_di_type; |
| 880 | | 868 | |
| 881 | ////// | 869 | return struct_type; |
| | 870 | } |
| 882 | | 871 | |
| 883 | // now create a top level decl node for the type | 872 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 884 | AstNode *struct_node = create_node(c, NodeTypeStructDecl); | 873 | TypeTableEntry *struct_type = resolve_record_decl(c, record_decl); |
| 885 | buf_init_from_buf(&struct_node->data.struct_decl.name, full_type_name); | | |
| 886 | struct_node->data.struct_decl.kind = ContainerKindStruct; | | |
| 887 | struct_node->data.struct_decl.visib_mod = VisibModExport; | | |
| 888 | struct_node->data.struct_decl.directives = create_empty_directives(c); | | |
| 889 | struct_node->data.struct_decl.type_entry = struct_type; | | |
| 890 | | 874 | |
| 891 | for (uint32_t i = 0; i < field_count; i += 1) { | 875 | if (struct_type->id == TypeTableEntryIdInvalid) { |
| 892 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 876 | return; |
| 893 | AstNode *type_node = make_type_node(c, type_struct_field->type_entry); | 877 | } |
| 894 | AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node); | 878 | |
| 895 | struct_node->data.struct_decl.fields.append(field_node); | 879 | assert(struct_type->id == TypeTableEntryIdStruct); |
| | 880 | |
| | 881 | if (c->struct_decl_table.maybe_get(&struct_type->name)) { |
| | 882 | return; |
| | 883 | } |
| | 884 | c->struct_decl_table.put(&struct_type->name, struct_type); |
| | 885 | |
| | 886 | // make an alias without the "struct_" prefix. this will get emitted at the |
| | 887 | // end if it doesn't conflict with anything else |
| | 888 | if (decl_name(record_decl)[0] != 0) { |
| | 889 | add_alias(c, decl_name(record_decl), buf_ptr(&struct_type->name)); |
| 896 | } | 890 | } |
| 897 | | 891 | |
| 898 | normalize_parent_ptrs(struct_node); | 892 | if (struct_type->data.structure.complete) { |
| 899 | c->root->data.root.top_level_decls.append(struct_node); | 893 | // now create a top level decl node for the type |
| | 894 | AstNode *struct_node = create_node(c, NodeTypeStructDecl); |
| | 895 | buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name); |
| | 896 | struct_node->data.struct_decl.kind = ContainerKindStruct; |
| | 897 | struct_node->data.struct_decl.visib_mod = VisibModExport; |
| | 898 | struct_node->data.struct_decl.directives = create_empty_directives(c); |
| | 899 | struct_node->data.struct_decl.type_entry = struct_type; |
| | 900 | |
| | 901 | for (uint32_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { |
| | 902 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| | 903 | AstNode *type_node = make_type_node(c, type_struct_field->type_entry); |
| | 904 | AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node); |
| | 905 | struct_node->data.struct_decl.fields.append(field_node); |
| | 906 | } |
| | 907 | |
| | 908 | normalize_parent_ptrs(struct_node); |
| | 909 | c->root->data.root.top_level_decls.append(struct_node); |
| | 910 | } else { |
| | 911 | TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&struct_type->name), |
| | 912 | c->codegen->builtin_types.entry_u8); |
| | 913 | add_typedef_node(c, typedecl_type); |
| | 914 | } |
| 900 | } | 915 | } |
| 901 | | 916 | |
| 902 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { | 917 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { |
| ... | @@ -1253,6 +1268,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch | ... | @@ -1253,6 +1268,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1253 | c->global_value_table.init(8); | 1268 | c->global_value_table.init(8); |
| 1254 | c->enum_type_table.init(8); | 1269 | c->enum_type_table.init(8); |
| 1255 | c->struct_type_table.init(8); | 1270 | c->struct_type_table.init(8); |
| | 1271 | c->struct_decl_table.init(8); |
| 1256 | c->fn_table.init(8); | 1272 | c->fn_table.init(8); |
| 1257 | c->macro_table.init(8); | 1273 | c->macro_table.init(8); |
| 1258 | c->codegen = codegen; | 1274 | c->codegen = codegen; |