| author | |
| committer | |
| log | ac36f98e72f7ef33346bc772e4f257b79d04fcff |
| tree | 88fc4a2e89dcecbfbb4c42eee9ed6411512d45c9 |
| parent | 32901926f088cd9617e7d98e23b0b056b5495193 |
12 files changed, 727 insertions(+), 592 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -485,6 +485,7 @@ set(ZIG_STD_FILES |
| 485 | 485 | "json.zig" |
| 486 | 486 | "lazy_init.zig" |
| 487 | 487 | "linked_list.zig" |
| 488 | "macho.zig" | |
| 488 | 489 | "math/acos.zig" |
| 489 | 490 | "math/acosh.zig" |
| 490 | 491 | "math/asin.zig" |
src/analyze.cpp+115-85| ... | ... | @@ -19,12 +19,12 @@ |
| 19 | 19 | |
| 20 | 20 | static const size_t default_backward_branch_quota = 1000; |
| 21 | 21 | |
| 22 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type); | |
| 23 | static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type); | |
| 22 | static Error resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type); | |
| 23 | static Error resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type); | |
| 24 | 24 | |
| 25 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type); | |
| 26 | static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type); | |
| 27 | static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type); | |
| 25 | static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type); | |
| 26 | static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type); | |
| 27 | static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type); | |
| 28 | 28 | static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry); |
| 29 | 29 | |
| 30 | 30 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| ... | ... | @@ -370,15 +370,20 @@ uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) { |
| 370 | 370 | return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref); |
| 371 | 371 | } |
| 372 | 372 | |
| 373 | bool type_is_copyable(CodeGen *g, TypeTableEntry *type_entry) { | |
| 374 | type_ensure_zero_bits_known(g, type_entry); | |
| 373 | Result<bool> type_is_copyable(CodeGen *g, TypeTableEntry *type_entry) { | |
| 374 | Error err; | |
| 375 | if ((err = type_ensure_zero_bits_known(g, type_entry))) | |
| 376 | return err; | |
| 377 | ||
| 375 | 378 | if (!type_has_bits(type_entry)) |
| 376 | 379 | return true; |
| 377 | 380 | |
| 378 | 381 | if (!handle_is_ptr(type_entry)) |
| 379 | 382 | return true; |
| 380 | 383 | |
| 381 | ensure_complete_type(g, type_entry); | |
| 384 | if ((err = ensure_complete_type(g, type_entry))) | |
| 385 | return err; | |
| 386 | ||
| 382 | 387 | return type_entry->is_copyable; |
| 383 | 388 | } |
| 384 | 389 | |
| ... | ... | @@ -447,7 +452,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 447 | 452 | } |
| 448 | 453 | } |
| 449 | 454 | |
| 450 | type_ensure_zero_bits_known(g, child_type); | |
| 455 | assertNoError(type_ensure_zero_bits_known(g, child_type)); | |
| 451 | 456 | |
| 452 | 457 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer); |
| 453 | 458 | entry->is_copyable = true; |
| ... | ... | @@ -554,11 +559,11 @@ TypeTableEntry *get_optional_type(CodeGen *g, TypeTableEntry *child_type) { |
| 554 | 559 | TypeTableEntry *entry = child_type->optional_parent; |
| 555 | 560 | return entry; |
| 556 | 561 | } else { |
| 557 | ensure_complete_type(g, child_type); | |
| 562 | assertNoError(ensure_complete_type(g, child_type)); | |
| 558 | 563 | |
| 559 | 564 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdOptional); |
| 560 | 565 | assert(child_type->type_ref || child_type->zero_bits); |
| 561 | entry->is_copyable = type_is_copyable(g, child_type); | |
| 566 | entry->is_copyable = type_is_copyable(g, child_type).unwrap(); | |
| 562 | 567 | |
| 563 | 568 | buf_resize(&entry->name, 0); |
| 564 | 569 | buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); |
| ... | ... | @@ -650,7 +655,7 @@ TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, T |
| 650 | 655 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorUnion); |
| 651 | 656 | entry->is_copyable = true; |
| 652 | 657 | assert(payload_type->di_type); |
| 653 | ensure_complete_type(g, payload_type); | |
| 658 | assertNoError(ensure_complete_type(g, payload_type)); | |
| 654 | 659 | |
| 655 | 660 | buf_resize(&entry->name, 0); |
| 656 | 661 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); |
| ... | ... | @@ -739,7 +744,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 739 | 744 | return entry; |
| 740 | 745 | } |
| 741 | 746 | |
| 742 | ensure_complete_type(g, child_type); | |
| 747 | assertNoError(ensure_complete_type(g, child_type)); | |
| 743 | 748 | |
| 744 | 749 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray); |
| 745 | 750 | entry->zero_bits = (array_size == 0) || child_type->zero_bits; |
| ... | ... | @@ -1050,13 +1055,13 @@ TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g) { |
| 1050 | 1055 | } |
| 1051 | 1056 | |
| 1052 | 1057 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1058 | Error err; | |
| 1053 | 1059 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); |
| 1054 | 1060 | if (table_entry) { |
| 1055 | 1061 | return table_entry->value; |
| 1056 | 1062 | } |
| 1057 | 1063 | if (fn_type_id->return_type != nullptr) { |
| 1058 | ensure_complete_type(g, fn_type_id->return_type); | |
| 1059 | if (type_is_invalid(fn_type_id->return_type)) | |
| 1064 | if ((err = ensure_complete_type(g, fn_type_id->return_type))) | |
| 1060 | 1065 | return g->builtin_types.entry_invalid; |
| 1061 | 1066 | assert(fn_type_id->return_type->id != TypeTableEntryIdOpaque); |
| 1062 | 1067 | } else { |
| ... | ... | @@ -1172,8 +1177,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1172 | 1177 | gen_param_info->src_index = i; |
| 1173 | 1178 | gen_param_info->gen_index = SIZE_MAX; |
| 1174 | 1179 | |
| 1175 | ensure_complete_type(g, type_entry); | |
| 1176 | if (type_is_invalid(type_entry)) | |
| 1180 | if ((err = ensure_complete_type(g, type_entry))) | |
| 1177 | 1181 | return g->builtin_types.entry_invalid; |
| 1178 | 1182 | |
| 1179 | 1183 | if (type_has_bits(type_entry)) { |
| ... | ... | @@ -1493,6 +1497,7 @@ TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry) { |
| 1493 | 1497 | static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, FnTableEntry *fn_entry) { |
| 1494 | 1498 | assert(proto_node->type == NodeTypeFnProto); |
| 1495 | 1499 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1500 | Error err; | |
| 1496 | 1501 | |
| 1497 | 1502 | FnTypeId fn_type_id = {0}; |
| 1498 | 1503 | init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); |
| ... | ... | @@ -1550,7 +1555,8 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1550 | 1555 | return g->builtin_types.entry_invalid; |
| 1551 | 1556 | } |
| 1552 | 1557 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 1553 | type_ensure_zero_bits_known(g, type_entry); | |
| 1558 | if ((err = type_ensure_zero_bits_known(g, type_entry))) | |
| 1559 | return g->builtin_types.entry_invalid; | |
| 1554 | 1560 | if (!type_has_bits(type_entry)) { |
| 1555 | 1561 | add_node_error(g, param_node->data.param_decl.type, |
| 1556 | 1562 | buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", |
| ... | ... | @@ -1598,7 +1604,8 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1598 | 1604 | case TypeTableEntryIdUnion: |
| 1599 | 1605 | case TypeTableEntryIdFn: |
| 1600 | 1606 | case TypeTableEntryIdPromise: |
| 1601 | type_ensure_zero_bits_known(g, type_entry); | |
| 1607 | if ((err = type_ensure_zero_bits_known(g, type_entry))) | |
| 1608 | return g->builtin_types.entry_invalid; | |
| 1602 | 1609 | if (type_requires_comptime(type_entry)) { |
| 1603 | 1610 | add_node_error(g, param_node->data.param_decl.type, |
| 1604 | 1611 | buf_sprintf("parameter of type '%s' must be declared comptime", |
| ... | ... | @@ -1729,24 +1736,25 @@ bool type_is_invalid(TypeTableEntry *type_entry) { |
| 1729 | 1736 | } |
| 1730 | 1737 | |
| 1731 | 1738 | |
| 1732 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | |
| 1739 | static Error resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | |
| 1733 | 1740 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 1734 | 1741 | |
| 1735 | 1742 | if (enum_type->data.enumeration.complete) |
| 1736 | return; | |
| 1743 | return ErrorNone; | |
| 1737 | 1744 | |
| 1738 | resolve_enum_zero_bits(g, enum_type); | |
| 1739 | if (type_is_invalid(enum_type)) | |
| 1740 | return; | |
| 1745 | Error err; | |
| 1746 | if ((err = resolve_enum_zero_bits(g, enum_type))) | |
| 1747 | return err; | |
| 1741 | 1748 | |
| 1742 | 1749 | AstNode *decl_node = enum_type->data.enumeration.decl_node; |
| 1743 | 1750 | |
| 1744 | 1751 | if (enum_type->data.enumeration.embedded_in_current) { |
| 1745 | 1752 | if (!enum_type->data.enumeration.reported_infinite_err) { |
| 1753 | enum_type->data.enumeration.is_invalid = true; | |
| 1746 | 1754 | enum_type->data.enumeration.reported_infinite_err = true; |
| 1747 | 1755 | add_node_error(g, decl_node, buf_sprintf("enum '%s' contains itself", buf_ptr(&enum_type->name))); |
| 1748 | 1756 | } |
| 1749 | return; | |
| 1757 | return ErrorSemanticAnalyzeFail; | |
| 1750 | 1758 | } |
| 1751 | 1759 | |
| 1752 | 1760 | assert(!enum_type->data.enumeration.zero_bits_loop_flag); |
| ... | ... | @@ -1778,7 +1786,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1778 | 1786 | enum_type->data.enumeration.complete = true; |
| 1779 | 1787 | |
| 1780 | 1788 | if (enum_type->data.enumeration.is_invalid) |
| 1781 | return; | |
| 1789 | return ErrorSemanticAnalyzeFail; | |
| 1782 | 1790 | |
| 1783 | 1791 | if (enum_type->zero_bits) { |
| 1784 | 1792 | enum_type->type_ref = LLVMVoidType(); |
| ... | ... | @@ -1797,7 +1805,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1797 | 1805 | |
| 1798 | 1806 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); |
| 1799 | 1807 | enum_type->di_type = replacement_di_type; |
| 1800 | return; | |
| 1808 | return ErrorNone; | |
| 1801 | 1809 | } |
| 1802 | 1810 | |
| 1803 | 1811 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; |
| ... | ... | @@ -1815,6 +1823,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1815 | 1823 | |
| 1816 | 1824 | ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); |
| 1817 | 1825 | enum_type->di_type = tag_di_type; |
| 1826 | return ErrorNone; | |
| 1818 | 1827 | } |
| 1819 | 1828 | |
| 1820 | 1829 | |
| ... | ... | @@ -1897,15 +1906,15 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1897 | 1906 | return struct_type; |
| 1898 | 1907 | } |
| 1899 | 1908 | |
| 1900 | static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | |
| 1909 | static Error resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | |
| 1901 | 1910 | assert(struct_type->id == TypeTableEntryIdStruct); |
| 1902 | 1911 | |
| 1903 | 1912 | if (struct_type->data.structure.complete) |
| 1904 | return; | |
| 1913 | return ErrorNone; | |
| 1905 | 1914 | |
| 1906 | resolve_struct_zero_bits(g, struct_type); | |
| 1907 | if (struct_type->data.structure.is_invalid) | |
| 1908 | return; | |
| 1915 | Error err; | |
| 1916 | if ((err = resolve_struct_zero_bits(g, struct_type))) | |
| 1917 | return err; | |
| 1909 | 1918 | |
| 1910 | 1919 | AstNode *decl_node = struct_type->data.structure.decl_node; |
| 1911 | 1920 | |
| ... | ... | @@ -1916,7 +1925,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1916 | 1925 | add_node_error(g, decl_node, |
| 1917 | 1926 | buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); |
| 1918 | 1927 | } |
| 1919 | return; | |
| 1928 | return ErrorSemanticAnalyzeFail; | |
| 1920 | 1929 | } |
| 1921 | 1930 | |
| 1922 | 1931 | assert(!struct_type->data.structure.zero_bits_loop_flag); |
| ... | ... | @@ -1943,8 +1952,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1943 | 1952 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1944 | 1953 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1945 | 1954 | |
| 1946 | ensure_complete_type(g, field_type); | |
| 1947 | if (type_is_invalid(field_type)) { | |
| 1955 | if ((err = ensure_complete_type(g, field_type))) { | |
| 1948 | 1956 | struct_type->data.structure.is_invalid = true; |
| 1949 | 1957 | break; |
| 1950 | 1958 | } |
| ... | ... | @@ -2026,7 +2034,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 2026 | 2034 | struct_type->data.structure.complete = true; |
| 2027 | 2035 | |
| 2028 | 2036 | if (struct_type->data.structure.is_invalid) |
| 2029 | return; | |
| 2037 | return ErrorSemanticAnalyzeFail; | |
| 2030 | 2038 | |
| 2031 | 2039 | if (struct_type->zero_bits) { |
| 2032 | 2040 | struct_type->type_ref = LLVMVoidType(); |
| ... | ... | @@ -2045,7 +2053,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 2045 | 2053 | 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); |
| 2046 | 2054 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); |
| 2047 | 2055 | struct_type->di_type = replacement_di_type; |
| 2048 | return; | |
| 2056 | return ErrorNone; | |
| 2049 | 2057 | } |
| 2050 | 2058 | assert(struct_type->di_type); |
| 2051 | 2059 | |
| ... | ... | @@ -2128,17 +2136,19 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 2128 | 2136 | |
| 2129 | 2137 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); |
| 2130 | 2138 | struct_type->di_type = replacement_di_type; |
| 2139 | ||
| 2140 | return ErrorNone; | |
| 2131 | 2141 | } |
| 2132 | 2142 | |
| 2133 | static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | |
| 2143 | static Error resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { | |
| 2134 | 2144 | assert(union_type->id == TypeTableEntryIdUnion); |
| 2135 | 2145 | |
| 2136 | 2146 | if (union_type->data.unionation.complete) |
| 2137 | return; | |
| 2147 | return ErrorNone; | |
| 2138 | 2148 | |
| 2139 | resolve_union_zero_bits(g, union_type); | |
| 2140 | if (type_is_invalid(union_type)) | |
| 2141 | return; | |
| 2149 | Error err; | |
| 2150 | if ((err = resolve_union_zero_bits(g, union_type))) | |
| 2151 | return err; | |
| 2142 | 2152 | |
| 2143 | 2153 | AstNode *decl_node = union_type->data.unionation.decl_node; |
| 2144 | 2154 | |
| ... | ... | @@ -2148,7 +2158,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2148 | 2158 | union_type->data.unionation.is_invalid = true; |
| 2149 | 2159 | add_node_error(g, decl_node, buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); |
| 2150 | 2160 | } |
| 2151 | return; | |
| 2161 | return ErrorSemanticAnalyzeFail; | |
| 2152 | 2162 | } |
| 2153 | 2163 | |
| 2154 | 2164 | assert(!union_type->data.unionation.zero_bits_loop_flag); |
| ... | ... | @@ -2179,8 +2189,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2179 | 2189 | TypeUnionField *union_field = &union_type->data.unionation.fields[i]; |
| 2180 | 2190 | TypeTableEntry *field_type = union_field->type_entry; |
| 2181 | 2191 | |
| 2182 | ensure_complete_type(g, field_type); | |
| 2183 | if (type_is_invalid(field_type)) { | |
| 2192 | if ((err = ensure_complete_type(g, field_type))) { | |
| 2184 | 2193 | union_type->data.unionation.is_invalid = true; |
| 2185 | 2194 | continue; |
| 2186 | 2195 | } |
| ... | ... | @@ -2219,7 +2228,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2219 | 2228 | union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; |
| 2220 | 2229 | |
| 2221 | 2230 | if (union_type->data.unionation.is_invalid) |
| 2222 | return; | |
| 2231 | return ErrorSemanticAnalyzeFail; | |
| 2223 | 2232 | |
| 2224 | 2233 | if (union_type->zero_bits) { |
| 2225 | 2234 | union_type->type_ref = LLVMVoidType(); |
| ... | ... | @@ -2238,7 +2247,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2238 | 2247 | |
| 2239 | 2248 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); |
| 2240 | 2249 | union_type->di_type = replacement_di_type; |
| 2241 | return; | |
| 2250 | return ErrorNone; | |
| 2242 | 2251 | } |
| 2243 | 2252 | |
| 2244 | 2253 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| ... | ... | @@ -2274,7 +2283,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2274 | 2283 | |
| 2275 | 2284 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); |
| 2276 | 2285 | union_type->di_type = replacement_di_type; |
| 2277 | return; | |
| 2286 | return ErrorNone; | |
| 2278 | 2287 | } |
| 2279 | 2288 | |
| 2280 | 2289 | LLVMTypeRef union_type_ref; |
| ... | ... | @@ -2293,7 +2302,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2293 | 2302 | |
| 2294 | 2303 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, tag_type->di_type); |
| 2295 | 2304 | union_type->di_type = tag_type->di_type; |
| 2296 | return; | |
| 2305 | return ErrorNone; | |
| 2297 | 2306 | } else { |
| 2298 | 2307 | union_type_ref = most_aligned_union_member->type_ref; |
| 2299 | 2308 | } |
| ... | ... | @@ -2367,19 +2376,21 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 2367 | 2376 | |
| 2368 | 2377 | ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); |
| 2369 | 2378 | union_type->di_type = replacement_di_type; |
| 2379 | ||
| 2380 | return ErrorNone; | |
| 2370 | 2381 | } |
| 2371 | 2382 | |
| 2372 | static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | |
| 2383 | static Error resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | |
| 2373 | 2384 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 2374 | 2385 | |
| 2375 | 2386 | if (enum_type->data.enumeration.zero_bits_known) |
| 2376 | return; | |
| 2387 | return ErrorNone; | |
| 2377 | 2388 | |
| 2378 | 2389 | if (enum_type->data.enumeration.zero_bits_loop_flag) { |
| 2379 | 2390 | add_node_error(g, enum_type->data.enumeration.decl_node, |
| 2380 | 2391 | buf_sprintf("'%s' depends on itself", buf_ptr(&enum_type->name))); |
| 2381 | 2392 | enum_type->data.enumeration.is_invalid = true; |
| 2382 | return; | |
| 2393 | return ErrorSemanticAnalyzeFail; | |
| 2383 | 2394 | } |
| 2384 | 2395 | |
| 2385 | 2396 | enum_type->data.enumeration.zero_bits_loop_flag = true; |
| ... | ... | @@ -2398,7 +2409,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2398 | 2409 | enum_type->data.enumeration.is_invalid = true; |
| 2399 | 2410 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 2400 | 2411 | enum_type->data.enumeration.zero_bits_known = true; |
| 2401 | return; | |
| 2412 | return ErrorSemanticAnalyzeFail; | |
| 2402 | 2413 | } |
| 2403 | 2414 | |
| 2404 | 2415 | enum_type->data.enumeration.src_field_count = field_count; |
| ... | ... | @@ -2525,13 +2536,18 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 2525 | 2536 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 2526 | 2537 | enum_type->zero_bits = !type_has_bits(tag_int_type); |
| 2527 | 2538 | enum_type->data.enumeration.zero_bits_known = true; |
| 2539 | assert(!enum_type->data.enumeration.is_invalid); | |
| 2540 | ||
| 2541 | return ErrorNone; | |
| 2528 | 2542 | } |
| 2529 | 2543 | |
| 2530 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | |
| 2544 | static Error resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | |
| 2531 | 2545 | assert(struct_type->id == TypeTableEntryIdStruct); |
| 2532 | 2546 | |
| 2547 | Error err; | |
| 2548 | ||
| 2533 | 2549 | if (struct_type->data.structure.zero_bits_known) |
| 2534 | return; | |
| 2550 | return ErrorNone; | |
| 2535 | 2551 | |
| 2536 | 2552 | if (struct_type->data.structure.zero_bits_loop_flag) { |
| 2537 | 2553 | // If we get here it's due to recursion. This is a design flaw in the compiler, |
| ... | ... | @@ -2547,7 +2563,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2547 | 2563 | struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); |
| 2548 | 2564 | } |
| 2549 | 2565 | } |
| 2550 | return; | |
| 2566 | return ErrorNone; | |
| 2551 | 2567 | } |
| 2552 | 2568 | |
| 2553 | 2569 | struct_type->data.structure.zero_bits_loop_flag = true; |
| ... | ... | @@ -2596,8 +2612,7 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2596 | 2612 | buf_sprintf("enums, not structs, support field assignment")); |
| 2597 | 2613 | } |
| 2598 | 2614 | |
| 2599 | type_ensure_zero_bits_known(g, field_type); | |
| 2600 | if (type_is_invalid(field_type)) { | |
| 2615 | if ((err = type_ensure_zero_bits_known(g, field_type))) { | |
| 2601 | 2616 | struct_type->data.structure.is_invalid = true; |
| 2602 | 2617 | continue; |
| 2603 | 2618 | } |
| ... | ... | @@ -2634,16 +2649,24 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 2634 | 2649 | struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; |
| 2635 | 2650 | struct_type->zero_bits = (gen_field_index == 0); |
| 2636 | 2651 | struct_type->data.structure.zero_bits_known = true; |
| 2652 | ||
| 2653 | if (struct_type->data.structure.is_invalid) { | |
| 2654 | return ErrorSemanticAnalyzeFail; | |
| 2655 | } | |
| 2656 | ||
| 2657 | return ErrorNone; | |
| 2637 | 2658 | } |
| 2638 | 2659 | |
| 2639 | static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | |
| 2660 | static Error resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | |
| 2640 | 2661 | assert(union_type->id == TypeTableEntryIdUnion); |
| 2641 | 2662 | |
| 2663 | Error err; | |
| 2664 | ||
| 2642 | 2665 | if (union_type->data.unionation.zero_bits_known) |
| 2643 | return; | |
| 2666 | return ErrorNone; | |
| 2644 | 2667 | |
| 2645 | 2668 | if (type_is_invalid(union_type)) |
| 2646 | return; | |
| 2669 | return ErrorSemanticAnalyzeFail; | |
| 2647 | 2670 | |
| 2648 | 2671 | if (union_type->data.unionation.zero_bits_loop_flag) { |
| 2649 | 2672 | // If we get here it's due to recursion. From this we conclude that the struct is |
| ... | ... | @@ -2660,7 +2683,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2660 | 2683 | LLVMPointerType(LLVMInt8Type(), 0)); |
| 2661 | 2684 | } |
| 2662 | 2685 | } |
| 2663 | return; | |
| 2686 | return ErrorNone; | |
| 2664 | 2687 | } |
| 2665 | 2688 | |
| 2666 | 2689 | union_type->data.unionation.zero_bits_loop_flag = true; |
| ... | ... | @@ -2679,7 +2702,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2679 | 2702 | union_type->data.unionation.is_invalid = true; |
| 2680 | 2703 | union_type->data.unionation.zero_bits_loop_flag = false; |
| 2681 | 2704 | union_type->data.unionation.zero_bits_known = true; |
| 2682 | return; | |
| 2705 | return ErrorSemanticAnalyzeFail; | |
| 2683 | 2706 | } |
| 2684 | 2707 | union_type->data.unionation.src_field_count = field_count; |
| 2685 | 2708 | union_type->data.unionation.fields = allocate<TypeUnionField>(field_count); |
| ... | ... | @@ -2711,13 +2734,13 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2711 | 2734 | tag_int_type = analyze_type_expr(g, scope, enum_type_node); |
| 2712 | 2735 | if (type_is_invalid(tag_int_type)) { |
| 2713 | 2736 | union_type->data.unionation.is_invalid = true; |
| 2714 | return; | |
| 2737 | return ErrorSemanticAnalyzeFail; | |
| 2715 | 2738 | } |
| 2716 | 2739 | if (tag_int_type->id != TypeTableEntryIdInt) { |
| 2717 | 2740 | add_node_error(g, enum_type_node, |
| 2718 | 2741 | buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); |
| 2719 | 2742 | union_type->data.unionation.is_invalid = true; |
| 2720 | return; | |
| 2743 | return ErrorSemanticAnalyzeFail; | |
| 2721 | 2744 | } |
| 2722 | 2745 | } else { |
| 2723 | 2746 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| ... | ... | @@ -2744,13 +2767,13 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2744 | 2767 | TypeTableEntry *enum_type = analyze_type_expr(g, scope, enum_type_node); |
| 2745 | 2768 | if (type_is_invalid(enum_type)) { |
| 2746 | 2769 | union_type->data.unionation.is_invalid = true; |
| 2747 | return; | |
| 2770 | return ErrorSemanticAnalyzeFail; | |
| 2748 | 2771 | } |
| 2749 | 2772 | if (enum_type->id != TypeTableEntryIdEnum) { |
| 2750 | 2773 | union_type->data.unionation.is_invalid = true; |
| 2751 | 2774 | add_node_error(g, enum_type_node, |
| 2752 | 2775 | buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); |
| 2753 | return; | |
| 2776 | return ErrorSemanticAnalyzeFail; | |
| 2754 | 2777 | } |
| 2755 | 2778 | tag_type = enum_type; |
| 2756 | 2779 | abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count |
| ... | ... | @@ -2789,8 +2812,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2789 | 2812 | } |
| 2790 | 2813 | } else { |
| 2791 | 2814 | field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); |
| 2792 | type_ensure_zero_bits_known(g, field_type); | |
| 2793 | if (type_is_invalid(field_type)) { | |
| 2815 | if ((err = type_ensure_zero_bits_known(g, field_type))) { | |
| 2794 | 2816 | union_type->data.unionation.is_invalid = true; |
| 2795 | 2817 | continue; |
| 2796 | 2818 | } |
| ... | ... | @@ -2883,7 +2905,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2883 | 2905 | union_type->data.unionation.abi_alignment = abi_alignment_so_far; |
| 2884 | 2906 | |
| 2885 | 2907 | if (union_type->data.unionation.is_invalid) |
| 2886 | return; | |
| 2908 | return ErrorSemanticAnalyzeFail; | |
| 2887 | 2909 | |
| 2888 | 2910 | bool src_have_tag = decl_node->data.container_decl.auto_enum || |
| 2889 | 2911 | decl_node->data.container_decl.init_arg_expr != nullptr; |
| ... | ... | @@ -2905,7 +2927,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2905 | 2927 | add_node_error(g, source_node, |
| 2906 | 2928 | buf_sprintf("%s union does not support enum tag type", qual_str)); |
| 2907 | 2929 | union_type->data.unionation.is_invalid = true; |
| 2908 | return; | |
| 2930 | return ErrorSemanticAnalyzeFail; | |
| 2909 | 2931 | } |
| 2910 | 2932 | |
| 2911 | 2933 | if (create_enum_type) { |
| ... | ... | @@ -2970,6 +2992,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2970 | 2992 | union_type->data.unionation.gen_field_count = gen_field_index; |
| 2971 | 2993 | union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); |
| 2972 | 2994 | union_type->data.unionation.zero_bits_known = true; |
| 2995 | assert(!union_type->data.unionation.is_invalid); | |
| 2996 | return ErrorNone; | |
| 2973 | 2997 | } |
| 2974 | 2998 | |
| 2975 | 2999 | static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) { |
| ... | ... | @@ -3463,13 +3487,13 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent |
| 3463 | 3487 | variable_entry->shadowable = false; |
| 3464 | 3488 | variable_entry->mem_slot_index = SIZE_MAX; |
| 3465 | 3489 | variable_entry->src_arg_index = SIZE_MAX; |
| 3466 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | |
| 3467 | 3490 | |
| 3468 | 3491 | assert(name); |
| 3469 | ||
| 3470 | 3492 | buf_init_from_buf(&variable_entry->name, name); |
| 3471 | 3493 | |
| 3472 | if (value->type->id != TypeTableEntryIdInvalid) { | |
| 3494 | if (!type_is_invalid(value->type)) { | |
| 3495 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | |
| 3496 | ||
| 3473 | 3497 | VariableTableEntry *existing_var = find_variable(g, parent_scope, name); |
| 3474 | 3498 | if (existing_var && !existing_var->shadowable) { |
| 3475 | 3499 | ErrorMsg *msg = add_node_error(g, source_node, |
| ... | ... | @@ -5311,13 +5335,13 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_ |
| 5311 | 5335 | |
| 5312 | 5336 | |
| 5313 | 5337 | void init_const_undefined(CodeGen *g, ConstExprValue *const_val) { |
| 5338 | Error err; | |
| 5314 | 5339 | TypeTableEntry *wanted_type = const_val->type; |
| 5315 | 5340 | if (wanted_type->id == TypeTableEntryIdArray) { |
| 5316 | 5341 | const_val->special = ConstValSpecialStatic; |
| 5317 | 5342 | const_val->data.x_array.special = ConstArraySpecialUndef; |
| 5318 | 5343 | } else if (wanted_type->id == TypeTableEntryIdStruct) { |
| 5319 | ensure_complete_type(g, wanted_type); | |
| 5320 | if (type_is_invalid(wanted_type)) { | |
| 5344 | if ((err = ensure_complete_type(g, wanted_type))) { | |
| 5321 | 5345 | return; |
| 5322 | 5346 | } |
| 5323 | 5347 | |
| ... | ... | @@ -5350,27 +5374,33 @@ ConstExprValue *create_const_vals(size_t count) { |
| 5350 | 5374 | return vals; |
| 5351 | 5375 | } |
| 5352 | 5376 | |
| 5353 | void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) { | |
| 5377 | Error ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) { | |
| 5378 | if (type_is_invalid(type_entry)) | |
| 5379 | return ErrorSemanticAnalyzeFail; | |
| 5354 | 5380 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 5355 | 5381 | if (!type_entry->data.structure.complete) |
| 5356 | resolve_struct_type(g, type_entry); | |
| 5382 | return resolve_struct_type(g, type_entry); | |
| 5357 | 5383 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 5358 | 5384 | if (!type_entry->data.enumeration.complete) |
| 5359 | resolve_enum_type(g, type_entry); | |
| 5385 | return resolve_enum_type(g, type_entry); | |
| 5360 | 5386 | } else if (type_entry->id == TypeTableEntryIdUnion) { |
| 5361 | 5387 | if (!type_entry->data.unionation.complete) |
| 5362 | resolve_union_type(g, type_entry); | |
| 5388 | return resolve_union_type(g, type_entry); | |
| 5363 | 5389 | } |
| 5390 | return ErrorNone; | |
| 5364 | 5391 | } |
| 5365 | 5392 | |
| 5366 | void type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry) { | |
| 5393 | Error type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry) { | |
| 5394 | if (type_is_invalid(type_entry)) | |
| 5395 | return ErrorSemanticAnalyzeFail; | |
| 5367 | 5396 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 5368 | resolve_struct_zero_bits(g, type_entry); | |
| 5397 | return resolve_struct_zero_bits(g, type_entry); | |
| 5369 | 5398 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 5370 | resolve_enum_zero_bits(g, type_entry); | |
| 5399 | return resolve_enum_zero_bits(g, type_entry); | |
| 5371 | 5400 | } else if (type_entry->id == TypeTableEntryIdUnion) { |
| 5372 | resolve_union_zero_bits(g, type_entry); | |
| 5401 | return resolve_union_zero_bits(g, type_entry); | |
| 5373 | 5402 | } |
| 5403 | return ErrorNone; | |
| 5374 | 5404 | } |
| 5375 | 5405 | |
| 5376 | 5406 | bool ir_get_var_is_comptime(VariableTableEntry *var) { |
| ... | ... | @@ -6213,7 +6243,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { |
| 6213 | 6243 | } |
| 6214 | 6244 | |
| 6215 | 6245 | uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) { |
| 6216 | type_ensure_zero_bits_known(g, type_entry); | |
| 6246 | assertNoError(type_ensure_zero_bits_known(g, type_entry)); | |
| 6217 | 6247 | if (type_entry->zero_bits) return 0; |
| 6218 | 6248 | |
| 6219 | 6249 | // We need to make this function work without requiring ensure_complete_type |
src/analyze.hpp+4-3| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #define ZIG_ANALYZE_HPP |
| 10 | 10 | |
| 11 | 11 | #include "all_types.hpp" |
| 12 | #include "result.hpp" | |
| 12 | 13 | |
| 13 | 14 | void semantic_analyze(CodeGen *g); |
| 14 | 15 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| ... | ... | @@ -88,8 +89,8 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou |
| 88 | 89 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index); |
| 89 | 90 | FnTableEntry *scope_get_fn_if_root(Scope *scope); |
| 90 | 91 | bool type_requires_comptime(TypeTableEntry *type_entry); |
| 91 | void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry); | |
| 92 | void type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry); | |
| 92 | Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry); | |
| 93 | Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry); | |
| 93 | 94 | void complete_enum(CodeGen *g, TypeTableEntry *enum_type); |
| 94 | 95 | bool ir_get_var_is_comptime(VariableTableEntry *var); |
| 95 | 96 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b); |
| ... | ... | @@ -178,7 +179,7 @@ TypeTableEntryId type_id_at_index(size_t index); |
| 178 | 179 | size_t type_id_len(); |
| 179 | 180 | size_t type_id_index(TypeTableEntry *entry); |
| 180 | 181 | TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| 181 | bool type_is_copyable(CodeGen *g, TypeTableEntry *type_entry); | |
| 182 | Result<bool> type_is_copyable(CodeGen *g, TypeTableEntry *type_entry); | |
| 182 | 183 | LinkLib *create_link_lib(Buf *name); |
| 183 | 184 | bool calling_convention_does_first_arg_return(CallingConvention cc); |
| 184 | 185 | LinkLib *add_link_lib(CodeGen *codegen, Buf *lib); |
src/ir.cpp+94-99| ... | ... | @@ -8711,6 +8711,7 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * |
| 8711 | 8711 | } |
| 8712 | 8712 | |
| 8713 | 8713 | static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, TypeTableEntry *expected_type, IrInstruction **instructions, size_t instruction_count) { |
| 8714 | Error err; | |
| 8714 | 8715 | assert(instruction_count >= 1); |
| 8715 | 8716 | IrInstruction *prev_inst = instructions[0]; |
| 8716 | 8717 | if (type_is_invalid(prev_inst->value.type)) { |
| ... | ... | @@ -9172,8 +9173,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 9172 | 9173 | if (prev_type->id == TypeTableEntryIdEnum && cur_type->id == TypeTableEntryIdUnion && |
| 9173 | 9174 | (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) |
| 9174 | 9175 | { |
| 9175 | type_ensure_zero_bits_known(ira->codegen, cur_type); | |
| 9176 | if (type_is_invalid(cur_type)) | |
| 9176 | if ((err = type_ensure_zero_bits_known(ira->codegen, cur_type))) | |
| 9177 | 9177 | return ira->codegen->builtin_types.entry_invalid; |
| 9178 | 9178 | if (cur_type->data.unionation.tag_type == prev_type) { |
| 9179 | 9179 | continue; |
| ... | ... | @@ -9183,8 +9183,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 9183 | 9183 | if (cur_type->id == TypeTableEntryIdEnum && prev_type->id == TypeTableEntryIdUnion && |
| 9184 | 9184 | (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) |
| 9185 | 9185 | { |
| 9186 | type_ensure_zero_bits_known(ira->codegen, prev_type); | |
| 9187 | if (type_is_invalid(prev_type)) | |
| 9186 | if ((err = type_ensure_zero_bits_known(ira->codegen, prev_type))) | |
| 9188 | 9187 | return ira->codegen->builtin_types.entry_invalid; |
| 9189 | 9188 | if (prev_type->data.unionation.tag_type == cur_type) { |
| 9190 | 9189 | prev_inst = cur_inst; |
| ... | ... | @@ -9999,11 +9998,11 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 9999 | 9998 | static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, |
| 10000 | 9999 | IrInstruction *target, TypeTableEntry *wanted_type) |
| 10001 | 10000 | { |
| 10001 | Error err; | |
| 10002 | 10002 | assert(wanted_type->id == TypeTableEntryIdInt); |
| 10003 | 10003 | |
| 10004 | 10004 | TypeTableEntry *actual_type = target->value.type; |
| 10005 | ensure_complete_type(ira->codegen, actual_type); | |
| 10006 | if (type_is_invalid(actual_type)) | |
| 10005 | if ((err = ensure_complete_type(ira->codegen, actual_type))) | |
| 10007 | 10006 | return ira->codegen->invalid_instruction; |
| 10008 | 10007 | |
| 10009 | 10008 | if (wanted_type != actual_type->data.enumeration.tag_int_type) { |
| ... | ... | @@ -10069,6 +10068,7 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc |
| 10069 | 10068 | static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr, |
| 10070 | 10069 | IrInstruction *target, TypeTableEntry *wanted_type) |
| 10071 | 10070 | { |
| 10071 | Error err; | |
| 10072 | 10072 | assert(wanted_type->id == TypeTableEntryIdUnion); |
| 10073 | 10073 | assert(target->value.type->id == TypeTableEntryIdEnum); |
| 10074 | 10074 | |
| ... | ... | @@ -10078,8 +10078,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so |
| 10078 | 10078 | return ira->codegen->invalid_instruction; |
| 10079 | 10079 | TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag); |
| 10080 | 10080 | assert(union_field != nullptr); |
| 10081 | type_ensure_zero_bits_known(ira->codegen, union_field->type_entry); | |
| 10082 | if (type_is_invalid(union_field->type_entry)) | |
| 10081 | if ((err = type_ensure_zero_bits_known(ira->codegen, union_field->type_entry))) | |
| 10083 | 10082 | return ira->codegen->invalid_instruction; |
| 10084 | 10083 | if (!union_field->type_entry->zero_bits) { |
| 10085 | 10084 | AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at( |
| ... | ... | @@ -10169,12 +10168,12 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction |
| 10169 | 10168 | static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *source_instr, |
| 10170 | 10169 | IrInstruction *target, TypeTableEntry *wanted_type) |
| 10171 | 10170 | { |
| 10171 | Error err; | |
| 10172 | 10172 | assert(wanted_type->id == TypeTableEntryIdEnum); |
| 10173 | 10173 | |
| 10174 | 10174 | TypeTableEntry *actual_type = target->value.type; |
| 10175 | 10175 | |
| 10176 | ensure_complete_type(ira->codegen, wanted_type); | |
| 10177 | if (type_is_invalid(wanted_type)) | |
| 10176 | if ((err = ensure_complete_type(ira->codegen, wanted_type))) | |
| 10178 | 10177 | return ira->codegen->invalid_instruction; |
| 10179 | 10178 | |
| 10180 | 10179 | if (actual_type != wanted_type->data.enumeration.tag_int_type) { |
| ... | ... | @@ -10517,6 +10516,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 10517 | 10516 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 10518 | 10517 | TypeTableEntry *wanted_type, IrInstruction *value) |
| 10519 | 10518 | { |
| 10519 | Error err; | |
| 10520 | 10520 | TypeTableEntry *actual_type = value->value.type; |
| 10521 | 10521 | AstNode *source_node = source_instr->source_node; |
| 10522 | 10522 | |
| ... | ... | @@ -10796,8 +10796,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10796 | 10796 | if (actual_type->id == TypeTableEntryIdComptimeFloat || |
| 10797 | 10797 | actual_type->id == TypeTableEntryIdComptimeInt) |
| 10798 | 10798 | { |
| 10799 | ensure_complete_type(ira->codegen, wanted_type); | |
| 10800 | if (type_is_invalid(wanted_type)) | |
| 10799 | if ((err = ensure_complete_type(ira->codegen, wanted_type))) | |
| 10801 | 10800 | return ira->codegen->invalid_instruction; |
| 10802 | 10801 | if (wanted_type->id == TypeTableEntryIdEnum) { |
| 10803 | 10802 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.enumeration.tag_int_type, value); |
| ... | ... | @@ -10853,8 +10852,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10853 | 10852 | |
| 10854 | 10853 | // cast from union to the enum type of the union |
| 10855 | 10854 | if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) { |
| 10856 | type_ensure_zero_bits_known(ira->codegen, actual_type); | |
| 10857 | if (type_is_invalid(actual_type)) | |
| 10855 | if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) | |
| 10858 | 10856 | return ira->codegen->invalid_instruction; |
| 10859 | 10857 | |
| 10860 | 10858 | if (actual_type->data.unionation.tag_type == wanted_type) { |
| ... | ... | @@ -10867,7 +10865,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10867 | 10865 | (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum || |
| 10868 | 10866 | wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) |
| 10869 | 10867 | { |
| 10870 | type_ensure_zero_bits_known(ira->codegen, wanted_type); | |
| 10868 | if ((err = type_ensure_zero_bits_known(ira->codegen, wanted_type))) | |
| 10869 | return ira->codegen->invalid_instruction; | |
| 10870 | ||
| 10871 | 10871 | if (wanted_type->data.unionation.tag_type == actual_type) { |
| 10872 | 10872 | return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type); |
| 10873 | 10873 | } |
| ... | ... | @@ -10879,7 +10879,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10879 | 10879 | if (union_type->data.unionation.decl_node->data.container_decl.auto_enum || |
| 10880 | 10880 | union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr) |
| 10881 | 10881 | { |
| 10882 | type_ensure_zero_bits_known(ira->codegen, union_type); | |
| 10882 | if ((err = type_ensure_zero_bits_known(ira->codegen, union_type))) | |
| 10883 | return ira->codegen->invalid_instruction; | |
| 10884 | ||
| 10883 | 10885 | if (union_type->data.unionation.tag_type == actual_type) { |
| 10884 | 10886 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, union_type, value); |
| 10885 | 10887 | if (type_is_invalid(cast1->value.type)) |
| ... | ... | @@ -10923,8 +10925,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10923 | 10925 | types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, |
| 10924 | 10926 | actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) |
| 10925 | 10927 | { |
| 10926 | type_ensure_zero_bits_known(ira->codegen, actual_type); | |
| 10927 | if (type_is_invalid(actual_type)) { | |
| 10928 | if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) { | |
| 10928 | 10929 | return ira->codegen->invalid_instruction; |
| 10929 | 10930 | } |
| 10930 | 10931 | if (!type_has_bits(actual_type)) { |
| ... | ... | @@ -11323,6 +11324,7 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 11323 | 11324 | } |
| 11324 | 11325 | |
| 11325 | 11326 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 11327 | Error err; | |
| 11326 | 11328 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 11327 | 11329 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 11328 | 11330 | AstNode *source_node = bin_op_instruction->base.source_node; |
| ... | ... | @@ -11458,8 +11460,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 11458 | 11460 | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2); |
| 11459 | 11461 | if (type_is_invalid(resolved_type)) |
| 11460 | 11462 | return resolved_type; |
| 11461 | type_ensure_zero_bits_known(ira->codegen, resolved_type); | |
| 11462 | if (type_is_invalid(resolved_type)) | |
| 11463 | if ((err = type_ensure_zero_bits_known(ira->codegen, resolved_type))) | |
| 11463 | 11464 | return resolved_type; |
| 11464 | 11465 | |
| 11465 | 11466 | bool operator_allowed; |
| ... | ... | @@ -12406,6 +12407,7 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi |
| 12406 | 12407 | } |
| 12407 | 12408 | |
| 12408 | 12409 | static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { |
| 12410 | Error err; | |
| 12409 | 12411 | VariableTableEntry *var = decl_var_instruction->var; |
| 12410 | 12412 | |
| 12411 | 12413 | IrInstruction *init_value = decl_var_instruction->init_value->other; |
| ... | ... | @@ -12439,8 +12441,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 12439 | 12441 | if (type_is_invalid(result_type)) { |
| 12440 | 12442 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12441 | 12443 | } else { |
| 12442 | type_ensure_zero_bits_known(ira->codegen, result_type); | |
| 12443 | if (type_is_invalid(result_type)) { | |
| 12444 | if ((err = type_ensure_zero_bits_known(ira->codegen, result_type))) { | |
| 12444 | 12445 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12445 | 12446 | } |
| 12446 | 12447 | } |
| ... | ... | @@ -12958,6 +12959,7 @@ static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t in |
| 12958 | 12959 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 12959 | 12960 | VariableTableEntry *var) |
| 12960 | 12961 | { |
| 12962 | Error err; | |
| 12961 | 12963 | if (var->mem_slot_index != SIZE_MAX && var->owner_exec->analysis == nullptr) { |
| 12962 | 12964 | assert(ira->codegen->errors.length != 0); |
| 12963 | 12965 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -13012,7 +13014,8 @@ no_mem_slot: |
| 13012 | 13014 | instruction->scope, instruction->source_node, var); |
| 13013 | 13015 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, |
| 13014 | 13016 | var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); |
| 13015 | type_ensure_zero_bits_known(ira->codegen, var->value->type); | |
| 13017 | if ((err = type_ensure_zero_bits_known(ira->codegen, var->value->type))) | |
| 13018 | return ira->codegen->invalid_instruction; | |
| 13016 | 13019 | |
| 13017 | 13020 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); |
| 13018 | 13021 | var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack; |
| ... | ... | @@ -13024,6 +13027,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 13024 | 13027 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, |
| 13025 | 13028 | IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline) |
| 13026 | 13029 | { |
| 13030 | Error err; | |
| 13027 | 13031 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 13028 | 13032 | size_t first_arg_1_or_0 = first_arg_ptr ? 1 : 0; |
| 13029 | 13033 | |
| ... | ... | @@ -13388,8 +13392,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 13388 | 13392 | inst_fn_type_id.return_type = specified_return_type; |
| 13389 | 13393 | } |
| 13390 | 13394 | |
| 13391 | type_ensure_zero_bits_known(ira->codegen, specified_return_type); | |
| 13392 | if (type_is_invalid(specified_return_type)) | |
| 13395 | if ((err = type_ensure_zero_bits_known(ira->codegen, specified_return_type))) | |
| 13393 | 13396 | return ira->codegen->builtin_types.entry_invalid; |
| 13394 | 13397 | |
| 13395 | 13398 | if (type_requires_comptime(specified_return_type)) { |
| ... | ... | @@ -13664,12 +13667,12 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp |
| 13664 | 13667 | } |
| 13665 | 13668 | |
| 13666 | 13669 | static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 13670 | Error err; | |
| 13667 | 13671 | IrInstruction *value = un_op_instruction->value->other; |
| 13668 | 13672 | TypeTableEntry *type_entry = ir_resolve_type(ira, value); |
| 13669 | 13673 | if (type_is_invalid(type_entry)) |
| 13670 | 13674 | return ira->codegen->builtin_types.entry_invalid; |
| 13671 | ensure_complete_type(ira->codegen, type_entry); | |
| 13672 | if (type_is_invalid(type_entry)) | |
| 13675 | if ((err = ensure_complete_type(ira->codegen, type_entry))) | |
| 13673 | 13676 | return ira->codegen->builtin_types.entry_invalid; |
| 13674 | 13677 | |
| 13675 | 13678 | switch (type_entry->id) { |
| ... | ... | @@ -14023,6 +14026,7 @@ static TypeTableEntry *adjust_ptr_len(CodeGen *g, TypeTableEntry *ptr_type, PtrL |
| 14023 | 14026 | } |
| 14024 | 14027 | |
| 14025 | 14028 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| 14029 | Error err; | |
| 14026 | 14030 | IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other; |
| 14027 | 14031 | if (type_is_invalid(array_ptr->value.type)) |
| 14028 | 14032 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -14131,8 +14135,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 14131 | 14135 | return ira->codegen->builtin_types.entry_invalid; |
| 14132 | 14136 | |
| 14133 | 14137 | bool safety_check_on = elem_ptr_instruction->safety_check_on; |
| 14134 | ensure_complete_type(ira->codegen, return_type->data.pointer.child_type); | |
| 14135 | if (type_is_invalid(return_type->data.pointer.child_type)) | |
| 14138 | if ((err = ensure_complete_type(ira->codegen, return_type->data.pointer.child_type))) | |
| 14136 | 14139 | return ira->codegen->builtin_types.entry_invalid; |
| 14137 | 14140 | |
| 14138 | 14141 | uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); |
| ... | ... | @@ -14352,9 +14355,10 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 14352 | 14355 | static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 14353 | 14356 | IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type) |
| 14354 | 14357 | { |
| 14358 | Error err; | |
| 14359 | ||
| 14355 | 14360 | TypeTableEntry *bare_type = container_ref_type(container_type); |
| 14356 | ensure_complete_type(ira->codegen, bare_type); | |
| 14357 | if (type_is_invalid(bare_type)) | |
| 14361 | if ((err = ensure_complete_type(ira->codegen, bare_type))) | |
| 14358 | 14362 | return ira->codegen->invalid_instruction; |
| 14359 | 14363 | |
| 14360 | 14364 | assert(container_ptr->value.type->id == TypeTableEntryIdPointer); |
| ... | ... | @@ -14553,6 +14557,7 @@ static ErrorTableEntry *find_err_table_entry(TypeTableEntry *err_set_type, Buf * |
| 14553 | 14557 | } |
| 14554 | 14558 | |
| 14555 | 14559 | static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) { |
| 14560 | Error err; | |
| 14556 | 14561 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; |
| 14557 | 14562 | if (type_is_invalid(container_ptr->value.type)) |
| 14558 | 14563 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -14654,8 +14659,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 14654 | 14659 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 14655 | 14660 | } |
| 14656 | 14661 | if (child_type->id == TypeTableEntryIdEnum) { |
| 14657 | ensure_complete_type(ira->codegen, child_type); | |
| 14658 | if (type_is_invalid(child_type)) | |
| 14662 | if ((err = ensure_complete_type(ira->codegen, child_type))) | |
| 14659 | 14663 | return ira->codegen->builtin_types.entry_invalid; |
| 14660 | 14664 | |
| 14661 | 14665 | TypeEnumField *field = find_enum_type_field(child_type, field_name); |
| ... | ... | @@ -14679,8 +14683,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 14679 | 14683 | (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr || |
| 14680 | 14684 | child_type->data.unionation.decl_node->data.container_decl.auto_enum)) |
| 14681 | 14685 | { |
| 14682 | ensure_complete_type(ira->codegen, child_type); | |
| 14683 | if (type_is_invalid(child_type)) | |
| 14686 | if ((err = ensure_complete_type(ira->codegen, child_type))) | |
| 14684 | 14687 | return ira->codegen->builtin_types.entry_invalid; |
| 14685 | 14688 | TypeUnionField *field = find_union_type_field(child_type, field_name); |
| 14686 | 14689 | if (field) { |
| ... | ... | @@ -15257,6 +15260,7 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 15257 | 15260 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 15258 | 15261 | IrInstructionSliceType *slice_type_instruction) |
| 15259 | 15262 | { |
| 15263 | Error err; | |
| 15260 | 15264 | uint32_t align_bytes; |
| 15261 | 15265 | if (slice_type_instruction->align_value != nullptr) { |
| 15262 | 15266 | if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes)) |
| ... | ... | @@ -15306,7 +15310,8 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 15306 | 15310 | case TypeTableEntryIdBoundFn: |
| 15307 | 15311 | case TypeTableEntryIdPromise: |
| 15308 | 15312 | { |
| 15309 | type_ensure_zero_bits_known(ira->codegen, child_type); | |
| 15313 | if ((err = type_ensure_zero_bits_known(ira->codegen, child_type))) | |
| 15314 | return ira->codegen->builtin_types.entry_invalid; | |
| 15310 | 15315 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 15311 | 15316 | is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0); |
| 15312 | 15317 | TypeTableEntry *result_type = get_slice_type(ira->codegen, slice_ptr_type); |
| ... | ... | @@ -15444,11 +15449,11 @@ static TypeTableEntry *ir_analyze_instruction_promise_type(IrAnalyze *ira, IrIns |
| 15444 | 15449 | static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 15445 | 15450 | IrInstructionSizeOf *size_of_instruction) |
| 15446 | 15451 | { |
| 15452 | Error err; | |
| 15447 | 15453 | IrInstruction *type_value = size_of_instruction->type_value->other; |
| 15448 | 15454 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| 15449 | 15455 | |
| 15450 | ensure_complete_type(ira->codegen, type_entry); | |
| 15451 | if (type_is_invalid(type_entry)) | |
| 15456 | if ((err = ensure_complete_type(ira->codegen, type_entry))) | |
| 15452 | 15457 | return ira->codegen->builtin_types.entry_invalid; |
| 15453 | 15458 | |
| 15454 | 15459 | switch (type_entry->id) { |
| ... | ... | @@ -15819,6 +15824,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 15819 | 15824 | static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15820 | 15825 | IrInstructionSwitchTarget *switch_target_instruction) |
| 15821 | 15826 | { |
| 15827 | Error err; | |
| 15822 | 15828 | IrInstruction *target_value_ptr = switch_target_instruction->target_value_ptr->other; |
| 15823 | 15829 | if (type_is_invalid(target_value_ptr->value.type)) |
| 15824 | 15830 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -15845,8 +15851,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15845 | 15851 | if (pointee_val->special == ConstValSpecialRuntime) |
| 15846 | 15852 | pointee_val = nullptr; |
| 15847 | 15853 | } |
| 15848 | ensure_complete_type(ira->codegen, target_type); | |
| 15849 | if (type_is_invalid(target_type)) | |
| 15854 | if ((err = ensure_complete_type(ira->codegen, target_type))) | |
| 15850 | 15855 | return ira->codegen->builtin_types.entry_invalid; |
| 15851 | 15856 | |
| 15852 | 15857 | switch (target_type->id) { |
| ... | ... | @@ -15910,8 +15915,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 15910 | 15915 | return tag_type; |
| 15911 | 15916 | } |
| 15912 | 15917 | case TypeTableEntryIdEnum: { |
| 15913 | type_ensure_zero_bits_known(ira->codegen, target_type); | |
| 15914 | if (type_is_invalid(target_type)) | |
| 15918 | if ((err = type_ensure_zero_bits_known(ira->codegen, target_type))) | |
| 15915 | 15919 | return ira->codegen->builtin_types.entry_invalid; |
| 15916 | 15920 | if (target_type->data.enumeration.src_field_count < 2) { |
| 15917 | 15921 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| ... | ... | @@ -16113,10 +16117,10 @@ static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionR |
| 16113 | 16117 | static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction, |
| 16114 | 16118 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields) |
| 16115 | 16119 | { |
| 16120 | Error err; | |
| 16116 | 16121 | assert(container_type->id == TypeTableEntryIdUnion); |
| 16117 | 16122 | |
| 16118 | ensure_complete_type(ira->codegen, container_type); | |
| 16119 | if (type_is_invalid(container_type)) | |
| 16123 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16120 | 16124 | return ira->codegen->builtin_types.entry_invalid; |
| 16121 | 16125 | |
| 16122 | 16126 | if (instr_field_count != 1) { |
| ... | ... | @@ -16145,8 +16149,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir |
| 16145 | 16149 | if (casted_field_value == ira->codegen->invalid_instruction) |
| 16146 | 16150 | return ira->codegen->builtin_types.entry_invalid; |
| 16147 | 16151 | |
| 16148 | type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type); | |
| 16149 | if (type_is_invalid(casted_field_value->value.type)) | |
| 16152 | if ((err = type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type))) | |
| 16150 | 16153 | return ira->codegen->builtin_types.entry_invalid; |
| 16151 | 16154 | |
| 16152 | 16155 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope); |
| ... | ... | @@ -16180,6 +16183,7 @@ static TypeTableEntry *ir_analyze_container_init_fields_union(IrAnalyze *ira, Ir |
| 16180 | 16183 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |
| 16181 | 16184 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields) |
| 16182 | 16185 | { |
| 16186 | Error err; | |
| 16183 | 16187 | if (container_type->id == TypeTableEntryIdUnion) { |
| 16184 | 16188 | return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields); |
| 16185 | 16189 | } |
| ... | ... | @@ -16190,8 +16194,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru |
| 16190 | 16194 | return ira->codegen->builtin_types.entry_invalid; |
| 16191 | 16195 | } |
| 16192 | 16196 | |
| 16193 | ensure_complete_type(ira->codegen, container_type); | |
| 16194 | if (type_is_invalid(container_type)) | |
| 16197 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16195 | 16198 | return ira->codegen->builtin_types.entry_invalid; |
| 16196 | 16199 | |
| 16197 | 16200 | size_t actual_field_count = container_type->data.structure.src_field_count; |
| ... | ... | @@ -16572,6 +16575,7 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 16572 | 16575 | } |
| 16573 | 16576 | |
| 16574 | 16577 | static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionTagName *instruction) { |
| 16578 | Error err; | |
| 16575 | 16579 | IrInstruction *target = instruction->target->other; |
| 16576 | 16580 | if (type_is_invalid(target->value.type)) |
| 16577 | 16581 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -16579,8 +16583,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn |
| 16579 | 16583 | assert(target->value.type->id == TypeTableEntryIdEnum); |
| 16580 | 16584 | |
| 16581 | 16585 | if (instr_is_comptime(target)) { |
| 16582 | type_ensure_zero_bits_known(ira->codegen, target->value.type); | |
| 16583 | if (type_is_invalid(target->value.type)) | |
| 16586 | if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type))) | |
| 16584 | 16587 | return ira->codegen->builtin_types.entry_invalid; |
| 16585 | 16588 | TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint); |
| 16586 | 16589 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); |
| ... | ... | @@ -16604,6 +16607,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn |
| 16604 | 16607 | static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 16605 | 16608 | IrInstructionFieldParentPtr *instruction) |
| 16606 | 16609 | { |
| 16610 | Error err; | |
| 16607 | 16611 | IrInstruction *type_value = instruction->type_value->other; |
| 16608 | 16612 | TypeTableEntry *container_type = ir_resolve_type(ira, type_value); |
| 16609 | 16613 | if (type_is_invalid(container_type)) |
| ... | ... | @@ -16624,8 +16628,7 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 16624 | 16628 | return ira->codegen->builtin_types.entry_invalid; |
| 16625 | 16629 | } |
| 16626 | 16630 | |
| 16627 | ensure_complete_type(ira->codegen, container_type); | |
| 16628 | if (type_is_invalid(container_type)) | |
| 16631 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16629 | 16632 | return ira->codegen->builtin_types.entry_invalid; |
| 16630 | 16633 | |
| 16631 | 16634 | TypeStructField *field = find_struct_type_field(container_type, field_name); |
| ... | ... | @@ -16697,13 +16700,13 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 16697 | 16700 | static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, |
| 16698 | 16701 | IrInstructionOffsetOf *instruction) |
| 16699 | 16702 | { |
| 16703 | Error err; | |
| 16700 | 16704 | IrInstruction *type_value = instruction->type_value->other; |
| 16701 | 16705 | TypeTableEntry *container_type = ir_resolve_type(ira, type_value); |
| 16702 | 16706 | if (type_is_invalid(container_type)) |
| 16703 | 16707 | return ira->codegen->builtin_types.entry_invalid; |
| 16704 | 16708 | |
| 16705 | ensure_complete_type(ira->codegen, container_type); | |
| 16706 | if (type_is_invalid(container_type)) | |
| 16709 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16707 | 16710 | return ira->codegen->builtin_types.entry_invalid; |
| 16708 | 16711 | |
| 16709 | 16712 | IrInstruction *field_name_value = instruction->field_name->other; |
| ... | ... | @@ -16750,6 +16753,7 @@ static void ensure_field_index(TypeTableEntry *type, const char *field_name, siz |
| 16750 | 16753 | |
| 16751 | 16754 | static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, TypeTableEntry *root = nullptr) |
| 16752 | 16755 | { |
| 16756 | Error err; | |
| 16753 | 16757 | static ConstExprValue *type_info_var = nullptr; |
| 16754 | 16758 | static TypeTableEntry *type_info_type = nullptr; |
| 16755 | 16759 | if (type_info_var == nullptr) |
| ... | ... | @@ -16757,8 +16761,7 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na |
| 16757 | 16761 | type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); |
| 16758 | 16762 | assert(type_info_var->type->id == TypeTableEntryIdMetaType); |
| 16759 | 16763 | |
| 16760 | ensure_complete_type(ira->codegen, type_info_var->data.x_type); | |
| 16761 | if (type_is_invalid(type_info_var->data.x_type)) | |
| 16764 | if ((err = ensure_complete_type(ira->codegen, type_info_var->data.x_type))) | |
| 16762 | 16765 | return ira->codegen->builtin_types.entry_invalid; |
| 16763 | 16766 | |
| 16764 | 16767 | type_info_type = type_info_var->data.x_type; |
| ... | ... | @@ -16785,8 +16788,7 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na |
| 16785 | 16788 | |
| 16786 | 16789 | VariableTableEntry *var = tld->var; |
| 16787 | 16790 | |
| 16788 | ensure_complete_type(ira->codegen, var->value->type); | |
| 16789 | if (type_is_invalid(var->value->type)) | |
| 16791 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | |
| 16790 | 16792 | return ira->codegen->builtin_types.entry_invalid; |
| 16791 | 16793 | assert(var->value->type->id == TypeTableEntryIdMetaType); |
| 16792 | 16794 | return var->value->data.x_type; |
| ... | ... | @@ -16794,9 +16796,9 @@ static TypeTableEntry *ir_type_info_get_type(IrAnalyze *ira, const char *type_na |
| 16794 | 16796 | |
| 16795 | 16797 | static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) |
| 16796 | 16798 | { |
| 16799 | Error err; | |
| 16797 | 16800 | TypeTableEntry *type_info_definition_type = ir_type_info_get_type(ira, "Definition"); |
| 16798 | ensure_complete_type(ira->codegen, type_info_definition_type); | |
| 16799 | if (type_is_invalid(type_info_definition_type)) | |
| 16801 | if ((err = ensure_complete_type(ira->codegen, type_info_definition_type))) | |
| 16800 | 16802 | return false; |
| 16801 | 16803 | |
| 16802 | 16804 | ensure_field_index(type_info_definition_type, "name", 0); |
| ... | ... | @@ -16804,18 +16806,15 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 16804 | 16806 | ensure_field_index(type_info_definition_type, "data", 2); |
| 16805 | 16807 | |
| 16806 | 16808 | TypeTableEntry *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type); |
| 16807 | ensure_complete_type(ira->codegen, type_info_definition_data_type); | |
| 16808 | if (type_is_invalid(type_info_definition_data_type)) | |
| 16809 | if ((err = ensure_complete_type(ira->codegen, type_info_definition_data_type))) | |
| 16809 | 16810 | return false; |
| 16810 | 16811 | |
| 16811 | 16812 | TypeTableEntry *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type); |
| 16812 | ensure_complete_type(ira->codegen, type_info_fn_def_type); | |
| 16813 | if (type_is_invalid(type_info_fn_def_type)) | |
| 16813 | if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_type))) | |
| 16814 | 16814 | return false; |
| 16815 | 16815 | |
| 16816 | 16816 | TypeTableEntry *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type); |
| 16817 | ensure_complete_type(ira->codegen, type_info_fn_def_inline_type); | |
| 16818 | if (type_is_invalid(type_info_fn_def_inline_type)) | |
| 16817 | if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_inline_type))) | |
| 16819 | 16818 | return false; |
| 16820 | 16819 | |
| 16821 | 16820 | // Loop through our definitions once to figure out how many definitions we will generate info for. |
| ... | ... | @@ -16895,8 +16894,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 16895 | 16894 | case TldIdVar: |
| 16896 | 16895 | { |
| 16897 | 16896 | VariableTableEntry *var = ((TldVar *)curr_entry->value)->var; |
| 16898 | ensure_complete_type(ira->codegen, var->value->type); | |
| 16899 | if (type_is_invalid(var->value->type)) | |
| 16897 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | |
| 16900 | 16898 | return false; |
| 16901 | 16899 | |
| 16902 | 16900 | if (var->value->type->id == TypeTableEntryIdMetaType) |
| ... | ... | @@ -17027,8 +17025,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 17027 | 17025 | case TldIdContainer: |
| 17028 | 17026 | { |
| 17029 | 17027 | TypeTableEntry *type_entry = ((TldContainer *)curr_entry->value)->type_entry; |
| 17030 | ensure_complete_type(ira->codegen, type_entry); | |
| 17031 | if (type_is_invalid(type_entry)) | |
| 17028 | if ((err = ensure_complete_type(ira->codegen, type_entry))) | |
| 17032 | 17029 | return false; |
| 17033 | 17030 | |
| 17034 | 17031 | // This is a type. |
| ... | ... | @@ -17055,11 +17052,11 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 17055 | 17052 | } |
| 17056 | 17053 | |
| 17057 | 17054 | static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { |
| 17055 | Error err; | |
| 17058 | 17056 | assert(type_entry != nullptr); |
| 17059 | 17057 | assert(!type_is_invalid(type_entry)); |
| 17060 | 17058 | |
| 17061 | ensure_complete_type(ira->codegen, type_entry); | |
| 17062 | if (type_is_invalid(type_entry)) | |
| 17059 | if ((err = ensure_complete_type(ira->codegen, type_entry))) | |
| 17063 | 17060 | return nullptr; |
| 17064 | 17061 | |
| 17065 | 17062 | const auto make_enum_field_val = [ira](ConstExprValue *enum_field_val, TypeEnumField *enum_field, |
| ... | ... | @@ -17093,8 +17090,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 17093 | 17090 | } |
| 17094 | 17091 | |
| 17095 | 17092 | TypeTableEntry *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer"); |
| 17096 | ensure_complete_type(ira->codegen, type_info_pointer_type); | |
| 17097 | assert(!type_is_invalid(type_info_pointer_type)); | |
| 17093 | assertNoError(ensure_complete_type(ira->codegen, type_info_pointer_type)); | |
| 17098 | 17094 | |
| 17099 | 17095 | ConstExprValue *result = create_const_vals(1); |
| 17100 | 17096 | result->special = ConstValSpecialStatic; |
| ... | ... | @@ -17106,8 +17102,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 17106 | 17102 | // size: Size |
| 17107 | 17103 | ensure_field_index(result->type, "size", 0); |
| 17108 | 17104 | TypeTableEntry *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type); |
| 17109 | ensure_complete_type(ira->codegen, type_info_pointer_size_type); | |
| 17110 | assert(!type_is_invalid(type_info_pointer_size_type)); | |
| 17105 | assertNoError(ensure_complete_type(ira->codegen, type_info_pointer_size_type)); | |
| 17111 | 17106 | fields[0].special = ConstValSpecialStatic; |
| 17112 | 17107 | fields[0].type = type_info_pointer_size_type; |
| 17113 | 17108 | bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); |
| ... | ... | @@ -18896,13 +18891,13 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 18896 | 18891 | } |
| 18897 | 18892 | |
| 18898 | 18893 | static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) { |
| 18894 | Error err; | |
| 18899 | 18895 | IrInstruction *container = instruction->container->other; |
| 18900 | 18896 | if (type_is_invalid(container->value.type)) |
| 18901 | 18897 | return ira->codegen->builtin_types.entry_invalid; |
| 18902 | 18898 | TypeTableEntry *container_type = ir_resolve_type(ira, container); |
| 18903 | 18899 | |
| 18904 | ensure_complete_type(ira->codegen, container_type); | |
| 18905 | if (type_is_invalid(container_type)) | |
| 18900 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 18906 | 18901 | return ira->codegen->builtin_types.entry_invalid; |
| 18907 | 18902 | |
| 18908 | 18903 | uint64_t result; |
| ... | ... | @@ -18934,13 +18929,13 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns |
| 18934 | 18929 | } |
| 18935 | 18930 | |
| 18936 | 18931 | static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) { |
| 18932 | Error err; | |
| 18937 | 18933 | IrInstruction *container_type_value = instruction->container_type->other; |
| 18938 | 18934 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); |
| 18939 | 18935 | if (type_is_invalid(container_type)) |
| 18940 | 18936 | return ira->codegen->builtin_types.entry_invalid; |
| 18941 | 18937 | |
| 18942 | ensure_complete_type(ira->codegen, container_type); | |
| 18943 | if (type_is_invalid(container_type)) | |
| 18938 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 18944 | 18939 | return ira->codegen->builtin_types.entry_invalid; |
| 18945 | 18940 | |
| 18946 | 18941 | |
| ... | ... | @@ -18981,13 +18976,13 @@ static TypeTableEntry *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInst |
| 18981 | 18976 | } |
| 18982 | 18977 | |
| 18983 | 18978 | static TypeTableEntry *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) { |
| 18979 | Error err; | |
| 18984 | 18980 | IrInstruction *container_type_value = instruction->container_type->other; |
| 18985 | 18981 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); |
| 18986 | 18982 | if (type_is_invalid(container_type)) |
| 18987 | 18983 | return ira->codegen->builtin_types.entry_invalid; |
| 18988 | 18984 | |
| 18989 | ensure_complete_type(ira->codegen, container_type); | |
| 18990 | if (type_is_invalid(container_type)) | |
| 18985 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 18991 | 18986 | return ira->codegen->builtin_types.entry_invalid; |
| 18992 | 18987 | |
| 18993 | 18988 | uint64_t member_index; |
| ... | ... | @@ -19068,13 +19063,13 @@ static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructi |
| 19068 | 19063 | } |
| 19069 | 19064 | |
| 19070 | 19065 | static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { |
| 19066 | Error err; | |
| 19071 | 19067 | IrInstruction *type_value = instruction->type_value->other; |
| 19072 | 19068 | if (type_is_invalid(type_value->value.type)) |
| 19073 | 19069 | return ira->codegen->builtin_types.entry_invalid; |
| 19074 | 19070 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| 19075 | 19071 | |
| 19076 | type_ensure_zero_bits_known(ira->codegen, type_entry); | |
| 19077 | if (type_is_invalid(type_entry)) | |
| 19072 | if ((err = type_ensure_zero_bits_known(ira->codegen, type_entry))) | |
| 19078 | 19073 | return ira->codegen->builtin_types.entry_invalid; |
| 19079 | 19074 | |
| 19080 | 19075 | switch (type_entry->id) { |
| ... | ... | @@ -19930,6 +19925,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 19930 | 19925 | } |
| 19931 | 19926 | |
| 19932 | 19927 | static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { |
| 19928 | Error err; | |
| 19933 | 19929 | IrInstruction *dest_type_value = instruction->dest_type->other; |
| 19934 | 19930 | TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value); |
| 19935 | 19931 | if (type_is_invalid(dest_type)) |
| ... | ... | @@ -19940,12 +19936,10 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc |
| 19940 | 19936 | if (type_is_invalid(src_type)) |
| 19941 | 19937 | return ira->codegen->builtin_types.entry_invalid; |
| 19942 | 19938 | |
| 19943 | ensure_complete_type(ira->codegen, dest_type); | |
| 19944 | if (type_is_invalid(dest_type)) | |
| 19939 | if ((err = ensure_complete_type(ira->codegen, dest_type))) | |
| 19945 | 19940 | return ira->codegen->builtin_types.entry_invalid; |
| 19946 | 19941 | |
| 19947 | ensure_complete_type(ira->codegen, src_type); | |
| 19948 | if (type_is_invalid(src_type)) | |
| 19942 | if ((err = ensure_complete_type(ira->codegen, src_type))) | |
| 19949 | 19943 | return ira->codegen->builtin_types.entry_invalid; |
| 19950 | 19944 | |
| 19951 | 19945 | if (get_codegen_ptr_type(src_type) != nullptr) { |
| ... | ... | @@ -20031,6 +20025,7 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc |
| 20031 | 20025 | } |
| 20032 | 20026 | |
| 20033 | 20027 | static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { |
| 20028 | Error err; | |
| 20034 | 20029 | IrInstruction *dest_type_value = instruction->dest_type->other; |
| 20035 | 20030 | TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value); |
| 20036 | 20031 | if (type_is_invalid(dest_type)) |
| ... | ... | @@ -20041,7 +20036,8 @@ static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstr |
| 20041 | 20036 | return ira->codegen->builtin_types.entry_invalid; |
| 20042 | 20037 | } |
| 20043 | 20038 | |
| 20044 | type_ensure_zero_bits_known(ira->codegen, dest_type); | |
| 20039 | if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) | |
| 20040 | return ira->codegen->builtin_types.entry_invalid; | |
| 20045 | 20041 | if (!type_has_bits(dest_type)) { |
| 20046 | 20042 | ir_add_error(ira, dest_type_value, |
| 20047 | 20043 | buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); |
| ... | ... | @@ -20174,6 +20170,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr |
| 20174 | 20170 | } |
| 20175 | 20171 | |
| 20176 | 20172 | static TypeTableEntry *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) { |
| 20173 | Error err; | |
| 20177 | 20174 | TypeTableEntry *child_type = ir_resolve_type(ira, instruction->child_type->other); |
| 20178 | 20175 | if (type_is_invalid(child_type)) |
| 20179 | 20176 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -20191,8 +20188,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruc |
| 20191 | 20188 | if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes)) |
| 20192 | 20189 | return ira->codegen->builtin_types.entry_invalid; |
| 20193 | 20190 | } else { |
| 20194 | type_ensure_zero_bits_known(ira->codegen, child_type); | |
| 20195 | if (type_is_invalid(child_type)) | |
| 20191 | if ((err = type_ensure_zero_bits_known(ira->codegen, child_type))) | |
| 20196 | 20192 | return ira->codegen->builtin_types.entry_invalid; |
| 20197 | 20193 | align_bytes = get_abi_alignment(ira->codegen, child_type); |
| 20198 | 20194 | } |
| ... | ... | @@ -20312,22 +20308,21 @@ static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruc |
| 20312 | 20308 | } |
| 20313 | 20309 | |
| 20314 | 20310 | static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstructionTagType *instruction) { |
| 20311 | Error err; | |
| 20315 | 20312 | IrInstruction *target_inst = instruction->target->other; |
| 20316 | 20313 | TypeTableEntry *enum_type = ir_resolve_type(ira, target_inst); |
| 20317 | 20314 | if (type_is_invalid(enum_type)) |
| 20318 | 20315 | return ira->codegen->builtin_types.entry_invalid; |
| 20319 | 20316 | |
| 20320 | 20317 | if (enum_type->id == TypeTableEntryIdEnum) { |
| 20321 | ensure_complete_type(ira->codegen, enum_type); | |
| 20322 | if (type_is_invalid(enum_type)) | |
| 20318 | if ((err = ensure_complete_type(ira->codegen, enum_type))) | |
| 20323 | 20319 | return ira->codegen->builtin_types.entry_invalid; |
| 20324 | 20320 | |
| 20325 | 20321 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 20326 | 20322 | out_val->data.x_type = enum_type->data.enumeration.tag_int_type; |
| 20327 | 20323 | return ira->codegen->builtin_types.entry_type; |
| 20328 | 20324 | } else if (enum_type->id == TypeTableEntryIdUnion) { |
| 20329 | ensure_complete_type(ira->codegen, enum_type); | |
| 20330 | if (type_is_invalid(enum_type)) | |
| 20325 | if ((err = ensure_complete_type(ira->codegen, enum_type))) | |
| 20331 | 20326 | return ira->codegen->builtin_types.entry_invalid; |
| 20332 | 20327 | |
| 20333 | 20328 | AstNode *decl_node = enum_type->data.unionation.decl_node; |
| ... | ... | @@ -20830,6 +20825,7 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction |
| 20830 | 20825 | } |
| 20831 | 20826 | |
| 20832 | 20827 | static TypeTableEntry *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { |
| 20828 | Error err; | |
| 20833 | 20829 | IrInstruction *target = instruction->target->other; |
| 20834 | 20830 | if (type_is_invalid(target->value.type)) |
| 20835 | 20831 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -20840,8 +20836,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInst |
| 20840 | 20836 | return ira->codegen->builtin_types.entry_invalid; |
| 20841 | 20837 | } |
| 20842 | 20838 | |
| 20843 | type_ensure_zero_bits_known(ira->codegen, target->value.type); | |
| 20844 | if (type_is_invalid(target->value.type)) | |
| 20839 | if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type))) | |
| 20845 | 20840 | return ira->codegen->builtin_types.entry_invalid; |
| 20846 | 20841 | |
| 20847 | 20842 | TypeTableEntry *tag_type = target->value.type->data.enumeration.tag_int_type; |
| ... | ... | @@ -20852,6 +20847,7 @@ static TypeTableEntry *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInst |
| 20852 | 20847 | } |
| 20853 | 20848 | |
| 20854 | 20849 | static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) { |
| 20850 | Error err; | |
| 20855 | 20851 | IrInstruction *dest_type_value = instruction->dest_type->other; |
| 20856 | 20852 | TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value); |
| 20857 | 20853 | if (type_is_invalid(dest_type)) |
| ... | ... | @@ -20863,8 +20859,7 @@ static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInst |
| 20863 | 20859 | return ira->codegen->builtin_types.entry_invalid; |
| 20864 | 20860 | } |
| 20865 | 20861 | |
| 20866 | type_ensure_zero_bits_known(ira->codegen, dest_type); | |
| 20867 | if (type_is_invalid(dest_type)) | |
| 20862 | if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) | |
| 20868 | 20863 | return ira->codegen->builtin_types.entry_invalid; |
| 20869 | 20864 | |
| 20870 | 20865 | TypeTableEntry *tag_type = dest_type->data.enumeration.tag_int_type; |
src/result.hpp created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | /* | |
| 2 | * Copyright (c) 2018 Andrew Kelley | |
| 3 | * | |
| 4 | * This file is part of zig, which is MIT licensed. | |
| 5 | * See http://opensource.org/licenses/MIT | |
| 6 | */ | |
| 7 | ||
| 8 | #ifndef ZIG_RESULT_HPP | |
| 9 | #define ZIG_RESULT_HPP | |
| 10 | ||
| 11 | #include "error.hpp" | |
| 12 | ||
| 13 | #include <assert.h> | |
| 14 | ||
| 15 | static inline void assertNoError(Error err) { | |
| 16 | assert(err == ErrorNone); | |
| 17 | } | |
| 18 | ||
| 19 | template<typename T> | |
| 20 | struct Result { | |
| 21 | T data; | |
| 22 | Error err; | |
| 23 | ||
| 24 | Result(T x) : data(x), err(ErrorNone) {} | |
| 25 | ||
| 26 | Result(Error err) : err(err) { | |
| 27 | assert(err != ErrorNone); | |
| 28 | } | |
| 29 | ||
| 30 | T unwrap() { | |
| 31 | assert(err == ErrorNone); | |
| 32 | return data; | |
| 33 | } | |
| 34 | }; | |
| 35 | ||
| 36 | #endif |
src/util.hpp+2| ... | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | #define ATTRIBUTE_PRINTF(a, b) |
| 22 | 22 | #define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) |
| 23 | 23 | #define ATTRIBUTE_NORETURN __declspec(noreturn) |
| 24 | #define ATTRIBUTE_MUST_USE | |
| 24 | 25 | |
| 25 | 26 | #else |
| 26 | 27 | |
| ... | ... | @@ -28,6 +29,7 @@ |
| 28 | 29 | #define ATTRIBUTE_PRINTF(a, b) __attribute__((format(printf, a, b))) |
| 29 | 30 | #define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) |
| 30 | 31 | #define ATTRIBUTE_NORETURN __attribute__((noreturn)) |
| 32 | #define ATTRIBUTE_MUST_USE __attribute__((warn_unused_result)) | |
| 31 | 33 | |
| 32 | 34 | #endif |
| 33 | 35 |
std/c/darwin.zig+5-347| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | const macho = @import("../macho.zig"); | |
| 2 | ||
| 1 | 3 | extern "c" fn __error() *c_int; |
| 2 | 4 | pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; |
| 3 | 5 | pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header; |
| ... | ... | @@ -40,6 +42,9 @@ pub extern "c" fn socket(domain: c_int, type: c_int, protocol: c_int) c_int; |
| 40 | 42 | /// absolute as the header is not part of any section. |
| 41 | 43 | pub extern "c" var _mh_execute_header: if (@sizeOf(usize) == 8) mach_header_64 else mach_header; |
| 42 | 44 | |
| 45 | pub const mach_header_64 = macho.mach_header_64; | |
| 46 | pub const mach_header = macho.mach_header; | |
| 47 | ||
| 43 | 48 | pub use @import("../os/darwin/errno.zig"); |
| 44 | 49 | |
| 45 | 50 | pub const _errno = __error; |
| ... | ... | @@ -146,353 +151,6 @@ pub const Kevent = extern struct { |
| 146 | 151 | udata: usize, |
| 147 | 152 | }; |
| 148 | 153 | |
| 149 | pub const mach_header = extern struct { | |
| 150 | magic: u32, | |
| 151 | cputype: cpu_type_t, | |
| 152 | cpusubtype: cpu_subtype_t, | |
| 153 | filetype: u32, | |
| 154 | ncmds: u32, | |
| 155 | sizeofcmds: u32, | |
| 156 | flags: u32, | |
| 157 | }; | |
| 158 | ||
| 159 | pub const mach_header_64 = extern struct { | |
| 160 | magic: u32, | |
| 161 | cputype: cpu_type_t, | |
| 162 | cpusubtype: cpu_subtype_t, | |
| 163 | filetype: u32, | |
| 164 | ncmds: u32, | |
| 165 | sizeofcmds: u32, | |
| 166 | flags: u32, | |
| 167 | reserved: u32, | |
| 168 | }; | |
| 169 | ||
| 170 | pub const load_command = extern struct { | |
| 171 | cmd: u32, | |
| 172 | cmdsize: u32, | |
| 173 | }; | |
| 174 | ||
| 175 | ||
| 176 | /// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD | |
| 177 | /// "stab" style symbol table information as described in the header files | |
| 178 | /// <nlist.h> and <stab.h>. | |
| 179 | pub const symtab_command = extern struct { | |
| 180 | cmd: u32, /// LC_SYMTAB | |
| 181 | cmdsize: u32, /// sizeof(struct symtab_command) | |
| 182 | symoff: u32, /// symbol table offset | |
| 183 | nsyms: u32, /// number of symbol table entries | |
| 184 | stroff: u32, /// string table offset | |
| 185 | strsize: u32, /// string table size in bytes | |
| 186 | }; | |
| 187 | ||
| 188 | /// The linkedit_data_command contains the offsets and sizes of a blob | |
| 189 | /// of data in the __LINKEDIT segment. | |
| 190 | const linkedit_data_command = extern struct { | |
| 191 | cmd: u32,/// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS or LC_LINKER_OPTIMIZATION_HINT. | |
| 192 | cmdsize: u32, /// sizeof(struct linkedit_data_command) | |
| 193 | dataoff: u32 , /// file offset of data in __LINKEDIT segment | |
| 194 | datasize: u32 , /// file size of data in __LINKEDIT segment | |
| 195 | }; | |
| 196 | ||
| 197 | /// The segment load command indicates that a part of this file is to be | |
| 198 | /// mapped into the task's address space. The size of this segment in memory, | |
| 199 | /// vmsize, maybe equal to or larger than the amount to map from this file, | |
| 200 | /// filesize. The file is mapped starting at fileoff to the beginning of | |
| 201 | /// the segment in memory, vmaddr. The rest of the memory of the segment, | |
| 202 | /// if any, is allocated zero fill on demand. The segment's maximum virtual | |
| 203 | /// memory protection and initial virtual memory protection are specified | |
| 204 | /// by the maxprot and initprot fields. If the segment has sections then the | |
| 205 | /// section structures directly follow the segment command and their size is | |
| 206 | /// reflected in cmdsize. | |
| 207 | pub const segment_command = extern struct { | |
| 208 | cmd: u32,/// LC_SEGMENT | |
| 209 | cmdsize: u32,/// includes sizeof section structs | |
| 210 | segname: [16]u8,/// segment name | |
| 211 | vmaddr: u32,/// memory address of this segment | |
| 212 | vmsize: u32,/// memory size of this segment | |
| 213 | fileoff: u32,/// file offset of this segment | |
| 214 | filesize: u32,/// amount to map from the file | |
| 215 | maxprot: vm_prot_t,/// maximum VM protection | |
| 216 | initprot: vm_prot_t,/// initial VM protection | |
| 217 | nsects: u32,/// number of sections in segment | |
| 218 | flags: u32, | |
| 219 | }; | |
| 220 | ||
| 221 | /// The 64-bit segment load command indicates that a part of this file is to be | |
| 222 | /// mapped into a 64-bit task's address space. If the 64-bit segment has | |
| 223 | /// sections then section_64 structures directly follow the 64-bit segment | |
| 224 | /// command and their size is reflected in cmdsize. | |
| 225 | pub const segment_command_64 = extern struct { | |
| 226 | cmd: u32, /// LC_SEGMENT_64 | |
| 227 | cmdsize: u32, /// includes sizeof section_64 structs | |
| 228 | segname: [16]u8, /// segment name | |
| 229 | vmaddr: u64, /// memory address of this segment | |
| 230 | vmsize: u64, /// memory size of this segment | |
| 231 | fileoff: u64, /// file offset of this segment | |
| 232 | filesize: u64, /// amount to map from the file | |
| 233 | maxprot: vm_prot_t, /// maximum VM protection | |
| 234 | initprot: vm_prot_t, /// initial VM protection | |
| 235 | nsects: u32, /// number of sections in segment | |
| 236 | flags: u32, | |
| 237 | }; | |
| 238 | ||
| 239 | /// A segment is made up of zero or more sections. Non-MH_OBJECT files have | |
| 240 | /// all of their segments with the proper sections in each, and padded to the | |
| 241 | /// specified segment alignment when produced by the link editor. The first | |
| 242 | /// segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header | |
| 243 | /// and load commands of the object file before its first section. The zero | |
| 244 | /// fill sections are always last in their segment (in all formats). This | |
| 245 | /// allows the zeroed segment padding to be mapped into memory where zero fill | |
| 246 | /// sections might be. The gigabyte zero fill sections, those with the section | |
| 247 | /// type S_GB_ZEROFILL, can only be in a segment with sections of this type. | |
| 248 | /// These segments are then placed after all other segments. | |
| 249 | /// | |
| 250 | /// The MH_OBJECT format has all of its sections in one segment for | |
| 251 | /// compactness. There is no padding to a specified segment boundary and the | |
| 252 | /// mach_header and load commands are not part of the segment. | |
| 253 | /// | |
| 254 | /// Sections with the same section name, sectname, going into the same segment, | |
| 255 | /// segname, are combined by the link editor. The resulting section is aligned | |
| 256 | /// to the maximum alignment of the combined sections and is the new section's | |
| 257 | /// alignment. The combined sections are aligned to their original alignment in | |
| 258 | /// the combined section. Any padded bytes to get the specified alignment are | |
| 259 | /// zeroed. | |
| 260 | /// | |
| 261 | /// The format of the relocation entries referenced by the reloff and nreloc | |
| 262 | /// fields of the section structure for mach object files is described in the | |
| 263 | /// header file <reloc.h>. | |
| 264 | pub const @"section" = extern struct { | |
| 265 | sectname: [16]u8, /// name of this section | |
| 266 | segname: [16]u8, /// segment this section goes in | |
| 267 | addr: u32, /// memory address of this section | |
| 268 | size: u32, /// size in bytes of this section | |
| 269 | offset: u32, /// file offset of this section | |
| 270 | @"align": u32, /// section alignment (power of 2) | |
| 271 | reloff: u32, /// file offset of relocation entries | |
| 272 | nreloc: u32, /// number of relocation entries | |
| 273 | flags: u32, /// flags (section type and attributes | |
| 274 | reserved1: u32, /// reserved (for offset or index) | |
| 275 | reserved2: u32, /// reserved (for count or sizeof) | |
| 276 | }; | |
| 277 | ||
| 278 | pub const section_64 = extern struct { | |
| 279 | sectname: [16]u8, /// name of this section | |
| 280 | segname: [16]u8, /// segment this section goes in | |
| 281 | addr: u64, /// memory address of this section | |
| 282 | size: u64, /// size in bytes of this section | |
| 283 | offset: u32, /// file offset of this section | |
| 284 | @"align": u32, /// section alignment (power of 2) | |
| 285 | reloff: u32, /// file offset of relocation entries | |
| 286 | nreloc: u32, /// number of relocation entries | |
| 287 | flags: u32, /// flags (section type and attributes | |
| 288 | reserved1: u32, /// reserved (for offset or index) | |
| 289 | reserved2: u32, /// reserved (for count or sizeof) | |
| 290 | reserved3: u32, /// reserved | |
| 291 | }; | |
| 292 | ||
| 293 | pub const nlist = extern struct { | |
| 294 | n_strx: u32, | |
| 295 | n_type: u8, | |
| 296 | n_sect: u8, | |
| 297 | n_desc: i16, | |
| 298 | n_value: u32, | |
| 299 | }; | |
| 300 | ||
| 301 | pub const nlist_64 = extern struct { | |
| 302 | n_strx: u32, | |
| 303 | n_type: u8, | |
| 304 | n_sect: u8, | |
| 305 | n_desc: u16, | |
| 306 | n_value: u64, | |
| 307 | }; | |
| 308 | ||
| 309 | /// After MacOS X 10.1 when a new load command is added that is required to be | |
| 310 | /// understood by the dynamic linker for the image to execute properly the | |
| 311 | /// LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic | |
| 312 | /// linker sees such a load command it it does not understand will issue a | |
| 313 | /// "unknown load command required for execution" error and refuse to use the | |
| 314 | /// image. Other load commands without this bit that are not understood will | |
| 315 | /// simply be ignored. | |
| 316 | pub const LC_REQ_DYLD = 0x80000000; | |
| 317 | ||
| 318 | pub const LC_SEGMENT = 0x1; /// segment of this file to be mapped | |
| 319 | pub const LC_SYMTAB = 0x2; /// link-edit stab symbol table info | |
| 320 | pub const LC_SYMSEG = 0x3; /// link-edit gdb symbol table info (obsolete) | |
| 321 | pub const LC_THREAD = 0x4; /// thread | |
| 322 | pub const LC_UNIXTHREAD = 0x5; /// unix thread (includes a stack) | |
| 323 | pub const LC_LOADFVMLIB = 0x6; /// load a specified fixed VM shared library | |
| 324 | pub const LC_IDFVMLIB = 0x7; /// fixed VM shared library identification | |
| 325 | pub const LC_IDENT = 0x8; /// object identification info (obsolete) | |
| 326 | pub const LC_FVMFILE = 0x9; /// fixed VM file inclusion (internal use) | |
| 327 | pub const LC_PREPAGE = 0xa; /// prepage command (internal use) | |
| 328 | pub const LC_DYSYMTAB = 0xb; /// dynamic link-edit symbol table info | |
| 329 | pub const LC_LOAD_DYLIB = 0xc; /// load a dynamically linked shared library | |
| 330 | pub const LC_ID_DYLIB = 0xd; /// dynamically linked shared lib ident | |
| 331 | pub const LC_LOAD_DYLINKER = 0xe; /// load a dynamic linker | |
| 332 | pub const LC_ID_DYLINKER = 0xf; /// dynamic linker identification | |
| 333 | pub const LC_PREBOUND_DYLIB = 0x10; /// modules prebound for a dynamically | |
| 334 | pub const LC_ROUTINES = 0x11; /// image routines | |
| 335 | pub const LC_SUB_FRAMEWORK = 0x12; /// sub framework | |
| 336 | pub const LC_SUB_UMBRELLA = 0x13; /// sub umbrella | |
| 337 | pub const LC_SUB_CLIENT = 0x14; /// sub client | |
| 338 | pub const LC_SUB_LIBRARY = 0x15; /// sub library | |
| 339 | pub const LC_TWOLEVEL_HINTS = 0x16; /// two-level namespace lookup hints | |
| 340 | pub const LC_PREBIND_CKSUM = 0x17; /// prebind checksum | |
| 341 | ||
| 342 | /// load a dynamically linked shared library that is allowed to be missing | |
| 343 | /// (all symbols are weak imported). | |
| 344 | pub const LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD); | |
| 345 | ||
| 346 | pub const LC_SEGMENT_64 = 0x19; /// 64-bit segment of this file to be mapped | |
| 347 | pub const LC_ROUTINES_64 = 0x1a; /// 64-bit image routines | |
| 348 | pub const LC_UUID = 0x1b; /// the uuid | |
| 349 | pub const LC_RPATH = (0x1c | LC_REQ_DYLD); /// runpath additions | |
| 350 | pub const LC_CODE_SIGNATURE = 0x1d; /// local of code signature | |
| 351 | pub const LC_SEGMENT_SPLIT_INFO = 0x1e; /// local of info to split segments | |
| 352 | pub const LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD); /// load and re-export dylib | |
| 353 | pub const LC_LAZY_LOAD_DYLIB = 0x20; /// delay load of dylib until first use | |
| 354 | pub const LC_ENCRYPTION_INFO = 0x21; /// encrypted segment information | |
| 355 | pub const LC_DYLD_INFO = 0x22; /// compressed dyld information | |
| 356 | pub const LC_DYLD_INFO_ONLY = (0x22|LC_REQ_DYLD); /// compressed dyld information only | |
| 357 | pub const LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD); /// load upward dylib | |
| 358 | pub const LC_VERSION_MIN_MACOSX = 0x24; /// build for MacOSX min OS version | |
| 359 | pub const LC_VERSION_MIN_IPHONEOS = 0x25; /// build for iPhoneOS min OS version | |
| 360 | pub const LC_FUNCTION_STARTS = 0x26; /// compressed table of function start addresses | |
| 361 | pub const LC_DYLD_ENVIRONMENT = 0x27; /// string for dyld to treat like environment variable | |
| 362 | pub const LC_MAIN = (0x28|LC_REQ_DYLD); /// replacement for LC_UNIXTHREAD | |
| 363 | pub const LC_DATA_IN_CODE = 0x29; /// table of non-instructions in __text | |
| 364 | pub const LC_SOURCE_VERSION = 0x2A; /// source version used to build binary | |
| 365 | pub const LC_DYLIB_CODE_SIGN_DRS = 0x2B; /// Code signing DRs copied from linked dylibs | |
| 366 | pub const LC_ENCRYPTION_INFO_64 = 0x2C; /// 64-bit encrypted segment information | |
| 367 | pub const LC_LINKER_OPTION = 0x2D; /// linker options in MH_OBJECT files | |
| 368 | pub const LC_LINKER_OPTIMIZATION_HINT = 0x2E; /// optimization hints in MH_OBJECT files | |
| 369 | pub const LC_VERSION_MIN_TVOS = 0x2F; /// build for AppleTV min OS version | |
| 370 | pub const LC_VERSION_MIN_WATCHOS = 0x30; /// build for Watch min OS version | |
| 371 | pub const LC_NOTE = 0x31; /// arbitrary data included within a Mach-O file | |
| 372 | pub const LC_BUILD_VERSION = 0x32; /// build for platform min OS version | |
| 373 | ||
| 374 | pub const MH_MAGIC = 0xfeedface; /// the mach magic number | |
| 375 | pub const MH_CIGAM = 0xcefaedfe; /// NXSwapInt(MH_MAGIC) | |
| 376 | ||
| 377 | pub const MH_MAGIC_64 = 0xfeedfacf; /// the 64-bit mach magic number | |
| 378 | pub const MH_CIGAM_64 = 0xcffaedfe; /// NXSwapInt(MH_MAGIC_64) | |
| 379 | ||
| 380 | pub const MH_OBJECT = 0x1; /// relocatable object file | |
| 381 | pub const MH_EXECUTE = 0x2; /// demand paged executable file | |
| 382 | pub const MH_FVMLIB = 0x3; /// fixed VM shared library file | |
| 383 | pub const MH_CORE = 0x4; /// core file | |
| 384 | pub const MH_PRELOAD = 0x5; /// preloaded executable file | |
| 385 | pub const MH_DYLIB = 0x6; /// dynamically bound shared library | |
| 386 | pub const MH_DYLINKER = 0x7; /// dynamic link editor | |
| 387 | pub const MH_BUNDLE = 0x8; /// dynamically bound bundle file | |
| 388 | pub const MH_DYLIB_STUB = 0x9; /// shared library stub for static linking only, no section contents | |
| 389 | pub const MH_DSYM = 0xa; /// companion file with only debug sections | |
| 390 | pub const MH_KEXT_BUNDLE = 0xb; /// x86_64 kexts | |
| 391 | ||
| 392 | // Constants for the flags field of the mach_header | |
| 393 | ||
| 394 | pub const MH_NOUNDEFS = 0x1; /// the object file has no undefined references | |
| 395 | pub const MH_INCRLINK = 0x2; /// the object file is the output of an incremental link against a base file and can't be link edited again | |
| 396 | pub const MH_DYLDLINK = 0x4; /// the object file is input for the dynamic linker and can't be staticly link edited again | |
| 397 | pub const MH_BINDATLOAD = 0x8; /// the object file's undefined references are bound by the dynamic linker when loaded. | |
| 398 | pub const MH_PREBOUND = 0x10; /// the file has its dynamic undefined references prebound. | |
| 399 | pub const MH_SPLIT_SEGS = 0x20; /// the file has its read-only and read-write segments split | |
| 400 | pub const MH_LAZY_INIT = 0x40; /// the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) | |
| 401 | pub const MH_TWOLEVEL = 0x80; /// the image is using two-level name space bindings | |
| 402 | pub const MH_FORCE_FLAT = 0x100; /// the executable is forcing all images to use flat name space bindings | |
| 403 | pub const MH_NOMULTIDEFS = 0x200; /// this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. | |
| 404 | pub const MH_NOFIXPREBINDING = 0x400; /// do not have dyld notify the prebinding agent about this executable | |
| 405 | pub const MH_PREBINDABLE = 0x800; /// the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. | |
| 406 | pub const MH_ALLMODSBOUND = 0x1000; /// indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. | |
| 407 | pub const MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;/// safe to divide up the sections into sub-sections via symbols for dead code stripping | |
| 408 | pub const MH_CANONICAL = 0x4000; /// the binary has been canonicalized via the unprebind operation | |
| 409 | pub const MH_WEAK_DEFINES = 0x8000; /// the final linked image contains external weak symbols | |
| 410 | pub const MH_BINDS_TO_WEAK = 0x10000; /// the final linked image uses weak symbols | |
| 411 | ||
| 412 | pub const MH_ALLOW_STACK_EXECUTION = 0x20000;/// When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes. | |
| 413 | pub const MH_ROOT_SAFE = 0x40000; /// When this bit is set, the binary declares it is safe for use in processes with uid zero | |
| 414 | ||
| 415 | pub const MH_SETUID_SAFE = 0x80000; /// When this bit is set, the binary declares it is safe for use in processes when issetugid() is true | |
| 416 | ||
| 417 | pub const MH_NO_REEXPORTED_DYLIBS = 0x100000; /// When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported | |
| 418 | pub const MH_PIE = 0x200000; /// When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. | |
| 419 | pub const MH_DEAD_STRIPPABLE_DYLIB = 0x400000; /// Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib. | |
| 420 | pub const MH_HAS_TLV_DESCRIPTORS = 0x800000; /// Contains a section of type S_THREAD_LOCAL_VARIABLES | |
| 421 | ||
| 422 | pub const MH_NO_HEAP_EXECUTION = 0x1000000; /// When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes. | |
| 423 | ||
| 424 | pub const MH_APP_EXTENSION_SAFE = 0x02000000; /// The code was linked for use in an application extension. | |
| 425 | ||
| 426 | pub const MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000; /// The external symbols listed in the nlist symbol table do not include all the symbols listed in the dyld info. | |
| 427 | ||
| 428 | ||
| 429 | /// The flags field of a section structure is separated into two parts a section | |
| 430 | /// type and section attributes. The section types are mutually exclusive (it | |
| 431 | /// can only have one type) but the section attributes are not (it may have more | |
| 432 | /// than one attribute). | |
| 433 | /// 256 section types | |
| 434 | pub const SECTION_TYPE = 0x000000ff; | |
| 435 | pub const SECTION_ATTRIBUTES = 0xffffff00; /// 24 section attributes | |
| 436 | ||
| 437 | pub const S_REGULAR = 0x0; /// regular section | |
| 438 | pub const S_ZEROFILL = 0x1; /// zero fill on demand section | |
| 439 | pub const S_CSTRING_LITERALS = 0x2; /// section with only literal C string | |
| 440 | pub const S_4BYTE_LITERALS = 0x3; /// section with only 4 byte literals | |
| 441 | pub const S_8BYTE_LITERALS = 0x4; /// section with only 8 byte literals | |
| 442 | pub const S_LITERAL_POINTERS = 0x5; /// section with only pointers to | |
| 443 | ||
| 444 | ||
| 445 | pub const N_STAB = 0xe0; /// if any of these bits set, a symbolic debugging entry | |
| 446 | pub const N_PEXT = 0x10; /// private external symbol bit | |
| 447 | pub const N_TYPE = 0x0e; /// mask for the type bits | |
| 448 | pub const N_EXT = 0x01; /// external symbol bit, set for external symbols | |
| 449 | ||
| 450 | ||
| 451 | pub const N_GSYM = 0x20; /// global symbol: name,,NO_SECT,type,0 | |
| 452 | pub const N_FNAME = 0x22; /// procedure name (f77 kludge): name,,NO_SECT,0,0 | |
| 453 | pub const N_FUN = 0x24; /// procedure: name,,n_sect,linenumber,address | |
| 454 | pub const N_STSYM = 0x26; /// static symbol: name,,n_sect,type,address | |
| 455 | pub const N_LCSYM = 0x28; /// .lcomm symbol: name,,n_sect,type,address | |
| 456 | pub const N_BNSYM = 0x2e; /// begin nsect sym: 0,,n_sect,0,address | |
| 457 | pub const N_AST = 0x32; /// AST file path: name,,NO_SECT,0,0 | |
| 458 | pub const N_OPT = 0x3c; /// emitted with gcc2_compiled and in gcc source | |
| 459 | pub const N_RSYM = 0x40; /// register sym: name,,NO_SECT,type,register | |
| 460 | pub const N_SLINE = 0x44; /// src line: 0,,n_sect,linenumber,address | |
| 461 | pub const N_ENSYM = 0x4e; /// end nsect sym: 0,,n_sect,0,address | |
| 462 | pub const N_SSYM = 0x60; /// structure elt: name,,NO_SECT,type,struct_offset | |
| 463 | pub const N_SO = 0x64; /// source file name: name,,n_sect,0,address | |
| 464 | pub const N_OSO = 0x66; /// object file name: name,,0,0,st_mtime | |
| 465 | pub const N_LSYM = 0x80; /// local sym: name,,NO_SECT,type,offset | |
| 466 | pub const N_BINCL = 0x82; /// include file beginning: name,,NO_SECT,0,sum | |
| 467 | pub const N_SOL = 0x84; /// #included file name: name,,n_sect,0,address | |
| 468 | pub const N_PARAMS = 0x86; /// compiler parameters: name,,NO_SECT,0,0 | |
| 469 | pub const N_VERSION = 0x88; /// compiler version: name,,NO_SECT,0,0 | |
| 470 | pub const N_OLEVEL = 0x8A; /// compiler -O level: name,,NO_SECT,0,0 | |
| 471 | pub const N_PSYM = 0xa0; /// parameter: name,,NO_SECT,type,offset | |
| 472 | pub const N_EINCL = 0xa2; /// include file end: name,,NO_SECT,0,0 | |
| 473 | pub const N_ENTRY = 0xa4; /// alternate entry: name,,n_sect,linenumber,address | |
| 474 | pub const N_LBRAC = 0xc0; /// left bracket: 0,,NO_SECT,nesting level,address | |
| 475 | pub const N_EXCL = 0xc2; /// deleted include file: name,,NO_SECT,0,sum | |
| 476 | pub const N_RBRAC = 0xe0; /// right bracket: 0,,NO_SECT,nesting level,address | |
| 477 | pub const N_BCOMM = 0xe2; /// begin common: name,,NO_SECT,0,0 | |
| 478 | pub const N_ECOMM = 0xe4; /// end common: name,,n_sect,0,0 | |
| 479 | pub const N_ECOML = 0xe8; /// end common (local name): 0,,n_sect,0,address | |
| 480 | pub const N_LENG = 0xfe; /// second stab entry with length information | |
| 481 | ||
| 482 | /// If a segment contains any sections marked with S_ATTR_DEBUG then all | |
| 483 | /// sections in that segment must have this attribute. No section other than | |
| 484 | /// a section marked with this attribute may reference the contents of this | |
| 485 | /// section. A section with this attribute may contain no symbols and must have | |
| 486 | /// a section type S_REGULAR. The static linker will not copy section contents | |
| 487 | /// from sections with this attribute into its output file. These sections | |
| 488 | /// generally contain DWARF debugging info. | |
| 489 | pub const S_ATTR_DEBUG = 0x02000000; /// a debug section | |
| 490 | ||
| 491 | pub const cpu_type_t = integer_t; | |
| 492 | pub const cpu_subtype_t = integer_t; | |
| 493 | pub const integer_t = c_int; | |
| 494 | pub const vm_prot_t = c_int; | |
| 495 | ||
| 496 | 154 | // sys/types.h on macos uses #pragma pack(4) so these checks are |
| 497 | 155 | // to make sure the struct is laid out the same. These values were |
| 498 | 156 | // produced from C code using the offsetof macro. |
std/c/linux.zig+3| ... | ... | @@ -8,3 +8,6 @@ pub const pthread_attr_t = extern struct { |
| 8 | 8 | __size: [56]u8, |
| 9 | 9 | __align: c_long, |
| 10 | 10 | }; |
| 11 | ||
| 12 | /// See std.elf for constants for this | |
| 13 | pub extern fn getauxval(__type: c_ulong) c_ulong; |
std/debug/index.zig+85-58| ... | ... | @@ -4,6 +4,7 @@ const mem = std.mem; |
| 4 | 4 | const io = std.io; |
| 5 | 5 | const os = std.os; |
| 6 | 6 | const elf = std.elf; |
| 7 | const macho = std.macho; | |
| 7 | 8 | const DW = std.dwarf; |
| 8 | 9 | const ArrayList = std.ArrayList; |
| 9 | 10 | const builtin = @import("builtin"); |
| ... | ... | @@ -369,33 +370,7 @@ pub const OpenSelfDebugInfoError = error{ |
| 369 | 370 | |
| 370 | 371 | pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { |
| 371 | 372 | switch (builtin.os) { |
| 372 | builtin.Os.linux => { | |
| 373 | const st = try allocator.create(DebugInfo{ | |
| 374 | .self_exe_file = undefined, | |
| 375 | .elf = undefined, | |
| 376 | .debug_info = undefined, | |
| 377 | .debug_abbrev = undefined, | |
| 378 | .debug_str = undefined, | |
| 379 | .debug_line = undefined, | |
| 380 | .debug_ranges = null, | |
| 381 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | |
| 382 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | |
| 383 | }); | |
| 384 | errdefer allocator.destroy(st); | |
| 385 | st.self_exe_file = try os.openSelfExe(); | |
| 386 | errdefer st.self_exe_file.close(); | |
| 387 | ||
| 388 | try st.elf.openFile(allocator, &st.self_exe_file); | |
| 389 | errdefer st.elf.close(); | |
| 390 | ||
| 391 | st.debug_info = (try st.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; | |
| 392 | st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo; | |
| 393 | st.debug_str = (try st.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo; | |
| 394 | st.debug_line = (try st.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo; | |
| 395 | st.debug_ranges = (try st.elf.findSection(".debug_ranges")); | |
| 396 | try scanAllCompileUnits(st); | |
| 397 | return st; | |
| 398 | }, | |
| 373 | builtin.Os.linux => return openSelfDebugInfoLinux(allocator), | |
| 399 | 374 | builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator), |
| 400 | 375 | builtin.Os.windows => { |
| 401 | 376 | // TODO: https://github.com/ziglang/zig/issues/721 |
| ... | ... | @@ -405,40 +380,91 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { |
| 405 | 380 | } |
| 406 | 381 | } |
| 407 | 382 | |
| 383 | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { | |
| 384 | var di = DebugInfo{ | |
| 385 | .self_exe_file = undefined, | |
| 386 | .elf = undefined, | |
| 387 | .debug_info = undefined, | |
| 388 | .debug_abbrev = undefined, | |
| 389 | .debug_str = undefined, | |
| 390 | .debug_line = undefined, | |
| 391 | .debug_ranges = null, | |
| 392 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | |
| 393 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | |
| 394 | }; | |
| 395 | di.self_exe_file = try os.openSelfExe(); | |
| 396 | errdefer di.self_exe_file.close(); | |
| 397 | ||
| 398 | try di.elf.openFile(allocator, &di.self_exe_file); | |
| 399 | errdefer di.elf.close(); | |
| 400 | ||
| 401 | di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; | |
| 402 | di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo; | |
| 403 | di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo; | |
| 404 | di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo; | |
| 405 | di.debug_ranges = (try di.elf.findSection(".debug_ranges")); | |
| 406 | try scanAllCompileUnits(&di); | |
| 407 | return di; | |
| 408 | } | |
| 409 | ||
| 410 | pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { | |
| 411 | var file_stream = io.FileInStream.init(elf.in_file); | |
| 412 | const in = &file_stream.stream; | |
| 413 | ||
| 414 | section_loop: for (elf.section_headers) |*elf_section| { | |
| 415 | if (elf_section.sh_type == SHT_NULL) continue; | |
| 416 | ||
| 417 | const name_offset = elf.string_section.offset + elf_section.name; | |
| 418 | try elf.in_file.seekTo(name_offset); | |
| 419 | ||
| 420 | for (name) |expected_c| { | |
| 421 | const target_c = try in.readByte(); | |
| 422 | if (target_c == 0 or expected_c != target_c) continue :section_loop; | |
| 423 | } | |
| 424 | ||
| 425 | { | |
| 426 | const null_byte = try in.readByte(); | |
| 427 | if (null_byte == 0) return elf_section; | |
| 428 | } | |
| 429 | } | |
| 430 | ||
| 431 | return null; | |
| 432 | } | |
| 433 | ||
| 408 | 434 | fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 409 | 435 | const hdr = &std.c._mh_execute_header; |
| 410 | assert(hdr.magic == std.c.MH_MAGIC_64); | |
| 436 | assert(hdr.magic == std.macho.MH_MAGIC_64); | |
| 411 | 437 | |
| 412 | 438 | const hdr_base = @ptrCast([*]u8, hdr); |
| 413 | var ptr = hdr_base + @sizeOf(std.c.mach_header_64); | |
| 439 | var ptr = hdr_base + @sizeOf(macho.mach_header_64); | |
| 414 | 440 | var ncmd: u32 = hdr.ncmds; |
| 415 | 441 | const symtab = while (ncmd != 0) : (ncmd -= 1) { |
| 416 | const lc = @ptrCast(*std.c.load_command, ptr); | |
| 442 | const lc = @ptrCast(*std.macho.load_command, ptr); | |
| 417 | 443 | switch (lc.cmd) { |
| 418 | std.c.LC_SYMTAB => break @ptrCast(*std.c.symtab_command, ptr), | |
| 444 | std.macho.LC_SYMTAB => break @ptrCast(*std.macho.symtab_command, ptr), | |
| 419 | 445 | else => {}, |
| 420 | 446 | } |
| 421 | 447 | ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403 |
| 422 | 448 | } else { |
| 423 | 449 | return error.MissingDebugInfo; |
| 424 | 450 | }; |
| 425 | const syms = @ptrCast([*]std.c.nlist_64, hdr_base + symtab.symoff)[0..symtab.nsyms]; | |
| 451 | const syms = @ptrCast([*]macho.nlist_64, hdr_base + symtab.symoff)[0..symtab.nsyms]; | |
| 426 | 452 | const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize]; |
| 427 | 453 | |
| 428 | 454 | const symbols_buf = try allocator.alloc(MachoSymbol, syms.len); |
| 429 | 455 | |
| 430 | var ofile: ?*std.c.nlist_64 = null; | |
| 456 | var ofile: ?*macho.nlist_64 = null; | |
| 431 | 457 | var reloc: u64 = 0; |
| 432 | 458 | var symbol_index: usize = 0; |
| 433 | 459 | var last_len: u64 = 0; |
| 434 | 460 | for (syms) |*sym| { |
| 435 | if (sym.n_type & std.c.N_STAB != 0) { | |
| 461 | if (sym.n_type & std.macho.N_STAB != 0) { | |
| 436 | 462 | switch (sym.n_type) { |
| 437 | std.c.N_OSO => { | |
| 463 | std.macho.N_OSO => { | |
| 438 | 464 | ofile = sym; |
| 439 | 465 | reloc = 0; |
| 440 | 466 | }, |
| 441 | std.c.N_FUN => { | |
| 467 | std.macho.N_FUN => { | |
| 442 | 468 | if (sym.n_sect == 0) { |
| 443 | 469 | last_len = sym.n_value; |
| 444 | 470 | } else { |
| ... | ... | @@ -450,7 +476,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 450 | 476 | symbol_index += 1; |
| 451 | 477 | } |
| 452 | 478 | }, |
| 453 | std.c.N_BNSYM => { | |
| 479 | std.macho.N_BNSYM => { | |
| 454 | 480 | if (reloc == 0) { |
| 455 | 481 | reloc = sym.n_value; |
| 456 | 482 | } |
| ... | ... | @@ -459,8 +485,8 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { |
| 459 | 485 | } |
| 460 | 486 | } |
| 461 | 487 | } |
| 462 | const sentinel = try allocator.createOne(std.c.nlist_64); | |
| 463 | sentinel.* = std.c.nlist_64{ | |
| 488 | const sentinel = try allocator.createOne(macho.nlist_64); | |
| 489 | sentinel.* = macho.nlist_64{ | |
| 464 | 490 | .n_strx = 0, |
| 465 | 491 | .n_type = 36, |
| 466 | 492 | .n_sect = 0, |
| ... | ... | @@ -515,8 +541,8 @@ fn printLineFromFile(out_stream: var, line_info: *const LineInfo) !void { |
| 515 | 541 | } |
| 516 | 542 | |
| 517 | 543 | const MachoSymbol = struct { |
| 518 | nlist: *std.c.nlist_64, | |
| 519 | ofile: ?*std.c.nlist_64, | |
| 544 | nlist: *macho.nlist_64, | |
| 545 | ofile: ?*macho.nlist_64, | |
| 520 | 546 | reloc: u64, |
| 521 | 547 | |
| 522 | 548 | /// Returns the address from the macho file |
| ... | ... | @@ -530,9 +556,9 @@ const MachoSymbol = struct { |
| 530 | 556 | }; |
| 531 | 557 | |
| 532 | 558 | const MachOFile = struct { |
| 533 | bytes: []align(@alignOf(std.c.mach_header_64)) const u8, | |
| 534 | sect_debug_info: ?*const std.c.section_64, | |
| 535 | sect_debug_line: ?*const std.c.section_64, | |
| 559 | bytes: []align(@alignOf(macho.mach_header_64)) const u8, | |
| 560 | sect_debug_info: ?*const macho.section_64, | |
| 561 | sect_debug_line: ?*const macho.section_64, | |
| 536 | 562 | }; |
| 537 | 563 | |
| 538 | 564 | pub const DebugInfo = switch (builtin.os) { |
| ... | ... | @@ -542,10 +568,10 @@ pub const DebugInfo = switch (builtin.os) { |
| 542 | 568 | ofiles: OFileTable, |
| 543 | 569 | |
| 544 | 570 | const OFileTable = std.HashMap( |
| 545 | *std.c.nlist_64, | |
| 571 | *macho.nlist_64, | |
| 546 | 572 | MachOFile, |
| 547 | std.hash_map.getHashPtrAddrFn(*std.c.nlist_64), | |
| 548 | std.hash_map.getTrivialEqlFn(*std.c.nlist_64), | |
| 573 | std.hash_map.getHashPtrAddrFn(*macho.nlist_64), | |
| 574 | std.hash_map.getTrivialEqlFn(*macho.nlist_64), | |
| 549 | 575 | ); |
| 550 | 576 | |
| 551 | 577 | pub fn allocator(self: DebugInfo) *mem.Allocator { |
| ... | ... | @@ -563,7 +589,7 @@ pub const DebugInfo = switch (builtin.os) { |
| 563 | 589 | abbrev_table_list: ArrayList(AbbrevTableHeader), |
| 564 | 590 | compile_unit_list: ArrayList(CompileUnit), |
| 565 | 591 | |
| 566 | pub fn allocator(self: *const DebugInfo) *mem.Allocator { | |
| 592 | pub fn allocator(self: DebugInfo) *mem.Allocator { | |
| 567 | 593 | return self.abbrev_table_list.allocator; |
| 568 | 594 | } |
| 569 | 595 | |
| ... | ... | @@ -983,30 +1009,31 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 983 | 1009 | const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx); |
| 984 | 1010 | |
| 985 | 1011 | gop.kv.value = MachOFile{ |
| 986 | .bytes = try std.io.readFileAllocAligned(di.ofiles.allocator, ofile_path, @alignOf(std.c.mach_header_64)), | |
| 1012 | .bytes = try std.io.readFileAllocAligned(di.ofiles.allocator, ofile_path, @alignOf(macho.mach_header_64)), | |
| 987 | 1013 | .sect_debug_info = null, |
| 988 | 1014 | .sect_debug_line = null, |
| 989 | 1015 | }; |
| 990 | const hdr = @ptrCast(*const std.c.mach_header_64, gop.kv.value.bytes.ptr); | |
| 991 | if (hdr.magic != std.c.MH_MAGIC_64) return error.InvalidDebugInfo; | |
| 1016 | const hdr = @ptrCast(*const macho.mach_header_64, gop.kv.value.bytes.ptr); | |
| 1017 | if (hdr.magic != std.macho.MH_MAGIC_64) return error.InvalidDebugInfo; | |
| 992 | 1018 | |
| 993 | 1019 | const hdr_base = @ptrCast([*]const u8, hdr); |
| 994 | var ptr = hdr_base + @sizeOf(std.c.mach_header_64); | |
| 1020 | var ptr = hdr_base + @sizeOf(macho.mach_header_64); | |
| 995 | 1021 | var ncmd: u32 = hdr.ncmds; |
| 996 | 1022 | const segcmd = while (ncmd != 0) : (ncmd -= 1) { |
| 997 | const lc = @ptrCast(*const std.c.load_command, ptr); | |
| 1023 | const lc = @ptrCast(*const std.macho.load_command, ptr); | |
| 998 | 1024 | switch (lc.cmd) { |
| 999 | std.c.LC_SEGMENT_64 => break @ptrCast(*const std.c.segment_command_64, ptr), | |
| 1025 | std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, ptr), | |
| 1000 | 1026 | else => {}, |
| 1001 | 1027 | } |
| 1002 | 1028 | ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403 |
| 1003 | 1029 | } else { |
| 1004 | 1030 | return error.MissingDebugInfo; |
| 1005 | 1031 | }; |
| 1006 | const sections = @alignCast(@alignOf(std.c.section_64), @ptrCast([*]const std.c.section_64, ptr + @sizeOf(std.c.segment_command_64)))[0..segcmd.nsects]; | |
| 1032 | const sections = @alignCast(@alignOf(macho.section_64), @ptrCast([*]const macho.section_64, ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects]; | |
| 1007 | 1033 | for (sections) |*sect| { |
| 1008 | if (sect.flags & std.c.SECTION_TYPE == std.c.S_REGULAR and | |
| 1009 | (sect.flags & std.c.SECTION_ATTRIBUTES) & std.c.S_ATTR_DEBUG == std.c.S_ATTR_DEBUG) { | |
| 1034 | if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and | |
| 1035 | (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG) | |
| 1036 | { | |
| 1010 | 1037 | const sect_name = mem.toSliceConst(u8, &sect.sectname); |
| 1011 | 1038 | if (mem.eql(u8, sect_name, "__debug_line")) { |
| 1012 | 1039 | gop.kv.value.sect_debug_line = sect; |
| ... | ... | @@ -1052,7 +1079,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1052 | 1079 | |
| 1053 | 1080 | const opcode_base = readByteMem(&ptr); |
| 1054 | 1081 | |
| 1055 | const standard_opcode_lengths = ptr[0..opcode_base - 1]; | |
| 1082 | const standard_opcode_lengths = ptr[0 .. opcode_base - 1]; | |
| 1056 | 1083 | ptr += opcode_base - 1; |
| 1057 | 1084 | |
| 1058 | 1085 | var include_directories = ArrayList([]const u8).init(di.allocator()); |
std/elf.zig+5| ... | ... | @@ -869,6 +869,11 @@ pub const Phdr = switch (@sizeOf(usize)) { |
| 869 | 869 | 8 => Elf64_Phdr, |
| 870 | 870 | else => @compileError("expected pointer size of 32 or 64"), |
| 871 | 871 | }; |
| 872 | pub const Shdr = switch (@sizeOf(usize)) { | |
| 873 | 4 => Elf32_Shdr, | |
| 874 | 8 => Elf64_Shdr, | |
| 875 | else => @compileError("expected pointer size of 32 or 64"), | |
| 876 | }; | |
| 872 | 877 | pub const Sym = switch (@sizeOf(usize)) { |
| 873 | 878 | 4 => Elf32_Sym, |
| 874 | 879 | 8 => Elf64_Sym, |
std/macho.zig created+348| ... | ... | @@ -0,0 +1,348 @@ |
| 1 | ||
| 2 | pub const mach_header = extern struct { | |
| 3 | magic: u32, | |
| 4 | cputype: cpu_type_t, | |
| 5 | cpusubtype: cpu_subtype_t, | |
| 6 | filetype: u32, | |
| 7 | ncmds: u32, | |
| 8 | sizeofcmds: u32, | |
| 9 | flags: u32, | |
| 10 | }; | |
| 11 | ||
| 12 | pub const mach_header_64 = extern struct { | |
| 13 | magic: u32, | |
| 14 | cputype: cpu_type_t, | |
| 15 | cpusubtype: cpu_subtype_t, | |
| 16 | filetype: u32, | |
| 17 | ncmds: u32, | |
| 18 | sizeofcmds: u32, | |
| 19 | flags: u32, | |
| 20 | reserved: u32, | |
| 21 | }; | |
| 22 | ||
| 23 | pub const load_command = extern struct { | |
| 24 | cmd: u32, | |
| 25 | cmdsize: u32, | |
| 26 | }; | |
| 27 | ||
| 28 | ||
| 29 | /// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD | |
| 30 | /// "stab" style symbol table information as described in the header files | |
| 31 | /// <nlist.h> and <stab.h>. | |
| 32 | pub const symtab_command = extern struct { | |
| 33 | cmd: u32, /// LC_SYMTAB | |
| 34 | cmdsize: u32, /// sizeof(struct symtab_command) | |
| 35 | symoff: u32, /// symbol table offset | |
| 36 | nsyms: u32, /// number of symbol table entries | |
| 37 | stroff: u32, /// string table offset | |
| 38 | strsize: u32, /// string table size in bytes | |
| 39 | }; | |
| 40 | ||
| 41 | /// The linkedit_data_command contains the offsets and sizes of a blob | |
| 42 | /// of data in the __LINKEDIT segment. | |
| 43 | const linkedit_data_command = extern struct { | |
| 44 | cmd: u32,/// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS or LC_LINKER_OPTIMIZATION_HINT. | |
| 45 | cmdsize: u32, /// sizeof(struct linkedit_data_command) | |
| 46 | dataoff: u32 , /// file offset of data in __LINKEDIT segment | |
| 47 | datasize: u32 , /// file size of data in __LINKEDIT segment | |
| 48 | }; | |
| 49 | ||
| 50 | /// The segment load command indicates that a part of this file is to be | |
| 51 | /// mapped into the task's address space. The size of this segment in memory, | |
| 52 | /// vmsize, maybe equal to or larger than the amount to map from this file, | |
| 53 | /// filesize. The file is mapped starting at fileoff to the beginning of | |
| 54 | /// the segment in memory, vmaddr. The rest of the memory of the segment, | |
| 55 | /// if any, is allocated zero fill on demand. The segment's maximum virtual | |
| 56 | /// memory protection and initial virtual memory protection are specified | |
| 57 | /// by the maxprot and initprot fields. If the segment has sections then the | |
| 58 | /// section structures directly follow the segment command and their size is | |
| 59 | /// reflected in cmdsize. | |
| 60 | pub const segment_command = extern struct { | |
| 61 | cmd: u32,/// LC_SEGMENT | |
| 62 | cmdsize: u32,/// includes sizeof section structs | |
| 63 | segname: [16]u8,/// segment name | |
| 64 | vmaddr: u32,/// memory address of this segment | |
| 65 | vmsize: u32,/// memory size of this segment | |
| 66 | fileoff: u32,/// file offset of this segment | |
| 67 | filesize: u32,/// amount to map from the file | |
| 68 | maxprot: vm_prot_t,/// maximum VM protection | |
| 69 | initprot: vm_prot_t,/// initial VM protection | |
| 70 | nsects: u32,/// number of sections in segment | |
| 71 | flags: u32, | |
| 72 | }; | |
| 73 | ||
| 74 | /// The 64-bit segment load command indicates that a part of this file is to be | |
| 75 | /// mapped into a 64-bit task's address space. If the 64-bit segment has | |
| 76 | /// sections then section_64 structures directly follow the 64-bit segment | |
| 77 | /// command and their size is reflected in cmdsize. | |
| 78 | pub const segment_command_64 = extern struct { | |
| 79 | cmd: u32, /// LC_SEGMENT_64 | |
| 80 | cmdsize: u32, /// includes sizeof section_64 structs | |
| 81 | segname: [16]u8, /// segment name | |
| 82 | vmaddr: u64, /// memory address of this segment | |
| 83 | vmsize: u64, /// memory size of this segment | |
| 84 | fileoff: u64, /// file offset of this segment | |
| 85 | filesize: u64, /// amount to map from the file | |
| 86 | maxprot: vm_prot_t, /// maximum VM protection | |
| 87 | initprot: vm_prot_t, /// initial VM protection | |
| 88 | nsects: u32, /// number of sections in segment | |
| 89 | flags: u32, | |
| 90 | }; | |
| 91 | ||
| 92 | /// A segment is made up of zero or more sections. Non-MH_OBJECT files have | |
| 93 | /// all of their segments with the proper sections in each, and padded to the | |
| 94 | /// specified segment alignment when produced by the link editor. The first | |
| 95 | /// segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header | |
| 96 | /// and load commands of the object file before its first section. The zero | |
| 97 | /// fill sections are always last in their segment (in all formats). This | |
| 98 | /// allows the zeroed segment padding to be mapped into memory where zero fill | |
| 99 | /// sections might be. The gigabyte zero fill sections, those with the section | |
| 100 | /// type S_GB_ZEROFILL, can only be in a segment with sections of this type. | |
| 101 | /// These segments are then placed after all other segments. | |
| 102 | /// | |
| 103 | /// The MH_OBJECT format has all of its sections in one segment for | |
| 104 | /// compactness. There is no padding to a specified segment boundary and the | |
| 105 | /// mach_header and load commands are not part of the segment. | |
| 106 | /// | |
| 107 | /// Sections with the same section name, sectname, going into the same segment, | |
| 108 | /// segname, are combined by the link editor. The resulting section is aligned | |
| 109 | /// to the maximum alignment of the combined sections and is the new section's | |
| 110 | /// alignment. The combined sections are aligned to their original alignment in | |
| 111 | /// the combined section. Any padded bytes to get the specified alignment are | |
| 112 | /// zeroed. | |
| 113 | /// | |
| 114 | /// The format of the relocation entries referenced by the reloff and nreloc | |
| 115 | /// fields of the section structure for mach object files is described in the | |
| 116 | /// header file <reloc.h>. | |
| 117 | pub const @"section" = extern struct { | |
| 118 | sectname: [16]u8, /// name of this section | |
| 119 | segname: [16]u8, /// segment this section goes in | |
| 120 | addr: u32, /// memory address of this section | |
| 121 | size: u32, /// size in bytes of this section | |
| 122 | offset: u32, /// file offset of this section | |
| 123 | @"align": u32, /// section alignment (power of 2) | |
| 124 | reloff: u32, /// file offset of relocation entries | |
| 125 | nreloc: u32, /// number of relocation entries | |
| 126 | flags: u32, /// flags (section type and attributes | |
| 127 | reserved1: u32, /// reserved (for offset or index) | |
| 128 | reserved2: u32, /// reserved (for count or sizeof) | |
| 129 | }; | |
| 130 | ||
| 131 | pub const section_64 = extern struct { | |
| 132 | sectname: [16]u8, /// name of this section | |
| 133 | segname: [16]u8, /// segment this section goes in | |
| 134 | addr: u64, /// memory address of this section | |
| 135 | size: u64, /// size in bytes of this section | |
| 136 | offset: u32, /// file offset of this section | |
| 137 | @"align": u32, /// section alignment (power of 2) | |
| 138 | reloff: u32, /// file offset of relocation entries | |
| 139 | nreloc: u32, /// number of relocation entries | |
| 140 | flags: u32, /// flags (section type and attributes | |
| 141 | reserved1: u32, /// reserved (for offset or index) | |
| 142 | reserved2: u32, /// reserved (for count or sizeof) | |
| 143 | reserved3: u32, /// reserved | |
| 144 | }; | |
| 145 | ||
| 146 | pub const nlist = extern struct { | |
| 147 | n_strx: u32, | |
| 148 | n_type: u8, | |
| 149 | n_sect: u8, | |
| 150 | n_desc: i16, | |
| 151 | n_value: u32, | |
| 152 | }; | |
| 153 | ||
| 154 | pub const nlist_64 = extern struct { | |
| 155 | n_strx: u32, | |
| 156 | n_type: u8, | |
| 157 | n_sect: u8, | |
| 158 | n_desc: u16, | |
| 159 | n_value: u64, | |
| 160 | }; | |
| 161 | ||
| 162 | /// After MacOS X 10.1 when a new load command is added that is required to be | |
| 163 | /// understood by the dynamic linker for the image to execute properly the | |
| 164 | /// LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic | |
| 165 | /// linker sees such a load command it it does not understand will issue a | |
| 166 | /// "unknown load command required for execution" error and refuse to use the | |
| 167 | /// image. Other load commands without this bit that are not understood will | |
| 168 | /// simply be ignored. | |
| 169 | pub const LC_REQ_DYLD = 0x80000000; | |
| 170 | ||
| 171 | pub const LC_SEGMENT = 0x1; /// segment of this file to be mapped | |
| 172 | pub const LC_SYMTAB = 0x2; /// link-edit stab symbol table info | |
| 173 | pub const LC_SYMSEG = 0x3; /// link-edit gdb symbol table info (obsolete) | |
| 174 | pub const LC_THREAD = 0x4; /// thread | |
| 175 | pub const LC_UNIXTHREAD = 0x5; /// unix thread (includes a stack) | |
| 176 | pub const LC_LOADFVMLIB = 0x6; /// load a specified fixed VM shared library | |
| 177 | pub const LC_IDFVMLIB = 0x7; /// fixed VM shared library identification | |
| 178 | pub const LC_IDENT = 0x8; /// object identification info (obsolete) | |
| 179 | pub const LC_FVMFILE = 0x9; /// fixed VM file inclusion (internal use) | |
| 180 | pub const LC_PREPAGE = 0xa; /// prepage command (internal use) | |
| 181 | pub const LC_DYSYMTAB = 0xb; /// dynamic link-edit symbol table info | |
| 182 | pub const LC_LOAD_DYLIB = 0xc; /// load a dynamically linked shared library | |
| 183 | pub const LC_ID_DYLIB = 0xd; /// dynamically linked shared lib ident | |
| 184 | pub const LC_LOAD_DYLINKER = 0xe; /// load a dynamic linker | |
| 185 | pub const LC_ID_DYLINKER = 0xf; /// dynamic linker identification | |
| 186 | pub const LC_PREBOUND_DYLIB = 0x10; /// modules prebound for a dynamically | |
| 187 | pub const LC_ROUTINES = 0x11; /// image routines | |
| 188 | pub const LC_SUB_FRAMEWORK = 0x12; /// sub framework | |
| 189 | pub const LC_SUB_UMBRELLA = 0x13; /// sub umbrella | |
| 190 | pub const LC_SUB_CLIENT = 0x14; /// sub client | |
| 191 | pub const LC_SUB_LIBRARY = 0x15; /// sub library | |
| 192 | pub const LC_TWOLEVEL_HINTS = 0x16; /// two-level namespace lookup hints | |
| 193 | pub const LC_PREBIND_CKSUM = 0x17; /// prebind checksum | |
| 194 | ||
| 195 | /// load a dynamically linked shared library that is allowed to be missing | |
| 196 | /// (all symbols are weak imported). | |
| 197 | pub const LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD); | |
| 198 | ||
| 199 | pub const LC_SEGMENT_64 = 0x19; /// 64-bit segment of this file to be mapped | |
| 200 | pub const LC_ROUTINES_64 = 0x1a; /// 64-bit image routines | |
| 201 | pub const LC_UUID = 0x1b; /// the uuid | |
| 202 | pub const LC_RPATH = (0x1c | LC_REQ_DYLD); /// runpath additions | |
| 203 | pub const LC_CODE_SIGNATURE = 0x1d; /// local of code signature | |
| 204 | pub const LC_SEGMENT_SPLIT_INFO = 0x1e; /// local of info to split segments | |
| 205 | pub const LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD); /// load and re-export dylib | |
| 206 | pub const LC_LAZY_LOAD_DYLIB = 0x20; /// delay load of dylib until first use | |
| 207 | pub const LC_ENCRYPTION_INFO = 0x21; /// encrypted segment information | |
| 208 | pub const LC_DYLD_INFO = 0x22; /// compressed dyld information | |
| 209 | pub const LC_DYLD_INFO_ONLY = (0x22|LC_REQ_DYLD); /// compressed dyld information only | |
| 210 | pub const LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD); /// load upward dylib | |
| 211 | pub const LC_VERSION_MIN_MACOSX = 0x24; /// build for MacOSX min OS version | |
| 212 | pub const LC_VERSION_MIN_IPHONEOS = 0x25; /// build for iPhoneOS min OS version | |
| 213 | pub const LC_FUNCTION_STARTS = 0x26; /// compressed table of function start addresses | |
| 214 | pub const LC_DYLD_ENVIRONMENT = 0x27; /// string for dyld to treat like environment variable | |
| 215 | pub const LC_MAIN = (0x28|LC_REQ_DYLD); /// replacement for LC_UNIXTHREAD | |
| 216 | pub const LC_DATA_IN_CODE = 0x29; /// table of non-instructions in __text | |
| 217 | pub const LC_SOURCE_VERSION = 0x2A; /// source version used to build binary | |
| 218 | pub const LC_DYLIB_CODE_SIGN_DRS = 0x2B; /// Code signing DRs copied from linked dylibs | |
| 219 | pub const LC_ENCRYPTION_INFO_64 = 0x2C; /// 64-bit encrypted segment information | |
| 220 | pub const LC_LINKER_OPTION = 0x2D; /// linker options in MH_OBJECT files | |
| 221 | pub const LC_LINKER_OPTIMIZATION_HINT = 0x2E; /// optimization hints in MH_OBJECT files | |
| 222 | pub const LC_VERSION_MIN_TVOS = 0x2F; /// build for AppleTV min OS version | |
| 223 | pub const LC_VERSION_MIN_WATCHOS = 0x30; /// build for Watch min OS version | |
| 224 | pub const LC_NOTE = 0x31; /// arbitrary data included within a Mach-O file | |
| 225 | pub const LC_BUILD_VERSION = 0x32; /// build for platform min OS version | |
| 226 | ||
| 227 | pub const MH_MAGIC = 0xfeedface; /// the mach magic number | |
| 228 | pub const MH_CIGAM = 0xcefaedfe; /// NXSwapInt(MH_MAGIC) | |
| 229 | ||
| 230 | pub const MH_MAGIC_64 = 0xfeedfacf; /// the 64-bit mach magic number | |
| 231 | pub const MH_CIGAM_64 = 0xcffaedfe; /// NXSwapInt(MH_MAGIC_64) | |
| 232 | ||
| 233 | pub const MH_OBJECT = 0x1; /// relocatable object file | |
| 234 | pub const MH_EXECUTE = 0x2; /// demand paged executable file | |
| 235 | pub const MH_FVMLIB = 0x3; /// fixed VM shared library file | |
| 236 | pub const MH_CORE = 0x4; /// core file | |
| 237 | pub const MH_PRELOAD = 0x5; /// preloaded executable file | |
| 238 | pub const MH_DYLIB = 0x6; /// dynamically bound shared library | |
| 239 | pub const MH_DYLINKER = 0x7; /// dynamic link editor | |
| 240 | pub const MH_BUNDLE = 0x8; /// dynamically bound bundle file | |
| 241 | pub const MH_DYLIB_STUB = 0x9; /// shared library stub for static linking only, no section contents | |
| 242 | pub const MH_DSYM = 0xa; /// companion file with only debug sections | |
| 243 | pub const MH_KEXT_BUNDLE = 0xb; /// x86_64 kexts | |
| 244 | ||
| 245 | // Constants for the flags field of the mach_header | |
| 246 | ||
| 247 | pub const MH_NOUNDEFS = 0x1; /// the object file has no undefined references | |
| 248 | pub const MH_INCRLINK = 0x2; /// the object file is the output of an incremental link against a base file and can't be link edited again | |
| 249 | pub const MH_DYLDLINK = 0x4; /// the object file is input for the dynamic linker and can't be staticly link edited again | |
| 250 | pub const MH_BINDATLOAD = 0x8; /// the object file's undefined references are bound by the dynamic linker when loaded. | |
| 251 | pub const MH_PREBOUND = 0x10; /// the file has its dynamic undefined references prebound. | |
| 252 | pub const MH_SPLIT_SEGS = 0x20; /// the file has its read-only and read-write segments split | |
| 253 | pub const MH_LAZY_INIT = 0x40; /// the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) | |
| 254 | pub const MH_TWOLEVEL = 0x80; /// the image is using two-level name space bindings | |
| 255 | pub const MH_FORCE_FLAT = 0x100; /// the executable is forcing all images to use flat name space bindings | |
| 256 | pub const MH_NOMULTIDEFS = 0x200; /// this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. | |
| 257 | pub const MH_NOFIXPREBINDING = 0x400; /// do not have dyld notify the prebinding agent about this executable | |
| 258 | pub const MH_PREBINDABLE = 0x800; /// the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. | |
| 259 | pub const MH_ALLMODSBOUND = 0x1000; /// indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. | |
| 260 | pub const MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;/// safe to divide up the sections into sub-sections via symbols for dead code stripping | |
| 261 | pub const MH_CANONICAL = 0x4000; /// the binary has been canonicalized via the unprebind operation | |
| 262 | pub const MH_WEAK_DEFINES = 0x8000; /// the final linked image contains external weak symbols | |
| 263 | pub const MH_BINDS_TO_WEAK = 0x10000; /// the final linked image uses weak symbols | |
| 264 | ||
| 265 | pub const MH_ALLOW_STACK_EXECUTION = 0x20000;/// When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes. | |
| 266 | pub const MH_ROOT_SAFE = 0x40000; /// When this bit is set, the binary declares it is safe for use in processes with uid zero | |
| 267 | ||
| 268 | pub const MH_SETUID_SAFE = 0x80000; /// When this bit is set, the binary declares it is safe for use in processes when issetugid() is true | |
| 269 | ||
| 270 | pub const MH_NO_REEXPORTED_DYLIBS = 0x100000; /// When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported | |
| 271 | pub const MH_PIE = 0x200000; /// When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. | |
| 272 | pub const MH_DEAD_STRIPPABLE_DYLIB = 0x400000; /// Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib. | |
| 273 | pub const MH_HAS_TLV_DESCRIPTORS = 0x800000; /// Contains a section of type S_THREAD_LOCAL_VARIABLES | |
| 274 | ||
| 275 | pub const MH_NO_HEAP_EXECUTION = 0x1000000; /// When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes. | |
| 276 | ||
| 277 | pub const MH_APP_EXTENSION_SAFE = 0x02000000; /// The code was linked for use in an application extension. | |
| 278 | ||
| 279 | pub const MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000; /// The external symbols listed in the nlist symbol table do not include all the symbols listed in the dyld info. | |
| 280 | ||
| 281 | ||
| 282 | /// The flags field of a section structure is separated into two parts a section | |
| 283 | /// type and section attributes. The section types are mutually exclusive (it | |
| 284 | /// can only have one type) but the section attributes are not (it may have more | |
| 285 | /// than one attribute). | |
| 286 | /// 256 section types | |
| 287 | pub const SECTION_TYPE = 0x000000ff; | |
| 288 | pub const SECTION_ATTRIBUTES = 0xffffff00; /// 24 section attributes | |
| 289 | ||
| 290 | pub const S_REGULAR = 0x0; /// regular section | |
| 291 | pub const S_ZEROFILL = 0x1; /// zero fill on demand section | |
| 292 | pub const S_CSTRING_LITERALS = 0x2; /// section with only literal C string | |
| 293 | pub const S_4BYTE_LITERALS = 0x3; /// section with only 4 byte literals | |
| 294 | pub const S_8BYTE_LITERALS = 0x4; /// section with only 8 byte literals | |
| 295 | pub const S_LITERAL_POINTERS = 0x5; /// section with only pointers to | |
| 296 | ||
| 297 | ||
| 298 | pub const N_STAB = 0xe0; /// if any of these bits set, a symbolic debugging entry | |
| 299 | pub const N_PEXT = 0x10; /// private external symbol bit | |
| 300 | pub const N_TYPE = 0x0e; /// mask for the type bits | |
| 301 | pub const N_EXT = 0x01; /// external symbol bit, set for external symbols | |
| 302 | ||
| 303 | ||
| 304 | pub const N_GSYM = 0x20; /// global symbol: name,,NO_SECT,type,0 | |
| 305 | pub const N_FNAME = 0x22; /// procedure name (f77 kludge): name,,NO_SECT,0,0 | |
| 306 | pub const N_FUN = 0x24; /// procedure: name,,n_sect,linenumber,address | |
| 307 | pub const N_STSYM = 0x26; /// static symbol: name,,n_sect,type,address | |
| 308 | pub const N_LCSYM = 0x28; /// .lcomm symbol: name,,n_sect,type,address | |
| 309 | pub const N_BNSYM = 0x2e; /// begin nsect sym: 0,,n_sect,0,address | |
| 310 | pub const N_AST = 0x32; /// AST file path: name,,NO_SECT,0,0 | |
| 311 | pub const N_OPT = 0x3c; /// emitted with gcc2_compiled and in gcc source | |
| 312 | pub const N_RSYM = 0x40; /// register sym: name,,NO_SECT,type,register | |
| 313 | pub const N_SLINE = 0x44; /// src line: 0,,n_sect,linenumber,address | |
| 314 | pub const N_ENSYM = 0x4e; /// end nsect sym: 0,,n_sect,0,address | |
| 315 | pub const N_SSYM = 0x60; /// structure elt: name,,NO_SECT,type,struct_offset | |
| 316 | pub const N_SO = 0x64; /// source file name: name,,n_sect,0,address | |
| 317 | pub const N_OSO = 0x66; /// object file name: name,,0,0,st_mtime | |
| 318 | pub const N_LSYM = 0x80; /// local sym: name,,NO_SECT,type,offset | |
| 319 | pub const N_BINCL = 0x82; /// include file beginning: name,,NO_SECT,0,sum | |
| 320 | pub const N_SOL = 0x84; /// #included file name: name,,n_sect,0,address | |
| 321 | pub const N_PARAMS = 0x86; /// compiler parameters: name,,NO_SECT,0,0 | |
| 322 | pub const N_VERSION = 0x88; /// compiler version: name,,NO_SECT,0,0 | |
| 323 | pub const N_OLEVEL = 0x8A; /// compiler -O level: name,,NO_SECT,0,0 | |
| 324 | pub const N_PSYM = 0xa0; /// parameter: name,,NO_SECT,type,offset | |
| 325 | pub const N_EINCL = 0xa2; /// include file end: name,,NO_SECT,0,0 | |
| 326 | pub const N_ENTRY = 0xa4; /// alternate entry: name,,n_sect,linenumber,address | |
| 327 | pub const N_LBRAC = 0xc0; /// left bracket: 0,,NO_SECT,nesting level,address | |
| 328 | pub const N_EXCL = 0xc2; /// deleted include file: name,,NO_SECT,0,sum | |
| 329 | pub const N_RBRAC = 0xe0; /// right bracket: 0,,NO_SECT,nesting level,address | |
| 330 | pub const N_BCOMM = 0xe2; /// begin common: name,,NO_SECT,0,0 | |
| 331 | pub const N_ECOMM = 0xe4; /// end common: name,,n_sect,0,0 | |
| 332 | pub const N_ECOML = 0xe8; /// end common (local name): 0,,n_sect,0,address | |
| 333 | pub const N_LENG = 0xfe; /// second stab entry with length information | |
| 334 | ||
| 335 | /// If a segment contains any sections marked with S_ATTR_DEBUG then all | |
| 336 | /// sections in that segment must have this attribute. No section other than | |
| 337 | /// a section marked with this attribute may reference the contents of this | |
| 338 | /// section. A section with this attribute may contain no symbols and must have | |
| 339 | /// a section type S_REGULAR. The static linker will not copy section contents | |
| 340 | /// from sections with this attribute into its output file. These sections | |
| 341 | /// generally contain DWARF debugging info. | |
| 342 | pub const S_ATTR_DEBUG = 0x02000000; /// a debug section | |
| 343 | ||
| 344 | pub const cpu_type_t = integer_t; | |
| 345 | pub const cpu_subtype_t = integer_t; | |
| 346 | pub const integer_t = c_int; | |
| 347 | pub const vm_prot_t = c_int; | |
| 348 |
std/os/index.zig+29| ... | ... | @@ -635,6 +635,35 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { |
| 635 | 635 | pub var linux_aux_raw = []usize{0} ** 38; |
| 636 | 636 | pub var posix_environ_raw: [][*]u8 = undefined; |
| 637 | 637 | |
| 638 | /// See std.elf for the constants. | |
| 639 | pub fn linuxGetAuxVal(index: usize) usize { | |
| 640 | if (builtin.link_libc) { | |
| 641 | return usize(std.c.getauxval(index)); | |
| 642 | } else { | |
| 643 | return linux_aux_raw[index]; | |
| 644 | } | |
| 645 | } | |
| 646 | ||
| 647 | pub fn getBaseAddress() usize { | |
| 648 | switch (builtin.os) { | |
| 649 | builtin.Os.linux => { | |
| 650 | const base = linuxGetAuxVal(std.elf.AT_BASE); | |
| 651 | if (base != 0) { | |
| 652 | return base; | |
| 653 | } | |
| 654 | const phdr = linuxGetAuxVal(std.elf.AT_PHDR); | |
| 655 | const ElfHeader = switch (@sizeOf(usize)) { | |
| 656 | 4 => std.elf.Elf32_Ehdr, | |
| 657 | 8 => std.elf.Elf64_Ehdr, | |
| 658 | else => @compileError("Unsupported architecture"), | |
| 659 | }; | |
| 660 | return phdr - @sizeOf(ElfHeader); | |
| 661 | }, | |
| 662 | builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header), | |
| 663 | else => @compileError("Unsupported OS"), | |
| 664 | } | |
| 665 | } | |
| 666 | ||
| 638 | 667 | /// Caller must free result when done. |
| 639 | 668 | /// TODO make this go through libc when we have it |
| 640 | 669 | pub fn getEnvMap(allocator: *Allocator) !BufMap { |