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");
2828instructions: std.MultiArrayList(zir.Inst) = .{},
2929string_bytes: ArrayListUnmanaged(u8) = .{},
3030extra: ArrayListUnmanaged(u32) = .{},
31decl_map: std.StringArrayHashMapUnmanaged(void) = .{},
32decls: ArrayListUnmanaged(*Decl) = .{},
3331/// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert
3432/// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.
3533ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,
......@@ -110,8 +108,6 @@ pub fn deinit(astgen: *AstGen) void {
110108 astgen.instructions.deinit(gpa);
111109 astgen.extra.deinit(gpa);
112110 astgen.string_bytes.deinit(gpa);
113 astgen.decl_map.deinit(gpa);
114 astgen.decls.deinit(gpa);
115111}
116112
117113pub const ResultLoc = union(enum) {
......@@ -1183,13 +1179,6 @@ fn blockExprStmts(
11831179 // in the above while loop.
11841180 const zir_tags = gz.astgen.instructions.items(.tag);
11851181 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 },
11931182 // For some instructions, swap in a slightly different ZIR tag
11941183 // so we can avoid a separate ensure_result_used instruction.
11951184 .call_none_chkused => unreachable,
......@@ -1257,6 +1246,8 @@ fn blockExprStmts(
12571246 .fn_type_cc,
12581247 .fn_type_cc_var_args,
12591248 .int,
1249 .float,
1250 .float128,
12601251 .intcast,
12611252 .int_type,
12621253 .is_non_null,
......@@ -1334,7 +1325,10 @@ fn blockExprStmts(
13341325 .struct_decl_extern,
13351326 .union_decl,
13361327 .enum_decl,
1328 .enum_decl_nonexhaustive,
13371329 .opaque_decl,
1330 .int_to_enum,
1331 .enum_to_int,
13381332 => break :b false,
13391333
13401334 // ZIR instructions that are always either `noreturn` or `void`.
......@@ -1823,15 +1817,18 @@ fn containerDecl(
18231817 defer bit_bag.deinit(gpa);
18241818
18251819 var cur_bit_bag: u32 = 0;
1826 var member_index: usize = 0;
1827 while (true) {
1828 const member_node = container_decl.ast.members[member_index];
1820 var field_index: usize = 0;
1821 for (container_decl.ast.members) |member_node| {
18291822 const member = switch (node_tags[member_node]) {
18301823 .container_field_init => tree.containerFieldInit(member_node),
18311824 .container_field_align => tree.containerFieldAlign(member_node),
18321825 .container_field => tree.containerField(member_node),
1833 else => unreachable,
1826 else => continue,
18341827 };
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 }
18351832 if (member.comptime_token) |comptime_token| {
18361833 return mod.failTok(scope, comptime_token, "TODO implement comptime struct fields", .{});
18371834 }
......@@ -1858,17 +1855,9 @@ fn containerDecl(
18581855 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
18591856 }
18601857
1861 member_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 }
1858 field_index += 1;
18701859 }
1871 const empty_slot_count = 16 - ((member_index - 1) % 16);
1860 const empty_slot_count = 16 - ((field_index - 1) % 16);
18721861 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
18731862
18741863 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
......@@ -1885,7 +1874,172 @@ fn containerDecl(
18851874 return mod.failTok(scope, container_decl.ast.main_token, "TODO AstGen for union decl", .{});
18861875 },
18871876 .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", .{});
18892043 },
18902044 .keyword_opaque => {
18912045 const result = try gz.addNode(.opaque_decl, node);
......@@ -1901,11 +2055,11 @@ fn errorSetDecl(
19012055 rl: ResultLoc,
19022056 node: ast.Node.Index,
19032057) InnerError!zir.Inst.Ref {
1904 const mod = gz.astgen.mod;
2058 const astgen = gz.astgen;
2059 const mod = astgen.mod;
19052060 const tree = gz.tree();
19062061 const main_tokens = tree.nodes.items(.main_token);
19072062 const token_tags = tree.tokens.items(.tag);
1908 const arena = gz.astgen.arena;
19092063
19102064 // Count how many fields there are.
19112065 const error_token = main_tokens[node];
......@@ -1922,6 +2076,11 @@ fn errorSetDecl(
19222076 } else unreachable; // TODO should not need else unreachable here
19232077 };
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
19252084 const fields = try arena.alloc([]const u8, count);
19262085 {
19272086 var tok_i = error_token + 2;
......@@ -1930,7 +2089,7 @@ fn errorSetDecl(
19302089 switch (token_tags[tok_i]) {
19312090 .doc_comment, .comma => {},
19322091 .identifier => {
1933 fields[field_i] = try mod.identifierTokenString(scope, tok_i);
2092 fields[field_i] = try mod.identifierTokenStringTreeArena(scope, tok_i, tree, arena);
19342093 field_i += 1;
19352094 },
19362095 .r_brace => break,
......@@ -1940,18 +2099,19 @@ fn errorSetDecl(
19402099 }
19412100 const error_set = try arena.create(Module.ErrorSet);
19422101 error_set.* = .{
1943 .owner_decl = gz.astgen.decl,
1944 .node_offset = gz.astgen.decl.nodeIndexToRelative(node),
2102 .owner_decl = astgen.decl,
2103 .node_offset = astgen.decl.nodeIndexToRelative(node),
19452104 .names_ptr = fields.ptr,
19462105 .names_len = @intCast(u32, fields.len),
19472106 };
19482107 const error_set_ty = try Type.Tag.error_set.create(arena, error_set);
1949 const typed_value = try arena.create(TypedValue);
1950 typed_value.* = .{
2108 const error_set_val = try Value.Tag.ty.create(arena, error_set_ty);
2109 const new_decl = try mod.createAnonymousDecl(scope, &new_decl_arena, .{
19512110 .ty = Type.initTag(.type),
1952 .val = try Value.Tag.ty.create(arena, error_set_ty),
1953 };
1954 const result = try gz.addConst(typed_value);
2111 .val = error_set_val,
2112 });
2113 const decl_index = try mod.declareDeclDependency(astgen.decl, new_decl);
2114 const result = try gz.addDecl(.decl_val, decl_index, node);
19552115 return rvalue(gz, scope, rl, result, node);
19562116}
19572117
......@@ -3426,7 +3586,8 @@ fn identifier(
34263586 const tracy = trace(@src());
34273587 defer tracy.end();
34283588
3429 const mod = gz.astgen.mod;
3589 const astgen = gz.astgen;
3590 const mod = astgen.mod;
34303591 const tree = gz.tree();
34313592 const main_tokens = tree.nodes.items(.main_token);
34323593
......@@ -3459,7 +3620,7 @@ fn identifier(
34593620 const result = try gz.add(.{
34603621 .tag = .int_type,
34613622 .data = .{ .int_type = .{
3462 .src_node = gz.astgen.decl.nodeIndexToRelative(ident),
3623 .src_node = astgen.decl.nodeIndexToRelative(ident),
34633624 .signedness = signedness,
34643625 .bit_count = bit_count,
34653626 } },
......@@ -3497,13 +3658,13 @@ fn identifier(
34973658 };
34983659 }
34993660
3500 const gop = try gz.astgen.decl_map.getOrPut(mod.gpa, ident_name);
3501 if (!gop.found_existing) {
3502 const decl = mod.lookupDeclName(scope, ident_name) orelse
3503 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
3504 try gz.astgen.decls.append(mod.gpa, decl);
3505 }
3506 const decl_index = @intCast(u32, gop.index);
3661 const decl = mod.lookupDeclName(scope, ident_name) orelse {
3662 // TODO insert a "dependency on the non-existence of a decl" here to make this
3663 // compile error go away when the decl is introduced. This data should be in a global
3664 // sparse map since it is only relevant when a compile error occurs.
3665 return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
3666 };
3667 const decl_index = try mod.declareDeclDependency(astgen.decl, decl);
35073668 switch (rl) {
35083669 .ref, .none_or_ref => return gz.addDecl(.decl_ref, decl_index, ident),
35093670 else => return rvalue(gz, scope, rl, try gz.addDecl(.decl_val, decl_index, ident), ident),
......@@ -3638,12 +3799,23 @@ fn floatLiteral(
36383799 const float_number = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) {
36393800 error.InvalidCharacter => unreachable, // validated by tokenizer
36403801 };
3641 const typed_value = try arena.create(TypedValue);
3642 typed_value.* = .{
3643 .ty = Type.initTag(.comptime_float),
3644 .val = try Value.Tag.float_128.create(arena, float_number),
3645 };
3646 const result = try gz.addConst(typed_value);
3802 // If the value fits into a f32 without losing any precision, store it that way.
3803 @setFloatMode(.Strict);
3804 const smaller_float = @floatCast(f32, float_number);
3805 const bigger_again: f128 = smaller_float;
3806 if (bigger_again == float_number) {
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 });
36473819 return rvalue(gz, scope, rl, result, node);
36483820}
36493821
......@@ -3955,6 +4127,20 @@ fn builtinCall(
39554127 .bit_cast => return bitCast(gz, scope, rl, node, params[0], params[1]),
39564128 .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
39584144 .add_with_overflow,
39594145 .align_cast,
39604146 .align_of,
......@@ -3981,7 +4167,6 @@ fn builtinCall(
39814167 .div_floor,
39824168 .div_trunc,
39834169 .embed_file,
3984 .enum_to_int,
39854170 .error_name,
39864171 .error_return_trace,
39874172 .err_set_cast,
......@@ -3991,7 +4176,6 @@ fn builtinCall(
39914176 .float_to_int,
39924177 .has_decl,
39934178 .has_field,
3994 .int_to_enum,
39954179 .int_to_float,
39964180 .int_to_ptr,
39974181 .memcpy,
src/BuiltinFn.zig+1-1
......@@ -484,7 +484,7 @@ pub const list = list: {
484484 "@intToEnum",
485485 .{
486486 .tag = .int_to_enum,
487 .param_count = 1,
487 .param_count = 2,
488488 },
489489 },
490490 .{
src/Module.zig+80-16
......@@ -290,6 +290,18 @@ pub const Decl = struct {
290290 return decl.container.fullyQualifiedNameHash(mem.spanZ(decl.name));
291291 }
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
293305 pub fn typedValue(decl: *Decl) error{AnalysisFail}!TypedValue {
294306 const tvm = decl.typedValueManaged() orelse return error.AnalysisFail;
295307 return tvm.typed_value;
......@@ -375,8 +387,7 @@ pub const Struct = struct {
375387 };
376388
377389 pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 {
378 // TODO this should return e.g. "std.fs.Dir.OpenOptions"
379 return gpa.dupe(u8, mem.spanZ(s.owner_decl.name));
390 return s.owner_decl.getFullyQualifiedName(gpa);
380391 }
381392
382393 pub fn srcLoc(s: Struct) SrcLoc {
......@@ -387,6 +398,39 @@ pub const Struct = struct {
387398 }
388399};
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
390434/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
391435/// Extern functions do not have this data structure; they are represented by
392436/// the `Decl` only, with a `Value` tag of `extern_fn`.
......@@ -634,6 +678,11 @@ pub const Scope = struct {
634678 // TODO container scope qualified names.
635679 return std.zig.hashSrc(name);
636680 }
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 }
637686 };
638687
639688 pub const File = struct {
......@@ -1030,7 +1079,6 @@ pub const Scope = struct {
10301079 .instructions = gz.astgen.instructions.toOwnedSlice(),
10311080 .string_bytes = gz.astgen.string_bytes.toOwnedSlice(gpa),
10321081 .extra = gz.astgen.extra.toOwnedSlice(gpa),
1033 .decls = gz.astgen.decls.toOwnedSlice(gpa),
10341082 };
10351083 }
10361084
......@@ -1242,6 +1290,16 @@ pub const Scope = struct {
12421290 });
12431291 }
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
12451303 pub fn addUnNode(
12461304 gz: *GenZir,
12471305 tag: zir.Inst.Tag,
......@@ -1450,13 +1508,6 @@ pub const Scope = struct {
14501508 return new_index;
14511509 }
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
14601511 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
14611512 return gz.astgen.indexToRef(try gz.addAsIndex(inst));
14621513 }
......@@ -3120,12 +3171,14 @@ fn astgenAndSemaVarDecl(
31203171 return type_changed;
31213172}
31223173
3123pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !void {
3124 try depender.dependencies.ensureCapacity(mod.gpa, depender.dependencies.items().len + 1);
3125 try dependee.dependants.ensureCapacity(mod.gpa, dependee.dependants.items().len + 1);
3174/// Returns the depender's index of the dependee.
3175pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !u32 {
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, {});
31283179 dependee.dependants.putAssumeCapacity(depender, {});
3180 const gop = depender.dependencies.getOrPutAssumeCapacity(dependee);
3181 return @intCast(u32, gop.index);
31293182}
31303183
31313184pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree {
......@@ -4445,7 +4498,17 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode {
44454498/// Otherwise, returns a reference to the source code bytes directly.
44464499/// See also `appendIdentStr` and `parseStrLit`.
44474500pub 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 {
44494512 const token_tags = tree.tokens.items(.tag);
44504513 assert(token_tags[token] == .identifier);
44514514 const ident_name = tree.tokenSlice(token);
......@@ -4455,7 +4518,8 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
44554518 var buf: ArrayListUnmanaged(u8) = .{};
44564519 defer buf.deinit(mod.gpa);
44574520 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;
44594523}
44604524
44614525/// 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(
168168 .cmp_lte => try sema.zirCmp(block, inst, .lte),
169169 .cmp_neq => try sema.zirCmp(block, inst, .neq),
170170 .coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
171 .@"const" => try sema.zirConst(block, inst),
172171 .decl_ref => try sema.zirDeclRef(block, inst),
173172 .decl_val => try sema.zirDeclVal(block, inst),
174173 .load => try sema.zirLoad(block, inst),
......@@ -179,6 +178,8 @@ pub fn analyzeBody(
179178 .elem_val_node => try sema.zirElemValNode(block, inst),
180179 .enum_literal => try sema.zirEnumLiteral(block, inst),
181180 .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),
182183 .err_union_code => try sema.zirErrUnionCode(block, inst),
183184 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
184185 .err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
......@@ -201,6 +202,8 @@ pub fn analyzeBody(
201202 .import => try sema.zirImport(block, inst),
202203 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
203204 .int => try sema.zirInt(block, inst),
205 .float => try sema.zirFloat(block, inst),
206 .float128 => try sema.zirFloat128(block, inst),
204207 .int_type => try sema.zirIntType(block, inst),
205208 .intcast => try sema.zirIntcast(block, inst),
206209 .is_err => try sema.zirIsErr(block, inst),
......@@ -264,7 +267,8 @@ pub fn analyzeBody(
264267 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
265268 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
266269 .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),
268272 .union_decl => try sema.zirUnionDecl(block, inst),
269273 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
270274
......@@ -498,18 +502,6 @@ fn resolveInstConst(
498502 };
499503}
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
513505fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
514506 const tracy = trace(@src());
515507 defer tracy.end();
......@@ -617,7 +609,12 @@ fn zirStructDecl(
617609 return sema.analyzeDeclVal(block, src, new_decl);
618610}
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 {
621618 const tracy = trace(@src());
622619 defer tracy.end();
623620
......@@ -1070,6 +1067,31 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
10701067 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
10711068}
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
10731095fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {
10741096 const tracy = trace(@src());
10751097 defer tracy.end();
......@@ -1385,7 +1407,7 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
13851407
13861408 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13871409 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;
13891411 return sema.analyzeDeclRef(block, src, decl);
13901412}
13911413
......@@ -1395,7 +1417,7 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
13951417
13961418 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
13971419 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;
13991421 return sema.analyzeDeclVal(block, src, decl);
14001422}
14011423
......@@ -1852,6 +1874,120 @@ fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) I
18521874 });
18531875}
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
18551991/// Pointer in, pointer out.
18561992fn zirOptionalPayloadPtr(
18571993 sema: *Sema,
......@@ -4630,7 +4766,7 @@ fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl
46304766}
46314767
46324768fn 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);
46344770 sema.mod.ensureDeclAnalyzed(decl) catch |err| {
46354771 if (sema.func) |func| {
46364772 func.state = .dependency_failure;
src/type.zig+301-1556
......@@ -93,9 +93,15 @@ pub const Type = extern union {
9393
9494 .anyerror_void_error_union, .error_union => return .ErrorUnion,
9595
96 .empty_struct => return .Struct,
97 .empty_struct_literal => return .Struct,
98 .@"struct" => return .Struct,
96 .empty_struct,
97 .empty_struct_literal,
98 .@"struct",
99 => return .Struct,
100
101 .enum_full,
102 .enum_nonexhaustive,
103 .enum_simple,
104 => return .Enum,
99105
100106 .var_args_param => unreachable, // can be any type
101107 }
......@@ -614,6 +620,8 @@ pub const Type = extern union {
614620 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
615621 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
616622 .@"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),
617625 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
618626 }
619627 }
......@@ -629,8 +637,8 @@ pub const Type = extern union {
629637 self: Type,
630638 comptime fmt: []const u8,
631639 options: std.fmt.FormatOptions,
632 out_stream: anytype,
633 ) @TypeOf(out_stream).Error!void {
640 writer: anytype,
641 ) @TypeOf(writer).Error!void {
634642 comptime assert(fmt.len == 0);
635643 var ty = self;
636644 while (true) {
......@@ -670,132 +678,149 @@ pub const Type = extern union {
670678 .comptime_float,
671679 .noreturn,
672680 .var_args_param,
673 => return out_stream.writeAll(@tagName(t)),
674
675 .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"),
676 .@"null" => return out_stream.writeAll("@Type(.Null)"),
677 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),
678
679 .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"),
680 .@"struct" => return out_stream.writeAll("(struct)"),
681 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
682 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
683 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
684 .fn_void_no_args => return out_stream.writeAll("fn() void"),
685 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
686 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),
687 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
681 => return writer.writeAll(@tagName(t)),
682
683 .enum_literal => return writer.writeAll("@Type(.EnumLiteral)"),
684 .@"null" => return writer.writeAll("@Type(.Null)"),
685 .@"undefined" => return writer.writeAll("@Type(.Undefined)"),
686
687 .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"),
688
689 .@"struct" => {
690 const struct_obj = self.castTag(.@"struct").?.data;
691 return struct_obj.owner_decl.renderFullyQualifiedName(writer);
692 },
693 .enum_full, .enum_nonexhaustive => {
694 const enum_full = self.castTag(.enum_full).?.data;
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"),
688713 .function => {
689714 const payload = ty.castTag(.function).?.data;
690 try out_stream.writeAll("fn(");
715 try writer.writeAll("fn(");
691716 for (payload.param_types) |param_type, i| {
692 if (i != 0) try out_stream.writeAll(", ");
693 try param_type.format("", .{}, out_stream);
717 if (i != 0) try writer.writeAll(", ");
718 try param_type.format("", .{}, writer);
694719 }
695720 if (payload.is_var_args) {
696721 if (payload.param_types.len != 0) {
697 try out_stream.writeAll(", ");
722 try writer.writeAll(", ");
698723 }
699 try out_stream.writeAll("...");
724 try writer.writeAll("...");
700725 }
701 try out_stream.writeAll(") callconv(.");
702 try out_stream.writeAll(@tagName(payload.cc));
703 try out_stream.writeAll(")");
726 try writer.writeAll(") callconv(.");
727 try writer.writeAll(@tagName(payload.cc));
728 try writer.writeAll(")");
704729 ty = payload.return_type;
705730 continue;
706731 },
707732
708733 .array_u8 => {
709734 const len = ty.castTag(.array_u8).?.data;
710 return out_stream.print("[{d}]u8", .{len});
735 return writer.print("[{d}]u8", .{len});
711736 },
712737 .array_u8_sentinel_0 => {
713738 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});
715740 },
716741 .array => {
717742 const payload = ty.castTag(.array).?.data;
718 try out_stream.print("[{d}]", .{payload.len});
743 try writer.print("[{d}]", .{payload.len});
719744 ty = payload.elem_type;
720745 continue;
721746 },
722747 .array_sentinel => {
723748 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 });
725750 ty = payload.elem_type;
726751 continue;
727752 },
728753 .single_const_pointer => {
729754 const pointee_type = ty.castTag(.single_const_pointer).?.data;
730 try out_stream.writeAll("*const ");
755 try writer.writeAll("*const ");
731756 ty = pointee_type;
732757 continue;
733758 },
734759 .single_mut_pointer => {
735760 const pointee_type = ty.castTag(.single_mut_pointer).?.data;
736 try out_stream.writeAll("*");
761 try writer.writeAll("*");
737762 ty = pointee_type;
738763 continue;
739764 },
740765 .many_const_pointer => {
741766 const pointee_type = ty.castTag(.many_const_pointer).?.data;
742 try out_stream.writeAll("[*]const ");
767 try writer.writeAll("[*]const ");
743768 ty = pointee_type;
744769 continue;
745770 },
746771 .many_mut_pointer => {
747772 const pointee_type = ty.castTag(.many_mut_pointer).?.data;
748 try out_stream.writeAll("[*]");
773 try writer.writeAll("[*]");
749774 ty = pointee_type;
750775 continue;
751776 },
752777 .c_const_pointer => {
753778 const pointee_type = ty.castTag(.c_const_pointer).?.data;
754 try out_stream.writeAll("[*c]const ");
779 try writer.writeAll("[*c]const ");
755780 ty = pointee_type;
756781 continue;
757782 },
758783 .c_mut_pointer => {
759784 const pointee_type = ty.castTag(.c_mut_pointer).?.data;
760 try out_stream.writeAll("[*c]");
785 try writer.writeAll("[*c]");
761786 ty = pointee_type;
762787 continue;
763788 },
764789 .const_slice => {
765790 const pointee_type = ty.castTag(.const_slice).?.data;
766 try out_stream.writeAll("[]const ");
791 try writer.writeAll("[]const ");
767792 ty = pointee_type;
768793 continue;
769794 },
770795 .mut_slice => {
771796 const pointee_type = ty.castTag(.mut_slice).?.data;
772 try out_stream.writeAll("[]");
797 try writer.writeAll("[]");
773798 ty = pointee_type;
774799 continue;
775800 },
776801 .int_signed => {
777802 const bits = ty.castTag(.int_signed).?.data;
778 return out_stream.print("i{d}", .{bits});
803 return writer.print("i{d}", .{bits});
779804 },
780805 .int_unsigned => {
781806 const bits = ty.castTag(.int_unsigned).?.data;
782 return out_stream.print("u{d}", .{bits});
807 return writer.print("u{d}", .{bits});
783808 },
784809 .optional => {
785810 const child_type = ty.castTag(.optional).?.data;
786 try out_stream.writeByte('?');
811 try writer.writeByte('?');
787812 ty = child_type;
788813 continue;
789814 },
790815 .optional_single_const_pointer => {
791816 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;
792 try out_stream.writeAll("?*const ");
817 try writer.writeAll("?*const ");
793818 ty = pointee_type;
794819 continue;
795820 },
796821 .optional_single_mut_pointer => {
797822 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;
798 try out_stream.writeAll("?*");
823 try writer.writeAll("?*");
799824 ty = pointee_type;
800825 continue;
801826 },
......@@ -804,48 +829,46 @@ pub const Type = extern union {
804829 const payload = ty.castTag(.pointer).?.data;
805830 if (payload.sentinel) |some| switch (payload.size) {
806831 .One, .C => unreachable,
807 .Many => try out_stream.print("[*:{}]", .{some}),
808 .Slice => try out_stream.print("[:{}]", .{some}),
832 .Many => try writer.print("[*:{}]", .{some}),
833 .Slice => try writer.print("[:{}]", .{some}),
809834 } else switch (payload.size) {
810 .One => try out_stream.writeAll("*"),
811 .Many => try out_stream.writeAll("[*]"),
812 .C => try out_stream.writeAll("[*c]"),
813 .Slice => try out_stream.writeAll("[]"),
835 .One => try writer.writeAll("*"),
836 .Many => try writer.writeAll("[*]"),
837 .C => try writer.writeAll("[*c]"),
838 .Slice => try writer.writeAll("[]"),
814839 }
815840 if (payload.@"align" != 0) {
816 try out_stream.print("align({d}", .{payload.@"align"});
841 try writer.print("align({d}", .{payload.@"align"});
817842
818843 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 });
820845 }
821 try out_stream.writeAll(") ");
846 try writer.writeAll(") ");
822847 }
823 if (!payload.mutable) try out_stream.writeAll("const ");
824 if (payload.@"volatile") try out_stream.writeAll("volatile ");
825 if (payload.@"allowzero") try out_stream.writeAll("allowzero ");
848 if (!payload.mutable) try writer.writeAll("const ");
849 if (payload.@"volatile") try writer.writeAll("volatile ");
850 if (payload.@"allowzero") try writer.writeAll("allowzero ");
826851
827852 ty = payload.pointee_type;
828853 continue;
829854 },
830855 .error_union => {
831856 const payload = ty.castTag(.error_union).?.data;
832 try payload.error_set.format("", .{}, out_stream);
833 try out_stream.writeAll("!");
857 try payload.error_set.format("", .{}, writer);
858 try writer.writeAll("!");
834859 ty = payload.payload;
835860 continue;
836861 },
837862 .error_set => {
838863 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));
840865 },
841866 .error_set_single => {
842867 const name = ty.castTag(.error_set_single).?.data;
843 return out_stream.print("error{{{s}}}", .{name});
868 return writer.print("error{{{s}}}", .{name});
844869 },
845 .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"),
846 .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"),
847 // TODO use declaration name
848 .@"opaque" => return out_stream.writeAll("opaque {}"),
870 .inferred_alloc_const => return writer.writeAll("(inferred_alloc_const)"),
871 .inferred_alloc_mut => return writer.writeAll("(inferred_alloc_mut)"),
849872 }
850873 unreachable;
851874 }
......@@ -954,6 +977,19 @@ pub const Type = extern union {
954977 return false;
955978 }
956979 },
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
958994 // TODO lazy types
959995 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
......@@ -1112,13 +1148,37 @@ pub const Type = extern union {
11121148 } else if (!payload.payload.hasCodeGenBits()) {
11131149 return payload.error_set.abiAlignment(target);
11141150 }
1115 @panic("TODO abiAlignment error union");
1151 return std.math.max(
1152 payload.payload.abiAlignment(target),
1153 payload.error_set.abiAlignment(target),
1154 );
11161155 },
11171156
11181157 .@"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);
11201181 },
1121
11221182 .c_void,
11231183 .void,
11241184 .type,
......@@ -1166,6 +1226,11 @@ pub const Type = extern union {
11661226 .@"struct" => {
11671227 @panic("TODO abiSize struct");
11681228 },
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
11701235 .u8,
11711236 .i8,
......@@ -1276,76 +1341,25 @@ pub const Type = extern union {
12761341 };
12771342 }
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
12791361 pub fn isSinglePointer(self: Type) bool {
12801362 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
13491363 .single_const_pointer,
13501364 .single_mut_pointer,
13511365 .single_const_pointer_to_comptime_int,
......@@ -1354,73 +1368,14 @@ pub const Type = extern union {
13541368 => true,
13551369
13561370 .pointer => self.castTag(.pointer).?.data.size == .One,
1371
1372 else => false,
13571373 };
13581374 }
13591375
13601376 /// Asserts the `Type` is a pointer.
13611377 pub fn ptrSize(self: Type) std.builtin.TypeInfo.Pointer.Size {
13621378 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
14241379 .const_slice,
14251380 .mut_slice,
14261381 .const_slice_u8,
......@@ -1442,159 +1397,26 @@ pub const Type = extern union {
14421397 => .One,
14431398
14441399 .pointer => self.castTag(.pointer).?.data.size,
1400
1401 else => unreachable,
14451402 };
14461403 }
14471404
14481405 pub fn isSlice(self: Type) bool {
14491406 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
15201407 .const_slice,
15211408 .mut_slice,
15221409 .const_slice_u8,
15231410 => true,
15241411
15251412 .pointer => self.castTag(.pointer).?.data.size == .Slice,
1413
1414 else => false,
15261415 };
15271416 }
15281417
15291418 pub fn isConstPtr(self: Type) bool {
15301419 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
15981420 .single_const_pointer,
15991421 .many_const_pointer,
16001422 .c_const_pointer,
......@@ -1604,170 +1426,40 @@ pub const Type = extern union {
16041426 => true,
16051427
16061428 .pointer => !self.castTag(.pointer).?.data.mutable,
1429
1430 else => false,
16071431 };
16081432 }
16091433
16101434 pub fn isVolatilePtr(self: Type) bool {
16111435 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
16851436 .pointer => {
16861437 const payload = self.castTag(.pointer).?.data;
16871438 return payload.@"volatile";
16881439 },
1440 else => false,
16891441 };
16901442 }
16911443
16921444 pub fn isAllowzeroPtr(self: Type) bool {
16931445 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
17671446 .pointer => {
17681447 const payload = self.castTag(.pointer).?.data;
17691448 return payload.@"allowzero";
17701449 },
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,
17711463 };
17721464 }
17731465
......@@ -1833,64 +1525,6 @@ pub const Type = extern union {
18331525 /// Asserts the type is a pointer or array type.
18341526 pub fn elemType(self: Type) Type {
18351527 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
18941528 .array => self.castTag(.array).?.data.elem_type,
18951529 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
18961530 .single_const_pointer,
......@@ -1902,9 +1536,12 @@ pub const Type = extern union {
19021536 .const_slice,
19031537 .mut_slice,
19041538 => self.castPointer().?.data,
1539
19051540 .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
19061541 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
19071542 .pointer => self.castTag(.pointer).?.data.pointee_type,
1543
1544 else => unreachable,
19081545 };
19091546 }
19101547
......@@ -1972,148 +1609,18 @@ pub const Type = extern union {
19721609 /// Asserts the type is an array or vector.
19731610 pub fn arrayLen(self: Type) u64 {
19741611 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
20451612 .array => self.castTag(.array).?.data.len,
20461613 .array_sentinel => self.castTag(.array_sentinel).?.data.len,
20471614 .array_u8 => self.castTag(.array_u8).?.data,
20481615 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data,
1616
1617 else => unreachable,
20491618 };
20501619 }
20511620
20521621 /// Asserts the type is an array, pointer or vector.
20531622 pub fn sentinel(self: Type) ?Value {
20541623 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
21171624 .single_const_pointer,
21181625 .single_mut_pointer,
21191626 .many_const_pointer,
......@@ -2128,6 +1635,8 @@ pub const Type = extern union {
21281635 .pointer => return self.castTag(.pointer).?.data.sentinel,
21291636 .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel,
21301637 .array_u8_sentinel_0 => return Value.initTag(.zero),
1638
1639 else => unreachable,
21311640 };
21321641 }
21331642
......@@ -2139,68 +1648,6 @@ pub const Type = extern union {
21391648 /// Returns true if and only if the type is a fixed-width, signed integer.
21401649 pub fn isSignedInt(self: Type) bool {
21411650 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
22041651 .int_signed,
22051652 .i8,
22061653 .isize,
......@@ -2211,79 +1658,16 @@ pub const Type = extern union {
22111658 .i16,
22121659 .i32,
22131660 .i64,
2214 .u128,
22151661 .i128,
22161662 => true,
1663
1664 else => false,
22171665 };
22181666 }
22191667
22201668 /// Returns true if and only if the type is a fixed-width, unsigned integer.
22211669 pub fn isUnsignedInt(self: Type) bool {
22221670 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
22871671 .int_unsigned,
22881672 .u8,
22891673 .usize,
......@@ -2294,65 +1678,16 @@ pub const Type = extern union {
22941678 .u16,
22951679 .u32,
22961680 .u64,
1681 .u128,
22971682 => true,
1683
1684 else => false,
22981685 };
22991686 }
23001687
23011688 /// Asserts the type is an integer.
23021689 pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } {
23031690 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
23561691 .int_unsigned => .{
23571692 .signedness = .unsigned,
23581693 .bits = self.castTag(.int_unsigned).?.data,
......@@ -2381,75 +1716,13 @@ pub const Type = extern union {
23811716 .c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
23821717 .c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
23831718 .c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
1719
1720 else => unreachable,
23841721 };
23851722 }
23861723
23871724 pub fn isNamedInt(self: Type) bool {
23881725 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
24531726 .usize,
24541727 .isize,
24551728 .c_short,
......@@ -2461,6 +1734,8 @@ pub const Type = extern union {
24611734 .c_longlong,
24621735 .c_ulonglong,
24631736 => true,
1737
1738 else => false,
24641739 };
24651740 }
24661741
......@@ -2499,74 +1774,7 @@ pub const Type = extern union {
24991774 .fn_ccc_void_no_args => 0,
25001775 .function => self.castTag(.function).?.data.param_types.len,
25011776
2502 .f16,
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,
1777 else => unreachable,
25701778 };
25711779 }
25721780
......@@ -2583,74 +1791,7 @@ pub const Type = extern union {
25831791 std.mem.copy(Type, types, payload.param_types);
25841792 },
25851793
2586 .f16,
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,
1794 else => unreachable,
26541795 }
26551796 }
26561797
......@@ -2662,321 +1803,49 @@ pub const Type = extern union {
26621803 return payload.param_types[index];
26631804 },
26641805
2665 .fn_noreturn_no_args,
2666 .fn_void_no_args,
2667 .fn_naked_noreturn_no_args,
2668 .fn_ccc_void_no_args,
2669 .f16,
2670 .f32,
2671 .f64,
2672 .f128,
2673 .c_longdouble,
2674 .c_void,
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
1806 else => unreachable,
1807 }
1808 }
1809
1810 /// Asserts the type is a function.
1811 pub fn fnReturnType(self: Type) Type {
1812 return switch (self.tag()) {
1813 .fn_noreturn_no_args => Type.initTag(.noreturn),
1814 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
1815
27461816 .fn_void_no_args,
27471817 .fn_ccc_void_no_args,
27481818 => Type.initTag(.void),
27491819
27501820 .function => self.castTag(.function).?.data.return_type,
2751
2752 .f16,
2753 .f32,
2754 .f64,
2755 .f128,
2756 .c_longdouble,
2757 .c_void,
2758 .bool,
2759 .void,
2760 .type,
2761 .anyerror,
2762 .comptime_int,
2763 .comptime_float,
2764 .noreturn,
2765 .@"null",
2766 .@"undefined",
2767 .array,
2768 .array_sentinel,
2769 .array_u8,
2770 .array_u8_sentinel_0,
2771 .pointer,
2772 .single_const_pointer,
2773 .single_mut_pointer,
2774 .many_const_pointer,
2775 .many_mut_pointer,
2776 .c_const_pointer,
2777 .c_mut_pointer,
2778 .const_slice,
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,
1821
1822 else => unreachable,
1823 };
1824 }
1825
1826 /// Asserts the type is a function.
1827 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
1828 return switch (self.tag()) {
1829 .fn_noreturn_no_args => .Unspecified,
1830 .fn_void_no_args => .Unspecified,
1831 .fn_naked_noreturn_no_args => .Naked,
1832 .fn_ccc_void_no_args => .C,
1833 .function => self.castTag(.function).?.data.cc,
1834
1835 else => unreachable,
1836 };
1837 }
1838
1839 /// Asserts the type is a function.
1840 pub fn fnIsVarArgs(self: Type) bool {
1841 return switch (self.tag()) {
1842 .fn_noreturn_no_args => false,
1843 .fn_void_no_args => false,
1844 .fn_naked_noreturn_no_args => false,
1845 .fn_ccc_void_no_args => false,
1846 .function => self.castTag(.function).?.data.is_var_args,
1847
1848 else => unreachable,
29801849 };
29811850 }
29821851
......@@ -3013,50 +1882,7 @@ pub const Type = extern union {
30131882 .int_signed,
30141883 => true,
30151884
3016 .c_void,
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,
1885 else => false,
30601886 };
30611887 }
30621888
......@@ -3127,6 +1953,23 @@ pub const Type = extern union {
31271953 }
31281954 return Value.initTag(.empty_struct_value);
31291955 },
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
31311974 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
31321975 .void => return Value.initTag(.void_value),
......@@ -3166,87 +2009,6 @@ pub const Type = extern union {
31662009 };
31672010 }
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
32502012 pub fn isIndexable(self: Type) bool {
32512013 const zig_tag = self.zigTypeTag();
32522014 // TODO tuples are indexable
......@@ -3257,80 +2019,12 @@ pub const Type = extern union {
32572019 /// Asserts that the type is a container. (note: ErrorSet is not a container).
32582020 pub fn getContainerScope(self: Type) *Module.Scope.Container {
32592021 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
33312022 .@"struct" => &self.castTag(.@"struct").?.data.container,
2023 .enum_full => &self.castTag(.enum_full).?.data.container,
33322024 .empty_struct => self.castTag(.empty_struct).?.data,
33332025 .@"opaque" => &self.castTag(.@"opaque").?.data,
2026
2027 else => unreachable,
33342028 };
33352029 }
33362030
......@@ -3390,7 +2084,43 @@ pub const Type = extern union {
33902084 }
33912085
33922086 pub fn isExhaustiveEnum(ty: Type) bool {
3393 return false; // TODO
2087 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 }
33942124 }
33952125
33962126 /// This enum does not directly correspond to `std.builtin.TypeId` because
......@@ -3482,6 +2212,9 @@ pub const Type = extern union {
34822212 empty_struct,
34832213 @"opaque",
34842214 @"struct",
2215 enum_simple,
2216 enum_full,
2217 enum_nonexhaustive,
34852218
34862219 pub const last_no_payload_tag = Tag.inferred_alloc_const;
34872220 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -3568,6 +2301,8 @@ pub const Type = extern union {
35682301 .error_set_single => Payload.Name,
35692302 .@"opaque" => Payload.Opaque,
35702303 .@"struct" => Payload.Struct,
2304 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
2305 .enum_simple => Payload.EnumSimple,
35712306 .empty_struct => Payload.ContainerScope,
35722307 };
35732308 }
......@@ -3705,6 +2440,16 @@ pub const Type = extern union {
37052440 base: Payload = .{ .tag = .@"struct" },
37062441 data: *Module.Struct,
37072442 };
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 };
37082453 };
37092454};
37102455
src/value.zig+57-780
......@@ -103,6 +103,8 @@ pub const Value = extern union {
103103 float_64,
104104 float_128,
105105 enum_literal,
106 /// A specific enum tag, indicated by the field index (declaration order).
107 enum_field_index,
106108 @"error",
107109 error_union,
108110 /// This is a special value that tracks a set of types that have been stored
......@@ -186,6 +188,8 @@ pub const Value = extern union {
186188 .enum_literal,
187189 => Payload.Bytes,
188190
191 .enum_field_index => Payload.U32,
192
189193 .ty => Payload.Ty,
190194 .int_type => Payload.IntType,
191195 .int_u64 => Payload.U64,
......@@ -394,6 +398,7 @@ pub const Value = extern union {
394398 };
395399 return Value{ .ptr_otherwise = &new_payload.base };
396400 },
401 .enum_field_index => return self.copyPayloadShallow(allocator, Payload.U32),
397402 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
398403 .error_union => {
399404 const payload = self.castTag(.error_union).?;
......@@ -416,6 +421,8 @@ pub const Value = extern union {
416421 return Value{ .ptr_otherwise = &new_payload.base };
417422 }
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.
419426 pub fn format(
420427 self: Value,
421428 comptime fmt: []const u8,
......@@ -506,6 +513,7 @@ pub const Value = extern union {
506513 },
507514 .empty_array => return out_stream.writeAll(".{}"),
508515 .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}),
509517 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(self.castTag(.bytes).?.data)}),
510518 .repeated => {
511519 try out_stream.writeAll("(repeated) ");
......@@ -626,6 +634,7 @@ pub const Value = extern union {
626634 .float_64,
627635 .float_128,
628636 .enum_literal,
637 .enum_field_index,
629638 .@"error",
630639 .error_union,
631640 .empty_struct_value,
......@@ -638,76 +647,6 @@ pub const Value = extern union {
638647 /// Asserts the value is an integer.
639648 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {
640649 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
711650 .zero,
712651 .bool_false,
713652 => return BigIntMutable.init(&space.limbs, 0).toConst(),
......@@ -720,82 +659,15 @@ pub const Value = extern union {
720659 .int_i64 => return BigIntMutable.init(&space.limbs, self.castTag(.int_i64).?.data).toConst(),
721660 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt(),
722661 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt(),
662
663 .undef => unreachable,
664 else => unreachable,
723665 }
724666 }
725667
726668 /// Asserts the value is an integer and it fits in a u64
727669 pub fn toUnsignedInt(self: Value) u64 {
728670 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
799671 .zero,
800672 .bool_false,
801673 => return 0,
......@@ -808,82 +680,15 @@ pub const Value = extern union {
808680 .int_i64 => return @intCast(u64, self.castTag(.int_i64).?.data),
809681 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(u64) catch unreachable,
810682 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(u64) catch unreachable,
683
684 .undef => unreachable,
685 else => unreachable,
811686 }
812687 }
813688
814689 /// Asserts the value is an integer and it fits in a i64
815690 pub fn toSignedInt(self: Value) i64 {
816691 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
887692 .zero,
888693 .bool_false,
889694 => return 0,
......@@ -896,6 +701,9 @@ pub const Value = extern union {
896701 .int_i64 => return self.castTag(.int_i64).?.data,
897702 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
898703 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
704
705 .undef => unreachable,
706 else => unreachable,
899707 }
900708 }
901709
......@@ -929,75 +737,6 @@ pub const Value = extern union {
929737 /// Returns the number of bits the value requires to represent stored in twos complement form.
930738 pub fn intBitCountTwosComp(self: Value) usize {
931739 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
1001740 .zero,
1002741 .bool_false,
1003742 => return 0,
......@@ -1016,80 +755,14 @@ pub const Value = extern union {
1016755 },
1017756 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
1018757 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
758
759 else => unreachable,
1019760 }
1020761 }
1021762
1022763 /// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
1023764 pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
1024765 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
1093766 .zero,
1094767 .undef,
1095768 .bool_false,
......@@ -1144,6 +817,8 @@ pub const Value = extern union {
1144817 .ComptimeInt => return true,
1145818 else => unreachable,
1146819 },
820
821 else => unreachable,
1147822 }
1148823 }
1149824
......@@ -1180,77 +855,6 @@ pub const Value = extern union {
1180855 /// Asserts the value is a float
1181856 pub fn floatHasFraction(self: Value) bool {
1182857 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
1254858 .zero,
1255859 .one,
1256860 => false,
......@@ -1260,76 +864,13 @@ pub const Value = extern union {
1260864 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1261865 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1262866 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
867
868 else => unreachable,
1263869 };
1264870 }
1265871
1266872 pub fn orderAgainstZero(lhs: Value) std.math.Order {
1267873 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
1333874 .zero,
1334875 .bool_false,
1335876 => .eq,
......@@ -1347,6 +888,8 @@ pub const Value = extern union {
1347888 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1348889 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1349890 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
891
892 else => unreachable,
1350893 };
1351894 }
1352895
......@@ -1396,10 +939,12 @@ pub const Value = extern union {
1396939 }
1397940
1398941 pub fn eql(a: Value, b: Value) bool {
1399 if (a.tag() == b.tag()) {
1400 if (a.tag() == .void_value or a.tag() == .null_value) {
942 const a_tag = a.tag();
943 const b_tag = b.tag();
944 if (a_tag == b_tag) {
945 if (a_tag == .void_value or a_tag == .null_value) {
1401946 return true;
1402 } else if (a.tag() == .enum_literal) {
947 } else if (a_tag == .enum_literal) {
1403948 const a_name = a.castTag(.enum_literal).?.data;
1404949 const b_name = b.castTag(.enum_literal).?.data;
1405950 return std.mem.eql(u8, a_name, b_name);
......@@ -1416,6 +961,10 @@ pub const Value = extern union {
1416961 return compare(a, .eq, b);
1417962 }
1418963
964 pub fn hash_u32(self: Value) u32 {
965 return @truncate(u32, self.hash());
966 }
967
1419968 pub fn hash(self: Value) u64 {
1420969 var hasher = std.hash.Wyhash.init(0);
1421970
......@@ -1493,11 +1042,18 @@ pub const Value = extern union {
14931042 .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),
14941043 .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
14971049 .enum_literal => {
14981050 const payload = self.castTag(.enum_literal).?;
14991051 hasher.update(payload.data);
15001052 },
1053 .enum_field_index => {
1054 const payload = self.castTag(.enum_field_index).?;
1055 std.hash.autoHash(&hasher, payload.data);
1056 },
15011057 .bytes => {
15021058 const payload = self.castTag(.bytes).?;
15031059 hasher.update(payload.data);
......@@ -1573,80 +1129,6 @@ pub const Value = extern union {
15731129 /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
15741130 pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
15751131 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
16501132 .ref_val => self.castTag(.ref_val).?.data,
16511133 .decl_ref => self.castTag(.decl_ref).?.data.value(),
16521134 .elem_ptr => {
......@@ -1654,6 +1136,8 @@ pub const Value = extern union {
16541136 const array_val = try elem_ptr.array_ptr.pointerDeref(allocator);
16551137 return array_val.elemValue(allocator, elem_ptr.index);
16561138 },
1139
1140 else => unreachable,
16571141 };
16581142 }
16591143
......@@ -1661,86 +1145,14 @@ pub const Value = extern union {
16611145 /// or an unknown-length pointer, and returns the element value at the index.
16621146 pub fn elemValue(self: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value {
16631147 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
17381148 .empty_array => unreachable, // out of bounds array index
17391149
17401150 .bytes => return Tag.int_u64.create(allocator, self.castTag(.bytes).?.data[index]),
17411151
17421152 // No matter the index; all the elements are the same!
17431153 .repeated => return self.castTag(.repeated).?.data,
1154
1155 else => unreachable,
17441156 }
17451157 }
17461158
......@@ -1766,161 +1178,18 @@ pub const Value = extern union {
17661178 /// Valid for all types. Asserts the value is not undefined and not unreachable.
17671179 pub fn isNull(self: Value) bool {
17681180 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
18421181 .undef => unreachable,
18431182 .unreachable_value => unreachable,
18441183 .inferred_alloc => unreachable,
18451184 .null_value => true,
1185
1186 else => false,
18461187 };
18471188 }
18481189
18491190 /// Valid for all types. Asserts the value is not undefined and not unreachable.
18501191 pub fn getError(self: Value) ?[]const u8 {
18511192 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
19241193 .error_union => {
19251194 const data = self.castTag(.error_union).?.data;
19261195 return if (data.tag() == .@"error")
......@@ -1932,6 +1201,8 @@ pub const Value = extern union {
19321201 .undef => unreachable,
19331202 .unreachable_value => unreachable,
19341203 .inferred_alloc => unreachable,
1204
1205 else => null,
19351206 };
19361207 }
19371208 /// Valid for all types. Asserts the value is not undefined.
......@@ -2021,6 +1292,7 @@ pub const Value = extern union {
20211292 .float_128,
20221293 .void_value,
20231294 .enum_literal,
1295 .enum_field_index,
20241296 .@"error",
20251297 .error_union,
20261298 .empty_struct_value,
......@@ -2038,6 +1310,11 @@ pub const Value = extern union {
20381310 pub const Payload = struct {
20391311 tag: Tag,
20401312
1313 pub const U32 = struct {
1314 base: Payload,
1315 data: u32,
1316 };
1317
20411318 pub const U64 = struct {
20421319 base: Payload,
20431320 data: u64,
src/zir.zig+68-19
......@@ -37,8 +37,6 @@ pub const Code = struct {
3737 string_bytes: []u8,
3838 /// The meaning of this data is determined by `Inst.Tag` value.
3939 extra: []u32,
40 /// Used for decl_val and decl_ref instructions.
41 decls: []*Module.Decl,
4240
4341 /// Returns the requested data, as well as the new index which is at the start of the
4442 /// trailers for the object.
......@@ -78,7 +76,6 @@ pub const Code = struct {
7876 code.instructions.deinit(gpa);
7977 gpa.free(code.string_bytes);
8078 gpa.free(code.extra);
81 gpa.free(code.decls);
8279 code.* = undefined;
8380 }
8481
......@@ -267,9 +264,6 @@ pub const Inst = struct {
267264 /// only the taken branch is analyzed. The then block and else block must
268265 /// terminate with an "inline" variant of a noreturn instruction.
269266 condbr_inline,
270 /// A comptime known value.
271 /// Uses the `const` union field.
272 @"const",
273267 /// A struct type definition. Contains references to ZIR instructions for
274268 /// the field types, defaults, and alignments.
275269 /// Uses the `pl_node` union field. Payload is `StructDecl`.
......@@ -286,6 +280,8 @@ pub const Inst = struct {
286280 /// the field value expressions and optional type tag expression.
287281 /// Uses the `pl_node` union field. Payload is `EnumDecl`.
288282 enum_decl,
283 /// Same as `enum_decl`, except the enum is non-exhaustive.
284 enum_decl_nonexhaustive,
289285 /// An opaque type definition. Provides an AST node only.
290286 /// Uses the `node` union field.
291287 opaque_decl,
......@@ -369,6 +365,11 @@ pub const Inst = struct {
369365 import,
370366 /// Integer literal that fits in a u64. Uses the int union value.
371367 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,
372373 /// Convert an integer value to another integer type, asserting that the destination type
373374 /// can hold the same mathematical value.
374375 /// Uses the `pl_node` field. AST is the `@intCast` syntax.
......@@ -667,6 +668,12 @@ pub const Inst = struct {
667668 /// A struct literal with a specified type, with no fields.
668669 /// Uses the `un_node` field.
669670 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
671678 /// Returns whether the instruction is one of the control flow "noreturn" types.
672679 /// Function calls do not count.
......@@ -712,12 +719,12 @@ pub const Inst = struct {
712719 .cmp_gt,
713720 .cmp_neq,
714721 .coerce_result_ptr,
715 .@"const",
716722 .struct_decl,
717723 .struct_decl_packed,
718724 .struct_decl_extern,
719725 .union_decl,
720726 .enum_decl,
727 .enum_decl_nonexhaustive,
721728 .opaque_decl,
722729 .dbg_stmt_node,
723730 .decl_ref,
......@@ -740,6 +747,8 @@ pub const Inst = struct {
740747 .fn_type_cc,
741748 .fn_type_cc_var_args,
742749 .int,
750 .float,
751 .float128,
743752 .intcast,
744753 .int_type,
745754 .is_non_null,
......@@ -822,6 +831,8 @@ pub const Inst = struct {
822831 .switch_block_ref_under_multi,
823832 .validate_struct_init_ptr,
824833 .struct_init_empty,
834 .int_to_enum,
835 .enum_to_int,
825836 => false,
826837
827838 .@"break",
......@@ -1184,7 +1195,6 @@ pub const Inst = struct {
11841195 }
11851196 },
11861197 bin: Bin,
1187 @"const": *TypedValue,
11881198 /// For strings which may contain null bytes.
11891199 str: struct {
11901200 /// Offset into `string_bytes`.
......@@ -1226,6 +1236,16 @@ pub const Inst = struct {
12261236 /// Offset from Decl AST node index.
12271237 node: i32,
12281238 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 },
12291249 array_type_sentinel: struct {
12301250 len: Ref,
12311251 /// index into extra, points to an `ArrayTypeSentinel`
......@@ -1507,6 +1527,22 @@ pub const Inst = struct {
15071527 tag_type: Ref,
15081528 fields_len: u32,
15091529 };
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 };
15101546};
15111547
15121548pub const SpecialProng = enum { none, @"else", under };
......@@ -1581,6 +1617,7 @@ const Writer = struct {
15811617 .typeof,
15821618 .typeof_elem,
15831619 .struct_init_empty,
1620 .enum_to_int,
15841621 => try self.writeUnNode(stream, inst),
15851622
15861623 .ref,
......@@ -1594,11 +1631,12 @@ const Writer = struct {
15941631 => try self.writeBoolBr(stream, inst),
15951632
15961633 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
1597 .@"const" => try self.writeConst(stream, inst),
15981634 .param_type => try self.writeParamType(stream, inst),
15991635 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
16001636 .ptr_type => try self.writePtrType(stream, inst),
16011637 .int => try self.writeInt(stream, inst),
1638 .float => try self.writeFloat(stream, inst),
1639 .float128 => try self.writeFloat128(stream, inst),
16021640 .str => try self.writeStr(stream, inst),
16031641 .elided => try stream.writeAll(")"),
16041642 .int_type => try self.writeIntType(stream, inst),
......@@ -1619,6 +1657,7 @@ const Writer = struct {
16191657 .slice_sentinel,
16201658 .union_decl,
16211659 .enum_decl,
1660 .enum_decl_nonexhaustive,
16221661 => try self.writePlNode(stream, inst),
16231662
16241663 .add,
......@@ -1647,6 +1686,7 @@ const Writer = struct {
16471686 .merge_error_sets,
16481687 .bit_and,
16491688 .bit_or,
1689 .int_to_enum,
16501690 => try self.writePlNodeBin(stream, inst),
16511691
16521692 .call,
......@@ -1773,15 +1813,6 @@ const Writer = struct {
17731813 try stream.writeAll("TODO)");
17741814 }
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
17851816 fn writeParamType(
17861817 self: *Writer,
17871818 stream: anytype,
......@@ -1819,6 +1850,23 @@ const Writer = struct {
18191850 try stream.print("{d})", .{inst_data});
18201851 }
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
18221870 fn writeStr(
18231871 self: *Writer,
18241872 stream: anytype,
......@@ -2136,7 +2184,8 @@ const Writer = struct {
21362184
21372185 fn writePlNodeDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
21382186 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;
21402189 try stream.print("{s}) ", .{decl.name});
21412190 try self.writeSrc(stream, inst_data.src());
21422191 }