| ... | ... | @@ -36,6 +36,7 @@ struct Context { |
| 36 | 36 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_type_table; |
| 37 | 37 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> global_value_table; |
| 38 | 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 | 40 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> enum_type_table; |
| 40 | 41 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; |
| 41 | 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 | 52 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table); |
| 52 | 53 | |
| 53 | 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 | 58 | __attribute__ ((format (printf, 3, 4))) |
| ... | ... | @@ -79,12 +81,17 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...) |
| 79 | 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 | 90 | static AstNode *create_node(Context *c, NodeType type) { |
| 83 | 91 | AstNode *node = allocate<AstNode>(1); |
| 84 | 92 | node->type = type; |
| 85 | 93 | node->owner = c->import; |
| 86 | | node->create_index = c->codegen->next_node_index; |
| 87 | | c->codegen->next_node_index += 1; |
| 94 | node->create_index = get_next_node_index(c); |
| 88 | 95 | return node; |
| 89 | 96 | } |
| 90 | 97 | |
| ... | ... | @@ -437,18 +444,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 437 | 444 | case Type::Record: |
| 438 | 445 | { |
| 439 | 446 | const RecordType *record_ty = static_cast<const RecordType*>(ty); |
| 440 | | Buf *record_name = buf_create_from_str(decl_name(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; |
| 447 | return resolve_record_decl(c, record_ty->getDecl()); |
| 452 | 448 | } |
| 453 | 449 | case Type::Enum: |
| 454 | 450 | { |
| ... | ... | @@ -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 | 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 | 756 | if (!record_decl->isStruct()) { |
| 767 | 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); |
| 772 | | Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); |
| 761 | Buf *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)) { |
| 775 | | // we've already seen it |
| 776 | | return; |
| 767 | auto existing_entry = c->struct_type_table.maybe_get(bare_name); |
| 768 | if (existing_entry) { |
| 769 | return existing_entry->value; |
| 770 | } |
| 777 | 771 | } |
| 778 | 772 | |
| 779 | | RecordDecl *record_def = record_decl->getDefinition(); |
| 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); |
| 773 | Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); |
| 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 | 776 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, |
| 792 | 777 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); |
| 793 | 778 | |
| 794 | 779 | c->struct_type_table.put(bare_name, struct_type); |
| 795 | | // make an alias without the "struct_" prefix. this will get emitted at the |
| 796 | | // end if it doesn't conflict with anything else |
| 797 | | add_alias(c, buf_ptr(bare_name), buf_ptr(full_type_name)); |
| 780 | |
| 781 | RecordDecl *record_def = record_decl->getDefinition(); |
| 782 | if (!record_def) { |
| 783 | return struct_type; |
| 784 | } |
| 785 | |
| 798 | 786 | |
| 799 | 787 | // count fields and validate |
| 800 | 788 | uint32_t field_count = 0; |
| ... | ... | @@ -805,8 +793,8 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 805 | 793 | const FieldDecl *field_decl = *it; |
| 806 | 794 | |
| 807 | 795 | if (field_decl->isBitField()) { |
| 808 | | emit_warning(c, field_decl, "skipping struct %s - has bitfield\n", buf_ptr(bare_name)); |
| 809 | | return; |
| 796 | emit_warning(c, field_decl, "struct %s demoted to typedef - has bitfield\n", buf_ptr(bare_name)); |
| 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 | 825 | type_struct_field->type_entry = resolve_qual_type(c, field_decl->getType(), field_decl); |
| 838 | 826 | |
| 839 | 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)); |
| 841 | | return; |
| 828 | emit_warning(c, field_decl, "struct %s demoted to typedef - unresolved type\n", buf_ptr(bare_name)); |
| 829 | return struct_type; |
| 842 | 830 | } |
| 843 | 831 | |
| 844 | 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 | 866 | LLVMZigReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type); |
| 879 | 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 |
| 884 | | AstNode *struct_node = create_node(c, NodeTypeStructDecl); |
| 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; |
| 872 | static void visit_record_decl(Context *c, const RecordDecl *record_decl) { |
| 873 | TypeTableEntry *struct_type = resolve_record_decl(c, record_decl); |
| 890 | 874 | |
| 891 | | for (uint32_t i = 0; i < field_count; i += 1) { |
| 892 | | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 893 | | AstNode *type_node = make_type_node(c, type_struct_field->type_entry); |
| 894 | | AstNode *field_node = create_struct_field_node(c, buf_ptr(type_struct_field->name), type_node); |
| 895 | | struct_node->data.struct_decl.fields.append(field_node); |
| 875 | if (struct_type->id == TypeTableEntryIdInvalid) { |
| 876 | return; |
| 877 | } |
| 878 | |
| 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); |
| 899 | | c->root->data.root.top_level_decls.append(struct_node); |
| 892 | if (struct_type->data.structure.complete) { |
| 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 | 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 | 1268 | c->global_value_table.init(8); |
| 1254 | 1269 | c->enum_type_table.init(8); |
| 1255 | 1270 | c->struct_type_table.init(8); |
| 1271 | c->struct_decl_table.init(8); |
| 1256 | 1272 | c->fn_table.init(8); |
| 1257 | 1273 | c->macro_table.init(8); |
| 1258 | 1274 | c->codegen = codegen; |