authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-06 17:43:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-06 18:17:37-07:00
logb40d36c90ba894a12f2de4e6c881642edffad3ed
tree79bf2079c932adda3a904dcc2b1ac28a9d13acb2
parentec212c82bef3cbf01517eece67a8599348c7ac86

stage2: implement simple enums

A simple enum is an enum which has an automatic integer tag type, all tag values automatically assigned, and no top level declarations. Such enums are created directly in AstGen and shared by all the generic/comptime instantiations of the surrounding ZIR code. This commit implements, but does not yet add any test cases for, simple enums. A full enum is an enum for which any of the above conditions are not true. Full enums are created in Sema, and therefore will create a unique type per generic/comptime instantiation. This commit does not implement full enums. However the `enum_decl_nonexhaustive` ZIR instruction is added and the respective Type functions are filled out. This commit makes an improvement to ZIR code, removing the decls array and removing the decl_map from AstGen. Instead, decl_ref and decl_val ZIR instructions index into the `owner_decl.dependencies` ArrayHashMap. We already need this dependencies array for incremental compilation purposes, and so repurposing it to also use it for ZIR decl indexes makes for efficient memory usage. Similarly, this commit fixes up incorrect memory management by removing the `const` ZIR instruction. The two places it was used stored memory in the AstGen arena, which may get freed after Sema. Now it properly sets up a new anonymous Decl for error sets and uses a normal decl_val instruction. The other usage of `const` ZIR instruction was float literals. These are now changed to use `float` ZIR instruction when the value fits inside `zir.Inst.Data` and `float128` otherwise. AstGen + Sema: implement int_to_enum and enum_to_int. No tests yet; I expect to have to make some fixes before they will pass tests. Will do that in the branch before merging. AstGen: fix struct astgen incorrectly counting decls as fields. Type/Value: give up on trying to exhaustively list every tag all the time. This makes the file more manageable. Also found a bug with i128/u128 this way, since the name of the function was more obvious when looking at the tag values. Type: implement abiAlignment and abiSize for structs. This will need to get more sophisticated at some point, but for now it is progress. Value: add new `enum_field_index` tag. Value: add hash_u32, needed when using ArrayHashMap.

7 files changed, 898 insertions(+), 2443 deletions(-)

