| ... | @@ -18,6 +18,7 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | ... | @@ -18,6 +18,7 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 18 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node); | 18 | static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node); |
| 19 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, | 19 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 20 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); | 20 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); |
| | 21 | static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type); |
| 21 | | 22 | |
| 22 | static AstNode *first_executing_node(AstNode *node) { | 23 | static AstNode *first_executing_node(AstNode *node) { |
| 23 | switch (node->type) { | 24 | switch (node->type) { |
| ... | @@ -116,8 +117,27 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { | ... | @@ -116,8 +117,27 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 116 | entry->arrays_by_size.init(2); | 117 | entry->arrays_by_size.init(2); |
| 117 | entry->id = id; | 118 | entry->id = id; |
| 118 | | 119 | |
| 119 | if (id == TypeTableEntryIdStruct) { | 120 | switch (id) { |
| 120 | entry->data.structure.fn_table.init(8); | 121 | case TypeTableEntryIdInvalid: |
| | 122 | case TypeTableEntryIdMetaType: |
| | 123 | case TypeTableEntryIdVoid: |
| | 124 | case TypeTableEntryIdBool: |
| | 125 | case TypeTableEntryIdUnreachable: |
| | 126 | case TypeTableEntryIdInt: |
| | 127 | case TypeTableEntryIdFloat: |
| | 128 | case TypeTableEntryIdPointer: |
| | 129 | case TypeTableEntryIdArray: |
| | 130 | case TypeTableEntryIdNumberLiteral: |
| | 131 | case TypeTableEntryIdMaybe: |
| | 132 | // nothing to init |
| | 133 | break; |
| | 134 | case TypeTableEntryIdStruct: |
| | 135 | entry->data.structure.fn_table.init(8); |
| | 136 | break; |
| | 137 | case TypeTableEntryIdEnum: |
| | 138 | entry->data.enumeration.fn_table.init(8); |
| | 139 | break; |
| | 140 | |
| 121 | } | 141 | } |
| 122 | | 142 | |
| 123 | return entry; | 143 | return entry; |
| ... | @@ -139,6 +159,35 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) | ... | @@ -139,6 +159,35 @@ static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) |
| 139 | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; | 159 | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; |
| 140 | } | 160 | } |
| 141 | | 161 | |
| | 162 | static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) { |
| | 163 | switch (get_number_literal_kind_unsigned(x)) { |
| | 164 | case NumLitU8: |
| | 165 | return g->builtin_types.entry_u8; |
| | 166 | case NumLitU16: |
| | 167 | return g->builtin_types.entry_u16; |
| | 168 | case NumLitU32: |
| | 169 | return g->builtin_types.entry_u32; |
| | 170 | case NumLitU64: |
| | 171 | return g->builtin_types.entry_u64; |
| | 172 | default: |
| | 173 | zig_unreachable(); |
| | 174 | } |
| | 175 | } |
| | 176 | |
| | 177 | static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) { |
| | 178 | if (child_type->meta_parent) { |
| | 179 | return child_type->maybe_parent; |
| | 180 | } else { |
| | 181 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType); |
| | 182 | buf_resize(&entry->name, 0); |
| | 183 | buf_appendf(&entry->name, "(%s declaration)", buf_ptr(&child_type->name)); |
| | 184 | |
| | 185 | entry->data.meta_type.child_type = child_type; |
| | 186 | child_type->meta_parent = entry; |
| | 187 | return entry; |
| | 188 | } |
| | 189 | } |
| | 190 | |
| 142 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias) { | 191 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias) { |
| 143 | TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)]; | 192 | TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)]; |
| 144 | if (*parent_pointer) { | 193 | if (*parent_pointer) { |
| ... | @@ -146,8 +195,12 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool | ... | @@ -146,8 +195,12 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 146 | } else { | 195 | } else { |
| 147 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); | 196 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); |
| 148 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); | 197 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); |
| | 198 | |
| | 199 | const char *const_str = is_const ? "const " : ""; |
| | 200 | const char *noalias_str = is_noalias ? "noalias " : ""; |
| 149 | buf_resize(&entry->name, 0); | 201 | buf_resize(&entry->name, 0); |
| 150 | buf_appendf(&entry->name, "&%s%s", is_const ? "const " : "", buf_ptr(&child_type->name)); | 202 | buf_appendf(&entry->name, "&%s%s%s", const_str, noalias_str, buf_ptr(&child_type->name)); |
| | 203 | |
| 151 | entry->size_in_bits = g->pointer_size_bytes * 8; | 204 | entry->size_in_bits = g->pointer_size_bytes * 8; |
| 152 | entry->align_in_bits = g->pointer_size_bytes * 8; | 205 | entry->align_in_bits = g->pointer_size_bytes * 8; |
| 153 | assert(child_type->di_type); | 206 | assert(child_type->di_type); |
| ... | @@ -165,7 +218,6 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool | ... | @@ -165,7 +218,6 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 165 | static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *child_type) { | 218 | static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *child_type) { |
| 166 | if (child_type->maybe_parent) { | 219 | if (child_type->maybe_parent) { |
| 167 | TypeTableEntry *entry = child_type->maybe_parent; | 220 | TypeTableEntry *entry = child_type->maybe_parent; |
| 168 | import->block_context->type_table.put(&entry->name, entry); | | |
| 169 | return entry; | 221 | return entry; |
| 170 | } else { | 222 | } else { |
| 171 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMaybe); | 223 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMaybe); |
| ... | @@ -209,7 +261,6 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, Type | ... | @@ -209,7 +261,6 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, Type |
| 209 | | 261 | |
| 210 | entry->data.maybe.child_type = child_type; | 262 | entry->data.maybe.child_type = child_type; |
| 211 | | 263 | |
| 212 | import->block_context->type_table.put(&entry->name, entry); | | |
| 213 | child_type->maybe_parent = entry; | 264 | child_type->maybe_parent = entry; |
| 214 | return entry; | 265 | return entry; |
| 215 | } | 266 | } |
| ... | @@ -221,7 +272,6 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, | ... | @@ -221,7 +272,6 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, |
| 221 | auto existing_entry = child_type->arrays_by_size.maybe_get(array_size); | 272 | auto existing_entry = child_type->arrays_by_size.maybe_get(array_size); |
| 222 | if (existing_entry) { | 273 | if (existing_entry) { |
| 223 | TypeTableEntry *entry = existing_entry->value; | 274 | TypeTableEntry *entry = existing_entry->value; |
| 224 | import->block_context->type_table.put(&entry->name, entry); | | |
| 225 | return entry; | 275 | return entry; |
| 226 | } else { | 276 | } else { |
| 227 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); | 277 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); |
| ... | @@ -237,7 +287,6 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, | ... | @@ -237,7 +287,6 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, |
| 237 | entry->data.array.child_type = child_type; | 287 | entry->data.array.child_type = child_type; |
| 238 | entry->data.array.len = array_size; | 288 | entry->data.array.len = array_size; |
| 239 | | 289 | |
| 240 | import->block_context->type_table.put(&entry->name, entry); | | |
| 241 | child_type->arrays_by_size.put(array_size, entry); | 290 | child_type->arrays_by_size.put(array_size, entry); |
| 242 | return entry; | 291 | return entry; |
| 243 | } | 292 | } |
| ... | @@ -636,7 +685,165 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_ | ... | @@ -636,7 +685,165 @@ static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_ |
| 636 | } | 685 | } |
| 637 | } | 686 | } |
| 638 | | 687 | |
| 639 | static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) { | 688 | static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) { |
| | 689 | assert(enum_type->id == TypeTableEntryIdEnum); |
| | 690 | |
| | 691 | AstNode *decl_node = enum_type->data.enumeration.decl_node; |
| | 692 | |
| | 693 | if (enum_type->data.enumeration.embedded_in_current) { |
| | 694 | if (!enum_type->data.enumeration.reported_infinite_err) { |
| | 695 | enum_type->data.enumeration.reported_infinite_err = true; |
| | 696 | add_node_error(g, decl_node, buf_sprintf("enum has infinite size")); |
| | 697 | } |
| | 698 | return; |
| | 699 | } |
| | 700 | |
| | 701 | if (enum_type->data.enumeration.fields) { |
| | 702 | // we already resolved this type. skip |
| | 703 | return; |
| | 704 | } |
| | 705 | |
| | 706 | assert(enum_type->di_type); |
| | 707 | |
| | 708 | int field_count = decl_node->data.struct_decl.fields.length; |
| | 709 | |
| | 710 | enum_type->data.enumeration.field_count = field_count; |
| | 711 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| | 712 | LLVMZigDIEnumerator **di_enumerators = allocate<LLVMZigDIEnumerator*>(field_count); |
| | 713 | |
| | 714 | // we possibly allocate too much here since gen_field_count can be lower than field_count. |
| | 715 | // the only problem is potential wasted space though. |
| | 716 | LLVMZigDIType **union_inner_di_types = allocate<LLVMZigDIType*>(field_count); |
| | 717 | |
| | 718 | TypeTableEntry *biggest_union_member = nullptr; |
| | 719 | uint64_t biggest_align_in_bits = 0; |
| | 720 | uint64_t biggest_union_member_size_in_bits = 0; |
| | 721 | |
| | 722 | // set temporary flag |
| | 723 | enum_type->data.enumeration.embedded_in_current = true; |
| | 724 | |
| | 725 | int gen_field_index = 0; |
| | 726 | for (int i = 0; i < field_count; i += 1) { |
| | 727 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| | 728 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; |
| | 729 | type_enum_field->name = &field_node->data.struct_field.name; |
| | 730 | type_enum_field->type_entry = resolve_type(g, field_node->data.struct_field.type, |
| | 731 | import, import->block_context, false); |
| | 732 | |
| | 733 | di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i); |
| | 734 | |
| | 735 | if (type_enum_field->type_entry->id == TypeTableEntryIdStruct) { |
| | 736 | resolve_struct_type(g, import, type_enum_field->type_entry); |
| | 737 | } else if (type_enum_field->type_entry->id == TypeTableEntryIdEnum) { |
| | 738 | resolve_enum_type(g, import, type_enum_field->type_entry); |
| | 739 | } else if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) { |
| | 740 | enum_type->data.enumeration.is_invalid = true; |
| | 741 | continue; |
| | 742 | } else if (type_enum_field->type_entry->id == TypeTableEntryIdVoid) { |
| | 743 | continue; |
| | 744 | } |
| | 745 | |
| | 746 | union_inner_di_types[gen_field_index] = LLVMZigCreateDebugMemberType(g->dbuilder, |
| | 747 | LLVMZigTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), |
| | 748 | import->di_file, field_node->line + 1, |
| | 749 | type_enum_field->type_entry->size_in_bits, |
| | 750 | type_enum_field->type_entry->align_in_bits, |
| | 751 | 0, 0, type_enum_field->type_entry->di_type); |
| | 752 | |
| | 753 | biggest_align_in_bits = max(biggest_align_in_bits, type_enum_field->type_entry->align_in_bits); |
| | 754 | |
| | 755 | if (!biggest_union_member || |
| | 756 | type_enum_field->type_entry->size_in_bits > biggest_union_member->size_in_bits) |
| | 757 | { |
| | 758 | biggest_union_member = type_enum_field->type_entry; |
| | 759 | biggest_union_member_size_in_bits = biggest_union_member->size_in_bits; |
| | 760 | } |
| | 761 | |
| | 762 | gen_field_index += 1; |
| | 763 | } |
| | 764 | |
| | 765 | // unset temporary flag |
| | 766 | enum_type->data.enumeration.embedded_in_current = false; |
| | 767 | |
| | 768 | if (!enum_type->data.enumeration.is_invalid) { |
| | 769 | uint64_t tag_size_in_bits = get_number_literal_type_unsigned(g, field_count)->size_in_bits; |
| | 770 | enum_type->align_in_bits = tag_size_in_bits; |
| | 771 | enum_type->size_in_bits = tag_size_in_bits + biggest_union_member_size_in_bits; |
| | 772 | TypeTableEntry *tag_type_entry = get_int_type_unsigned(g, field_count); |
| | 773 | |
| | 774 | if (biggest_union_member) { |
| | 775 | // create llvm type for union |
| | 776 | LLVMTypeRef union_element_type = biggest_union_member->type_ref; |
| | 777 | LLVMTypeRef union_type_ref = LLVMStructType(&union_element_type, 1, false); |
| | 778 | |
| | 779 | // create llvm type for root struct |
| | 780 | LLVMTypeRef root_struct_element_types[] = { |
| | 781 | tag_type_entry->type_ref, |
| | 782 | union_type_ref, |
| | 783 | }; |
| | 784 | LLVMStructSetBody(enum_type->type_ref, root_struct_element_types, 2, false); |
| | 785 | |
| | 786 | // create debug type for tag |
| | 787 | LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(g->dbuilder, |
| | 788 | LLVMZigTypeToScope(enum_type->di_type), "AnonEnum", import->di_file, decl_node->line + 1, |
| | 789 | tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count, |
| | 790 | tag_type_entry->di_type, ""); |
| | 791 | |
| | 792 | // create debug type for union |
| | 793 | LLVMZigDIType *union_di_type = LLVMZigCreateDebugUnionType(g->dbuilder, |
| | 794 | LLVMZigTypeToScope(enum_type->di_type), "AnonUnion", import->di_file, decl_node->line + 1, |
| | 795 | biggest_union_member->size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, |
| | 796 | gen_field_index, 0, ""); |
| | 797 | |
| | 798 | // create debug types for members of root struct |
| | 799 | LLVMZigDIType *tag_member_di_type = LLVMZigCreateDebugMemberType(g->dbuilder, |
| | 800 | LLVMZigTypeToScope(enum_type->di_type), "tag_field", |
| | 801 | import->di_file, decl_node->line + 1, |
| | 802 | tag_type_entry->size_in_bits, |
| | 803 | tag_type_entry->align_in_bits, |
| | 804 | 0, 0, tag_di_type); |
| | 805 | LLVMZigDIType *union_member_di_type = LLVMZigCreateDebugMemberType(g->dbuilder, |
| | 806 | LLVMZigTypeToScope(enum_type->di_type), "union_field", |
| | 807 | import->di_file, decl_node->line + 1, |
| | 808 | biggest_union_member->size_in_bits, |
| | 809 | biggest_align_in_bits, |
| | 810 | tag_type_entry->size_in_bits, 0, union_di_type); |
| | 811 | |
| | 812 | // create debug type for root struct |
| | 813 | LLVMZigDIType *di_root_members[] = { |
| | 814 | tag_member_di_type, |
| | 815 | union_member_di_type, |
| | 816 | }; |
| | 817 | |
| | 818 | |
| | 819 | LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder, |
| | 820 | LLVMZigFileToScope(import->di_file), |
| | 821 | buf_ptr(&decl_node->data.struct_decl.name), |
| | 822 | import->di_file, decl_node->line + 1, enum_type->size_in_bits, enum_type->align_in_bits, 0, |
| | 823 | nullptr, di_root_members, 2, 0, nullptr, ""); |
| | 824 | |
| | 825 | LLVMZigReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); |
| | 826 | enum_type->di_type = replacement_di_type; |
| | 827 | } else { |
| | 828 | // create llvm type for root struct |
| | 829 | enum_type->type_ref = tag_type_entry->type_ref; |
| | 830 | |
| | 831 | // create debug type for tag |
| | 832 | LLVMZigDIType *tag_di_type = LLVMZigCreateDebugEnumerationType(g->dbuilder, |
| | 833 | LLVMZigFileToScope(import->di_file), buf_ptr(&decl_node->data.struct_decl.name), |
| | 834 | import->di_file, decl_node->line + 1, |
| | 835 | tag_type_entry->size_in_bits, tag_type_entry->align_in_bits, di_enumerators, field_count, |
| | 836 | tag_type_entry->di_type, ""); |
| | 837 | |
| | 838 | LLVMZigReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); |
| | 839 | enum_type->di_type = tag_di_type; |
| | 840 | |
| | 841 | } |
| | 842 | |
| | 843 | } |
| | 844 | } |
| | 845 | |
| | 846 | static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type) { |
| 640 | assert(struct_type->id == TypeTableEntryIdStruct); | 847 | assert(struct_type->id == TypeTableEntryIdStruct); |
| 641 | | 848 | |
| 642 | AstNode *decl_node = struct_type->data.structure.decl_node; | 849 | AstNode *decl_node = struct_type->data.structure.decl_node; |
| ... | @@ -672,7 +879,7 @@ static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTab | ... | @@ -672,7 +879,7 @@ static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTab |
| 672 | uint64_t first_field_align_in_bits = 0; | 879 | uint64_t first_field_align_in_bits = 0; |
| 673 | uint64_t offset_in_bits = 0; | 880 | uint64_t offset_in_bits = 0; |
| 674 | | 881 | |
| 675 | // this field should be set to true only during the recursive calls to resolve_container_type | 882 | // this field should be set to true only during the recursive calls to resolve_struct_type |
| 676 | struct_type->data.structure.embedded_in_current = true; | 883 | struct_type->data.structure.embedded_in_current = true; |
| 677 | | 884 | |
| 678 | int gen_field_index = 0; | 885 | int gen_field_index = 0; |
| ... | @@ -686,7 +893,9 @@ static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTab | ... | @@ -686,7 +893,9 @@ static void resolve_container_type(CodeGen *g, ImportTableEntry *import, TypeTab |
| 686 | type_struct_field->gen_index = -1; | 893 | type_struct_field->gen_index = -1; |
| 687 | | 894 | |
| 688 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { | 895 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { |
| 689 | resolve_container_type(g, import, type_struct_field->type_entry); | 896 | resolve_struct_type(g, import, type_struct_field->type_entry); |
| | 897 | } else if (type_struct_field->type_entry->id == TypeTableEntryIdEnum) { |
| | 898 | resolve_enum_type(g, import, type_struct_field->type_entry); |
| 690 | } else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) { | 899 | } else if (type_struct_field->type_entry->id == TypeTableEntryIdInvalid) { |
| 691 | struct_type->data.structure.is_invalid = true; | 900 | struct_type->data.structure.is_invalid = true; |
| 692 | continue; | 901 | continue; |
| ... | @@ -903,9 +1112,17 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -903,9 +1112,17 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 903 | { | 1112 | { |
| 904 | TypeTableEntry *type_entry = node->data.struct_decl.type_entry; | 1113 | TypeTableEntry *type_entry = node->data.struct_decl.type_entry; |
| 905 | | 1114 | |
| 906 | resolve_container_type(g, import, type_entry); | 1115 | // struct/enum member fns will get resolved independently |
| | 1116 | |
| | 1117 | switch (node->data.struct_decl.kind) { |
| | 1118 | case ContainerKindStruct: |
| | 1119 | resolve_struct_type(g, import, type_entry); |
| | 1120 | break; |
| | 1121 | case ContainerKindEnum: |
| | 1122 | resolve_enum_type(g, import, type_entry); |
| | 1123 | break; |
| | 1124 | } |
| 907 | | 1125 | |
| 908 | // struct member fns will get resolved independently | | |
| 909 | break; | 1126 | break; |
| 910 | } | 1127 | } |
| 911 | case NodeTypeVariableDeclaration: | 1128 | case NodeTypeVariableDeclaration: |
| ... | @@ -986,6 +1203,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, | ... | @@ -986,6 +1203,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, |
| 986 | case TypeTableEntryIdPointer: | 1203 | case TypeTableEntryIdPointer: |
| 987 | case TypeTableEntryIdArray: | 1204 | case TypeTableEntryIdArray: |
| 988 | case TypeTableEntryIdStruct: | 1205 | case TypeTableEntryIdStruct: |
| | 1206 | case TypeTableEntryIdEnum: |
| | 1207 | case TypeTableEntryIdMetaType: |
| 989 | return false; | 1208 | return false; |
| 990 | case TypeTableEntryIdInt: | 1209 | case TypeTableEntryIdInt: |
| 991 | if (is_num_lit_unsigned(num_lit)) { | 1210 | if (is_num_lit_unsigned(num_lit)) { |
| ... | @@ -1326,6 +1545,12 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1326,6 +1545,12 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 1326 | buf_ptr(&struct_type->name))); | 1545 | buf_ptr(&struct_type->name))); |
| 1327 | return_type = g->builtin_types.entry_invalid; | 1546 | return_type = g->builtin_types.entry_invalid; |
| 1328 | } | 1547 | } |
| | 1548 | } else if (struct_type->id == TypeTableEntryIdMetaType && |
| | 1549 | struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum) |
| | 1550 | { |
| | 1551 | //TypeTableEntry *enum_type = struct_type->data.meta_type.child_type; |
| | 1552 | |
| | 1553 | zig_panic("TODO enum field access"); |
| 1329 | } else { | 1554 | } else { |
| 1330 | if (struct_type->id != TypeTableEntryIdInvalid) { | 1555 | if (struct_type->id != TypeTableEntryIdInvalid) { |
| 1331 | add_node_error(g, node, | 1556 | add_node_error(g, node, |
| ... | @@ -1421,7 +1646,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1421,7 +1646,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, |
| 1421 | } else { | 1646 | } else { |
| 1422 | TypeTableEntry *container_type = find_container(context, variable_name); | 1647 | TypeTableEntry *container_type = find_container(context, variable_name); |
| 1423 | if (container_type) { | 1648 | if (container_type) { |
| 1424 | return container_type; | 1649 | return get_meta_type(g, container_type); |
| 1425 | } else { | 1650 | } else { |
| 1426 | add_node_error(g, node, | 1651 | add_node_error(g, node, |
| 1427 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); | 1652 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| ... | @@ -2179,6 +2404,10 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import | ... | @@ -2179,6 +2404,10 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 2179 | fn_table = &struct_type->data.pointer.child_type->data.structure.fn_table; | 2404 | fn_table = &struct_type->data.pointer.child_type->data.structure.fn_table; |
| 2180 | } else if (struct_type->id == TypeTableEntryIdInvalid) { | 2405 | } else if (struct_type->id == TypeTableEntryIdInvalid) { |
| 2181 | return struct_type; | 2406 | return struct_type; |
| | 2407 | } else if (struct_type->id == TypeTableEntryIdMetaType && |
| | 2408 | struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum) |
| | 2409 | { |
| | 2410 | zig_panic("TODO enum initialization"); |
| 2182 | } else { | 2411 | } else { |
| 2183 | add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr, | 2412 | add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr, |
| 2184 | buf_sprintf("member reference base type not struct or enum")); | 2413 | buf_sprintf("member reference base type not struct or enum")); |
| ... | @@ -2846,6 +3075,16 @@ static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2846,6 +3075,16 @@ static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 2846 | } | 3075 | } |
| 2847 | } | 3076 | } |
| 2848 | | 3077 | |
| | 3078 | static TypeTableEntryId container_to_type(ContainerKind kind) { |
| | 3079 | switch (kind) { |
| | 3080 | case ContainerKindStruct: |
| | 3081 | return TypeTableEntryIdStruct; |
| | 3082 | case ContainerKindEnum: |
| | 3083 | return TypeTableEntryIdEnum; |
| | 3084 | } |
| | 3085 | zig_unreachable(); |
| | 3086 | } |
| | 3087 | |
| 2849 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 3088 | static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 2850 | switch (node->type) { | 3089 | switch (node->type) { |
| 2851 | case NodeTypeStructDecl: | 3090 | case NodeTypeStructDecl: |
| ... | @@ -2860,11 +3099,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2860,11 +3099,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2860 | add_node_error(g, node, | 3099 | add_node_error(g, node, |
| 2861 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 3100 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 2862 | } else { | 3101 | } else { |
| 2863 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | 3102 | TypeTableEntryId type_id = container_to_type(node->data.struct_decl.kind); |
| | 3103 | TypeTableEntry *entry = new_type_table_entry(type_id); |
| | 3104 | switch (node->data.struct_decl.kind) { |
| | 3105 | case ContainerKindStruct: |
| | 3106 | entry->data.structure.decl_node = node; |
| | 3107 | break; |
| | 3108 | case ContainerKindEnum: |
| | 3109 | entry->data.enumeration.decl_node = node; |
| | 3110 | break; |
| | 3111 | } |
| | 3112 | |
| 2864 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); | 3113 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); |
| 2865 | entry->data.structure.decl_node = node; | | |
| 2866 | entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder, | 3114 | entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder, |
| 2867 | LLVMZigTag_DW_structure_type(), buf_ptr(&node->data.struct_decl.name), | 3115 | LLVMZigTag_DW_structure_type(), buf_ptr(name), |
| 2868 | LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1); | 3116 | LLVMZigFileToScope(import->di_file), import->di_file, node->line + 1); |
| 2869 | | 3117 | |
| 2870 | buf_init_from_buf(&entry->name, name); | 3118 | buf_init_from_buf(&entry->name, name); |