src/AstGen.zig+237-53
...@@ -28,8 +28,6 @@ const BuiltinFn = @import("BuiltinFn.zig");...@@ -28,8 +28,6 @@ const BuiltinFn = @import("BuiltinFn.zig");
28instructions: std.MultiArrayList(zir.Inst) = .{},28instructions: std.MultiArrayList(zir.Inst) = .{},
29string_bytes: ArrayListUnmanaged(u8) = .{},29string_bytes: ArrayListUnmanaged(u8) = .{},
30extra: ArrayListUnmanaged(u32) = .{},30extra: ArrayListUnmanaged(u32) = .{},
31decl_map: std.StringArrayHashMapUnmanaged(void) = .{},
32decls: ArrayListUnmanaged(*Decl) = .{},
33/// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert31/// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert
34/// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.32/// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.
35ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,33ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,
...@@ -110,8 +108,6 @@ pub fn deinit(astgen: *AstGen) void {...@@ -110,8 +108,6 @@ pub fn deinit(astgen: *AstGen) void {
110 astgen.instructions.deinit(gpa);108 astgen.instructions.deinit(gpa);
111 astgen.extra.deinit(gpa);109 astgen.extra.deinit(gpa);
112 astgen.string_bytes.deinit(gpa);110 astgen.string_bytes.deinit(gpa);
113 astgen.decl_map.deinit(gpa);
114 astgen.decls.deinit(gpa);
115}111}
116112
117pub const ResultLoc = union(enum) {113pub const ResultLoc = union(enum) {
...@@ -1183,13 +1179,6 @@ fn blockExprStmts(...@@ -1183,13 +1179,6 @@ fn blockExprStmts(
1183 // in the above while loop.1179 // in the above while loop.
1184 const zir_tags = gz.astgen.instructions.items(.tag);1180 const zir_tags = gz.astgen.instructions.items(.tag);
1185 switch (zir_tags[inst]) {1181 switch (zir_tags[inst]) {
1186 .@"const" => {
1187 const tv = gz.astgen.instructions.items(.data)[inst].@"const";
1188 break :b switch (tv.ty.zigTypeTag()) {
1189 .NoReturn, .Void => true,
1190 else => false,
1191 };
1192 },
1193 // For some instructions, swap in a slightly different ZIR tag1182 // For some instructions, swap in a slightly different ZIR tag
1194 // so we can avoid a separate ensure_result_used instruction.1183 // so we can avoid a separate ensure_result_used instruction.
1195 .call_none_chkused => unreachable,1184 .call_none_chkused => unreachable,
...@@ -1257,6 +1246,8 @@ fn blockExprStmts(...@@ -1257,6 +1246,8 @@ fn blockExprStmts(
1257 .fn_type_cc,1246 .fn_type_cc,
1258 .fn_type_cc_var_args,1247 .fn_type_cc_var_args,
1259 .int,1248 .int,
1249 .float,
1250 .float128,
1260 .intcast,1251 .intcast,
1261 .int_type,1252 .int_type,
1262 .is_non_null,1253 .is_non_null,
...@@ -1334,7 +1325,10 @@ fn blockExprStmts(...@@ -1334,7 +1325,10 @@ fn blockExprStmts(
1334 .struct_decl_extern,1325 .struct_decl_extern,
1335 .union_decl,1326 .union_decl,
1336 .enum_decl,1327 .enum_decl,
1328 .enum_decl_nonexhaustive,
1337 .opaque_decl,1329 .opaque_decl,
1330 .int_to_enum,
1331 .enum_to_int,
1338 => break :b false,1332 => break :b false,
13391333
1340 // ZIR instructions that are always either `noreturn` or `void`.1334 // ZIR instructions that are always either `noreturn` or `void`.
...@@ -1823,15 +1817,18 @@ fn containerDecl(...@@ -1823,15 +1817,18 @@ fn containerDecl(
1823 defer bit_bag.deinit(gpa);1817 defer bit_bag.deinit(gpa);
18241818
1825 var cur_bit_bag: u32 = 0;1819 var cur_bit_bag: u32 = 0;
1826 var member_index: usize = 0;1820 var field_index: usize = 0;
1827 while (true) {1821 for (container_decl.ast.members) |member_node| {
1828 const member_node = container_decl.ast.members[member_index];
1829 const member = switch (node_tags[member_node]) {1822 const member = switch (node_tags[member_node]) {
1830 .container_field_init => tree.containerFieldInit(member_node),1823 .container_field_init => tree.containerFieldInit(member_node),
1831 .container_field_align => tree.containerFieldAlign(member_node),1824 .container_field_align => tree.containerFieldAlign(member_node),
1832 .container_field => tree.containerField(member_node),1825 .container_field => tree.containerField(member_node),
1833 else => unreachable,1826 else => continue,
1834 };1827 };
1828 if (field_index % 16 == 0 and field_index != 0) {
1829 try bit_bag.append(gpa, cur_bit_bag);
1830 cur_bit_bag = 0;
1831 }
1835 if (member.comptime_token) |comptime_token| {1832 if (member.comptime_token) |comptime_token| {
1836 return mod.failTok(scope, comptime_token, "TODO implement comptime struct fields", .{});1833 return mod.failTok(scope, comptime_token, "TODO implement comptime struct fields", .{});
1837 }1834 }
...@@ -1858,17 +1855,9 @@ fn containerDecl(...@@ -1858,17 +1855,9 @@ fn containerDecl(
1858 fields_data.appendAssumeCapacity(@enumToInt(default_inst));1855 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
1859 }1856 }
18601857
1861 member_index += 1;1858 field_index += 1;
1862 if (member_index < container_decl.ast.members.len) {
1863 if (member_index % 16 == 0) {
1864 try bit_bag.append(gpa, cur_bit_bag);
1865 cur_bit_bag = 0;
1866 }
1867 } else {
1868 break;
1869 }
1870 }1859 }
1871 const empty_slot_count = 16 - ((member_index - 1) % 16);1860 const empty_slot_count = 16 - ((field_index - 1) % 16);
1872 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);1861 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
18731862
1874 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{1863 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
...@@ -1885,7 +1874,172 @@ fn containerDecl(...@@ -1885,7 +1874,172 @@ fn containerDecl(
1885 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for union decl", .{});1874 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for union decl", .{});
1886 },1875 },
1887 .keyword_enum => {1876 .keyword_enum => {
1888 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for enum decl", .{});1877 if (container_decl.layout_token) |t| {
1878 return mod.failTok(scope, t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{});
1879 }
1880 // Count total fields as well as how many have explicitly provided tag values.
1881 const counts = blk: {
1882 var values: usize = 0;
1883 var total_fields: usize = 0;
1884 var decls: usize = 0;
1885 var nonexhaustive_node: ast.Node.Index = 0;
1886 for (container_decl.ast.members) |member_node| {
1887 const member = switch (node_tags[member_node]) {
1888 .container_field_init => tree.containerFieldInit(member_node),
1889 .container_field_align => tree.containerFieldAlign(member_node),
1890 .container_field => tree.containerField(member_node),
1891 else => {
1892 decls += 1;
1893 continue;
1894 },
1895 };
1896 if (member.comptime_token) |comptime_token| {
1897 return mod.failTok(scope, comptime_token, "enum fields cannot be marked comptime", .{});
1898 }
1899 if (member.ast.type_expr != 0) {
1900 return mod.failNode(scope, member.ast.type_expr, "enum fields do not have types", .{});
1901 }
1902 if (member.ast.align_expr != 0) {
1903 return mod.failNode(scope, member.ast.align_expr, "enum fields do not have alignments", .{});
1904 }
1905 const name_token = member.ast.name_token;
1906 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
1907 if (nonexhaustive_node != 0) {
1908 const msg = msg: {
1909 const msg = try mod.errMsg(
1910 scope,
1911 gz.nodeSrcLoc(member_node),
1912 "redundant non-exhaustive enum mark",
1913 .{},
1914 );
1915 errdefer msg.destroy(gpa);
1916 const other_src = gz.nodeSrcLoc(nonexhaustive_node);
1917 try mod.errNote(scope, other_src, msg, "other mark here", .{});
1918 break :msg msg;
1919 };
1920 return mod.failWithOwnedErrorMsg(scope, msg);
1921 }
1922 nonexhaustive_node = member_node;
1923 if (member.ast.value_expr != 0) {
1924 return mod.failNode(scope, member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
1925 }
1926 continue;
1927 }
1928 total_fields += 1;
1929 if (member.ast.value_expr != 0) {
1930 values += 1;
1931 }
1932 }
1933 break :blk .{
1934 .total_fields = total_fields,
1935 .values = values,
1936 .decls = decls,
1937 .nonexhaustive_node = nonexhaustive_node,
1938 };
1939 };
1940 if (counts.total_fields == 0) {
1941 // One can construct an enum with no tags, and it functions the same as `noreturn`. But
1942 // this is only useful for generic code; when explicitly using `enum {}` syntax, there
1943 // must be at least one tag.
1944 return mod.failNode(scope, node, "enum declarations must have at least one tag", .{});
1945 }
1946 if (counts.nonexhaustive_node != 0 and arg_inst == .none) {
1947 const msg = msg: {
1948 const msg = try mod.errMsg(
1949 scope,
1950 gz.nodeSrcLoc(node),
1951 "non-exhaustive enum missing integer tag type",
1952 .{},
1953 );
1954 errdefer msg.destroy(gpa);
1955 const other_src = gz.nodeSrcLoc(counts.nonexhaustive_node);
1956 try mod.errNote(scope, other_src, msg, "marked non-exhaustive here", .{});
1957 break :msg msg;
1958 };
1959 return mod.failWithOwnedErrorMsg(scope, msg);
1960 }
1961 if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {
1962 // No explicitly provided tag values and no top level declarations! In this case,
1963 // we can construct the enum type in AstGen and it will be correctly shared by all
1964 // generic function instantiations and comptime function calls.
1965 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
1966 errdefer new_decl_arena.deinit();
1967 const arena = &new_decl_arena.allocator;
1968
1969 var fields_map: std.StringArrayHashMapUnmanaged(void) = .{};
1970 try fields_map.ensureCapacity(arena, counts.total_fields);
1971 for (container_decl.ast.members) |member_node| {
1972 if (member_node == counts.nonexhaustive_node)
1973 continue;
1974 const member = switch (node_tags[member_node]) {
1975 .container_field_init => tree.containerFieldInit(member_node),
1976 .container_field_align => tree.containerFieldAlign(member_node),
1977 .container_field => tree.containerField(member_node),
1978 else => unreachable, // We checked earlier.
1979 };
1980 const name_token = member.ast.name_token;
1981 const tag_name = try mod.identifierTokenStringTreeArena(
1982 scope,
1983 name_token,
1984 tree,
1985 arena,
1986 );
1987 const gop = fields_map.getOrPutAssumeCapacity(tag_name);
1988 if (gop.found_existing) {
1989 const msg = msg: {
1990 const msg = try mod.errMsg(
1991 scope,
1992 gz.tokSrcLoc(name_token),
1993 "duplicate enum tag",
1994 .{},
1995 );
1996 errdefer msg.destroy(gpa);
1997 // Iterate to find the other tag. We don't eagerly store it in a hash
1998 // map because in the hot path there will be no compile error and we
1999 // don't need to waste time with a hash map.
2000 const bad_node = for (container_decl.ast.members) |other_member_node| {
2001 const other_member = switch (node_tags[other_member_node]) {
2002 .container_field_init => tree.containerFieldInit(member_node),
2003 .container_field_align => tree.containerFieldAlign(member_node),
2004 .container_field => tree.containerField(member_node),
2005 else => unreachable, // We checked earlier.
2006 };
2007 const other_tag_name = try mod.identifierTokenStringTreeArena(
2008 scope,
2009 name_token,
2010 tree,
2011 arena,
2012 );
2013 if (mem.eql(u8, tag_name, other_tag_name))
2014 break other_member_node;
2015 } else unreachable;
2016 const other_src = gz.nodeSrcLoc(bad_node);
2017 try mod.errNote(scope, other_src, msg, "other tag here", .{});
2018 break :msg msg;
2019 };
2020 return mod.failWithOwnedErrorMsg(scope, msg);
2021 }
2022 }
2023 const enum_simple = try arena.create(Module.EnumSimple);
2024 enum_simple.* = .{
2025 .owner_decl = astgen.decl,
2026 .node_offset = astgen.decl.nodeIndexToRelative(node),
2027 .fields = fields_map,
2028 };
2029 const enum_ty = try Type.Tag.enum_simple.create(arena, enum_simple);
2030 const enum_val = try Value.Tag.ty.create(arena, enum_ty);
2031 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
2032 .ty = Type.initTag(.type),
2033 .val = enum_val,
2034 });
2035 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
2036 const result = try gz.addDecl(.decl_val, decl_index, node);
2037 return rvalue(gz, scope, rl, result, node);
2038 }
2039 // In this case we must generate ZIR code for the tag values, similar to
2040 // how structs are handled above. The new anonymous Decl will be created in
2041 // Sema, not AstGen.
2042 return mod.failNode(scope, node, "TODO AstGen for enum decl with decls or explicitly provided field values", .{});
1889 },2043 },
1890 .keyword_opaque => {2044 .keyword_opaque => {
1891 const result = try gz.addNode(.opaque_decl, node);2045 const result = try gz.addNode(.opaque_decl, node);
...@@ -1901,11 +2055,11 @@ fn errorSetDecl(...@@ -1901,11 +2055,11 @@ fn errorSetDecl(
1901 rl: ResultLoc,2055 rl: ResultLoc,
1902 node: ast.Node.Index,2056 node: ast.Node.Index,
1903) InnerError!zir.Inst.Ref {2057) InnerError!zir.Inst.Ref {
1904 const mod = gz.astgen.mod;2058 const astgen = gz.astgen;
2059 const mod = astgen.mod;
1905 const tree = gz.tree();2060 const tree = gz.tree();
1906 const main_tokens = tree.nodes.items(.main_token);2061 const main_tokens = tree.nodes.items(.main_token);
1907 const token_tags = tree.tokens.items(.tag);2062 const token_tags = tree.tokens.items(.tag);
1908 const arena = gz.astgen.arena;
19092063
1910 // Count how many fields there are.2064 // Count how many fields there are.
1911 const error_token = main_tokens[node];2065 const error_token = main_tokens[node];
...@@ -1922,6 +2076,11 @@ fn errorSetDecl(...@@ -1922,6 +2076,11 @@ fn errorSetDecl(
1922 } else unreachable; // TODO should not need else unreachable here2076 } else unreachable; // TODO should not need else unreachable here
1923 };2077 };
19242078
2079 const gpa = mod.gpa;
2080 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
2081 errdefer new_decl_arena.deinit();
2082 const arena = &new_decl_arena.allocator;
2083
1925 const fields = try arena.alloc([]const u8, count);2084 const fields = try arena.alloc([]const u8, count);
1926 {2085 {
1927 var tok_i = error_token + 2;2086 var tok_i = error_token + 2;
...@@ -1930,7 +2089,7 @@ fn errorSetDecl(...@@ -1930,7 +2089,7 @@ fn errorSetDecl(
1930 switch (token_tags[tok_i]) {2089 switch (token_tags[tok_i]) {
1931 .doc_comment, .comma => {},2090 .doc_comment, .comma => {},
1932 .identifier => {2091 .identifier => {
1933 fields[field_i] = try mod.identifierTokenString(scope, tok_i);2092 fields[field_i] = try mod.identifierTokenStringTreeArena(scope, tok_i, tree, arena);
1934 field_i += 1;2093 field_i += 1;
1935 },2094 },
1936 .r_brace => break,2095 .r_brace => break,
...@@ -1940,18 +2099,19 @@ fn errorSetDecl(...@@ -1940,18 +2099,19 @@ fn errorSetDecl(
1940 }2099 }
1941 const error_set = try arena.create(Module.ErrorSet);2100 const error_set = try arena.create(Module.ErrorSet);
1942 error_set.* = .{2101 error_set.* = .{
1943 .owner_decl = gz.astgen.decl,2102 .owner_decl = astgen.decl,
1944 .node_offset = gz.astgen.decl.nodeIndexToRelative(node),2103 .node_offset = astgen.decl.nodeIndexToRelative(node),
1945 .names_ptr = fields.ptr,2104 .names_ptr = fields.ptr,
1946 .names_len = @intCast(u32, fields.len),2105 .names_len = @intCast(u32, fields.len),
1947 };2106 };
1948 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);2107 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
1949 const typed_value = try arena.create(TypedValue);2108 const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
1950 typed_value.* = .{2109 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
1951 .ty = Type.initTag(.type),2110 .ty = Type.initTag(.type),
1952 .val = try Value.Tag.ty.create(arena, error_set_ty),2111 .val = error_set_val,
1953 };2112 });
1954 const result = try gz.addConst(typed_value);2113 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
2114 const result = try gz.addDecl(.decl_val, decl_index, node);
1955 return rvalue(gz, scope, rl, result, node);2115 return rvalue(gz, scope, rl, result, node);
1956}2116}
19572117
...@@ -3426,7 +3586,8 @@ fn identifier(...@@ -3426,7 +3586,8 @@ fn identifier(
3426 const tracy = trace(@src());3586 const tracy = trace(@src());
3427 defer tracy.end();3587 defer tracy.end();
34283588
3429 const mod = gz.astgen.mod;3589 const astgen = gz.astgen;
3590 const mod = astgen.mod;
3430 const tree = gz.tree();3591 const tree = gz.tree();
3431 const main_tokens = tree.nodes.items(.main_token);3592 const main_tokens = tree.nodes.items(.main_token);
34323593
...@@ -3459,7 +3620,7 @@ fn identifier(...@@ -3459,7 +3620,7 @@ fn identifier(
3459 const result = try gz.add(.{3620 const result = try gz.add(.{
3460 .tag = .int_type,3621 .tag = .int_type,
3461 .data = .{ .int_type = .{3622 .data = .{ .int_type = .{
3462 .src_node = gz.astgen.decl.nodeIndexToRelative(ident),3623 .src_node = astgen.decl.nodeIndexToRelative(ident),
3463 .signedness = signedness,3624 .signedness = signedness,
3464 .bit_count = bit_count,3625 .bit_count = bit_count,
3465 } },3626 } },
...@@ -3497,13 +3658,13 @@ fn identifier(...@@ -3497,13 +3658,13 @@ fn identifier(
3497 };3658 };
3498 }3659 }
34993660
3500 const gop = try gz.astgen.decl_map.getOrPut(mod.gpa, ident_name);3661 const decl = mod.lookupDeclName(scope, ident_name) orelse {
3501 if (!gop.found_existing) {3662 // TODO insert a "dependency on the non-existence of a decl" here to make this
3502 const decl = mod.lookupDeclName(scope, ident_name) orelse3663 // compile error go away when the decl is introduced. This data should be in a global
3503 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});3664 // sparse map since it is only relevant when a compile error occurs.
3504 try gz.astgen.decls.append(mod.gpa, decl);3665 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
3505 }3666 };
3506 const decl_index = @intCast(u32, gop.index);3667 const decl_index = try mod.declareDeclDependency(astgen.decl, decl);
3507 switch (rl) {3668 switch (rl) {
3508 .ref, .none_or_ref => return gz.addDecl(.decl_ref, decl_index, ident),3669 .ref, .none_or_ref => return gz.addDecl(.decl_ref, decl_index, ident),
3509 else => return rvalue(gz, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),3670 else => return rvalue(gz, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),
...@@ -3638,12 +3799,23 @@ fn floatLiteral(...@@ -3638,12 +3799,23 @@ fn floatLiteral(
3638 const float_number = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {3799 const float_number = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {
3639 error.InvalidCharacter => unreachable, // validated by tokenizer3800 error.InvalidCharacter => unreachable, // validated by tokenizer
3640 };3801 };
3641 const typed_value = try arena.create(TypedValue);3802 // If the value fits into a f32 without losing any precision, store it that way.
3642 typed_value.* = .{3803 @setFloatMode(.Strict);
3643 .ty = Type.initTag(.comptime_float),3804 const smaller_float = @floatCast(f32, float_number);
3644 .val = try Value.Tag.float_128.create(arena, float_number),3805 const bigger_again: f128 = smaller_float;
3645 };3806 if (bigger_again == float_number) {
3646 const result = try gz.addConst(typed_value);3807 const result = try gz.addFloat(smaller_float, node);
3808 return rvalue(gz, scope, rl, result, node);
3809 }
3810 // We need to use 128 bits. Break the float into 4 u32 values so we can
3811 // put it into the `extra` array.
3812 const int_bits = @bitCast(u128, float_number);
3813 const result = try gz.addPlNode(.float128, node, zir.Inst.Float128{
3814 .piece0 = @truncate(u32, int_bits),
3815 .piece1 = @truncate(u32, int_bits >> 32),
3816 .piece2 = @truncate(u32, int_bits >> 64),
3817 .piece3 = @truncate(u32, int_bits >> 96),
3818 });
3647 return rvalue(gz, scope, rl, result, node);3819 return rvalue(gz, scope, rl, result, node);
3648}3820}
36493821
...@@ -3955,6 +4127,20 @@ fn builtinCall(...@@ -3955,6 +4127,20 @@ fn builtinCall(
3955 .bit_cast => return bitCast(gz, scope, rl, node, params[0], params[1]),4127 .bit_cast => return bitCast(gz, scope, rl, node, params[0], params[1]),
3956 .TypeOf => return typeOf(gz, scope, rl, node, params),4128 .TypeOf => return typeOf(gz, scope, rl, node, params),
39574129
4130 .int_to_enum => {
4131 const result = try gz.addPlNode(.int_to_enum, node, zir.Inst.Bin{
4132 .lhs = try typeExpr(gz, scope, params[0]),
4133 .rhs = try expr(gz, scope, .none, params[1]),
4134 });
4135 return rvalue(gz, scope, rl, result, node);
4136 },
4137
4138 .enum_to_int => {
4139 const operand = try expr(gz, scope, .none, params[0]);
4140 const result = try gz.addUnNode(.enum_to_int, operand, node);
4141 return rvalue(gz, scope, rl, result, node);
4142 },
4143
3958 .add_with_overflow,4144 .add_with_overflow,
3959 .align_cast,4145 .align_cast,
3960 .align_of,4146 .align_of,
...@@ -3981,7 +4167,6 @@ fn builtinCall(...@@ -3981,7 +4167,6 @@ fn builtinCall(
3981 .div_floor,4167 .div_floor,
3982 .div_trunc,4168 .div_trunc,
3983 .embed_file,4169 .embed_file,
3984 .enum_to_int,
3985 .error_name,4170 .error_name,
3986 .error_return_trace,4171 .error_return_trace,
3987 .err_set_cast,4172 .err_set_cast,
...@@ -3991,7 +4176,6 @@ fn builtinCall(...@@ -3991,7 +4176,6 @@ fn builtinCall(
3991 .float_to_int,4176 .float_to_int,
3992 .has_decl,4177 .has_decl,
3993 .has_field,4178 .has_field,
3994 .int_to_enum,
3995 .int_to_float,4179 .int_to_float,
3996 .int_to_ptr,4180 .int_to_ptr,
3997 .memcpy,4181 .memcpy,
src/BuiltinFn.zig+1-1
...@@ -484,7 +484,7 @@ pub const list = list: {...@@ -484,7 +484,7 @@ pub const list = list: {
484 "@intToEnum",484 "@intToEnum",
485 .{485 .{
486 .tag = .int_to_enum,486 .tag = .int_to_enum,
487 .param_count = 1,487 .param_count = 2,
488 },488 },
489 },489 },
490 .{490 .{
src/Module.zig+80-16
...@@ -290,6 +290,18 @@ pub const Decl = struct {...@@ -290,6 +290,18 @@ pub const Decl = struct {
290 return decl.container.fullyQualifiedNameHash(mem.spanZ(decl.name));290 return decl.container.fullyQualifiedNameHash(mem.spanZ(decl.name));
291 }291 }
292292
293 pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void {
294 const unqualified_name = mem.spanZ(decl.name);
295 return decl.container.renderFullyQualifiedName(unqualified_name, writer);
296 }
297
298 pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 {
299 var buffer = std.ArrayList(u8).init(gpa);
300 defer buffer.deinit();
301 try decl.renderFullyQualifiedName(buffer.writer());
302 return buffer.toOwnedSlice();
303 }
304
293 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {305 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {
294 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;306 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;
295 return tvm.typed_value;307 return tvm.typed_value;
...@@ -375,8 +387,7 @@ pub const Struct = struct {...@@ -375,8 +387,7 @@ pub const Struct = struct {
375 };387 };
376388
377 pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 {389 pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 {
378 // TODO this should return e.g. "std.fs.Dir.OpenOptions"390 return s.owner_decl.getFullyQualifiedName(gpa);
379 return gpa.dupe(u8, mem.spanZ(s.owner_decl.name));
380 }391 }
381392
382 pub fn srcLoc(s: Struct) SrcLoc {393 pub fn srcLoc(s: Struct) SrcLoc {
...@@ -387,6 +398,39 @@ pub const Struct = struct {...@@ -387,6 +398,39 @@ pub const Struct = struct {
387 }398 }
388};399};
389400
401/// Represents the data that an enum declaration provides, when the fields
402/// are auto-numbered, and there are no declarations. The integer tag type
403/// is inferred to be the smallest power of two unsigned int that fits
404/// the number of fields.
405pub const EnumSimple = struct {
406 owner_decl: *Decl,
407 /// Set of field names in declaration order.
408 fields: std.StringArrayHashMapUnmanaged(void),
409 /// Offset from `owner_decl`, points to the enum decl AST node.
410 node_offset: i32,
411};
412
413/// Represents the data that an enum declaration provides, when there is
414/// at least one tag value explicitly specified, or at least one declaration.
415pub const EnumFull = struct {
416 owner_decl: *Decl,
417 /// An integer type which is used for the numerical value of the enum.
418 /// Whether zig chooses this type or the user specifies it, it is stored here.
419 tag_ty: Type,
420 /// Set of field names in declaration order.
421 fields: std.StringArrayHashMapUnmanaged(void),
422 /// Maps integer tag value to field index.
423 /// Entries are in declaration order, same as `fields`.
424 /// If this hash map is empty, it means the enum tags are auto-numbered.
425 values: ValueMap,
426 /// Represents the declarations inside this struct.
427 container: Scope.Container,
428 /// Offset from `owner_decl`, points to the enum decl AST node.
429 node_offset: i32,
430
431 pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.hash_u32, Value.eql, false);
432};
433
390/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.434/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
391/// Extern functions do not have this data structure; they are represented by435/// Extern functions do not have this data structure; they are represented by
392/// the `Decl` only, with a `Value` tag of `extern_fn`.436/// the `Decl` only, with a `Value` tag of `extern_fn`.
...@@ -634,6 +678,11 @@ pub const Scope = struct {...@@ -634,6 +678,11 @@ pub const Scope = struct {
634 // TODO container scope qualified names.678 // TODO container scope qualified names.
635 return std.zig.hashSrc(name);679 return std.zig.hashSrc(name);
636 }680 }
681
682 pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void {
683 // TODO this should render e.g. "std.fs.Dir.OpenOptions"
684 return writer.writeAll(name);
685 }
637 };686 };
638687
639 pub const File = struct {688 pub const File = struct {
...@@ -1030,7 +1079,6 @@ pub const Scope = struct {...@@ -1030,7 +1079,6 @@ pub const Scope = struct {
1030 .instructions = gz.astgen.instructions.toOwnedSlice(),1079 .instructions = gz.astgen.instructions.toOwnedSlice(),
1031 .string_bytes = gz.astgen.string_bytes.toOwnedSlice(gpa),1080 .string_bytes = gz.astgen.string_bytes.toOwnedSlice(gpa),
1032 .extra = gz.astgen.extra.toOwnedSlice(gpa),1081 .extra = gz.astgen.extra.toOwnedSlice(gpa),
1033 .decls = gz.astgen.decls.toOwnedSlice(gpa),
1034 };1082 };
1035 }1083 }
10361084
...@@ -1242,6 +1290,16 @@ pub const Scope = struct {...@@ -1242,6 +1290,16 @@ pub const Scope = struct {
1242 });1290 });
1243 }1291 }
12441292
1293 pub fn addFloat(gz: *GenZir, number: f32, src_node: ast.Node.Index) !zir.Inst.Ref {
1294 return gz.add(.{
1295 .tag = .float,
1296 .data = .{ .float = .{
1297 .src_node = gz.astgen.decl.nodeIndexToRelative(src_node),
1298 .number = number,
1299 } },
1300 });
1301 }
1302
1245 pub fn addUnNode(1303 pub fn addUnNode(
1246 gz: *GenZir,1304 gz: *GenZir,
1247 tag: zir.Inst.Tag,1305 tag: zir.Inst.Tag,
...@@ -1450,13 +1508,6 @@ pub const Scope = struct {...@@ -1450,13 +1508,6 @@ pub const Scope = struct {
1450 return new_index;1508 return new_index;
1451 }1509 }
14521510
1453 pub fn addConst(gz: *GenZir, typed_value: *TypedValue) !zir.Inst.Ref {
1454 return gz.add(.{
1455 .tag = .@"const",
1456 .data = .{ .@"const" = typed_value },
1457 });
1458 }
1459
1460 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {1511 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
1461 return gz.astgen.indexToRef(try gz.addAsIndex(inst));1512 return gz.astgen.indexToRef(try gz.addAsIndex(inst));
1462 }1513 }
...@@ -3120,12 +3171,14 @@ fn astgenAndSemaVarDecl(...@@ -3120,12 +3171,14 @@ fn astgenAndSemaVarDecl(
3120 return type_changed;3171 return type_changed;
3121}3172}
31223173
3123pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !void {3174/// Returns the depender's index of the dependee.
3124 try depender.dependencies.ensureCapacity(mod.gpa, depender.dependencies.items().len + 1);3175pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !u32 {
3125 try dependee.dependants.ensureCapacity(mod.gpa, dependee.dependants.items().len + 1);3176 try depender.dependencies.ensureCapacity(mod.gpa, depender.dependencies.count() + 1);
3177 try dependee.dependants.ensureCapacity(mod.gpa, dependee.dependants.count() + 1);
31263178
3127 depender.dependencies.putAssumeCapacity(dependee, {});
3128 dependee.dependants.putAssumeCapacity(depender, {});3179 dependee.dependants.putAssumeCapacity(depender, {});
3180 const gop = depender.dependencies.getOrPutAssumeCapacity(dependee);
3181 return @intCast(u32, gop.index);
3129}3182}
31303183
3131pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree {3184pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree {
...@@ -4445,7 +4498,17 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode {...@@ -4445,7 +4498,17 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode {
4445/// Otherwise, returns a reference to the source code bytes directly.4498/// Otherwise, returns a reference to the source code bytes directly.
4446/// See also `appendIdentStr` and `parseStrLit`.4499/// See also `appendIdentStr` and `parseStrLit`.
4447pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {4500pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {
4448 const tree = scope.tree();4501 return mod.identifierTokenStringTreeArena(scope, token, scope.tree(), scope.arena());
4502}
4503
4504/// `scope` is only used for error reporting.
4505pub fn identifierTokenStringTreeArena(
4506 mod: *Module,
4507 scope: *Scope,
4508 token: ast.TokenIndex,
4509 tree: *const ast.Tree,
4510 arena: *Allocator,
4511) InnerError![]const u8 {
4449 const token_tags = tree.tokens.items(.tag);4512 const token_tags = tree.tokens.items(.tag);
4450 assert(token_tags[token] == .identifier);4513 assert(token_tags[token] == .identifier);
4451 const ident_name = tree.tokenSlice(token);4514 const ident_name = tree.tokenSlice(token);
...@@ -4455,7 +4518,8 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)...@@ -4455,7 +4518,8 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
4455 var buf: ArrayListUnmanaged(u8) = .{};4518 var buf: ArrayListUnmanaged(u8) = .{};
4456 defer buf.deinit(mod.gpa);4519 defer buf.deinit(mod.gpa);
4457 try parseStrLit(mod, scope, token, &buf, ident_name, 1);4520 try parseStrLit(mod, scope, token, &buf, ident_name, 1);
4458 return buf.toOwnedSlice(mod.gpa);4521 const duped = try arena.dupe(u8, buf.items);
4522 return duped;
4459}4523}
44604524
4461/// Given an identifier token, obtain the string for it (possibly parsing as a string4525/// Given an identifier token, obtain the string for it (possibly parsing as a string
src/Sema.zig+154-18
...@@ -168,7 +168,6 @@ pub fn analyzeBody(...@@ -168,7 +168,6 @@ pub fn analyzeBody(
168 .cmp_lte => try sema.zirCmp(block, inst, .lte),168 .cmp_lte => try sema.zirCmp(block, inst, .lte),
169 .cmp_neq => try sema.zirCmp(block, inst, .neq),169 .cmp_neq => try sema.zirCmp(block, inst, .neq),
170 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),170 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
171 .@"const" => try sema.zirConst(block, inst),
172 .decl_ref => try sema.zirDeclRef(block, inst),171 .decl_ref => try sema.zirDeclRef(block, inst),
173 .decl_val => try sema.zirDeclVal(block, inst),172 .decl_val => try sema.zirDeclVal(block, inst),
174 .load => try sema.zirLoad(block, inst),173 .load => try sema.zirLoad(block, inst),
...@@ -179,6 +178,8 @@ pub fn analyzeBody(...@@ -179,6 +178,8 @@ pub fn analyzeBody(
179 .elem_val_node => try sema.zirElemValNode(block, inst),178 .elem_val_node => try sema.zirElemValNode(block, inst),
180 .enum_literal => try sema.zirEnumLiteral(block, inst),179 .enum_literal => try sema.zirEnumLiteral(block, inst),
181 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),180 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
181 .enum_to_int => try sema.zirEnumToInt(block, inst),
182 .int_to_enum => try sema.zirIntToEnum(block, inst),
182 .err_union_code => try sema.zirErrUnionCode(block, inst),183 .err_union_code => try sema.zirErrUnionCode(block, inst),
183 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),184 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
184 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),185 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
...@@ -201,6 +202,8 @@ pub fn analyzeBody(...@@ -201,6 +202,8 @@ pub fn analyzeBody(
201 .import => try sema.zirImport(block, inst),202 .import => try sema.zirImport(block, inst),
202 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),203 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
203 .int => try sema.zirInt(block, inst),204 .int => try sema.zirInt(block, inst),
205 .float => try sema.zirFloat(block, inst),
206 .float128 => try sema.zirFloat128(block, inst),
204 .int_type => try sema.zirIntType(block, inst),207 .int_type => try sema.zirIntType(block, inst),
205 .intcast => try sema.zirIntcast(block, inst),208 .intcast => try sema.zirIntcast(block, inst),
206 .is_err => try sema.zirIsErr(block, inst),209 .is_err => try sema.zirIsErr(block, inst),
...@@ -264,7 +267,8 @@ pub fn analyzeBody(...@@ -264,7 +267,8 @@ pub fn analyzeBody(
264 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),267 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
265 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),268 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
266 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),269 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
267 .enum_decl => try sema.zirEnumDecl(block, inst),270 .enum_decl => try sema.zirEnumDecl(block, inst, false),
271 .enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
268 .union_decl => try sema.zirUnionDecl(block, inst),272 .union_decl => try sema.zirUnionDecl(block, inst),
269 .opaque_decl => try sema.zirOpaqueDecl(block, inst),273 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
270274
...@@ -498,18 +502,6 @@ fn resolveInstConst(...@@ -498,18 +502,6 @@ fn resolveInstConst(
498 };502 };
499}503}
500504
501fn zirConst(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
502 const tracy = trace(@src());
503 defer tracy.end();
504
505 const tv_ptr = sema.code.instructions.items(.data)[inst].@"const";
506 // Move the TypedValue from old memory to new memory. This allows freeing the ZIR instructions
507 // after analysis. This happens, for example, with variable declaration initialization
508 // expressions.
509 const typed_value_copy = try tv_ptr.copy(sema.arena);
510 return sema.mod.constInst(sema.arena, .unneeded, typed_value_copy);
511}
512
513fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {505fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
514 const tracy = trace(@src());506 const tracy = trace(@src());
515 defer tracy.end();507 defer tracy.end();
...@@ -617,7 +609,12 @@ fn zirStructDecl(...@@ -617,7 +609,12 @@ fn zirStructDecl(
617 return sema.analyzeDeclVal(block, src, new_decl);609 return sema.analyzeDeclVal(block, src, new_decl);
618}610}
619611
620fn zirEnumDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {612fn zirEnumDecl(
613 sema: *Sema,
614 block: *Scope.Block,
615 inst: zir.Inst.Index,
616 nonexhaustive: bool,
617) InnerError!*Inst {
621 const tracy = trace(@src());618 const tracy = trace(@src());
622 defer tracy.end();619 defer tracy.end();
623620
...@@ -1070,6 +1067,31 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In...@@ -1070,6 +1067,31 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
1070 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);1067 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
1071}1068}
10721069
1070fn zirFloat(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1071 const arena = sema.arena;
1072 const inst_data = sema.code.instructions.items(.data)[inst].float;
1073 const src = inst_data.src();
1074 const number = inst_data.number;
1075
1076 return sema.mod.constInst(arena, src, .{
1077 .ty = Type.initTag(.comptime_float),
1078 .val = try Value.Tag.float_32.create(arena, number),
1079 });
1080}
1081
1082fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1083 const arena = sema.arena;
1084 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1085 const extra = sema.code.extraData(zir.Inst.Float128, inst_data.payload_index).data;
1086 const src = inst_data.src();
1087 const number = extra.get();
1088
1089 return sema.mod.constInst(arena, src, .{
1090 .ty = Type.initTag(.comptime_float),
1091 .val = try Value.Tag.float_128.create(arena, number),
1092 });
1093}
1094
1073fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {1095fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {
1074 const tracy = trace(@src());1096 const tracy = trace(@src());
1075 defer tracy.end();1097 defer tracy.end();
...@@ -1385,7 +1407,7 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -1385,7 +1407,7 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
13851407
1386 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1408 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1387 const src = inst_data.src();1409 const src = inst_data.src();
1388 const decl = sema.code.decls[inst_data.payload_index];1410 const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;
1389 return sema.analyzeDeclRef(block, src, decl);1411 return sema.analyzeDeclRef(block, src, decl);
1390}1412}
13911413
...@@ -1395,7 +1417,7 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -1395,7 +1417,7 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
13951417
1396 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1418 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1397 const src = inst_data.src();1419 const src = inst_data.src();
1398 const decl = sema.code.decls[inst_data.payload_index];1420 const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;
1399 return sema.analyzeDeclVal(block, src, decl);1421 return sema.analyzeDeclVal(block, src, decl);
1400}1422}
14011423
...@@ -1852,6 +1874,120 @@ fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) I...@@ -1852,6 +1874,120 @@ fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) I
1852 });1874 });
1853}1875}
18541876
1877fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1878 const mod = sema.mod;
1879 const arena = sema.arena;
1880 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1881 const src = inst_data.src();
1882 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1883 const operand = try sema.resolveInst(inst_data.operand);
1884
1885 const enum_tag: *Inst = switch (operand.ty.zigTypeTag()) {
1886 .Enum => operand,
1887 .Union => {
1888 //if (!operand.ty.unionHasTag()) {
1889 // return mod.fail(
1890 // &block.base,
1891 // operand_src,
1892 // "untagged union '{}' cannot be converted to integer",
1893 // .{dest_ty_src},
1894 // );
1895 //}
1896 return mod.fail(&block.base, operand_src, "TODO zirEnumToInt for tagged unions", .{});
1897 },
1898 else => {
1899 return mod.fail(&block.base, operand_src, "expected enum or tagged union, found {}", .{
1900 operand.ty,
1901 });
1902 },
1903 };
1904
1905 var int_tag_type_buffer: Type.Payload.Bits = undefined;
1906 const int_tag_ty = try enum_tag.ty.intTagType(&int_tag_type_buffer).copy(arena);
1907
1908 if (enum_tag.ty.onePossibleValue()) |opv| {
1909 return mod.constInst(arena, src, .{
1910 .ty = int_tag_ty,
1911 .val = opv,
1912 });
1913 }
1914
1915 if (enum_tag.value()) |enum_tag_val| {
1916 if (enum_tag_val.castTag(.enum_field_index)) |enum_field_payload| {
1917 const field_index = enum_field_payload.data;
1918 switch (enum_tag.ty.tag()) {
1919 .enum_full => {
1920 const enum_full = enum_tag.ty.castTag(.enum_full).?.data;
1921 const val = enum_full.values.entries.items[field_index].key;
1922 return mod.constInst(arena, src, .{
1923 .ty = int_tag_ty,
1924 .val = val,
1925 });
1926 },
1927 .enum_simple => {
1928 // Field index and integer values are the same.
1929 const val = try Value.Tag.int_u64.create(arena, field_index);
1930 return mod.constInst(arena, src, .{
1931 .ty = int_tag_ty,
1932 .val = val,
1933 });
1934 },
1935 else => unreachable,
1936 }
1937 } else {
1938 // Assume it is already an integer and return it directly.
1939 return mod.constInst(arena, src, .{
1940 .ty = int_tag_ty,
1941 .val = enum_tag_val,
1942 });
1943 }
1944 }
1945
1946 try sema.requireRuntimeBlock(block, src);
1947 return block.addUnOp(src, int_tag_ty, .bitcast, enum_tag);
1948}
1949
1950fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
1951 const mod = sema.mod;
1952 const target = mod.getTarget();
1953 const arena = sema.arena;
1954 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1955 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
1956 const src = inst_data.src();
1957 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1958 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1959 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
1960 const operand = try sema.resolveInst(extra.rhs);
1961
1962 if (dest_ty.zigTypeTag() != .Enum) {
1963 return mod.fail(&block.base, dest_ty_src, "expected enum, found {}", .{dest_ty});
1964 }
1965
1966 if (!dest_ty.isExhaustiveEnum()) {
1967 if (operand.value()) |int_val| {
1968 return mod.constInst(arena, src, .{
1969 .ty = dest_ty,
1970 .val = int_val,
1971 });
1972 }
1973 }
1974
1975 if (try sema.resolveDefinedValue(block, operand_src, operand)) |int_val| {
1976 if (!dest_ty.enumHasInt(int_val, target)) {
1977 return mod.fail(&block.base, src, "enum '{}' has no tag with value {}", .{
1978 dest_ty, int_val,
1979 });
1980 }
1981 return mod.constInst(arena, src, .{
1982 .ty = dest_ty,
1983 .val = int_val,
1984 });
1985 }
1986
1987 try sema.requireRuntimeBlock(block, src);
1988 return block.addUnOp(src, dest_ty, .bitcast, operand);
1989}
1990
1855/// Pointer in, pointer out.1991/// Pointer in, pointer out.
1856fn zirOptionalPayloadPtr(1992fn zirOptionalPayloadPtr(
1857 sema: *Sema,1993 sema: *Sema,
...@@ -4630,7 +4766,7 @@ fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl...@@ -4630,7 +4766,7 @@ fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl
4630}4766}
46314767
4632fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {4768fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
4633 try sema.mod.declareDeclDependency(sema.owner_decl, decl);4769 _ = try sema.mod.declareDeclDependency(sema.owner_decl, decl);
4634 sema.mod.ensureDeclAnalyzed(decl) catch |err| {4770 sema.mod.ensureDeclAnalyzed(decl) catch |err| {
4635 if (sema.func) |func| {4771 if (sema.func) |func| {
4636 func.state = .dependency_failure;4772 func.state = .dependency_failure;
src/type.zig+301-1556
...@@ -93,9 +93,15 @@ pub const Type = extern union {...@@ -93,9 +93,15 @@ pub const Type = extern union {
9393
94 .anyerror_void_error_union, .error_union => return .ErrorUnion,94 .anyerror_void_error_union, .error_union => return .ErrorUnion,
9595
96 .empty_struct => return .Struct,96 .empty_struct,
97 .empty_struct_literal => return .Struct,97 .empty_struct_literal,
98 .@"struct" => return .Struct,98 .@"struct",
99 => return .Struct,
100
101 .enum_full,
102 .enum_nonexhaustive,
103 .enum_simple,
104 => return .Enum,
99105
100 .var_args_param => unreachable, // can be any type106 .var_args_param => unreachable, // can be any type
101 }107 }
...@@ -614,6 +620,8 @@ pub const Type = extern union {...@@ -614,6 +620,8 @@ pub const Type = extern union {
614 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),620 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
615 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),621 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
616 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),622 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
623 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),
624 .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull),
617 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),625 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
618 }626 }
619 }627 }
...@@ -629,8 +637,8 @@ pub const Type = extern union {...@@ -629,8 +637,8 @@ pub const Type = extern union {
629 self: Type,637 self: Type,
630 comptime fmt: []const u8,638 comptime fmt: []const u8,
631 options: std.fmt.FormatOptions,639 options: std.fmt.FormatOptions,
632 out_stream: anytype,640 writer: anytype,
633 ) @TypeOf(out_stream).Error!void {641 ) @TypeOf(writer).Error!void {
634 comptime assert(fmt.len == 0);642 comptime assert(fmt.len == 0);
635 var ty = self;643 var ty = self;
636 while (true) {644 while (true) {
...@@ -670,132 +678,149 @@ pub const Type = extern union {...@@ -670,132 +678,149 @@ pub const Type = extern union {
670 .comptime_float,678 .comptime_float,
671 .noreturn,679 .noreturn,
672 .var_args_param,680 .var_args_param,
673 => return out_stream.writeAll(@tagName(t)),681 => return writer.writeAll(@tagName(t)),
674682
675 .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"),683 .enum_literal => return writer.writeAll("@Type(.EnumLiteral)"),
676 .@"null" => return out_stream.writeAll("@Type(.Null)"),684 .@"null" => return writer.writeAll("@Type(.Null)"),
677 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),685 .@"undefined" => return writer.writeAll("@Type(.Undefined)"),
678686
679 .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"),687 .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"),
680 .@"struct" => return out_stream.writeAll("(struct)"),688
681 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),689 .@"struct" => {
682 .const_slice_u8 => return out_stream.writeAll("[]const u8"),690 const struct_obj = self.castTag(.@"struct").?.data;
683 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),691 return struct_obj.owner_decl.renderFullyQualifiedName(writer);
684 .fn_void_no_args => return out_stream.writeAll("fn() void"),692 },
685 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),693 .enum_full, .enum_nonexhaustive => {
686 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),694 const enum_full = self.castTag(.enum_full).?.data;
687 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),695 return enum_full.owner_decl.renderFullyQualifiedName(writer);
696 },
697 .enum_simple => {
698 const enum_simple = self.castTag(.enum_simple).?.data;
699 return enum_simple.owner_decl.renderFullyQualifiedName(writer);
700 },
701 .@"opaque" => {
702 // TODO use declaration name
703 return writer.writeAll("opaque {}");
704 },
705
706 .anyerror_void_error_union => return writer.writeAll("anyerror!void"),
707 .const_slice_u8 => return writer.writeAll("[]const u8"),
708 .fn_noreturn_no_args => return writer.writeAll("fn() noreturn"),
709 .fn_void_no_args => return writer.writeAll("fn() void"),
710 .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"),
711 .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"),
712 .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),
688 .function => {713 .function => {
689 const payload = ty.castTag(.function).?.data;714 const payload = ty.castTag(.function).?.data;
690 try out_stream.writeAll("fn(");715 try writer.writeAll("fn(");
691 for (payload.param_types) |param_type, i| {716 for (payload.param_types) |param_type, i| {
692 if (i != 0) try out_stream.writeAll(", ");717 if (i != 0) try writer.writeAll(", ");
693 try param_type.format("", .{}, out_stream);718 try param_type.format("", .{}, writer);
694 }719 }
695 if (payload.is_var_args) {720 if (payload.is_var_args) {
696 if (payload.param_types.len != 0) {721 if (payload.param_types.len != 0) {
697 try out_stream.writeAll(", ");722 try writer.writeAll(", ");
698 }723 }
699 try out_stream.writeAll("...");724 try writer.writeAll("...");
700 }725 }
701 try out_stream.writeAll(") callconv(.");726 try writer.writeAll(") callconv(.");
702 try out_stream.writeAll(@tagName(payload.cc));727 try writer.writeAll(@tagName(payload.cc));
703 try out_stream.writeAll(")");728 try writer.writeAll(")");
704 ty = payload.return_type;729 ty = payload.return_type;
705 continue;730 continue;
706 },731 },
707732
708 .array_u8 => {733 .array_u8 => {
709 const len = ty.castTag(.array_u8).?.data;734 const len = ty.castTag(.array_u8).?.data;
710 return out_stream.print("[{d}]u8", .{len});735 return writer.print("[{d}]u8", .{len});
711 },736 },
712 .array_u8_sentinel_0 => {737 .array_u8_sentinel_0 => {
713 const len = ty.castTag(.array_u8_sentinel_0).?.data;738 const len = ty.castTag(.array_u8_sentinel_0).?.data;
714 return out_stream.print("[{d}:0]u8", .{len});739 return writer.print("[{d}:0]u8", .{len});
715 },740 },
716 .array => {741 .array => {
717 const payload = ty.castTag(.array).?.data;742 const payload = ty.castTag(.array).?.data;
718 try out_stream.print("[{d}]", .{payload.len});743 try writer.print("[{d}]", .{payload.len});
719 ty = payload.elem_type;744 ty = payload.elem_type;
720 continue;745 continue;
721 },746 },
722 .array_sentinel => {747 .array_sentinel => {
723 const payload = ty.castTag(.array_sentinel).?.data;748 const payload = ty.castTag(.array_sentinel).?.data;
724 try out_stream.print("[{d}:{}]", .{ payload.len, payload.sentinel });749 try writer.print("[{d}:{}]", .{ payload.len, payload.sentinel });
725 ty = payload.elem_type;750 ty = payload.elem_type;
726 continue;751 continue;
727 },752 },
728 .single_const_pointer => {753 .single_const_pointer => {
729 const pointee_type = ty.castTag(.single_const_pointer).?.data;754 const pointee_type = ty.castTag(.single_const_pointer).?.data;
730 try out_stream.writeAll("*const ");755 try writer.writeAll("*const ");
731 ty = pointee_type;756 ty = pointee_type;
732 continue;757 continue;
733 },758 },
734 .single_mut_pointer => {759 .single_mut_pointer => {
735 const pointee_type = ty.castTag(.single_mut_pointer).?.data;760 const pointee_type = ty.castTag(.single_mut_pointer).?.data;
736 try out_stream.writeAll("*");761 try writer.writeAll("*");
737 ty = pointee_type;762 ty = pointee_type;
738 continue;763 continue;
739 },764 },
740 .many_const_pointer => {765 .many_const_pointer => {
741 const pointee_type = ty.castTag(.many_const_pointer).?.data;766 const pointee_type = ty.castTag(.many_const_pointer).?.data;
742 try out_stream.writeAll("[*]const ");767 try writer.writeAll("[*]const ");
743 ty = pointee_type;768 ty = pointee_type;
744 continue;769 continue;
745 },770 },
746 .many_mut_pointer => {771 .many_mut_pointer => {
747 const pointee_type = ty.castTag(.many_mut_pointer).?.data;772 const pointee_type = ty.castTag(.many_mut_pointer).?.data;
748 try out_stream.writeAll("[*]");773 try writer.writeAll("[*]");
749 ty = pointee_type;774 ty = pointee_type;
750 continue;775 continue;
751 },776 },
752 .c_const_pointer => {777 .c_const_pointer => {
753 const pointee_type = ty.castTag(.c_const_pointer).?.data;778 const pointee_type = ty.castTag(.c_const_pointer).?.data;
754 try out_stream.writeAll("[*c]const ");779 try writer.writeAll("[*c]const ");
755 ty = pointee_type;780 ty = pointee_type;
756 continue;781 continue;
757 },782 },
758 .c_mut_pointer => {783 .c_mut_pointer => {
759 const pointee_type = ty.castTag(.c_mut_pointer).?.data;784 const pointee_type = ty.castTag(.c_mut_pointer).?.data;
760 try out_stream.writeAll("[*c]");785 try writer.writeAll("[*c]");
761 ty = pointee_type;786 ty = pointee_type;
762 continue;787 continue;
763 },788 },
764 .const_slice => {789 .const_slice => {
765 const pointee_type = ty.castTag(.const_slice).?.data;790 const pointee_type = ty.castTag(.const_slice).?.data;
766 try out_stream.writeAll("[]const ");791 try writer.writeAll("[]const ");
767 ty = pointee_type;792 ty = pointee_type;
768 continue;793 continue;
769 },794 },
770 .mut_slice => {795 .mut_slice => {
771 const pointee_type = ty.castTag(.mut_slice).?.data;796 const pointee_type = ty.castTag(.mut_slice).?.data;
772 try out_stream.writeAll("[]");797 try writer.writeAll("[]");
773 ty = pointee_type;798 ty = pointee_type;
774 continue;799 continue;
775 },800 },
776 .int_signed => {801 .int_signed => {
777 const bits = ty.castTag(.int_signed).?.data;802 const bits = ty.castTag(.int_signed).?.data;
778 return out_stream.print("i{d}", .{bits});803 return writer.print("i{d}", .{bits});
779 },804 },
780 .int_unsigned => {805 .int_unsigned => {
781 const bits = ty.castTag(.int_unsigned).?.data;806 const bits = ty.castTag(.int_unsigned).?.data;
782 return out_stream.print("u{d}", .{bits});807 return writer.print("u{d}", .{bits});
783 },808 },
784 .optional => {809 .optional => {
785 const child_type = ty.castTag(.optional).?.data;810 const child_type = ty.castTag(.optional).?.data;
786 try out_stream.writeByte('?');811 try writer.writeByte('?');
787 ty = child_type;812 ty = child_type;
788 continue;813 continue;
789 },814 },
790 .optional_single_const_pointer => {815 .optional_single_const_pointer => {
791 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;816 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;
792 try out_stream.writeAll("?*const ");817 try writer.writeAll("?*const ");
793 ty = pointee_type;818 ty = pointee_type;
794 continue;819 continue;
795 },820 },
796 .optional_single_mut_pointer => {821 .optional_single_mut_pointer => {
797 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;822 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;
798 try out_stream.writeAll("?*");823 try writer.writeAll("?*");
799 ty = pointee_type;824 ty = pointee_type;
800 continue;825 continue;
801 },826 },
...@@ -804,48 +829,46 @@ pub const Type = extern union {...@@ -804,48 +829,46 @@ pub const Type = extern union {
804 const payload = ty.castTag(.pointer).?.data;829 const payload = ty.castTag(.pointer).?.data;
805 if (payload.sentinel) |some| switch (payload.size) {830 if (payload.sentinel) |some| switch (payload.size) {
806 .One, .C => unreachable,831 .One, .C => unreachable,
807 .Many => try out_stream.print("[*:{}]", .{some}),832 .Many => try writer.print("[*:{}]", .{some}),
808 .Slice => try out_stream.print("[:{}]", .{some}),833 .Slice => try writer.print("[:{}]", .{some}),
809 } else switch (payload.size) {834 } else switch (payload.size) {
810 .One => try out_stream.writeAll("*"),835 .One => try writer.writeAll("*"),
811 .Many => try out_stream.writeAll("[*]"),836 .Many => try writer.writeAll("[*]"),
812 .C => try out_stream.writeAll("[*c]"),837 .C => try writer.writeAll("[*c]"),
813 .Slice => try out_stream.writeAll("[]"),838 .Slice => try writer.writeAll("[]"),
814 }839 }
815 if (payload.@"align" != 0) {840 if (payload.@"align" != 0) {
816 try out_stream.print("align({d}", .{payload.@"align"});841 try writer.print("align({d}", .{payload.@"align"});
817842
818 if (payload.bit_offset != 0) {843 if (payload.bit_offset != 0) {
819 try out_stream.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size });844 try writer.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size });
820 }845 }
821 try out_stream.writeAll(") ");846 try writer.writeAll(") ");
822 }847 }
823 if (!payload.mutable) try out_stream.writeAll("const ");848 if (!payload.mutable) try writer.writeAll("const ");
824 if (payload.@"volatile") try out_stream.writeAll("volatile ");849 if (payload.@"volatile") try writer.writeAll("volatile ");
825 if (payload.@"allowzero") try out_stream.writeAll("allowzero ");850 if (payload.@"allowzero") try writer.writeAll("allowzero ");
826851
827 ty = payload.pointee_type;852 ty = payload.pointee_type;
828 continue;853 continue;
829 },854 },
830 .error_union => {855 .error_union => {
831 const payload = ty.castTag(.error_union).?.data;856 const payload = ty.castTag(.error_union).?.data;
832 try payload.error_set.format("", .{}, out_stream);857 try payload.error_set.format("", .{}, writer);
833 try out_stream.writeAll("!");858 try writer.writeAll("!");
834 ty = payload.payload;859 ty = payload.payload;
835 continue;860 continue;
836 },861 },
837 .error_set => {862 .error_set => {
838 const error_set = ty.castTag(.error_set).?.data;863 const error_set = ty.castTag(.error_set).?.data;
839 return out_stream.writeAll(std.mem.spanZ(error_set.owner_decl.name));864 return writer.writeAll(std.mem.spanZ(error_set.owner_decl.name));
840 },865 },
841 .error_set_single => {866 .error_set_single => {
842 const name = ty.castTag(.error_set_single).?.data;867 const name = ty.castTag(.error_set_single).?.data;
843 return out_stream.print("error{{{s}}}", .{name});868 return writer.print("error{{{s}}}", .{name});
844 },869 },
845 .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"),870 .inferred_alloc_const => return writer.writeAll("(inferred_alloc_const)"),
846 .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"),871 .inferred_alloc_mut => return writer.writeAll("(inferred_alloc_mut)"),
847 // TODO use declaration name
848 .@"opaque" => return out_stream.writeAll("opaque {}"),
849 }872 }
850 unreachable;873 unreachable;
851 }874 }
...@@ -954,6 +977,19 @@ pub const Type = extern union {...@@ -954,6 +977,19 @@ pub const Type = extern union {
954 return false;977 return false;
955 }978 }
956 },979 },
980 .enum_full => {
981 const enum_full = self.castTag(.enum_full).?.data;
982 return enum_full.fields.count() >= 2;
983 },
984 .enum_simple => {
985 const enum_simple = self.castTag(.enum_simple).?.data;
986 return enum_simple.fields.count() >= 2;
987 },
988 .enum_nonexhaustive => {
989 var buffer: Payload.Bits = undefined;
990 const int_tag_ty = self.intTagType(&buffer);
991 return int_tag_ty.hasCodeGenBits();
992 },
957993
958 // TODO lazy types994 // TODO lazy types
959 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,995 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
...@@ -1112,13 +1148,37 @@ pub const Type = extern union {...@@ -1112,13 +1148,37 @@ pub const Type = extern union {
1112 } else if (!payload.payload.hasCodeGenBits()) {1148 } else if (!payload.payload.hasCodeGenBits()) {
1113 return payload.error_set.abiAlignment(target);1149 return payload.error_set.abiAlignment(target);
1114 }1150 }
1115 @panic("TODO abiAlignment error union");1151 return std.math.max(
1152 payload.payload.abiAlignment(target),
1153 payload.error_set.abiAlignment(target),
1154 );
1116 },1155 },
11171156
1118 .@"struct" => {1157 .@"struct" => {
1119 @panic("TODO abiAlignment struct");1158 // TODO take into account field alignment
1159 // also make this possible to fail, and lazy
1160 // I think we need to move all the functions from type.zig which can
1161 // fail into Sema.
1162 // Probably will need to introduce multi-stage struct resolution just
1163 // like we have in stage1.
1164 const struct_obj = self.castTag(.@"struct").?.data;
1165 var biggest: u32 = 0;
1166 for (struct_obj.fields.entries.items) |entry| {
1167 const field_ty = entry.value.ty;
1168 if (!field_ty.hasCodeGenBits()) continue;
1169 const field_align = field_ty.abiAlignment(target);
1170 if (field_align > biggest) {
1171 return field_align;
1172 }
1173 }
1174 assert(biggest != 0);
1175 return biggest;
1176 },
1177 .enum_full, .enum_nonexhaustive, .enum_simple => {
1178 var buffer: Payload.Bits = undefined;
1179 const int_tag_ty = self.intTagType(&buffer);
1180 return int_tag_ty.abiAlignment(target);
1120 },1181 },
1121
1122 .c_void,1182 .c_void,
1123 .void,1183 .void,
1124 .type,1184 .type,
...@@ -1166,6 +1226,11 @@ pub const Type = extern union {...@@ -1166,6 +1226,11 @@ pub const Type = extern union {
1166 .@"struct" => {1226 .@"struct" => {
1167 @panic("TODO abiSize struct");1227 @panic("TODO abiSize struct");
1168 },1228 },
1229 .enum_simple, .enum_full, .enum_nonexhaustive => {
1230 var buffer: Payload.Bits = undefined;
1231 const int_tag_ty = self.intTagType(&buffer);
1232 return int_tag_ty.abiSize(target);
1233 },
11691234
1170 .u8,1235 .u8,
1171 .i8,1236 .i8,
...@@ -1276,76 +1341,25 @@ pub const Type = extern union {...@@ -1276,76 +1341,25 @@ pub const Type = extern union {
1276 };1341 };
1277 }1342 }
12781343
1344 /// Asserts the type is an enum.
1345 pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {
1346 switch (self.tag()) {
1347 .enum_full, .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty,
1348 .enum_simple => {
1349 const enum_simple = self.castTag(.enum_simple).?.data;
1350 const bits = std.math.log2_int_ceil(usize, enum_simple.fields.count());
1351 buffer.* = .{
1352 .base = .{ .tag = .int_unsigned },
1353 .data = bits,
1354 };
1355 return Type.initPayload(&buffer.base);
1356 },
1357 else => unreachable,
1358 }
1359 }
1360
1279 pub fn isSinglePointer(self: Type) bool {1361 pub fn isSinglePointer(self: Type) bool {
1280 return switch (self.tag()) {1362 return switch (self.tag()) {
1281 .u8,
1282 .i8,
1283 .u16,
1284 .i16,
1285 .u32,
1286 .i32,
1287 .u64,
1288 .i64,
1289 .u128,
1290 .i128,
1291 .usize,
1292 .isize,
1293 .c_short,
1294 .c_ushort,
1295 .c_int,
1296 .c_uint,
1297 .c_long,
1298 .c_ulong,
1299 .c_longlong,
1300 .c_ulonglong,
1301 .c_longdouble,
1302 .f16,
1303 .f32,
1304 .f64,
1305 .f128,
1306 .c_void,
1307 .bool,
1308 .void,
1309 .type,
1310 .anyerror,
1311 .comptime_int,
1312 .comptime_float,
1313 .noreturn,
1314 .@"null",
1315 .@"undefined",
1316 .array,
1317 .array_sentinel,
1318 .array_u8,
1319 .array_u8_sentinel_0,
1320 .const_slice_u8,
1321 .fn_noreturn_no_args,
1322 .fn_void_no_args,
1323 .fn_naked_noreturn_no_args,
1324 .fn_ccc_void_no_args,
1325 .function,
1326 .int_unsigned,
1327 .int_signed,
1328 .optional,
1329 .optional_single_mut_pointer,
1330 .optional_single_const_pointer,
1331 .enum_literal,
1332 .many_const_pointer,
1333 .many_mut_pointer,
1334 .c_const_pointer,
1335 .c_mut_pointer,
1336 .const_slice,
1337 .mut_slice,
1338 .error_union,
1339 .anyerror_void_error_union,
1340 .error_set,
1341 .error_set_single,
1342 .@"struct",
1343 .empty_struct,
1344 .empty_struct_literal,
1345 .@"opaque",
1346 .var_args_param,
1347 => false,
1348
1349 .single_const_pointer,1363 .single_const_pointer,
1350 .single_mut_pointer,1364 .single_mut_pointer,
1351 .single_const_pointer_to_comptime_int,1365 .single_const_pointer_to_comptime_int,
...@@ -1354,73 +1368,14 @@ pub const Type = extern union {...@@ -1354,73 +1368,14 @@ pub const Type = extern union {
1354 => true,1368 => true,
13551369
1356 .pointer => self.castTag(.pointer).?.data.size == .One,1370 .pointer => self.castTag(.pointer).?.data.size == .One,
1371
1372 else => false,
1357 };1373 };
1358 }1374 }
13591375
1360 /// Asserts the `Type` is a pointer.1376 /// Asserts the `Type` is a pointer.
1361 pub fn ptrSize(self: Type) std.builtin.TypeInfo.Pointer.Size {1377 pub fn ptrSize(self: Type) std.builtin.TypeInfo.Pointer.Size {
1362 return switch (self.tag()) {1378 return switch (self.tag()) {
1363 .u8,
1364 .i8,
1365 .u16,
1366 .i16,
1367 .u32,
1368 .i32,
1369 .u64,
1370 .i64,
1371 .u128,
1372 .i128,
1373 .usize,
1374 .isize,
1375 .c_short,
1376 .c_ushort,
1377 .c_int,
1378 .c_uint,
1379 .c_long,
1380 .c_ulong,
1381 .c_longlong,
1382 .c_ulonglong,
1383 .c_longdouble,
1384 .f16,
1385 .f32,
1386 .f64,
1387 .f128,
1388 .c_void,
1389 .bool,
1390 .void,
1391 .type,
1392 .anyerror,
1393 .comptime_int,
1394 .comptime_float,
1395 .noreturn,
1396 .@"null",
1397 .@"undefined",
1398 .array,
1399 .array_sentinel,
1400 .array_u8,
1401 .array_u8_sentinel_0,
1402 .fn_noreturn_no_args,
1403 .fn_void_no_args,
1404 .fn_naked_noreturn_no_args,
1405 .fn_ccc_void_no_args,
1406 .function,
1407 .int_unsigned,
1408 .int_signed,
1409 .optional,
1410 .optional_single_mut_pointer,
1411 .optional_single_const_pointer,
1412 .enum_literal,
1413 .error_union,
1414 .anyerror_void_error_union,
1415 .error_set,
1416 .error_set_single,
1417 .empty_struct,
1418 .empty_struct_literal,
1419 .@"opaque",
1420 .@"struct",
1421 .var_args_param,
1422 => unreachable,
1423
1424 .const_slice,1379 .const_slice,
1425 .mut_slice,1380 .mut_slice,
1426 .const_slice_u8,1381 .const_slice_u8,
...@@ -1442,159 +1397,26 @@ pub const Type = extern union {...@@ -1442,159 +1397,26 @@ pub const Type = extern union {
1442 => .One,1397 => .One,
14431398
1444 .pointer => self.castTag(.pointer).?.data.size,1399 .pointer => self.castTag(.pointer).?.data.size,
1400
1401 else => unreachable,
1445 };1402 };
1446 }1403 }
14471404
1448 pub fn isSlice(self: Type) bool {1405 pub fn isSlice(self: Type) bool {
1449 return switch (self.tag()) {1406 return switch (self.tag()) {
1450 .u8,
1451 .i8,
1452 .u16,
1453 .i16,
1454 .u32,
1455 .i32,
1456 .u64,
1457 .i64,
1458 .u128,
1459 .i128,
1460 .usize,
1461 .isize,
1462 .c_short,
1463 .c_ushort,
1464 .c_int,
1465 .c_uint,
1466 .c_long,
1467 .c_ulong,
1468 .c_longlong,
1469 .c_ulonglong,
1470 .c_longdouble,
1471 .f16,
1472 .f32,
1473 .f64,
1474 .f128,
1475 .c_void,
1476 .bool,
1477 .void,
1478 .type,
1479 .anyerror,
1480 .comptime_int,
1481 .comptime_float,
1482 .noreturn,
1483 .@"null",
1484 .@"undefined",
1485 .array,
1486 .array_sentinel,
1487 .array_u8,
1488 .array_u8_sentinel_0,
1489 .single_const_pointer,
1490 .single_mut_pointer,
1491 .many_const_pointer,
1492 .many_mut_pointer,
1493 .c_const_pointer,
1494 .c_mut_pointer,
1495 .single_const_pointer_to_comptime_int,
1496 .fn_noreturn_no_args,
1497 .fn_void_no_args,
1498 .fn_naked_noreturn_no_args,
1499 .fn_ccc_void_no_args,
1500 .function,
1501 .int_unsigned,
1502 .int_signed,
1503 .optional,
1504 .optional_single_mut_pointer,
1505 .optional_single_const_pointer,
1506 .enum_literal,
1507 .error_union,
1508 .anyerror_void_error_union,
1509 .error_set,
1510 .error_set_single,
1511 .empty_struct,
1512 .empty_struct_literal,
1513 .inferred_alloc_const,
1514 .inferred_alloc_mut,
1515 .@"struct",
1516 .@"opaque",
1517 .var_args_param,
1518 => false,
1519
1520 .const_slice,1407 .const_slice,
1521 .mut_slice,1408 .mut_slice,
1522 .const_slice_u8,1409 .const_slice_u8,
1523 => true,1410 => true,
15241411
1525 .pointer => self.castTag(.pointer).?.data.size == .Slice,1412 .pointer => self.castTag(.pointer).?.data.size == .Slice,
1413
1414 else => false,
1526 };1415 };
1527 }1416 }
15281417
1529 pub fn isConstPtr(self: Type) bool {1418 pub fn isConstPtr(self: Type) bool {
1530 return switch (self.tag()) {1419 return switch (self.tag()) {
1531 .u8,
1532 .i8,
1533 .u16,
1534 .i16,
1535 .u32,
1536 .i32,
1537 .u64,
1538 .i64,
1539 .u128,
1540 .i128,
1541 .usize,
1542 .isize,
1543 .c_short,
1544 .c_ushort,
1545 .c_int,
1546 .c_uint,
1547 .c_long,
1548 .c_ulong,
1549 .c_longlong,
1550 .c_ulonglong,
1551 .c_longdouble,
1552 .f16,
1553 .f32,
1554 .f64,
1555 .f128,
1556 .c_void,
1557 .bool,
1558 .void,
1559 .type,
1560 .anyerror,
1561 .comptime_int,
1562 .comptime_float,
1563 .noreturn,
1564 .@"null",
1565 .@"undefined",
1566 .array,
1567 .array_sentinel,
1568 .array_u8,
1569 .array_u8_sentinel_0,
1570 .fn_noreturn_no_args,
1571 .fn_void_no_args,
1572 .fn_naked_noreturn_no_args,
1573 .fn_ccc_void_no_args,
1574 .function,
1575 .int_unsigned,
1576 .int_signed,
1577 .single_mut_pointer,
1578 .many_mut_pointer,
1579 .c_mut_pointer,
1580 .optional,
1581 .optional_single_mut_pointer,
1582 .optional_single_const_pointer,
1583 .enum_literal,
1584 .mut_slice,
1585 .error_union,
1586 .anyerror_void_error_union,
1587 .error_set,
1588 .error_set_single,
1589 .empty_struct,
1590 .empty_struct_literal,
1591 .inferred_alloc_const,
1592 .inferred_alloc_mut,
1593 .@"struct",
1594 .@"opaque",
1595 .var_args_param,
1596 => false,
1597
1598 .single_const_pointer,1420 .single_const_pointer,
1599 .many_const_pointer,1421 .many_const_pointer,
1600 .c_const_pointer,1422 .c_const_pointer,
...@@ -1604,170 +1426,40 @@ pub const Type = extern union {...@@ -1604,170 +1426,40 @@ pub const Type = extern union {
1604 => true,1426 => true,
16051427
1606 .pointer => !self.castTag(.pointer).?.data.mutable,1428 .pointer => !self.castTag(.pointer).?.data.mutable,
1429
1430 else => false,
1607 };1431 };
1608 }1432 }
16091433
1610 pub fn isVolatilePtr(self: Type) bool {1434 pub fn isVolatilePtr(self: Type) bool {
1611 return switch (self.tag()) {1435 return switch (self.tag()) {
1612 .u8,
1613 .i8,
1614 .u16,
1615 .i16,
1616 .u32,
1617 .i32,
1618 .u64,
1619 .i64,
1620 .u128,
1621 .i128,
1622 .usize,
1623 .isize,
1624 .c_short,
1625 .c_ushort,
1626 .c_int,
1627 .c_uint,
1628 .c_long,
1629 .c_ulong,
1630 .c_longlong,
1631 .c_ulonglong,
1632 .c_longdouble,
1633 .f16,
1634 .f32,
1635 .f64,
1636 .f128,
1637 .c_void,
1638 .bool,
1639 .void,
1640 .type,
1641 .anyerror,
1642 .comptime_int,
1643 .comptime_float,
1644 .noreturn,
1645 .@"null",
1646 .@"undefined",
1647 .array,
1648 .array_sentinel,
1649 .array_u8,
1650 .array_u8_sentinel_0,
1651 .fn_noreturn_no_args,
1652 .fn_void_no_args,
1653 .fn_naked_noreturn_no_args,
1654 .fn_ccc_void_no_args,
1655 .function,
1656 .int_unsigned,
1657 .int_signed,
1658 .single_mut_pointer,
1659 .single_const_pointer,
1660 .many_const_pointer,
1661 .many_mut_pointer,
1662 .c_const_pointer,
1663 .c_mut_pointer,
1664 .const_slice,
1665 .mut_slice,
1666 .single_const_pointer_to_comptime_int,
1667 .const_slice_u8,
1668 .optional,
1669 .optional_single_mut_pointer,
1670 .optional_single_const_pointer,
1671 .enum_literal,
1672 .error_union,
1673 .anyerror_void_error_union,
1674 .error_set,
1675 .error_set_single,
1676 .empty_struct,
1677 .empty_struct_literal,
1678 .inferred_alloc_const,
1679 .inferred_alloc_mut,
1680 .@"struct",
1681 .@"opaque",
1682 .var_args_param,
1683 => false,
1684
1685 .pointer => {1436 .pointer => {
1686 const payload = self.castTag(.pointer).?.data;1437 const payload = self.castTag(.pointer).?.data;
1687 return payload.@"volatile";1438 return payload.@"volatile";
1688 },1439 },
1440 else => false,
1689 };1441 };
1690 }1442 }
16911443
1692 pub fn isAllowzeroPtr(self: Type) bool {1444 pub fn isAllowzeroPtr(self: Type) bool {
1693 return switch (self.tag()) {1445 return switch (self.tag()) {
1694 .u8,
1695 .i8,
1696 .u16,
1697 .i16,
1698 .u32,
1699 .i32,
1700 .u64,
1701 .i64,
1702 .u128,
1703 .i128,
1704 .usize,
1705 .isize,
1706 .c_short,
1707 .c_ushort,
1708 .c_int,
1709 .c_uint,
1710 .c_long,
1711 .c_ulong,
1712 .c_longlong,
1713 .c_ulonglong,
1714 .c_longdouble,
1715 .f16,
1716 .f32,
1717 .f64,
1718 .f128,
1719 .c_void,
1720 .bool,
1721 .void,
1722 .type,
1723 .anyerror,
1724 .comptime_int,
1725 .comptime_float,
1726 .noreturn,
1727 .@"null",
1728 .@"undefined",
1729 .array,
1730 .array_sentinel,
1731 .array_u8,
1732 .array_u8_sentinel_0,
1733 .fn_noreturn_no_args,
1734 .fn_void_no_args,
1735 .fn_naked_noreturn_no_args,
1736 .fn_ccc_void_no_args,
1737 .function,
1738 .int_unsigned,
1739 .int_signed,
1740 .single_mut_pointer,
1741 .single_const_pointer,
1742 .many_const_pointer,
1743 .many_mut_pointer,
1744 .c_const_pointer,
1745 .c_mut_pointer,
1746 .const_slice,
1747 .mut_slice,
1748 .single_const_pointer_to_comptime_int,
1749 .const_slice_u8,
1750 .optional,
1751 .optional_single_mut_pointer,
1752 .optional_single_const_pointer,
1753 .enum_literal,
1754 .error_union,
1755 .anyerror_void_error_union,
1756 .error_set,
1757 .error_set_single,
1758 .empty_struct,
1759 .empty_struct_literal,
1760 .inferred_alloc_const,
1761 .inferred_alloc_mut,
1762 .@"struct",
1763 .@"opaque",
1764 .var_args_param,
1765 => false,
1766
1767 .pointer => {1446 .pointer => {
1768 const payload = self.castTag(.pointer).?.data;1447 const payload = self.castTag(.pointer).?.data;
1769 return payload.@"allowzero";1448 return payload.@"allowzero";
1770 },1449 },
1450 else => false,
1451 };
1452 }
1453
1454 pub fn isCPtr(self: Type) bool {
1455 return switch (self.tag()) {
1456 .c_const_pointer,
1457 .c_mut_pointer,
1458 => return true,
1459
1460 .pointer => self.castTag(.pointer).?.data.size == .C,
1461
1462 else => return false,
1771 };1463 };
1772 }1464 }
17731465
...@@ -1833,64 +1525,6 @@ pub const Type = extern union {...@@ -1833,64 +1525,6 @@ pub const Type = extern union {
1833 /// Asserts the type is a pointer or array type.1525 /// Asserts the type is a pointer or array type.
1834 pub fn elemType(self: Type) Type {1526 pub fn elemType(self: Type) Type {
1835 return switch (self.tag()) {1527 return switch (self.tag()) {
1836 .u8 => unreachable,
1837 .i8 => unreachable,
1838 .u16 => unreachable,
1839 .i16 => unreachable,
1840 .u32 => unreachable,
1841 .i32 => unreachable,
1842 .u64 => unreachable,
1843 .i64 => unreachable,
1844 .u128 => unreachable,
1845 .i128 => unreachable,
1846 .usize => unreachable,
1847 .isize => unreachable,
1848 .c_short => unreachable,
1849 .c_ushort => unreachable,
1850 .c_int => unreachable,
1851 .c_uint => unreachable,
1852 .c_long => unreachable,
1853 .c_ulong => unreachable,
1854 .c_longlong => unreachable,
1855 .c_ulonglong => unreachable,
1856 .c_longdouble => unreachable,
1857 .f16 => unreachable,
1858 .f32 => unreachable,
1859 .f64 => unreachable,
1860 .f128 => unreachable,
1861 .c_void => unreachable,
1862 .bool => unreachable,
1863 .void => unreachable,
1864 .type => unreachable,
1865 .anyerror => unreachable,
1866 .comptime_int => unreachable,
1867 .comptime_float => unreachable,
1868 .noreturn => unreachable,
1869 .@"null" => unreachable,
1870 .@"undefined" => unreachable,
1871 .fn_noreturn_no_args => unreachable,
1872 .fn_void_no_args => unreachable,
1873 .fn_naked_noreturn_no_args => unreachable,
1874 .fn_ccc_void_no_args => unreachable,
1875 .function => unreachable,
1876 .int_unsigned => unreachable,
1877 .int_signed => unreachable,
1878 .optional => unreachable,
1879 .optional_single_const_pointer => unreachable,
1880 .optional_single_mut_pointer => unreachable,
1881 .enum_literal => unreachable,
1882 .error_union => unreachable,
1883 .anyerror_void_error_union => unreachable,
1884 .error_set => unreachable,
1885 .error_set_single => unreachable,
1886 .@"struct" => unreachable,
1887 .empty_struct => unreachable,
1888 .empty_struct_literal => unreachable,
1889 .inferred_alloc_const => unreachable,
1890 .inferred_alloc_mut => unreachable,
1891 .@"opaque" => unreachable,
1892 .var_args_param => unreachable,
1893
1894 .array => self.castTag(.array).?.data.elem_type,1528 .array => self.castTag(.array).?.data.elem_type,
1895 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,1529 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
1896 .single_const_pointer,1530 .single_const_pointer,
...@@ -1902,9 +1536,12 @@ pub const Type = extern union {...@@ -1902,9 +1536,12 @@ pub const Type = extern union {
1902 .const_slice,1536 .const_slice,
1903 .mut_slice,1537 .mut_slice,
1904 => self.castPointer().?.data,1538 => self.castPointer().?.data,
1539
1905 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),1540 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
1906 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),1541 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
1907 .pointer => self.castTag(.pointer).?.data.pointee_type,1542 .pointer => self.castTag(.pointer).?.data.pointee_type,
1543
1544 else => unreachable,
1908 };1545 };
1909 }1546 }
19101547
...@@ -1972,148 +1609,18 @@ pub const Type = extern union {...@@ -1972,148 +1609,18 @@ pub const Type = extern union {
1972 /// Asserts the type is an array or vector.1609 /// Asserts the type is an array or vector.
1973 pub fn arrayLen(self: Type) u64 {1610 pub fn arrayLen(self: Type) u64 {
1974 return switch (self.tag()) {1611 return switch (self.tag()) {
1975 .u8,
1976 .i8,
1977 .u16,
1978 .i16,
1979 .u32,
1980 .i32,
1981 .u64,
1982 .i64,
1983 .u128,
1984 .i128,
1985 .usize,
1986 .isize,
1987 .c_short,
1988 .c_ushort,
1989 .c_int,
1990 .c_uint,
1991 .c_long,
1992 .c_ulong,
1993 .c_longlong,
1994 .c_ulonglong,
1995 .c_longdouble,
1996 .f16,
1997 .f32,
1998 .f64,
1999 .f128,
2000 .c_void,
2001 .bool,
2002 .void,
2003 .type,
2004 .anyerror,
2005 .comptime_int,
2006 .comptime_float,
2007 .noreturn,
2008 .@"null",
2009 .@"undefined",
2010 .fn_noreturn_no_args,
2011 .fn_void_no_args,
2012 .fn_naked_noreturn_no_args,
2013 .fn_ccc_void_no_args,
2014 .function,
2015 .pointer,
2016 .single_const_pointer,
2017 .single_mut_pointer,
2018 .many_const_pointer,
2019 .many_mut_pointer,
2020 .c_const_pointer,
2021 .c_mut_pointer,
2022 .const_slice,
2023 .mut_slice,
2024 .single_const_pointer_to_comptime_int,
2025 .const_slice_u8,
2026 .int_unsigned,
2027 .int_signed,
2028 .optional,
2029 .optional_single_mut_pointer,
2030 .optional_single_const_pointer,
2031 .enum_literal,
2032 .error_union,
2033 .anyerror_void_error_union,
2034 .error_set,
2035 .error_set_single,
2036 .@"struct",
2037 .empty_struct,
2038 .empty_struct_literal,
2039 .inferred_alloc_const,
2040 .inferred_alloc_mut,
2041 .@"opaque",
2042 .var_args_param,
2043 => unreachable,
2044
2045 .array => self.castTag(.array).?.data.len,1612 .array => self.castTag(.array).?.data.len,
2046 .array_sentinel => self.castTag(.array_sentinel).?.data.len,1613 .array_sentinel => self.castTag(.array_sentinel).?.data.len,
2047 .array_u8 => self.castTag(.array_u8).?.data,1614 .array_u8 => self.castTag(.array_u8).?.data,
2048 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data,1615 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data,
1616
1617 else => unreachable,
2049 };1618 };
2050 }1619 }
20511620
2052 /// Asserts the type is an array, pointer or vector.1621 /// Asserts the type is an array, pointer or vector.
2053 pub fn sentinel(self: Type) ?Value {1622 pub fn sentinel(self: Type) ?Value {
2054 return switch (self.tag()) {1623 return switch (self.tag()) {
2055 .u8,
2056 .i8,
2057 .u16,
2058 .i16,
2059 .u32,
2060 .i32,
2061 .u64,
2062 .i64,
2063 .u128,
2064 .i128,
2065 .usize,
2066 .isize,
2067 .c_short,
2068 .c_ushort,
2069 .c_int,
2070 .c_uint,
2071 .c_long,
2072 .c_ulong,
2073 .c_longlong,
2074 .c_ulonglong,
2075 .c_longdouble,
2076 .f16,
2077 .f32,
2078 .f64,
2079 .f128,
2080 .c_void,
2081 .bool,
2082 .void,
2083 .type,
2084 .anyerror,
2085 .comptime_int,
2086 .comptime_float,
2087 .noreturn,
2088 .@"null",
2089 .@"undefined",
2090 .fn_noreturn_no_args,
2091 .fn_void_no_args,
2092 .fn_naked_noreturn_no_args,
2093 .fn_ccc_void_no_args,
2094 .function,
2095 .const_slice,
2096 .mut_slice,
2097 .const_slice_u8,
2098 .int_unsigned,
2099 .int_signed,
2100 .optional,
2101 .optional_single_mut_pointer,
2102 .optional_single_const_pointer,
2103 .enum_literal,
2104 .error_union,
2105 .anyerror_void_error_union,
2106 .error_set,
2107 .error_set_single,
2108 .@"struct",
2109 .empty_struct,
2110 .empty_struct_literal,
2111 .inferred_alloc_const,
2112 .inferred_alloc_mut,
2113 .@"opaque",
2114 .var_args_param,
2115 => unreachable,
2116
2117 .single_const_pointer,1624 .single_const_pointer,
2118 .single_mut_pointer,1625 .single_mut_pointer,
2119 .many_const_pointer,1626 .many_const_pointer,
...@@ -2128,6 +1635,8 @@ pub const Type = extern union {...@@ -2128,6 +1635,8 @@ pub const Type = extern union {
2128 .pointer => return self.castTag(.pointer).?.data.sentinel,1635 .pointer => return self.castTag(.pointer).?.data.sentinel,
2129 .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel,1636 .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel,
2130 .array_u8_sentinel_0 => return Value.initTag(.zero),1637 .array_u8_sentinel_0 => return Value.initTag(.zero),
1638
1639 else => unreachable,
2131 };1640 };
2132 }1641 }
21331642
...@@ -2139,68 +1648,6 @@ pub const Type = extern union {...@@ -2139,68 +1648,6 @@ pub const Type = extern union {
2139 /// Returns true if and only if the type is a fixed-width, signed integer.1648 /// Returns true if and only if the type is a fixed-width, signed integer.
2140 pub fn isSignedInt(self: Type) bool {1649 pub fn isSignedInt(self: Type) bool {
2141 return switch (self.tag()) {1650 return switch (self.tag()) {
2142 .f16,
2143 .f32,
2144 .f64,
2145 .f128,
2146 .c_longdouble,
2147 .c_void,
2148 .bool,
2149 .void,
2150 .type,
2151 .anyerror,
2152 .comptime_int,
2153 .comptime_float,
2154 .noreturn,
2155 .@"null",
2156 .@"undefined",
2157 .fn_noreturn_no_args,
2158 .fn_void_no_args,
2159 .fn_naked_noreturn_no_args,
2160 .fn_ccc_void_no_args,
2161 .function,
2162 .array,
2163 .array_sentinel,
2164 .array_u8,
2165 .array_u8_sentinel_0,
2166 .pointer,
2167 .single_const_pointer,
2168 .single_mut_pointer,
2169 .many_const_pointer,
2170 .many_mut_pointer,
2171 .c_const_pointer,
2172 .c_mut_pointer,
2173 .const_slice,
2174 .mut_slice,
2175 .single_const_pointer_to_comptime_int,
2176 .const_slice_u8,
2177 .int_unsigned,
2178 .u8,
2179 .usize,
2180 .c_ushort,
2181 .c_uint,
2182 .c_ulong,
2183 .c_ulonglong,
2184 .u16,
2185 .u32,
2186 .u64,
2187 .optional,
2188 .optional_single_mut_pointer,
2189 .optional_single_const_pointer,
2190 .enum_literal,
2191 .error_union,
2192 .anyerror_void_error_union,
2193 .error_set,
2194 .error_set_single,
2195 .@"struct",
2196 .empty_struct,
2197 .empty_struct_literal,
2198 .inferred_alloc_const,
2199 .inferred_alloc_mut,
2200 .@"opaque",
2201 .var_args_param,
2202 => false,
2203
2204 .int_signed,1651 .int_signed,
2205 .i8,1652 .i8,
2206 .isize,1653 .isize,
...@@ -2211,79 +1658,16 @@ pub const Type = extern union {...@@ -2211,79 +1658,16 @@ pub const Type = extern union {
2211 .i16,1658 .i16,
2212 .i32,1659 .i32,
2213 .i64,1660 .i64,
2214 .u128,
2215 .i128,1661 .i128,
2216 => true,1662 => true,
1663
1664 else => false,
2217 };1665 };
2218 }1666 }
22191667
2220 /// Returns true if and only if the type is a fixed-width, unsigned integer.1668 /// Returns true if and only if the type is a fixed-width, unsigned integer.
2221 pub fn isUnsignedInt(self: Type) bool {1669 pub fn isUnsignedInt(self: Type) bool {
2222 return switch (self.tag()) {1670 return switch (self.tag()) {
2223 .f16,
2224 .f32,
2225 .f64,
2226 .f128,
2227 .c_longdouble,
2228 .c_void,
2229 .bool,
2230 .void,
2231 .type,
2232 .anyerror,
2233 .comptime_int,
2234 .comptime_float,
2235 .noreturn,
2236 .@"null",
2237 .@"undefined",
2238 .fn_noreturn_no_args,
2239 .fn_void_no_args,
2240 .fn_naked_noreturn_no_args,
2241 .fn_ccc_void_no_args,
2242 .function,
2243 .array,
2244 .array_sentinel,
2245 .array_u8,
2246 .array_u8_sentinel_0,
2247 .pointer,
2248 .single_const_pointer,
2249 .single_mut_pointer,
2250 .many_const_pointer,
2251 .many_mut_pointer,
2252 .c_const_pointer,
2253 .c_mut_pointer,
2254 .const_slice,
2255 .mut_slice,
2256 .single_const_pointer_to_comptime_int,
2257 .const_slice_u8,
2258 .int_signed,
2259 .i8,
2260 .isize,
2261 .c_short,
2262 .c_int,
2263 .c_long,
2264 .c_longlong,
2265 .i16,
2266 .i32,
2267 .i64,
2268 .u128,
2269 .i128,
2270 .optional,
2271 .optional_single_mut_pointer,
2272 .optional_single_const_pointer,
2273 .enum_literal,
2274 .error_union,
2275 .anyerror_void_error_union,
2276 .error_set,
2277 .error_set_single,
2278 .@"struct",
2279 .empty_struct,
2280 .empty_struct_literal,
2281 .inferred_alloc_const,
2282 .inferred_alloc_mut,
2283 .@"opaque",
2284 .var_args_param,
2285 => false,
2286
2287 .int_unsigned,1671 .int_unsigned,
2288 .u8,1672 .u8,
2289 .usize,1673 .usize,
...@@ -2294,65 +1678,16 @@ pub const Type = extern union {...@@ -2294,65 +1678,16 @@ pub const Type = extern union {
2294 .u16,1678 .u16,
2295 .u32,1679 .u32,
2296 .u64,1680 .u64,
1681 .u128,
2297 => true,1682 => true,
1683
1684 else => false,
2298 };1685 };
2299 }1686 }
23001687
2301 /// Asserts the type is an integer.1688 /// Asserts the type is an integer.
2302 pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } {1689 pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } {
2303 return switch (self.tag()) {1690 return switch (self.tag()) {
2304 .f16,
2305 .f32,
2306 .f64,
2307 .f128,
2308 .c_longdouble,
2309 .c_void,
2310 .bool,
2311 .void,
2312 .type,
2313 .anyerror,
2314 .comptime_int,
2315 .comptime_float,
2316 .noreturn,
2317 .@"null",
2318 .@"undefined",
2319 .fn_noreturn_no_args,
2320 .fn_void_no_args,
2321 .fn_naked_noreturn_no_args,
2322 .fn_ccc_void_no_args,
2323 .function,
2324 .array,
2325 .array_sentinel,
2326 .array_u8,
2327 .array_u8_sentinel_0,
2328 .pointer,
2329 .single_const_pointer,
2330 .single_mut_pointer,
2331 .many_const_pointer,
2332 .many_mut_pointer,
2333 .c_const_pointer,
2334 .c_mut_pointer,
2335 .const_slice,
2336 .mut_slice,
2337 .single_const_pointer_to_comptime_int,
2338 .const_slice_u8,
2339 .optional,
2340 .optional_single_mut_pointer,
2341 .optional_single_const_pointer,
2342 .enum_literal,
2343 .error_union,
2344 .anyerror_void_error_union,
2345 .error_set,
2346 .error_set_single,
2347 .@"struct",
2348 .empty_struct,
2349 .empty_struct_literal,
2350 .inferred_alloc_const,
2351 .inferred_alloc_mut,
2352 .@"opaque",
2353 .var_args_param,
2354 => unreachable,
2355
2356 .int_unsigned => .{1691 .int_unsigned => .{
2357 .signedness = .unsigned,1692 .signedness = .unsigned,
2358 .bits = self.castTag(.int_unsigned).?.data,1693 .bits = self.castTag(.int_unsigned).?.data,
...@@ -2381,75 +1716,13 @@ pub const Type = extern union {...@@ -2381,75 +1716,13 @@ pub const Type = extern union {
2381 .c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },1716 .c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
2382 .c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },1717 .c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
2383 .c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },1718 .c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
1719
1720 else => unreachable,
2384 };1721 };
2385 }1722 }
23861723
2387 pub fn isNamedInt(self: Type) bool {1724 pub fn isNamedInt(self: Type) bool {
2388 return switch (self.tag()) {1725 return switch (self.tag()) {
2389 .f16,
2390 .f32,
2391 .f64,
2392 .f128,
2393 .c_longdouble,
2394 .c_void,
2395 .bool,
2396 .void,
2397 .type,
2398 .anyerror,
2399 .comptime_int,
2400 .comptime_float,
2401 .noreturn,
2402 .@"null",
2403 .@"undefined",
2404 .fn_noreturn_no_args,
2405 .fn_void_no_args,
2406 .fn_naked_noreturn_no_args,
2407 .fn_ccc_void_no_args,
2408 .function,
2409 .array,
2410 .array_sentinel,
2411 .array_u8,
2412 .array_u8_sentinel_0,
2413 .pointer,
2414 .single_const_pointer,
2415 .single_mut_pointer,
2416 .many_const_pointer,
2417 .many_mut_pointer,
2418 .c_const_pointer,
2419 .c_mut_pointer,
2420 .const_slice,
2421 .mut_slice,
2422 .single_const_pointer_to_comptime_int,
2423 .const_slice_u8,
2424 .int_unsigned,
2425 .int_signed,
2426 .u8,
2427 .i8,
2428 .u16,
2429 .i16,
2430 .u32,
2431 .i32,
2432 .u64,
2433 .i64,
2434 .u128,
2435 .i128,
2436 .optional,
2437 .optional_single_mut_pointer,
2438 .optional_single_const_pointer,
2439 .enum_literal,
2440 .error_union,
2441 .anyerror_void_error_union,
2442 .error_set,
2443 .error_set_single,
2444 .@"struct",
2445 .empty_struct,
2446 .empty_struct_literal,
2447 .inferred_alloc_const,
2448 .inferred_alloc_mut,
2449 .@"opaque",
2450 .var_args_param,
2451 => false,
2452
2453 .usize,1726 .usize,
2454 .isize,1727 .isize,
2455 .c_short,1728 .c_short,
...@@ -2461,6 +1734,8 @@ pub const Type = extern union {...@@ -2461,6 +1734,8 @@ pub const Type = extern union {
2461 .c_longlong,1734 .c_longlong,
2462 .c_ulonglong,1735 .c_ulonglong,
2463 => true,1736 => true,
1737
1738 else => false,
2464 };1739 };
2465 }1740 }
24661741
...@@ -2499,74 +1774,7 @@ pub const Type = extern union {...@@ -2499,74 +1774,7 @@ pub const Type = extern union {
2499 .fn_ccc_void_no_args => 0,1774 .fn_ccc_void_no_args => 0,
2500 .function => self.castTag(.function).?.data.param_types.len,1775 .function => self.castTag(.function).?.data.param_types.len,
25011776
2502 .f16,1777 else => unreachable,
2503 .f32,
2504 .f64,
2505 .f128,
2506 .c_longdouble,
2507 .c_void,
2508 .bool,
2509 .void,
2510 .type,
2511 .anyerror,
2512 .comptime_int,
2513 .comptime_float,
2514 .noreturn,
2515 .@"null",
2516 .@"undefined",
2517 .array,
2518 .array_sentinel,
2519 .array_u8,
2520 .array_u8_sentinel_0,
2521 .pointer,
2522 .single_const_pointer,
2523 .single_mut_pointer,
2524 .many_const_pointer,
2525 .many_mut_pointer,
2526 .c_const_pointer,
2527 .c_mut_pointer,
2528 .const_slice,
2529 .mut_slice,
2530 .single_const_pointer_to_comptime_int,
2531 .const_slice_u8,
2532 .u8,
2533 .i8,
2534 .u16,
2535 .i16,
2536 .u32,
2537 .i32,
2538 .u64,
2539 .i64,
2540 .u128,
2541 .i128,
2542 .usize,
2543 .isize,
2544 .c_short,
2545 .c_ushort,
2546 .c_int,
2547 .c_uint,
2548 .c_long,
2549 .c_ulong,
2550 .c_longlong,
2551 .c_ulonglong,
2552 .int_unsigned,
2553 .int_signed,
2554 .optional,
2555 .optional_single_mut_pointer,
2556 .optional_single_const_pointer,
2557 .enum_literal,
2558 .error_union,
2559 .anyerror_void_error_union,
2560 .error_set,
2561 .error_set_single,
2562 .@"struct",
2563 .empty_struct,
2564 .empty_struct_literal,
2565 .inferred_alloc_const,
2566 .inferred_alloc_mut,
2567 .@"opaque",
2568 .var_args_param,
2569 => unreachable,
2570 };1778 };
2571 }1779 }
25721780
...@@ -2583,74 +1791,7 @@ pub const Type = extern union {...@@ -2583,74 +1791,7 @@ pub const Type = extern union {
2583 std.mem.copy(Type, types, payload.param_types);1791 std.mem.copy(Type, types, payload.param_types);
2584 },1792 },
25851793
2586 .f16,1794 else => unreachable,
2587 .f32,
2588 .f64,
2589 .f128,
2590 .c_longdouble,
2591 .c_void,
2592 .bool,
2593 .void,
2594 .type,
2595 .anyerror,
2596 .comptime_int,
2597 .comptime_float,
2598 .noreturn,
2599 .@"null",
2600 .@"undefined",
2601 .array,
2602 .array_sentinel,
2603 .array_u8,
2604 .array_u8_sentinel_0,
2605 .pointer,
2606 .single_const_pointer,
2607 .single_mut_pointer,
2608 .many_const_pointer,
2609 .many_mut_pointer,
2610 .c_const_pointer,
2611 .c_mut_pointer,
2612 .const_slice,
2613 .mut_slice,
2614 .single_const_pointer_to_comptime_int,
2615 .const_slice_u8,
2616 .u8,
2617 .i8,
2618 .u16,
2619 .i16,
2620 .u32,
2621 .i32,
2622 .u64,
2623 .i64,
2624 .u128,
2625 .i128,
2626 .usize,
2627 .isize,
2628 .c_short,
2629 .c_ushort,
2630 .c_int,
2631 .c_uint,
2632 .c_long,
2633 .c_ulong,
2634 .c_longlong,
2635 .c_ulonglong,
2636 .int_unsigned,
2637 .int_signed,
2638 .optional,
2639 .optional_single_mut_pointer,
2640 .optional_single_const_pointer,
2641 .enum_literal,
2642 .error_union,
2643 .anyerror_void_error_union,
2644 .error_set,
2645 .error_set_single,
2646 .@"struct",
2647 .empty_struct,
2648 .empty_struct_literal,
2649 .inferred_alloc_const,
2650 .inferred_alloc_mut,
2651 .@"opaque",
2652 .var_args_param,
2653 => unreachable,
2654 }1795 }
2655 }1796 }
26561797
...@@ -2662,321 +1803,49 @@ pub const Type = extern union {...@@ -2662,321 +1803,49 @@ pub const Type = extern union {
2662 return payload.param_types[index];1803 return payload.param_types[index];
2663 },1804 },
26641805
2665 .fn_noreturn_no_args,1806 else => unreachable,
2666 .fn_void_no_args,1807 }
2667 .fn_naked_noreturn_no_args,1808 }
2668 .fn_ccc_void_no_args,1809
2669 .f16,1810 /// Asserts the type is a function.
2670 .f32,1811 pub fn fnReturnType(self: Type) Type {
2671 .f64,1812 return switch (self.tag()) {
2672 .f128,1813 .fn_noreturn_no_args => Type.initTag(.noreturn),
2673 .c_longdouble,1814 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
2674 .c_void,1815
2675 .bool,
2676 .void,
2677 .type,
2678 .anyerror,
2679 .comptime_int,
2680 .comptime_float,
2681 .noreturn,
2682 .@"null",
2683 .@"undefined",
2684 .array,
2685 .array_sentinel,
2686 .array_u8,
2687 .array_u8_sentinel_0,
2688 .pointer,
2689 .single_const_pointer,
2690 .single_mut_pointer,
2691 .many_const_pointer,
2692 .many_mut_pointer,
2693 .c_const_pointer,
2694 .c_mut_pointer,
2695 .const_slice,
2696 .mut_slice,
2697 .single_const_pointer_to_comptime_int,
2698 .const_slice_u8,
2699 .u8,
2700 .i8,
2701 .u16,
2702 .i16,
2703 .u32,
2704 .i32,
2705 .u64,
2706 .i64,
2707 .u128,
2708 .i128,
2709 .usize,
2710 .isize,
2711 .c_short,
2712 .c_ushort,
2713 .c_int,
2714 .c_uint,
2715 .c_long,
2716 .c_ulong,
2717 .c_longlong,
2718 .c_ulonglong,
2719 .int_unsigned,
2720 .int_signed,
2721 .optional,
2722 .optional_single_mut_pointer,
2723 .optional_single_const_pointer,
2724 .enum_literal,
2725 .error_union,
2726 .anyerror_void_error_union,
2727 .error_set,
2728 .error_set_single,
2729 .@"struct",
2730 .empty_struct,
2731 .empty_struct_literal,
2732 .inferred_alloc_const,
2733 .inferred_alloc_mut,
2734 .@"opaque",
2735 .var_args_param,
2736 => unreachable,
2737 }
2738 }
2739
2740 /// Asserts the type is a function.
2741 pub fn fnReturnType(self: Type) Type {
2742 return switch (self.tag()) {
2743 .fn_noreturn_no_args => Type.initTag(.noreturn),
2744 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
2745
2746 .fn_void_no_args,1816 .fn_void_no_args,
2747 .fn_ccc_void_no_args,1817 .fn_ccc_void_no_args,
2748 => Type.initTag(.void),1818 => Type.initTag(.void),
27491819
2750 .function => self.castTag(.function).?.data.return_type,1820 .function => self.castTag(.function).?.data.return_type,
27511821
2752 .f16,1822 else => unreachable,
2753 .f32,1823 };
2754 .f64,1824 }
2755 .f128,1825
2756 .c_longdouble,1826 /// Asserts the type is a function.
2757 .c_void,1827 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
2758 .bool,1828 return switch (self.tag()) {
2759 .void,1829 .fn_noreturn_no_args => .Unspecified,
2760 .type,1830 .fn_void_no_args => .Unspecified,
2761 .anyerror,1831 .fn_naked_noreturn_no_args => .Naked,
2762 .comptime_int,1832 .fn_ccc_void_no_args => .C,
2763 .comptime_float,1833 .function => self.castTag(.function).?.data.cc,
2764 .noreturn,1834
2765 .@"null",1835 else => unreachable,
2766 .@"undefined",1836 };
2767 .array,1837 }
2768 .array_sentinel,1838
2769 .array_u8,1839 /// Asserts the type is a function.
2770 .array_u8_sentinel_0,1840 pub fn fnIsVarArgs(self: Type) bool {
2771 .pointer,1841 return switch (self.tag()) {
2772 .single_const_pointer,1842 .fn_noreturn_no_args => false,
2773 .single_mut_pointer,1843 .fn_void_no_args => false,
2774 .many_const_pointer,1844 .fn_naked_noreturn_no_args => false,
2775 .many_mut_pointer,1845 .fn_ccc_void_no_args => false,
2776 .c_const_pointer,1846 .function => self.castTag(.function).?.data.is_var_args,
2777 .c_mut_pointer,1847
2778 .const_slice,1848 else => unreachable,
2779 .mut_slice,
2780 .single_const_pointer_to_comptime_int,
2781 .const_slice_u8,
2782 .u8,
2783 .i8,
2784 .u16,
2785 .i16,
2786 .u32,
2787 .i32,
2788 .u64,
2789 .i64,
2790 .u128,
2791 .i128,
2792 .usize,
2793 .isize,
2794 .c_short,
2795 .c_ushort,
2796 .c_int,
2797 .c_uint,
2798 .c_long,
2799 .c_ulong,
2800 .c_longlong,
2801 .c_ulonglong,
2802 .int_unsigned,
2803 .int_signed,
2804 .optional,
2805 .optional_single_mut_pointer,
2806 .optional_single_const_pointer,
2807 .enum_literal,
2808 .error_union,
2809 .anyerror_void_error_union,
2810 .error_set,
2811 .error_set_single,
2812 .@"struct",
2813 .empty_struct,
2814 .empty_struct_literal,
2815 .inferred_alloc_const,
2816 .inferred_alloc_mut,
2817 .@"opaque",
2818 .var_args_param,
2819 => unreachable,
2820 };
2821 }
2822
2823 /// Asserts the type is a function.
2824 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
2825 return switch (self.tag()) {
2826 .fn_noreturn_no_args => .Unspecified,
2827 .fn_void_no_args => .Unspecified,
2828 .fn_naked_noreturn_no_args => .Naked,
2829 .fn_ccc_void_no_args => .C,
2830 .function => self.castTag(.function).?.data.cc,
2831
2832 .f16,
2833 .f32,
2834 .f64,
2835 .f128,
2836 .c_longdouble,
2837 .c_void,
2838 .bool,
2839 .void,
2840 .type,
2841 .anyerror,
2842 .comptime_int,
2843 .comptime_float,
2844 .noreturn,
2845 .@"null",
2846 .@"undefined",
2847 .array,
2848 .array_sentinel,
2849 .array_u8,
2850 .array_u8_sentinel_0,
2851 .pointer,
2852 .single_const_pointer,
2853 .single_mut_pointer,
2854 .many_const_pointer,
2855 .many_mut_pointer,
2856 .c_const_pointer,
2857 .c_mut_pointer,
2858 .const_slice,
2859 .mut_slice,
2860 .single_const_pointer_to_comptime_int,
2861 .const_slice_u8,
2862 .u8,
2863 .i8,
2864 .u16,
2865 .i16,
2866 .u32,
2867 .i32,
2868 .u64,
2869 .i64,
2870 .u128,
2871 .i128,
2872 .usize,
2873 .isize,
2874 .c_short,
2875 .c_ushort,
2876 .c_int,
2877 .c_uint,
2878 .c_long,
2879 .c_ulong,
2880 .c_longlong,
2881 .c_ulonglong,
2882 .int_unsigned,
2883 .int_signed,
2884 .optional,
2885 .optional_single_mut_pointer,
2886 .optional_single_const_pointer,
2887 .enum_literal,
2888 .error_union,
2889 .anyerror_void_error_union,
2890 .error_set,
2891 .error_set_single,
2892 .@"struct",
2893 .empty_struct,
2894 .empty_struct_literal,
2895 .inferred_alloc_const,
2896 .inferred_alloc_mut,
2897 .@"opaque",
2898 .var_args_param,
2899 => unreachable,
2900 };
2901 }
2902
2903 /// Asserts the type is a function.
2904 pub fn fnIsVarArgs(self: Type) bool {
2905 return switch (self.tag()) {
2906 .fn_noreturn_no_args => false,
2907 .fn_void_no_args => false,
2908 .fn_naked_noreturn_no_args => false,
2909 .fn_ccc_void_no_args => false,
2910 .function => self.castTag(.function).?.data.is_var_args,
2911
2912 .f16,
2913 .f32,
2914 .f64,
2915 .f128,
2916 .c_longdouble,
2917 .c_void,
2918 .bool,
2919 .void,
2920 .type,
2921 .anyerror,
2922 .comptime_int,
2923 .comptime_float,
2924 .noreturn,
2925 .@"null",
2926 .@"undefined",
2927 .array,
2928 .array_sentinel,
2929 .array_u8,
2930 .array_u8_sentinel_0,
2931 .pointer,
2932 .single_const_pointer,
2933 .single_mut_pointer,
2934 .many_const_pointer,
2935 .many_mut_pointer,
2936 .c_const_pointer,
2937 .c_mut_pointer,
2938 .const_slice,
2939 .mut_slice,
2940 .single_const_pointer_to_comptime_int,
2941 .const_slice_u8,
2942 .u8,
2943 .i8,
2944 .u16,
2945 .i16,
2946 .u32,
2947 .i32,
2948 .u64,
2949 .i64,
2950 .u128,
2951 .i128,
2952 .usize,
2953 .isize,
2954 .c_short,
2955 .c_ushort,
2956 .c_int,
2957 .c_uint,
2958 .c_long,
2959 .c_ulong,
2960 .c_longlong,
2961 .c_ulonglong,
2962 .int_unsigned,
2963 .int_signed,
2964 .optional,
2965 .optional_single_mut_pointer,
2966 .optional_single_const_pointer,
2967 .enum_literal,
2968 .error_union,
2969 .anyerror_void_error_union,
2970 .error_set,
2971 .error_set_single,
2972 .@"struct",
2973 .empty_struct,
2974 .empty_struct_literal,
2975 .inferred_alloc_const,
2976 .inferred_alloc_mut,
2977 .@"opaque",
2978 .var_args_param,
2979 => unreachable,
2980 };1849 };
2981 }1850 }
29821851
...@@ -3013,50 +1882,7 @@ pub const Type = extern union {...@@ -3013,50 +1882,7 @@ pub const Type = extern union {
3013 .int_signed,1882 .int_signed,
3014 => true,1883 => true,
30151884
3016 .c_void,1885 else => false,
3017 .bool,
3018 .void,
3019 .type,
3020 .anyerror,
3021 .noreturn,
3022 .@"null",
3023 .@"undefined",
3024 .fn_noreturn_no_args,
3025 .fn_void_no_args,
3026 .fn_naked_noreturn_no_args,
3027 .fn_ccc_void_no_args,
3028 .function,
3029 .array,
3030 .array_sentinel,
3031 .array_u8,
3032 .array_u8_sentinel_0,
3033 .pointer,
3034 .single_const_pointer,
3035 .single_mut_pointer,
3036 .many_const_pointer,
3037 .many_mut_pointer,
3038 .c_const_pointer,
3039 .c_mut_pointer,
3040 .const_slice,
3041 .mut_slice,
3042 .single_const_pointer_to_comptime_int,
3043 .const_slice_u8,
3044 .optional,
3045 .optional_single_mut_pointer,
3046 .optional_single_const_pointer,
3047 .enum_literal,
3048 .error_union,
3049 .anyerror_void_error_union,
3050 .error_set,
3051 .error_set_single,
3052 .@"struct",
3053 .empty_struct,
3054 .empty_struct_literal,
3055 .inferred_alloc_const,
3056 .inferred_alloc_mut,
3057 .@"opaque",
3058 .var_args_param,
3059 => false,
3060 };1886 };
3061 }1887 }
30621888
...@@ -3127,6 +1953,23 @@ pub const Type = extern union {...@@ -3127,6 +1953,23 @@ pub const Type = extern union {
3127 }1953 }
3128 return Value.initTag(.empty_struct_value);1954 return Value.initTag(.empty_struct_value);
3129 },1955 },
1956 .enum_full => {
1957 const enum_full = self.castTag(.enum_full).?.data;
1958 if (enum_full.fields.count() == 1) {
1959 return enum_full.values.entries.items[0].key;
1960 } else {
1961 return null;
1962 }
1963 },
1964 .enum_simple => {
1965 const enum_simple = self.castTag(.enum_simple).?.data;
1966 if (enum_simple.fields.count() == 1) {
1967 return Value.initTag(.zero);
1968 } else {
1969 return null;
1970 }
1971 },
1972 .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty.onePossibleValue(),
31301973
3131 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),1974 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
3132 .void => return Value.initTag(.void_value),1975 .void => return Value.initTag(.void_value),
...@@ -3166,87 +2009,6 @@ pub const Type = extern union {...@@ -3166,87 +2009,6 @@ pub const Type = extern union {
3166 };2009 };
3167 }2010 }
31682011
3169 pub fn isCPtr(self: Type) bool {
3170 return switch (self.tag()) {
3171 .f16,
3172 .f32,
3173 .f64,
3174 .f128,
3175 .c_longdouble,
3176 .comptime_int,
3177 .comptime_float,
3178 .u8,
3179 .i8,
3180 .u16,
3181 .i16,
3182 .u32,
3183 .i32,
3184 .u64,
3185 .i64,
3186 .u128,
3187 .i128,
3188 .usize,
3189 .isize,
3190 .c_short,
3191 .c_ushort,
3192 .c_int,
3193 .c_uint,
3194 .c_long,
3195 .c_ulong,
3196 .c_longlong,
3197 .c_ulonglong,
3198 .bool,
3199 .type,
3200 .anyerror,
3201 .fn_noreturn_no_args,
3202 .fn_void_no_args,
3203 .fn_naked_noreturn_no_args,
3204 .fn_ccc_void_no_args,
3205 .function,
3206 .single_const_pointer_to_comptime_int,
3207 .const_slice_u8,
3208 .c_void,
3209 .void,
3210 .noreturn,
3211 .@"null",
3212 .@"undefined",
3213 .int_unsigned,
3214 .int_signed,
3215 .array,
3216 .array_sentinel,
3217 .array_u8,
3218 .array_u8_sentinel_0,
3219 .single_const_pointer,
3220 .single_mut_pointer,
3221 .many_const_pointer,
3222 .many_mut_pointer,
3223 .const_slice,
3224 .mut_slice,
3225 .optional,
3226 .optional_single_mut_pointer,
3227 .optional_single_const_pointer,
3228 .enum_literal,
3229 .error_union,
3230 .anyerror_void_error_union,
3231 .error_set,
3232 .error_set_single,
3233 .@"struct",
3234 .empty_struct,
3235 .empty_struct_literal,
3236 .inferred_alloc_const,
3237 .inferred_alloc_mut,
3238 .@"opaque",
3239 .var_args_param,
3240 => return false,
3241
3242 .c_const_pointer,
3243 .c_mut_pointer,
3244 => return true,
3245
3246 .pointer => self.castTag(.pointer).?.data.size == .C,
3247 };
3248 }
3249
3250 pub fn isIndexable(self: Type) bool {2012 pub fn isIndexable(self: Type) bool {
3251 const zig_tag = self.zigTypeTag();2013 const zig_tag = self.zigTypeTag();
3252 // TODO tuples are indexable2014 // TODO tuples are indexable
...@@ -3257,80 +2019,12 @@ pub const Type = extern union {...@@ -3257,80 +2019,12 @@ pub const Type = extern union {
3257 /// Asserts that the type is a container. (note: ErrorSet is not a container).2019 /// Asserts that the type is a container. (note: ErrorSet is not a container).
3258 pub fn getContainerScope(self: Type) *Module.Scope.Container {2020 pub fn getContainerScope(self: Type) *Module.Scope.Container {
3259 return switch (self.tag()) {2021 return switch (self.tag()) {
3260 .f16,
3261 .f32,
3262 .f64,
3263 .f128,
3264 .c_longdouble,
3265 .comptime_int,
3266 .comptime_float,
3267 .u8,
3268 .i8,
3269 .u16,
3270 .i16,
3271 .u32,
3272 .i32,
3273 .u64,
3274 .i64,
3275 .u128,
3276 .i128,
3277 .usize,
3278 .isize,
3279 .c_short,
3280 .c_ushort,
3281 .c_int,
3282 .c_uint,
3283 .c_long,
3284 .c_ulong,
3285 .c_longlong,
3286 .c_ulonglong,
3287 .bool,
3288 .type,
3289 .anyerror,
3290 .fn_noreturn_no_args,
3291 .fn_void_no_args,
3292 .fn_naked_noreturn_no_args,
3293 .fn_ccc_void_no_args,
3294 .function,
3295 .single_const_pointer_to_comptime_int,
3296 .const_slice_u8,
3297 .c_void,
3298 .void,
3299 .noreturn,
3300 .@"null",
3301 .@"undefined",
3302 .int_unsigned,
3303 .int_signed,
3304 .array,
3305 .array_sentinel,
3306 .array_u8,
3307 .array_u8_sentinel_0,
3308 .single_const_pointer,
3309 .single_mut_pointer,
3310 .many_const_pointer,
3311 .many_mut_pointer,
3312 .const_slice,
3313 .mut_slice,
3314 .optional,
3315 .optional_single_mut_pointer,
3316 .optional_single_const_pointer,
3317 .enum_literal,
3318 .error_union,
3319 .anyerror_void_error_union,
3320 .error_set,
3321 .error_set_single,
3322 .c_const_pointer,
3323 .c_mut_pointer,
3324 .pointer,
3325 .inferred_alloc_const,
3326 .inferred_alloc_mut,
3327 .var_args_param,
3328 .empty_struct_literal,
3329 => unreachable,
3330
3331 .@"struct" => &self.castTag(.@"struct").?.data.container,2022 .@"struct" => &self.castTag(.@"struct").?.data.container,
2023 .enum_full => &self.castTag(.enum_full).?.data.container,
3332 .empty_struct => self.castTag(.empty_struct).?.data,2024 .empty_struct => self.castTag(.empty_struct).?.data,
3333 .@"opaque" => &self.castTag(.@"opaque").?.data,2025 .@"opaque" => &self.castTag(.@"opaque").?.data,
2026
2027 else => unreachable,
3334 };2028 };
3335 }2029 }
33362030
...@@ -3390,7 +2084,43 @@ pub const Type = extern union {...@@ -3390,7 +2084,43 @@ pub const Type = extern union {
3390 }2084 }
33912085
3392 pub fn isExhaustiveEnum(ty: Type) bool {2086 pub fn isExhaustiveEnum(ty: Type) bool {
3393 return false; // TODO2087 return switch (ty.tag()) {
2088 .enum_full, .enum_simple => true,
2089 else => false,
2090 };
2091 }
2092
2093 /// Asserts the type is an enum.
2094 pub fn enumHasInt(ty: Type, int: Value, target: Target) bool {
2095 const S = struct {
2096 fn intInRange(int_val: Value, end: usize) bool {
2097 if (int_val.compareWithZero(.lt)) return false;
2098 var end_payload: Value.Payload.U64 = .{
2099 .base = .{ .tag = .int_u64 },
2100 .data = end,
2101 };
2102 const end_val = Value.initPayload(&end_payload.base);
2103 if (int_val.compare(.gte, end_val)) return false;
2104 return true;
2105 }
2106 };
2107 switch (ty.tag()) {
2108 .enum_nonexhaustive => return int.intFitsInType(ty, target),
2109 .enum_full => {
2110 const enum_full = ty.castTag(.enum_full).?.data;
2111 if (enum_full.values.count() == 0) {
2112 return S.intInRange(int, enum_full.fields.count());
2113 } else {
2114 return enum_full.values.contains(int);
2115 }
2116 },
2117 .enum_simple => {
2118 const enum_simple = ty.castTag(.enum_simple).?.data;
2119 return S.intInRange(int, enum_simple.fields.count());
2120 },
2121
2122 else => unreachable,
2123 }
3394 }2124 }
33952125
3396 /// This enum does not directly correspond to `std.builtin.TypeId` because2126 /// This enum does not directly correspond to `std.builtin.TypeId` because
...@@ -3482,6 +2212,9 @@ pub const Type = extern union {...@@ -3482,6 +2212,9 @@ pub const Type = extern union {
3482 empty_struct,2212 empty_struct,
3483 @"opaque",2213 @"opaque",
3484 @"struct",2214 @"struct",
2215 enum_simple,
2216 enum_full,
2217 enum_nonexhaustive,
34852218
3486 pub const last_no_payload_tag = Tag.inferred_alloc_const;2219 pub const last_no_payload_tag = Tag.inferred_alloc_const;
3487 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;2220 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -3568,6 +2301,8 @@ pub const Type = extern union {...@@ -3568,6 +2301,8 @@ pub const Type = extern union {
3568 .error_set_single => Payload.Name,2301 .error_set_single => Payload.Name,
3569 .@"opaque" => Payload.Opaque,2302 .@"opaque" => Payload.Opaque,
3570 .@"struct" => Payload.Struct,2303 .@"struct" => Payload.Struct,
2304 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
2305 .enum_simple => Payload.EnumSimple,
3571 .empty_struct => Payload.ContainerScope,2306 .empty_struct => Payload.ContainerScope,
3572 };2307 };
3573 }2308 }
...@@ -3705,6 +2440,16 @@ pub const Type = extern union {...@@ -3705,6 +2440,16 @@ pub const Type = extern union {
3705 base: Payload = .{ .tag = .@"struct" },2440 base: Payload = .{ .tag = .@"struct" },
3706 data: *Module.Struct,2441 data: *Module.Struct,
3707 };2442 };
2443
2444 pub const EnumFull = struct {
2445 base: Payload,
2446 data: *Module.EnumFull,
2447 };
2448
2449 pub const EnumSimple = struct {
2450 base: Payload = .{ .tag = .enum_simple },
2451 data: *Module.EnumSimple,
2452 };
3708 };2453 };
3709};2454};
37102455
src/value.zig+57-780
...@@ -103,6 +103,8 @@ pub const Value = extern union {...@@ -103,6 +103,8 @@ pub const Value = extern union {
103 float_64,103 float_64,
104 float_128,104 float_128,
105 enum_literal,105 enum_literal,
106 /// A specific enum tag, indicated by the field index (declaration order).
107 enum_field_index,
106 @"error",108 @"error",
107 error_union,109 error_union,
108 /// This is a special value that tracks a set of types that have been stored110 /// This is a special value that tracks a set of types that have been stored
...@@ -186,6 +188,8 @@ pub const Value = extern union {...@@ -186,6 +188,8 @@ pub const Value = extern union {
186 .enum_literal,188 .enum_literal,
187 => Payload.Bytes,189 => Payload.Bytes,
188190
191 .enum_field_index => Payload.U32,
192
189 .ty => Payload.Ty,193 .ty => Payload.Ty,
190 .int_type => Payload.IntType,194 .int_type => Payload.IntType,
191 .int_u64 => Payload.U64,195 .int_u64 => Payload.U64,
...@@ -394,6 +398,7 @@ pub const Value = extern union {...@@ -394,6 +398,7 @@ pub const Value = extern union {
394 };398 };
395 return Value{ .ptr_otherwise = &new_payload.base };399 return Value{ .ptr_otherwise = &new_payload.base };
396 },400 },
401 .enum_field_index => return self.copyPayloadShallow(allocator, Payload.U32),
397 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),402 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
398 .error_union => {403 .error_union => {
399 const payload = self.castTag(.error_union).?;404 const payload = self.castTag(.error_union).?;
...@@ -416,6 +421,8 @@ pub const Value = extern union {...@@ -416,6 +421,8 @@ pub const Value = extern union {
416 return Value{ .ptr_otherwise = &new_payload.base };421 return Value{ .ptr_otherwise = &new_payload.base };
417 }422 }
418423
424 /// TODO this should become a debug dump() function. In order to print values in a meaningful way
425 /// we also need access to the type.
419 pub fn format(426 pub fn format(
420 self: Value,427 self: Value,
421 comptime fmt: []const u8,428 comptime fmt: []const u8,
...@@ -506,6 +513,7 @@ pub const Value = extern union {...@@ -506,6 +513,7 @@ pub const Value = extern union {
506 },513 },
507 .empty_array => return out_stream.writeAll(".{}"),514 .empty_array => return out_stream.writeAll(".{}"),
508 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(self.castTag(.enum_literal).?.data)}),515 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(self.castTag(.enum_literal).?.data)}),
516 .enum_field_index => return out_stream.print("(enum field {d})", .{self.castTag(.enum_field_index).?.data}),
509 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(self.castTag(.bytes).?.data)}),517 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(self.castTag(.bytes).?.data)}),
510 .repeated => {518 .repeated => {
511 try out_stream.writeAll("(repeated) ");519 try out_stream.writeAll("(repeated) ");
...@@ -626,6 +634,7 @@ pub const Value = extern union {...@@ -626,6 +634,7 @@ pub const Value = extern union {
626 .float_64,634 .float_64,
627 .float_128,635 .float_128,
628 .enum_literal,636 .enum_literal,
637 .enum_field_index,
629 .@"error",638 .@"error",
630 .error_union,639 .error_union,
631 .empty_struct_value,640 .empty_struct_value,
...@@ -638,76 +647,6 @@ pub const Value = extern union {...@@ -638,76 +647,6 @@ pub const Value = extern union {
638 /// Asserts the value is an integer.647 /// Asserts the value is an integer.
639 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {648 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {
640 switch (self.tag()) {649 switch (self.tag()) {
641 .ty,
642 .int_type,
643 .u8_type,
644 .i8_type,
645 .u16_type,
646 .i16_type,
647 .u32_type,
648 .i32_type,
649 .u64_type,
650 .i64_type,
651 .u128_type,
652 .i128_type,
653 .usize_type,
654 .isize_type,
655 .c_short_type,
656 .c_ushort_type,
657 .c_int_type,
658 .c_uint_type,
659 .c_long_type,
660 .c_ulong_type,
661 .c_longlong_type,
662 .c_ulonglong_type,
663 .c_longdouble_type,
664 .f16_type,
665 .f32_type,
666 .f64_type,
667 .f128_type,
668 .c_void_type,
669 .bool_type,
670 .void_type,
671 .type_type,
672 .anyerror_type,
673 .comptime_int_type,
674 .comptime_float_type,
675 .noreturn_type,
676 .null_type,
677 .undefined_type,
678 .fn_noreturn_no_args_type,
679 .fn_void_no_args_type,
680 .fn_naked_noreturn_no_args_type,
681 .fn_ccc_void_no_args_type,
682 .single_const_pointer_to_comptime_int_type,
683 .const_slice_u8_type,
684 .enum_literal_type,
685 .null_value,
686 .function,
687 .extern_fn,
688 .variable,
689 .ref_val,
690 .decl_ref,
691 .elem_ptr,
692 .bytes,
693 .repeated,
694 .float_16,
695 .float_32,
696 .float_64,
697 .float_128,
698 .void_value,
699 .unreachable_value,
700 .empty_array,
701 .enum_literal,
702 .error_union,
703 .@"error",
704 .empty_struct_value,
705 .inferred_alloc,
706 .abi_align_default,
707 => unreachable,
708
709 .undef => unreachable,
710
711 .zero,650 .zero,
712 .bool_false,651 .bool_false,
713 => return BigIntMutable.init(&space.limbs, 0).toConst(),652 => return BigIntMutable.init(&space.limbs, 0).toConst(),
...@@ -720,82 +659,15 @@ pub const Value = extern union {...@@ -720,82 +659,15 @@ pub const Value = extern union {
720 .int_i64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_i64).?.data).toConst(),659 .int_i64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_i64).?.data).toConst(),
721 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt(),660 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt(),
722 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt(),661 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt(),
662
663 .undef => unreachable,
664 else => unreachable,
723 }665 }
724 }666 }
725667
726 /// Asserts the value is an integer and it fits in a u64668 /// Asserts the value is an integer and it fits in a u64
727 pub fn toUnsignedInt(self: Value) u64 {669 pub fn toUnsignedInt(self: Value) u64 {
728 switch (self.tag()) {670 switch (self.tag()) {
729 .ty,
730 .int_type,
731 .u8_type,
732 .i8_type,
733 .u16_type,
734 .i16_type,
735 .u32_type,
736 .i32_type,
737 .u64_type,
738 .i64_type,
739 .u128_type,
740 .i128_type,
741 .usize_type,
742 .isize_type,
743 .c_short_type,
744 .c_ushort_type,
745 .c_int_type,
746 .c_uint_type,
747 .c_long_type,
748 .c_ulong_type,
749 .c_longlong_type,
750 .c_ulonglong_type,
751 .c_longdouble_type,
752 .f16_type,
753 .f32_type,
754 .f64_type,
755 .f128_type,
756 .c_void_type,
757 .bool_type,
758 .void_type,
759 .type_type,
760 .anyerror_type,
761 .comptime_int_type,
762 .comptime_float_type,
763 .noreturn_type,
764 .null_type,
765 .undefined_type,
766 .fn_noreturn_no_args_type,
767 .fn_void_no_args_type,
768 .fn_naked_noreturn_no_args_type,
769 .fn_ccc_void_no_args_type,
770 .single_const_pointer_to_comptime_int_type,
771 .const_slice_u8_type,
772 .enum_literal_type,
773 .null_value,
774 .function,
775 .extern_fn,
776 .variable,
777 .ref_val,
778 .decl_ref,
779 .elem_ptr,
780 .bytes,
781 .repeated,
782 .float_16,
783 .float_32,
784 .float_64,
785 .float_128,
786 .void_value,
787 .unreachable_value,
788 .empty_array,
789 .enum_literal,
790 .@"error",
791 .error_union,
792 .empty_struct_value,
793 .inferred_alloc,
794 .abi_align_default,
795 => unreachable,
796
797 .undef => unreachable,
798
799 .zero,671 .zero,
800 .bool_false,672 .bool_false,
801 => return 0,673 => return 0,
...@@ -808,82 +680,15 @@ pub const Value = extern union {...@@ -808,82 +680,15 @@ pub const Value = extern union {
808 .int_i64 => return @intCast(u64, self.castTag(.int_i64).?.data),680 .int_i64 => return @intCast(u64, self.castTag(.int_i64).?.data),
809 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(u64) catch unreachable,681 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(u64) catch unreachable,
810 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(u64) catch unreachable,682 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(u64) catch unreachable,
683
684 .undef => unreachable,
685 else => unreachable,
811 }686 }
812 }687 }
813688
814 /// Asserts the value is an integer and it fits in a i64689 /// Asserts the value is an integer and it fits in a i64
815 pub fn toSignedInt(self: Value) i64 {690 pub fn toSignedInt(self: Value) i64 {
816 switch (self.tag()) {691 switch (self.tag()) {
817 .ty,
818 .int_type,
819 .u8_type,
820 .i8_type,
821 .u16_type,
822 .i16_type,
823 .u32_type,
824 .i32_type,
825 .u64_type,
826 .i64_type,
827 .u128_type,
828 .i128_type,
829 .usize_type,
830 .isize_type,
831 .c_short_type,
832 .c_ushort_type,
833 .c_int_type,
834 .c_uint_type,
835 .c_long_type,
836 .c_ulong_type,
837 .c_longlong_type,
838 .c_ulonglong_type,
839 .c_longdouble_type,
840 .f16_type,
841 .f32_type,
842 .f64_type,
843 .f128_type,
844 .c_void_type,
845 .bool_type,
846 .void_type,
847 .type_type,
848 .anyerror_type,
849 .comptime_int_type,
850 .comptime_float_type,
851 .noreturn_type,
852 .null_type,
853 .undefined_type,
854 .fn_noreturn_no_args_type,
855 .fn_void_no_args_type,
856 .fn_naked_noreturn_no_args_type,
857 .fn_ccc_void_no_args_type,
858 .single_const_pointer_to_comptime_int_type,
859 .const_slice_u8_type,
860 .enum_literal_type,
861 .null_value,
862 .function,
863 .extern_fn,
864 .variable,
865 .ref_val,
866 .decl_ref,
867 .elem_ptr,
868 .bytes,
869 .repeated,
870 .float_16,
871 .float_32,
872 .float_64,
873 .float_128,
874 .void_value,
875 .unreachable_value,
876 .empty_array,
877 .enum_literal,
878 .@"error",
879 .error_union,
880 .empty_struct_value,
881 .inferred_alloc,
882 .abi_align_default,
883 => unreachable,
884
885 .undef => unreachable,
886
887 .zero,692 .zero,
888 .bool_false,693 .bool_false,
889 => return 0,694 => return 0,
...@@ -896,6 +701,9 @@ pub const Value = extern union {...@@ -896,6 +701,9 @@ pub const Value = extern union {
896 .int_i64 => return self.castTag(.int_i64).?.data,701 .int_i64 => return self.castTag(.int_i64).?.data,
897 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,702 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
898 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,703 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
704
705 .undef => unreachable,
706 else => unreachable,
899 }707 }
900 }708 }
901709
...@@ -929,75 +737,6 @@ pub const Value = extern union {...@@ -929,75 +737,6 @@ pub const Value = extern union {
929 /// Returns the number of bits the value requires to represent stored in twos complement form.737 /// Returns the number of bits the value requires to represent stored in twos complement form.
930 pub fn intBitCountTwosComp(self: Value) usize {738 pub fn intBitCountTwosComp(self: Value) usize {
931 switch (self.tag()) {739 switch (self.tag()) {
932 .ty,
933 .int_type,
934 .u8_type,
935 .i8_type,
936 .u16_type,
937 .i16_type,
938 .u32_type,
939 .i32_type,
940 .u64_type,
941 .i64_type,
942 .u128_type,
943 .i128_type,
944 .usize_type,
945 .isize_type,
946 .c_short_type,
947 .c_ushort_type,
948 .c_int_type,
949 .c_uint_type,
950 .c_long_type,
951 .c_ulong_type,
952 .c_longlong_type,
953 .c_ulonglong_type,
954 .c_longdouble_type,
955 .f16_type,
956 .f32_type,
957 .f64_type,
958 .f128_type,
959 .c_void_type,
960 .bool_type,
961 .void_type,
962 .type_type,
963 .anyerror_type,
964 .comptime_int_type,
965 .comptime_float_type,
966 .noreturn_type,
967 .null_type,
968 .undefined_type,
969 .fn_noreturn_no_args_type,
970 .fn_void_no_args_type,
971 .fn_naked_noreturn_no_args_type,
972 .fn_ccc_void_no_args_type,
973 .single_const_pointer_to_comptime_int_type,
974 .const_slice_u8_type,
975 .enum_literal_type,
976 .null_value,
977 .function,
978 .extern_fn,
979 .variable,
980 .ref_val,
981 .decl_ref,
982 .elem_ptr,
983 .bytes,
984 .undef,
985 .repeated,
986 .float_16,
987 .float_32,
988 .float_64,
989 .float_128,
990 .void_value,
991 .unreachable_value,
992 .empty_array,
993 .enum_literal,
994 .@"error",
995 .error_union,
996 .empty_struct_value,
997 .inferred_alloc,
998 .abi_align_default,
999 => unreachable,
1000
1001 .zero,740 .zero,
1002 .bool_false,741 .bool_false,
1003 => return 0,742 => return 0,
...@@ -1016,80 +755,14 @@ pub const Value = extern union {...@@ -1016,80 +755,14 @@ pub const Value = extern union {
1016 },755 },
1017 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),756 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
1018 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),757 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
758
759 else => unreachable,
1019 }760 }
1020 }761 }
1021762
1022 /// Asserts the value is an integer, and the destination type is ComptimeInt or Int.763 /// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
1023 pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {764 pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
1024 switch (self.tag()) {765 switch (self.tag()) {
1025 .ty,
1026 .int_type,
1027 .u8_type,
1028 .i8_type,
1029 .u16_type,
1030 .i16_type,
1031 .u32_type,
1032 .i32_type,
1033 .u64_type,
1034 .i64_type,
1035 .u128_type,
1036 .i128_type,
1037 .usize_type,
1038 .isize_type,
1039 .c_short_type,
1040 .c_ushort_type,
1041 .c_int_type,
1042 .c_uint_type,
1043 .c_long_type,
1044 .c_ulong_type,
1045 .c_longlong_type,
1046 .c_ulonglong_type,
1047 .c_longdouble_type,
1048 .f16_type,
1049 .f32_type,
1050 .f64_type,
1051 .f128_type,
1052 .c_void_type,
1053 .bool_type,
1054 .void_type,
1055 .type_type,
1056 .anyerror_type,
1057 .comptime_int_type,
1058 .comptime_float_type,
1059 .noreturn_type,
1060 .null_type,
1061 .undefined_type,
1062 .fn_noreturn_no_args_type,
1063 .fn_void_no_args_type,
1064 .fn_naked_noreturn_no_args_type,
1065 .fn_ccc_void_no_args_type,
1066 .single_const_pointer_to_comptime_int_type,
1067 .const_slice_u8_type,
1068 .enum_literal_type,
1069 .null_value,
1070 .function,
1071 .extern_fn,
1072 .variable,
1073 .ref_val,
1074 .decl_ref,
1075 .elem_ptr,
1076 .bytes,
1077 .repeated,
1078 .float_16,
1079 .float_32,
1080 .float_64,
1081 .float_128,
1082 .void_value,
1083 .unreachable_value,
1084 .empty_array,
1085 .enum_literal,
1086 .@"error",
1087 .error_union,
1088 .empty_struct_value,
1089 .inferred_alloc,
1090 .abi_align_default,
1091 => unreachable,
1092
1093 .zero,766 .zero,
1094 .undef,767 .undef,
1095 .bool_false,768 .bool_false,
...@@ -1144,6 +817,8 @@ pub const Value = extern union {...@@ -1144,6 +817,8 @@ pub const Value = extern union {
1144 .ComptimeInt => return true,817 .ComptimeInt => return true,
1145 else => unreachable,818 else => unreachable,
1146 },819 },
820
821 else => unreachable,
1147 }822 }
1148 }823 }
1149824
...@@ -1180,77 +855,6 @@ pub const Value = extern union {...@@ -1180,77 +855,6 @@ pub const Value = extern union {
1180 /// Asserts the value is a float855 /// Asserts the value is a float
1181 pub fn floatHasFraction(self: Value) bool {856 pub fn floatHasFraction(self: Value) bool {
1182 return switch (self.tag()) {857 return switch (self.tag()) {
1183 .ty,
1184 .int_type,
1185 .u8_type,
1186 .i8_type,
1187 .u16_type,
1188 .i16_type,
1189 .u32_type,
1190 .i32_type,
1191 .u64_type,
1192 .i64_type,
1193 .u128_type,
1194 .i128_type,
1195 .usize_type,
1196 .isize_type,
1197 .c_short_type,
1198 .c_ushort_type,
1199 .c_int_type,
1200 .c_uint_type,
1201 .c_long_type,
1202 .c_ulong_type,
1203 .c_longlong_type,
1204 .c_ulonglong_type,
1205 .c_longdouble_type,
1206 .f16_type,
1207 .f32_type,
1208 .f64_type,
1209 .f128_type,
1210 .c_void_type,
1211 .bool_type,
1212 .void_type,
1213 .type_type,
1214 .anyerror_type,
1215 .comptime_int_type,
1216 .comptime_float_type,
1217 .noreturn_type,
1218 .null_type,
1219 .undefined_type,
1220 .fn_noreturn_no_args_type,
1221 .fn_void_no_args_type,
1222 .fn_naked_noreturn_no_args_type,
1223 .fn_ccc_void_no_args_type,
1224 .single_const_pointer_to_comptime_int_type,
1225 .const_slice_u8_type,
1226 .enum_literal_type,
1227 .bool_true,
1228 .bool_false,
1229 .null_value,
1230 .function,
1231 .extern_fn,
1232 .variable,
1233 .ref_val,
1234 .decl_ref,
1235 .elem_ptr,
1236 .bytes,
1237 .repeated,
1238 .undef,
1239 .int_u64,
1240 .int_i64,
1241 .int_big_positive,
1242 .int_big_negative,
1243 .empty_array,
1244 .void_value,
1245 .unreachable_value,
1246 .enum_literal,
1247 .@"error",
1248 .error_union,
1249 .empty_struct_value,
1250 .inferred_alloc,
1251 .abi_align_default,
1252 => unreachable,
1253
1254 .zero,858 .zero,
1255 .one,859 .one,
1256 => false,860 => false,
...@@ -1260,76 +864,13 @@ pub const Value = extern union {...@@ -1260,76 +864,13 @@ pub const Value = extern union {
1260 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,864 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1261 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,865 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1262 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),866 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
867
868 else => unreachable,
1263 };869 };
1264 }870 }
1265871
1266 pub fn orderAgainstZero(lhs: Value) std.math.Order {872 pub fn orderAgainstZero(lhs: Value) std.math.Order {
1267 return switch (lhs.tag()) {873 return switch (lhs.tag()) {
1268 .ty,
1269 .int_type,
1270 .u8_type,
1271 .i8_type,
1272 .u16_type,
1273 .i16_type,
1274 .u32_type,
1275 .i32_type,
1276 .u64_type,
1277 .i64_type,
1278 .u128_type,
1279 .i128_type,
1280 .usize_type,
1281 .isize_type,
1282 .c_short_type,
1283 .c_ushort_type,
1284 .c_int_type,
1285 .c_uint_type,
1286 .c_long_type,
1287 .c_ulong_type,
1288 .c_longlong_type,
1289 .c_ulonglong_type,
1290 .c_longdouble_type,
1291 .f16_type,
1292 .f32_type,
1293 .f64_type,
1294 .f128_type,
1295 .c_void_type,
1296 .bool_type,
1297 .void_type,
1298 .type_type,
1299 .anyerror_type,
1300 .comptime_int_type,
1301 .comptime_float_type,
1302 .noreturn_type,
1303 .null_type,
1304 .undefined_type,
1305 .fn_noreturn_no_args_type,
1306 .fn_void_no_args_type,
1307 .fn_naked_noreturn_no_args_type,
1308 .fn_ccc_void_no_args_type,
1309 .single_const_pointer_to_comptime_int_type,
1310 .const_slice_u8_type,
1311 .enum_literal_type,
1312 .null_value,
1313 .function,
1314 .extern_fn,
1315 .variable,
1316 .ref_val,
1317 .decl_ref,
1318 .elem_ptr,
1319 .bytes,
1320 .repeated,
1321 .undef,
1322 .void_value,
1323 .unreachable_value,
1324 .empty_array,
1325 .enum_literal,
1326 .@"error",
1327 .error_union,
1328 .empty_struct_value,
1329 .inferred_alloc,
1330 .abi_align_default,
1331 => unreachable,
1332
1333 .zero,874 .zero,
1334 .bool_false,875 .bool_false,
1335 => .eq,876 => .eq,
...@@ -1347,6 +888,8 @@ pub const Value = extern union {...@@ -1347,6 +888,8 @@ pub const Value = extern union {
1347 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),888 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1348 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),889 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1349 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),890 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
891
892 else => unreachable,
1350 };893 };
1351 }894 }
1352895
...@@ -1396,10 +939,12 @@ pub const Value = extern union {...@@ -1396,10 +939,12 @@ pub const Value = extern union {
1396 }939 }
1397940
1398 pub fn eql(a: Value, b: Value) bool {941 pub fn eql(a: Value, b: Value) bool {
1399 if (a.tag() == b.tag()) {942 const a_tag = a.tag();
1400 if (a.tag() == .void_value or a.tag() == .null_value) {943 const b_tag = b.tag();
944 if (a_tag == b_tag) {
945 if (a_tag == .void_value or a_tag == .null_value) {
1401 return true;946 return true;
1402 } else if (a.tag() == .enum_literal) {947 } else if (a_tag == .enum_literal) {
1403 const a_name = a.castTag(.enum_literal).?.data;948 const a_name = a.castTag(.enum_literal).?.data;
1404 const b_name = b.castTag(.enum_literal).?.data;949 const b_name = b.castTag(.enum_literal).?.data;
1405 return std.mem.eql(u8, a_name, b_name);950 return std.mem.eql(u8, a_name, b_name);
...@@ -1416,6 +961,10 @@ pub const Value = extern union {...@@ -1416,6 +961,10 @@ pub const Value = extern union {
1416 return compare(a, .eq, b);961 return compare(a, .eq, b);
1417 }962 }
1418963
964 pub fn hash_u32(self: Value) u32 {
965 return @truncate(u32, self.hash());
966 }
967
1419 pub fn hash(self: Value) u64 {968 pub fn hash(self: Value) u64 {
1420 var hasher = std.hash.Wyhash.init(0);969 var hasher = std.hash.Wyhash.init(0);
1421970
...@@ -1493,11 +1042,18 @@ pub const Value = extern union {...@@ -1493,11 +1042,18 @@ pub const Value = extern union {
1493 .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),1042 .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),
1494 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),1043 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
14951044
1496 .float_16, .float_32, .float_64, .float_128 => {},1045 .float_16, .float_32, .float_64, .float_128 => {
1046 @panic("TODO implement Value.hash for floats");
1047 },
1048
1497 .enum_literal => {1049 .enum_literal => {
1498 const payload = self.castTag(.enum_literal).?;1050 const payload = self.castTag(.enum_literal).?;
1499 hasher.update(payload.data);1051 hasher.update(payload.data);
1500 },1052 },
1053 .enum_field_index => {
1054 const payload = self.castTag(.enum_field_index).?;
1055 std.hash.autoHash(&hasher, payload.data);
1056 },
1501 .bytes => {1057 .bytes => {
1502 const payload = self.castTag(.bytes).?;1058 const payload = self.castTag(.bytes).?;
1503 hasher.update(payload.data);1059 hasher.update(payload.data);
...@@ -1573,80 +1129,6 @@ pub const Value = extern union {...@@ -1573,80 +1129,6 @@ pub const Value = extern union {
1573 /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.1129 /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
1574 pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {1130 pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
1575 return switch (self.tag()) {1131 return switch (self.tag()) {
1576 .ty,
1577 .int_type,
1578 .u8_type,
1579 .i8_type,
1580 .u16_type,
1581 .i16_type,
1582 .u32_type,
1583 .i32_type,
1584 .u64_type,
1585 .i64_type,
1586 .u128_type,
1587 .i128_type,
1588 .usize_type,
1589 .isize_type,
1590 .c_short_type,
1591 .c_ushort_type,
1592 .c_int_type,
1593 .c_uint_type,
1594 .c_long_type,
1595 .c_ulong_type,
1596 .c_longlong_type,
1597 .c_ulonglong_type,
1598 .c_longdouble_type,
1599 .f16_type,
1600 .f32_type,
1601 .f64_type,
1602 .f128_type,
1603 .c_void_type,
1604 .bool_type,
1605 .void_type,
1606 .type_type,
1607 .anyerror_type,
1608 .comptime_int_type,
1609 .comptime_float_type,
1610 .noreturn_type,
1611 .null_type,
1612 .undefined_type,
1613 .fn_noreturn_no_args_type,
1614 .fn_void_no_args_type,
1615 .fn_naked_noreturn_no_args_type,
1616 .fn_ccc_void_no_args_type,
1617 .single_const_pointer_to_comptime_int_type,
1618 .const_slice_u8_type,
1619 .enum_literal_type,
1620 .zero,
1621 .one,
1622 .bool_true,
1623 .bool_false,
1624 .null_value,
1625 .function,
1626 .extern_fn,
1627 .variable,
1628 .int_u64,
1629 .int_i64,
1630 .int_big_positive,
1631 .int_big_negative,
1632 .bytes,
1633 .undef,
1634 .repeated,
1635 .float_16,
1636 .float_32,
1637 .float_64,
1638 .float_128,
1639 .void_value,
1640 .unreachable_value,
1641 .empty_array,
1642 .enum_literal,
1643 .@"error",
1644 .error_union,
1645 .empty_struct_value,
1646 .inferred_alloc,
1647 .abi_align_default,
1648 => unreachable,
1649
1650 .ref_val => self.castTag(.ref_val).?.data,1132 .ref_val => self.castTag(.ref_val).?.data,
1651 .decl_ref => self.castTag(.decl_ref).?.data.value(),1133 .decl_ref => self.castTag(.decl_ref).?.data.value(),
1652 .elem_ptr => {1134 .elem_ptr => {
...@@ -1654,6 +1136,8 @@ pub const Value = extern union {...@@ -1654,6 +1136,8 @@ pub const Value = extern union {
1654 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);1136 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
1655 return array_val.elemValue(allocator, elem_ptr.index);1137 return array_val.elemValue(allocator, elem_ptr.index);
1656 },1138 },
1139
1140 else => unreachable,
1657 };1141 };
1658 }1142 }
16591143
...@@ -1661,86 +1145,14 @@ pub const Value = extern union {...@@ -1661,86 +1145,14 @@ pub const Value = extern union {
1661 /// or an unknown-length pointer, and returns the element value at the index.1145 /// or an unknown-length pointer, and returns the element value at the index.
1662 pub fn elemValue(self: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value {1146 pub fn elemValue(self: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value {
1663 switch (self.tag()) {1147 switch (self.tag()) {
1664 .ty,
1665 .int_type,
1666 .u8_type,
1667 .i8_type,
1668 .u16_type,
1669 .i16_type,
1670 .u32_type,
1671 .i32_type,
1672 .u64_type,
1673 .i64_type,
1674 .u128_type,
1675 .i128_type,
1676 .usize_type,
1677 .isize_type,
1678 .c_short_type,
1679 .c_ushort_type,
1680 .c_int_type,
1681 .c_uint_type,
1682 .c_long_type,
1683 .c_ulong_type,
1684 .c_longlong_type,
1685 .c_ulonglong_type,
1686 .c_longdouble_type,
1687 .f16_type,
1688 .f32_type,
1689 .f64_type,
1690 .f128_type,
1691 .c_void_type,
1692 .bool_type,
1693 .void_type,
1694 .type_type,
1695 .anyerror_type,
1696 .comptime_int_type,
1697 .comptime_float_type,
1698 .noreturn_type,
1699 .null_type,
1700 .undefined_type,
1701 .fn_noreturn_no_args_type,
1702 .fn_void_no_args_type,
1703 .fn_naked_noreturn_no_args_type,
1704 .fn_ccc_void_no_args_type,
1705 .single_const_pointer_to_comptime_int_type,
1706 .const_slice_u8_type,
1707 .enum_literal_type,
1708 .zero,
1709 .one,
1710 .bool_true,
1711 .bool_false,
1712 .null_value,
1713 .function,
1714 .extern_fn,
1715 .variable,
1716 .int_u64,
1717 .int_i64,
1718 .int_big_positive,
1719 .int_big_negative,
1720 .undef,
1721 .elem_ptr,
1722 .ref_val,
1723 .decl_ref,
1724 .float_16,
1725 .float_32,
1726 .float_64,
1727 .float_128,
1728 .void_value,
1729 .unreachable_value,
1730 .enum_literal,
1731 .@"error",
1732 .error_union,
1733 .empty_struct_value,
1734 .inferred_alloc,
1735 .abi_align_default,
1736 => unreachable,
1737
1738 .empty_array => unreachable, // out of bounds array index1148 .empty_array => unreachable, // out of bounds array index
17391149
1740 .bytes => return Tag.int_u64.create(allocator, self.castTag(.bytes).?.data[index]),1150 .bytes => return Tag.int_u64.create(allocator, self.castTag(.bytes).?.data[index]),
17411151
1742 // No matter the index; all the elements are the same!1152 // No matter the index; all the elements are the same!
1743 .repeated => return self.castTag(.repeated).?.data,1153 .repeated => return self.castTag(.repeated).?.data,
1154
1155 else => unreachable,
1744 }1156 }
1745 }1157 }
17461158
...@@ -1766,161 +1178,18 @@ pub const Value = extern union {...@@ -1766,161 +1178,18 @@ pub const Value = extern union {
1766 /// Valid for all types. Asserts the value is not undefined and not unreachable.1178 /// Valid for all types. Asserts the value is not undefined and not unreachable.
1767 pub fn isNull(self: Value) bool {1179 pub fn isNull(self: Value) bool {
1768 return switch (self.tag()) {1180 return switch (self.tag()) {
1769 .ty,
1770 .int_type,
1771 .u8_type,
1772 .i8_type,
1773 .u16_type,
1774 .i16_type,
1775 .u32_type,
1776 .i32_type,
1777 .u64_type,
1778 .i64_type,
1779 .u128_type,
1780 .i128_type,
1781 .usize_type,
1782 .isize_type,
1783 .c_short_type,
1784 .c_ushort_type,
1785 .c_int_type,
1786 .c_uint_type,
1787 .c_long_type,
1788 .c_ulong_type,
1789 .c_longlong_type,
1790 .c_ulonglong_type,
1791 .c_longdouble_type,
1792 .f16_type,
1793 .f32_type,
1794 .f64_type,
1795 .f128_type,
1796 .c_void_type,
1797 .bool_type,
1798 .void_type,
1799 .type_type,
1800 .anyerror_type,
1801 .comptime_int_type,
1802 .comptime_float_type,
1803 .noreturn_type,
1804 .null_type,
1805 .undefined_type,
1806 .fn_noreturn_no_args_type,
1807 .fn_void_no_args_type,
1808 .fn_naked_noreturn_no_args_type,
1809 .fn_ccc_void_no_args_type,
1810 .single_const_pointer_to_comptime_int_type,
1811 .const_slice_u8_type,
1812 .enum_literal_type,
1813 .zero,
1814 .one,
1815 .empty_array,
1816 .bool_true,
1817 .bool_false,
1818 .function,
1819 .extern_fn,
1820 .variable,
1821 .int_u64,
1822 .int_i64,
1823 .int_big_positive,
1824 .int_big_negative,
1825 .ref_val,
1826 .decl_ref,
1827 .elem_ptr,
1828 .bytes,
1829 .repeated,
1830 .float_16,
1831 .float_32,
1832 .float_64,
1833 .float_128,
1834 .void_value,
1835 .enum_literal,
1836 .@"error",
1837 .error_union,
1838 .empty_struct_value,
1839 .abi_align_default,
1840 => false,
1841
1842 .undef => unreachable,1181 .undef => unreachable,
1843 .unreachable_value => unreachable,1182 .unreachable_value => unreachable,
1844 .inferred_alloc => unreachable,1183 .inferred_alloc => unreachable,
1845 .null_value => true,1184 .null_value => true,
1185
1186 else => false,
1846 };1187 };
1847 }1188 }
18481189
1849 /// Valid for all types. Asserts the value is not undefined and not unreachable.1190 /// Valid for all types. Asserts the value is not undefined and not unreachable.
1850 pub fn getError(self: Value) ?[]const u8 {1191 pub fn getError(self: Value) ?[]const u8 {
1851 return switch (self.tag()) {1192 return switch (self.tag()) {
1852 .ty,
1853 .int_type,
1854 .u8_type,
1855 .i8_type,
1856 .u16_type,
1857 .i16_type,
1858 .u32_type,
1859 .i32_type,
1860 .u64_type,
1861 .i64_type,
1862 .u128_type,
1863 .i128_type,
1864 .usize_type,
1865 .isize_type,
1866 .c_short_type,
1867 .c_ushort_type,
1868 .c_int_type,
1869 .c_uint_type,
1870 .c_long_type,
1871 .c_ulong_type,
1872 .c_longlong_type,
1873 .c_ulonglong_type,
1874 .c_longdouble_type,
1875 .f16_type,
1876 .f32_type,
1877 .f64_type,
1878 .f128_type,
1879 .c_void_type,
1880 .bool_type,
1881 .void_type,
1882 .type_type,
1883 .anyerror_type,
1884 .comptime_int_type,
1885 .comptime_float_type,
1886 .noreturn_type,
1887 .null_type,
1888 .undefined_type,
1889 .fn_noreturn_no_args_type,
1890 .fn_void_no_args_type,
1891 .fn_naked_noreturn_no_args_type,
1892 .fn_ccc_void_no_args_type,
1893 .single_const_pointer_to_comptime_int_type,
1894 .const_slice_u8_type,
1895 .enum_literal_type,
1896 .zero,
1897 .one,
1898 .null_value,
1899 .empty_array,
1900 .bool_true,
1901 .bool_false,
1902 .function,
1903 .extern_fn,
1904 .variable,
1905 .int_u64,
1906 .int_i64,
1907 .int_big_positive,
1908 .int_big_negative,
1909 .ref_val,
1910 .decl_ref,
1911 .elem_ptr,
1912 .bytes,
1913 .repeated,
1914 .float_16,
1915 .float_32,
1916 .float_64,
1917 .float_128,
1918 .void_value,
1919 .enum_literal,
1920 .empty_struct_value,
1921 .abi_align_default,
1922 => null,
1923
1924 .error_union => {1193 .error_union => {
1925 const data = self.castTag(.error_union).?.data;1194 const data = self.castTag(.error_union).?.data;
1926 return if (data.tag() == .@"error")1195 return if (data.tag() == .@"error")
...@@ -1932,6 +1201,8 @@ pub const Value = extern union {...@@ -1932,6 +1201,8 @@ pub const Value = extern union {
1932 .undef => unreachable,1201 .undef => unreachable,
1933 .unreachable_value => unreachable,1202 .unreachable_value => unreachable,
1934 .inferred_alloc => unreachable,1203 .inferred_alloc => unreachable,
1204
1205 else => null,
1935 };1206 };
1936 }1207 }
1937 /// Valid for all types. Asserts the value is not undefined.1208 /// Valid for all types. Asserts the value is not undefined.
...@@ -2021,6 +1292,7 @@ pub const Value = extern union {...@@ -2021,6 +1292,7 @@ pub const Value = extern union {
2021 .float_128,1292 .float_128,
2022 .void_value,1293 .void_value,
2023 .enum_literal,1294 .enum_literal,
1295 .enum_field_index,
2024 .@"error",1296 .@"error",
2025 .error_union,1297 .error_union,
2026 .empty_struct_value,1298 .empty_struct_value,
...@@ -2038,6 +1310,11 @@ pub const Value = extern union {...@@ -2038,6 +1310,11 @@ pub const Value = extern union {
2038 pub const Payload = struct {1310 pub const Payload = struct {
2039 tag: Tag,1311 tag: Tag,
20401312
1313 pub const U32 = struct {
1314 base: Payload,
1315 data: u32,
1316 };
1317
2041 pub const U64 = struct {1318 pub const U64 = struct {
2042 base: Payload,1319 base: Payload,
2043 data: u64,1320 data: u64,
src/zir.zig+68-19
...@@ -37,8 +37,6 @@ pub const Code = struct {...@@ -37,8 +37,6 @@ pub const Code = struct {
37 string_bytes: []u8,37 string_bytes: []u8,
38 /// The meaning of this data is determined by `Inst.Tag` value.38 /// The meaning of this data is determined by `Inst.Tag` value.
39 extra: []u32,39 extra: []u32,
40 /// Used for decl_val and decl_ref instructions.
41 decls: []*Module.Decl,
4240
43 /// Returns the requested data, as well as the new index which is at the start of the41 /// Returns the requested data, as well as the new index which is at the start of the
44 /// trailers for the object.42 /// trailers for the object.
...@@ -78,7 +76,6 @@ pub const Code = struct {...@@ -78,7 +76,6 @@ pub const Code = struct {
78 code.instructions.deinit(gpa);76 code.instructions.deinit(gpa);
79 gpa.free(code.string_bytes);77 gpa.free(code.string_bytes);
80 gpa.free(code.extra);78 gpa.free(code.extra);
81 gpa.free(code.decls);
82 code.* = undefined;79 code.* = undefined;
83 }80 }
8481
...@@ -267,9 +264,6 @@ pub const Inst = struct {...@@ -267,9 +264,6 @@ pub const Inst = struct {
267 /// only the taken branch is analyzed. The then block and else block must264 /// only the taken branch is analyzed. The then block and else block must
268 /// terminate with an "inline" variant of a noreturn instruction.265 /// terminate with an "inline" variant of a noreturn instruction.
269 condbr_inline,266 condbr_inline,
270 /// A comptime known value.
271 /// Uses the `const` union field.
272 @"const",
273 /// A struct type definition. Contains references to ZIR instructions for267 /// A struct type definition. Contains references to ZIR instructions for
274 /// the field types, defaults, and alignments.268 /// the field types, defaults, and alignments.
275 /// Uses the `pl_node` union field. Payload is `StructDecl`.269 /// Uses the `pl_node` union field. Payload is `StructDecl`.
...@@ -286,6 +280,8 @@ pub const Inst = struct {...@@ -286,6 +280,8 @@ pub const Inst = struct {
286 /// the field value expressions and optional type tag expression.280 /// the field value expressions and optional type tag expression.
287 /// Uses the `pl_node` union field. Payload is `EnumDecl`.281 /// Uses the `pl_node` union field. Payload is `EnumDecl`.
288 enum_decl,282 enum_decl,
283 /// Same as `enum_decl`, except the enum is non-exhaustive.
284 enum_decl_nonexhaustive,
289 /// An opaque type definition. Provides an AST node only.285 /// An opaque type definition. Provides an AST node only.
290 /// Uses the `node` union field.286 /// Uses the `node` union field.
291 opaque_decl,287 opaque_decl,
...@@ -369,6 +365,11 @@ pub const Inst = struct {...@@ -369,6 +365,11 @@ pub const Inst = struct {
369 import,365 import,
370 /// Integer literal that fits in a u64. Uses the int union value.366 /// Integer literal that fits in a u64. Uses the int union value.
371 int,367 int,
368 /// A float literal that fits in a f32. Uses the float union value.
369 float,
370 /// A float literal that fits in a f128. Uses the `pl_node` union value.
371 /// Payload is `Float128`.
372 float128,
372 /// Convert an integer value to another integer type, asserting that the destination type373 /// Convert an integer value to another integer type, asserting that the destination type
373 /// can hold the same mathematical value.374 /// can hold the same mathematical value.
374 /// Uses the `pl_node` field. AST is the `@intCast` syntax.375 /// Uses the `pl_node` field. AST is the `@intCast` syntax.
...@@ -667,6 +668,12 @@ pub const Inst = struct {...@@ -667,6 +668,12 @@ pub const Inst = struct {
667 /// A struct literal with a specified type, with no fields.668 /// A struct literal with a specified type, with no fields.
668 /// Uses the `un_node` field.669 /// Uses the `un_node` field.
669 struct_init_empty,670 struct_init_empty,
671 /// Converts an integer into an enum value.
672 /// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand.
673 int_to_enum,
674 /// Converts an enum value into an integer. Resulting type will be the tag type
675 /// of the enum. Uses `un_node`.
676 enum_to_int,
670677
671 /// Returns whether the instruction is one of the control flow "noreturn" types.678 /// Returns whether the instruction is one of the control flow "noreturn" types.
672 /// Function calls do not count.679 /// Function calls do not count.
...@@ -712,12 +719,12 @@ pub const Inst = struct {...@@ -712,12 +719,12 @@ pub const Inst = struct {
712 .cmp_gt,719 .cmp_gt,
713 .cmp_neq,720 .cmp_neq,
714 .coerce_result_ptr,721 .coerce_result_ptr,
715 .@"const",
716 .struct_decl,722 .struct_decl,
717 .struct_decl_packed,723 .struct_decl_packed,
718 .struct_decl_extern,724 .struct_decl_extern,
719 .union_decl,725 .union_decl,
720 .enum_decl,726 .enum_decl,
727 .enum_decl_nonexhaustive,
721 .opaque_decl,728 .opaque_decl,
722 .dbg_stmt_node,729 .dbg_stmt_node,
723 .decl_ref,730 .decl_ref,
...@@ -740,6 +747,8 @@ pub const Inst = struct {...@@ -740,6 +747,8 @@ pub const Inst = struct {
740 .fn_type_cc,747 .fn_type_cc,
741 .fn_type_cc_var_args,748 .fn_type_cc_var_args,
742 .int,749 .int,
750 .float,
751 .float128,
743 .intcast,752 .intcast,
744 .int_type,753 .int_type,
745 .is_non_null,754 .is_non_null,
...@@ -822,6 +831,8 @@ pub const Inst = struct {...@@ -822,6 +831,8 @@ pub const Inst = struct {
822 .switch_block_ref_under_multi,831 .switch_block_ref_under_multi,
823 .validate_struct_init_ptr,832 .validate_struct_init_ptr,
824 .struct_init_empty,833 .struct_init_empty,
834 .int_to_enum,
835 .enum_to_int,
825 => false,836 => false,
826837
827 .@"break",838 .@"break",
...@@ -1184,7 +1195,6 @@ pub const Inst = struct {...@@ -1184,7 +1195,6 @@ pub const Inst = struct {
1184 }1195 }
1185 },1196 },
1186 bin: Bin,1197 bin: Bin,
1187 @"const": *TypedValue,
1188 /// For strings which may contain null bytes.1198 /// For strings which may contain null bytes.
1189 str: struct {1199 str: struct {
1190 /// Offset into `string_bytes`.1200 /// Offset into `string_bytes`.
...@@ -1226,6 +1236,16 @@ pub const Inst = struct {...@@ -1226,6 +1236,16 @@ pub const Inst = struct {
1226 /// Offset from Decl AST node index.1236 /// Offset from Decl AST node index.
1227 node: i32,1237 node: i32,
1228 int: u64,1238 int: u64,
1239 float: struct {
1240 /// Offset from Decl AST node index.
1241 /// `Tag` determines which kind of AST node this points to.
1242 src_node: i32,
1243 number: f32,
1244
1245 pub fn src(self: @This()) LazySrcLoc {
1246 return .{ .node_offset = self.src_node };
1247 }
1248 },
1229 array_type_sentinel: struct {1249 array_type_sentinel: struct {
1230 len: Ref,1250 len: Ref,
1231 /// index into extra, points to an `ArrayTypeSentinel`1251 /// index into extra, points to an `ArrayTypeSentinel`
...@@ -1507,6 +1527,22 @@ pub const Inst = struct {...@@ -1507,6 +1527,22 @@ pub const Inst = struct {
1507 tag_type: Ref,1527 tag_type: Ref,
1508 fields_len: u32,1528 fields_len: u32,
1509 };1529 };
1530
1531 /// A f128 value, broken up into 4 u32 parts.
1532 pub const Float128 = struct {
1533 piece0: u32,
1534 piece1: u32,
1535 piece2: u32,
1536 piece3: u32,
1537
1538 pub fn get(self: Float128) f128 {
1539 const int_bits = @as(u128, self.piece0) |
1540 (@as(u128, self.piece1) << 32) |
1541 (@as(u128, self.piece2) << 64) |
1542 (@as(u128, self.piece3) << 96);
1543 return @bitCast(f128, int_bits);
1544 }
1545 };
1510};1546};
15111547
1512pub const SpecialProng = enum { none, @"else", under };1548pub const SpecialProng = enum { none, @"else", under };
...@@ -1581,6 +1617,7 @@ const Writer = struct {...@@ -1581,6 +1617,7 @@ const Writer = struct {
1581 .typeof,1617 .typeof,
1582 .typeof_elem,1618 .typeof_elem,
1583 .struct_init_empty,1619 .struct_init_empty,
1620 .enum_to_int,
1584 => try self.writeUnNode(stream, inst),1621 => try self.writeUnNode(stream, inst),
15851622
1586 .ref,1623 .ref,
...@@ -1594,11 +1631,12 @@ const Writer = struct {...@@ -1594,11 +1631,12 @@ const Writer = struct {
1594 => try self.writeBoolBr(stream, inst),1631 => try self.writeBoolBr(stream, inst),
15951632
1596 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),1633 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
1597 .@"const" => try self.writeConst(stream, inst),
1598 .param_type => try self.writeParamType(stream, inst),1634 .param_type => try self.writeParamType(stream, inst),
1599 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),1635 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
1600 .ptr_type => try self.writePtrType(stream, inst),1636 .ptr_type => try self.writePtrType(stream, inst),
1601 .int => try self.writeInt(stream, inst),1637 .int => try self.writeInt(stream, inst),
1638 .float => try self.writeFloat(stream, inst),
1639 .float128 => try self.writeFloat128(stream, inst),
1602 .str => try self.writeStr(stream, inst),1640 .str => try self.writeStr(stream, inst),
1603 .elided => try stream.writeAll(")"),1641 .elided => try stream.writeAll(")"),
1604 .int_type => try self.writeIntType(stream, inst),1642 .int_type => try self.writeIntType(stream, inst),
...@@ -1619,6 +1657,7 @@ const Writer = struct {...@@ -1619,6 +1657,7 @@ const Writer = struct {
1619 .slice_sentinel,1657 .slice_sentinel,
1620 .union_decl,1658 .union_decl,
1621 .enum_decl,1659 .enum_decl,
1660 .enum_decl_nonexhaustive,
1622 => try self.writePlNode(stream, inst),1661 => try self.writePlNode(stream, inst),
16231662
1624 .add,1663 .add,
...@@ -1647,6 +1686,7 @@ const Writer = struct {...@@ -1647,6 +1686,7 @@ const Writer = struct {
1647 .merge_error_sets,1686 .merge_error_sets,
1648 .bit_and,1687 .bit_and,
1649 .bit_or,1688 .bit_or,
1689 .int_to_enum,
1650 => try self.writePlNodeBin(stream, inst),1690 => try self.writePlNodeBin(stream, inst),
16511691
1652 .call,1692 .call,
...@@ -1773,15 +1813,6 @@ const Writer = struct {...@@ -1773,15 +1813,6 @@ const Writer = struct {
1773 try stream.writeAll("TODO)");1813 try stream.writeAll("TODO)");
1774 }1814 }
17751815
1776 fn writeConst(
1777 self: *Writer,
1778 stream: anytype,
1779 inst: Inst.Index,
1780 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1781 const inst_data = self.code.instructions.items(.data)[inst].@"const";
1782 try stream.writeAll("TODO)");
1783 }
1784
1785 fn writeParamType(1816 fn writeParamType(
1786 self: *Writer,1817 self: *Writer,
1787 stream: anytype,1818 stream: anytype,
...@@ -1819,6 +1850,23 @@ const Writer = struct {...@@ -1819,6 +1850,23 @@ const Writer = struct {
1819 try stream.print("{d})", .{inst_data});1850 try stream.print("{d})", .{inst_data});
1820 }1851 }
18211852
1853 fn writeFloat(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1854 const inst_data = self.code.instructions.items(.data)[inst].float;
1855 const src = inst_data.src();
1856 try stream.print("{d}) ", .{inst_data.number});
1857 try self.writeSrc(stream, src);
1858 }
1859
1860 fn writeFloat128(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1861 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1862 const extra = self.code.extraData(Inst.Float128, inst_data.payload_index).data;
1863 const src = inst_data.src();
1864 const number = extra.get();
1865 // TODO improve std.format to be able to print f128 values
1866 try stream.print("{d}) ", .{@floatCast(f64, number)});
1867 try self.writeSrc(stream, src);
1868 }
1869
1822 fn writeStr(1870 fn writeStr(
1823 self: *Writer,1871 self: *Writer,
1824 stream: anytype,1872 stream: anytype,
...@@ -2136,7 +2184,8 @@ const Writer = struct {...@@ -2136,7 +2184,8 @@ const Writer = struct {
21362184
2137 fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {2185 fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
2138 const inst_data = self.code.instructions.items(.data)[inst].pl_node;2186 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2139 const decl = self.code.decls[inst_data.payload_index];2187 const owner_decl = self.scope.ownerDecl().?;
2188 const decl = owner_decl.dependencies.entries.items[inst_data.payload_index].key;
2140 try stream.print("{s}) ", .{decl.name});2189 try stream.print("{s}) ", .{decl.name});
2141 try self.writeSrc(stream, inst_data.src());2190 try self.writeSrc(stream, inst_data.src());
2142 }2191 }