| author | |
| committer | |
| log | 0c601965ab6600fdaf5be3c017176a6871413026 |
| tree | 12c797047baf1bbc87a89c4b513bc2227b9f177f |
| parent | a1afe693951f6d2ad06961c06b3a2cc14ad6efd9 |
| signature | Commit is signed but in an unrecognized format. |
This provides us greatly increased type safety and prevents the common
mistake of using a zir.Inst.Ref where a zir.Inst.Index was expected or
vice-versa. It also increases the ergonomics of using the typed values
which can be directly referenced with a Ref over the previous zir.Const
approach.
The main pain point is casting between a []Ref and []u32, which could be
alleviated in the future with a new std.mem function.5 files changed, 548 insertions(+), 529 deletions(-)
lib/std/enums.zig+48-41| ... | @@ -32,7 +32,7 @@ pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_def | ... | @@ -32,7 +32,7 @@ pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_def |
| 32 | .fields = fields, | 32 | .fields = fields, |
| 33 | .decls = &[_]std.builtin.TypeInfo.Declaration{}, | 33 | .decls = &[_]std.builtin.TypeInfo.Declaration{}, |
| 34 | .is_tuple = false, | 34 | .is_tuple = false, |
| 35 | }}); | 35 | } }); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | /// Looks up the supplied fields in the given enum type. | 38 | /// Looks up the supplied fields in the given enum type. |
| ... | @@ -70,7 +70,7 @@ pub fn values(comptime E: type) []const E { | ... | @@ -70,7 +70,7 @@ pub fn values(comptime E: type) []const E { |
| 70 | 70 | ||
| 71 | test "std.enum.values" { | 71 | test "std.enum.values" { |
| 72 | const E = extern enum { a, b, c, d = 0 }; | 72 | const E = extern enum { a, b, c, d = 0 }; |
| 73 | testing.expectEqualSlices(E, &.{.a, .b, .c, .d}, values(E)); | 73 | testing.expectEqualSlices(E, &.{ .a, .b, .c, .d }, values(E)); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /// Returns the set of all unique named values in the given enum, in | 76 | /// Returns the set of all unique named values in the given enum, in |
| ... | @@ -82,10 +82,10 @@ pub fn uniqueValues(comptime E: type) []const E { | ... | @@ -82,10 +82,10 @@ pub fn uniqueValues(comptime E: type) []const E { |
| 82 | 82 | ||
| 83 | test "std.enum.uniqueValues" { | 83 | test "std.enum.uniqueValues" { |
| 84 | const E = extern enum { a, b, c, d = 0, e, f = 3 }; | 84 | const E = extern enum { a, b, c, d = 0, e, f = 3 }; |
| 85 | testing.expectEqualSlices(E, &.{.a, .b, .c, .f}, uniqueValues(E)); | 85 | testing.expectEqualSlices(E, &.{ .a, .b, .c, .f }, uniqueValues(E)); |
| 86 | 86 | ||
| 87 | const F = enum { a, b, c }; | 87 | const F = enum { a, b, c }; |
| 88 | testing.expectEqualSlices(F, &.{.a, .b, .c}, uniqueValues(F)); | 88 | testing.expectEqualSlices(F, &.{ .a, .b, .c }, uniqueValues(F)); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | /// Returns the set of all unique field values in the given enum, in | 91 | /// Returns the set of all unique field values in the given enum, in |
| ... | @@ -102,8 +102,7 @@ pub fn uniqueFields(comptime E: type) []const EnumField { | ... | @@ -102,8 +102,7 @@ pub fn uniqueFields(comptime E: type) []const EnumField { |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | var unique_fields: []const EnumField = &[_]EnumField{}; | 104 | var unique_fields: []const EnumField = &[_]EnumField{}; |
| 105 | outer: | 105 | outer: for (raw_fields) |candidate| { |
| 106 | for (raw_fields) |candidate| { | ||
| 107 | for (unique_fields) |u| { | 106 | for (unique_fields) |u| { |
| 108 | if (u.value == candidate.value) | 107 | if (u.value == candidate.value) |
| 109 | continue :outer; | 108 | continue :outer; |
| ... | @@ -116,28 +115,25 @@ pub fn uniqueFields(comptime E: type) []const EnumField { | ... | @@ -116,28 +115,25 @@ pub fn uniqueFields(comptime E: type) []const EnumField { |
| 116 | } | 115 | } |
| 117 | 116 | ||
| 118 | /// Determines the length of a direct-mapped enum array, indexed by | 117 | /// Determines the length of a direct-mapped enum array, indexed by |
| 119 | /// @intCast(usize, @enumToInt(enum_value)). The enum must be exhaustive. | 118 | /// @intCast(usize, @enumToInt(enum_value)). |
| 119 | /// If the enum is non-exhaustive, the resulting length will only be enough | ||
| 120 | /// to hold all explicit fields. | ||
| 120 | /// If the enum contains any fields with values that cannot be represented | 121 | /// If the enum contains any fields with values that cannot be represented |
| 121 | /// by usize, a compile error is issued. The max_unused_slots parameter limits | 122 | /// by usize, a compile error is issued. The max_unused_slots parameter limits |
| 122 | /// the total number of items which have no matching enum key (holes in the enum | 123 | /// the total number of items which have no matching enum key (holes in the enum |
| 123 | /// numbering). So for example, if an enum has values 1, 2, 5, and 6, max_unused_slots | 124 | /// numbering). So for example, if an enum has values 1, 2, 5, and 6, max_unused_slots |
| 124 | /// must be at least 3, to allow unused slots 0, 3, and 4. | 125 | /// must be at least 3, to allow unused slots 0, 3, and 4. |
| 125 | fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int { | 126 | fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int { |
| 126 | const info = @typeInfo(E).Enum; | ||
| 127 | if (!info.is_exhaustive) { | ||
| 128 | @compileError("Cannot create direct array of non-exhaustive enum "++@typeName(E)); | ||
| 129 | } | ||
| 130 | |||
| 131 | var max_value: comptime_int = -1; | 127 | var max_value: comptime_int = -1; |
| 132 | const max_usize: comptime_int = ~@as(usize, 0); | 128 | const max_usize: comptime_int = ~@as(usize, 0); |
| 133 | const fields = uniqueFields(E); | 129 | const fields = uniqueFields(E); |
| 134 | for (fields) |f| { | 130 | for (fields) |f| { |
| 135 | if (f.value < 0) { | 131 | if (f.value < 0) { |
| 136 | @compileError("Cannot create a direct enum array for "++@typeName(E)++", field ."++f.name++" has a negative value."); | 132 | @compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " has a negative value."); |
| 137 | } | 133 | } |
| 138 | if (f.value > max_value) { | 134 | if (f.value > max_value) { |
| 139 | if (f.value > max_usize) { | 135 | if (f.value > max_usize) { |
| 140 | @compileError("Cannot create a direct enum array for "++@typeName(E)++", field ."++f.name++" is larger than the max value of usize."); | 136 | @compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " is larger than the max value of usize."); |
| 141 | } | 137 | } |
| 142 | max_value = f.value; | 138 | max_value = f.value; |
| 143 | } | 139 | } |
| ... | @@ -147,14 +143,16 @@ fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) | ... | @@ -147,14 +143,16 @@ fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) |
| 147 | if (unused_slots > max_unused_slots) { | 143 | if (unused_slots > max_unused_slots) { |
| 148 | const unused_str = std.fmt.comptimePrint("{d}", .{unused_slots}); | 144 | const unused_str = std.fmt.comptimePrint("{d}", .{unused_slots}); |
| 149 | const allowed_str = std.fmt.comptimePrint("{d}", .{max_unused_slots}); | 145 | const allowed_str = std.fmt.comptimePrint("{d}", .{max_unused_slots}); |
| 150 | @compileError("Cannot create a direct enum array for "++@typeName(E)++". It would have "++unused_str++" unused slots, but only "++allowed_str++" are allowed."); | 146 | @compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ". It would have " ++ unused_str ++ " unused slots, but only " ++ allowed_str ++ " are allowed."); |
| 151 | } | 147 | } |
| 152 | 148 | ||
| 153 | return max_value + 1; | 149 | return max_value + 1; |
| 154 | } | 150 | } |
| 155 | 151 | ||
| 156 | /// Initializes an array of Data which can be indexed by | 152 | /// Initializes an array of Data which can be indexed by |
| 157 | /// @intCast(usize, @enumToInt(enum_value)). The enum must be exhaustive. | 153 | /// @intCast(usize, @enumToInt(enum_value)). |
| 154 | /// If the enum is non-exhaustive, the resulting array will only be large enough | ||
| 155 | /// to hold all explicit fields. | ||
| 158 | /// If the enum contains any fields with values that cannot be represented | 156 | /// If the enum contains any fields with values that cannot be represented |
| 159 | /// by usize, a compile error is issued. The max_unused_slots parameter limits | 157 | /// by usize, a compile error is issued. The max_unused_slots parameter limits |
| 160 | /// the total number of items which have no matching enum key (holes in the enum | 158 | /// the total number of items which have no matching enum key (holes in the enum |
| ... | @@ -243,9 +241,9 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E { | ... | @@ -243,9 +241,9 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E { |
| 243 | if (@hasField(E, n)) { | 241 | if (@hasField(E, n)) { |
| 244 | return @field(E, n); | 242 | return @field(E, n); |
| 245 | } | 243 | } |
| 246 | @compileError("Enum "++@typeName(E)++" has no field named "++n); | 244 | @compileError("Enum " ++ @typeName(E) ++ " has no field named " ++ n); |
| 247 | } | 245 | } |
| 248 | @compileError("Cannot cast from "++@typeName(@TypeOf(value))++" to "++@typeName(E)); | 246 | @compileError("Cannot cast from " ++ @typeName(@TypeOf(value)) ++ " to " ++ @typeName(E)); |
| 249 | } | 247 | } |
| 250 | } | 248 | } |
| 251 | 249 | ||
| ... | @@ -256,7 +254,7 @@ test "std.enums.nameCast" { | ... | @@ -256,7 +254,7 @@ test "std.enums.nameCast" { |
| 256 | testing.expectEqual(A.a, nameCast(A, A.a)); | 254 | testing.expectEqual(A.a, nameCast(A, A.a)); |
| 257 | testing.expectEqual(A.a, nameCast(A, B.a)); | 255 | testing.expectEqual(A.a, nameCast(A, B.a)); |
| 258 | testing.expectEqual(A.a, nameCast(A, "a")); | 256 | testing.expectEqual(A.a, nameCast(A, "a")); |
| 259 | testing.expectEqual(A.a, nameCast(A, @as(*const[1]u8, "a"))); | 257 | testing.expectEqual(A.a, nameCast(A, @as(*const [1]u8, "a"))); |
| 260 | testing.expectEqual(A.a, nameCast(A, @as([:0]const u8, "a"))); | 258 | testing.expectEqual(A.a, nameCast(A, @as([:0]const u8, "a"))); |
| 261 | testing.expectEqual(A.a, nameCast(A, @as([]const u8, "a"))); | 259 | testing.expectEqual(A.a, nameCast(A, @as([]const u8, "a"))); |
| 262 | 260 | ||
| ... | @@ -398,12 +396,12 @@ pub fn EnumArray(comptime E: type, comptime V: type) type { | ... | @@ -398,12 +396,12 @@ pub fn EnumArray(comptime E: type, comptime V: type) type { |
| 398 | pub fn NoExtension(comptime Self: type) type { | 396 | pub fn NoExtension(comptime Self: type) type { |
| 399 | return NoExt; | 397 | return NoExt; |
| 400 | } | 398 | } |
| 401 | const NoExt = struct{}; | 399 | const NoExt = struct {}; |
| 402 | 400 | ||
| 403 | /// A set type with an Indexer mapping from keys to indices. | 401 | /// A set type with an Indexer mapping from keys to indices. |
| 404 | /// Presence or absence is stored as a dense bitfield. This | 402 | /// Presence or absence is stored as a dense bitfield. This |
| 405 | /// type does no allocation and can be copied by value. | 403 | /// type does no allocation and can be copied by value. |
| 406 | pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { | 404 | pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { |
| 407 | comptime ensureIndexer(I); | 405 | comptime ensureIndexer(I); |
| 408 | return struct { | 406 | return struct { |
| 409 | const Self = @This(); | 407 | const Self = @This(); |
| ... | @@ -422,7 +420,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { | ... | @@ -422,7 +420,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { |
| 422 | 420 | ||
| 423 | bits: BitSet = BitSet.initEmpty(), | 421 | bits: BitSet = BitSet.initEmpty(), |
| 424 | 422 | ||
| 425 | /// Returns a set containing all possible keys. | 423 | /// Returns a set containing all possible keys. |
| 426 | pub fn initFull() Self { | 424 | pub fn initFull() Self { |
| 427 | return .{ .bits = BitSet.initFull() }; | 425 | return .{ .bits = BitSet.initFull() }; |
| 428 | } | 426 | } |
| ... | @@ -492,7 +490,8 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { | ... | @@ -492,7 +490,8 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { |
| 492 | pub fn next(self: *Iterator) ?Key { | 490 | pub fn next(self: *Iterator) ?Key { |
| 493 | return if (self.inner.next()) |index| | 491 | return if (self.inner.next()) |index| |
| 494 | Indexer.keyForIndex(index) | 492 | Indexer.keyForIndex(index) |
| 495 | else null; | 493 | else |
| 494 | null; | ||
| 496 | } | 495 | } |
| 497 | }; | 496 | }; |
| 498 | }; | 497 | }; |
| ... | @@ -501,7 +500,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { | ... | @@ -501,7 +500,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type { |
| 501 | /// A map from keys to values, using an index lookup. Uses a | 500 | /// A map from keys to values, using an index lookup. Uses a |
| 502 | /// bitfield to track presence and a dense array of values. | 501 | /// bitfield to track presence and a dense array of values. |
| 503 | /// This type does no allocation and can be copied by value. | 502 | /// This type does no allocation and can be copied by value. |
| 504 | pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type) type { | 503 | pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn (type) type) type { |
| 505 | comptime ensureIndexer(I); | 504 | comptime ensureIndexer(I); |
| 506 | return struct { | 505 | return struct { |
| 507 | const Self = @This(); | 506 | const Self = @This(); |
| ... | @@ -652,7 +651,8 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type | ... | @@ -652,7 +651,8 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type |
| 652 | .key = Indexer.keyForIndex(index), | 651 | .key = Indexer.keyForIndex(index), |
| 653 | .value = &self.values[index], | 652 | .value = &self.values[index], |
| 654 | } | 653 | } |
| 655 | else null; | 654 | else |
| 655 | null; | ||
| 656 | } | 656 | } |
| 657 | }; | 657 | }; |
| 658 | }; | 658 | }; |
| ... | @@ -660,7 +660,7 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type | ... | @@ -660,7 +660,7 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type |
| 660 | 660 | ||
| 661 | /// A dense array of values, using an indexed lookup. | 661 | /// A dense array of values, using an indexed lookup. |
| 662 | /// This type does no allocation and can be copied by value. | 662 | /// This type does no allocation and can be copied by value. |
| 663 | pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: fn(type)type) type { | 663 | pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: fn (type) type) type { |
| 664 | comptime ensureIndexer(I); | 664 | comptime ensureIndexer(I); |
| 665 | return struct { | 665 | return struct { |
| 666 | const Self = @This(); | 666 | const Self = @This(); |
| ... | @@ -769,9 +769,9 @@ pub fn ensureIndexer(comptime T: type) void { | ... | @@ -769,9 +769,9 @@ pub fn ensureIndexer(comptime T: type) void { |
| 769 | if (!@hasDecl(T, "count")) @compileError("Indexer must have decl count: usize."); | 769 | if (!@hasDecl(T, "count")) @compileError("Indexer must have decl count: usize."); |
| 770 | if (@TypeOf(T.count) != usize) @compileError("Indexer.count must be a usize."); | 770 | if (@TypeOf(T.count) != usize) @compileError("Indexer.count must be a usize."); |
| 771 | if (!@hasDecl(T, "indexOf")) @compileError("Indexer.indexOf must be a fn(Key)usize."); | 771 | if (!@hasDecl(T, "indexOf")) @compileError("Indexer.indexOf must be a fn(Key)usize."); |
| 772 | if (@TypeOf(T.indexOf) != fn(T.Key)usize) @compileError("Indexer must have decl indexOf: fn(Key)usize."); | 772 | if (@TypeOf(T.indexOf) != fn (T.Key) usize) @compileError("Indexer must have decl indexOf: fn(Key)usize."); |
| 773 | if (!@hasDecl(T, "keyForIndex")) @compileError("Indexer must have decl keyForIndex: fn(usize)Key."); | 773 | if (!@hasDecl(T, "keyForIndex")) @compileError("Indexer must have decl keyForIndex: fn(usize)Key."); |
| 774 | if (@TypeOf(T.keyForIndex) != fn(usize)T.Key) @compileError("Indexer.keyForIndex must be a fn(usize)Key."); | 774 | if (@TypeOf(T.keyForIndex) != fn (usize) T.Key) @compileError("Indexer.keyForIndex must be a fn(usize)Key."); |
| 775 | } | 775 | } |
| 776 | } | 776 | } |
| 777 | 777 | ||
| ... | @@ -802,14 +802,18 @@ pub fn EnumIndexer(comptime E: type) type { | ... | @@ -802,14 +802,18 @@ pub fn EnumIndexer(comptime E: type) type { |
| 802 | return struct { | 802 | return struct { |
| 803 | pub const Key = E; | 803 | pub const Key = E; |
| 804 | pub const count: usize = 0; | 804 | pub const count: usize = 0; |
| 805 | pub fn indexOf(e: E) usize { unreachable; } | 805 | pub fn indexOf(e: E) usize { |
| 806 | pub fn keyForIndex(i: usize) E { unreachable; } | 806 | unreachable; |
| 807 | } | ||
| 808 | pub fn keyForIndex(i: usize) E { | ||
| 809 | unreachable; | ||
| 810 | } | ||
| 807 | }; | 811 | }; |
| 808 | } | 812 | } |
| 809 | std.sort.sort(EnumField, &fields, {}, ascByValue); | 813 | std.sort.sort(EnumField, &fields, {}, ascByValue); |
| 810 | const min = fields[0].value; | 814 | const min = fields[0].value; |
| 811 | const max = fields[fields.len-1].value; | 815 | const max = fields[fields.len - 1].value; |
| 812 | if (max - min == fields.len-1) { | 816 | if (max - min == fields.len - 1) { |
| 813 | return struct { | 817 | return struct { |
| 814 | pub const Key = E; | 818 | pub const Key = E; |
| 815 | pub const count = fields.len; | 819 | pub const count = fields.len; |
| ... | @@ -844,7 +848,7 @@ pub fn EnumIndexer(comptime E: type) type { | ... | @@ -844,7 +848,7 @@ pub fn EnumIndexer(comptime E: type) type { |
| 844 | } | 848 | } |
| 845 | 849 | ||
| 846 | test "std.enums.EnumIndexer dense zeroed" { | 850 | test "std.enums.EnumIndexer dense zeroed" { |
| 847 | const E = enum{ b = 1, a = 0, c = 2 }; | 851 | const E = enum { b = 1, a = 0, c = 2 }; |
| 848 | const Indexer = EnumIndexer(E); | 852 | const Indexer = EnumIndexer(E); |
| 849 | ensureIndexer(Indexer); | 853 | ensureIndexer(Indexer); |
| 850 | testing.expectEqual(E, Indexer.Key); | 854 | testing.expectEqual(E, Indexer.Key); |
| ... | @@ -908,7 +912,7 @@ test "std.enums.EnumIndexer sparse" { | ... | @@ -908,7 +912,7 @@ test "std.enums.EnumIndexer sparse" { |
| 908 | } | 912 | } |
| 909 | 913 | ||
| 910 | test "std.enums.EnumIndexer repeats" { | 914 | test "std.enums.EnumIndexer repeats" { |
| 911 | const E = extern enum{ a = -2, c = 6, b = 4, b2 = 4 }; | 915 | const E = extern enum { a = -2, c = 6, b = 4, b2 = 4 }; |
| 912 | const Indexer = EnumIndexer(E); | 916 | const Indexer = EnumIndexer(E); |
| 913 | ensureIndexer(Indexer); | 917 | ensureIndexer(Indexer); |
| 914 | testing.expectEqual(E, Indexer.Key); | 918 | testing.expectEqual(E, Indexer.Key); |
| ... | @@ -957,7 +961,8 @@ test "std.enums.EnumSet" { | ... | @@ -957,7 +961,8 @@ test "std.enums.EnumSet" { |
| 957 | } | 961 | } |
| 958 | 962 | ||
| 959 | var mut = Set.init(.{ | 963 | var mut = Set.init(.{ |
| 960 | .a=true, .c=true, | 964 | .a = true, |
| 965 | .c = true, | ||
| 961 | }); | 966 | }); |
| 962 | testing.expectEqual(@as(usize, 2), mut.count()); | 967 | testing.expectEqual(@as(usize, 2), mut.count()); |
| 963 | testing.expectEqual(true, mut.contains(.a)); | 968 | testing.expectEqual(true, mut.contains(.a)); |
| ... | @@ -986,7 +991,7 @@ test "std.enums.EnumSet" { | ... | @@ -986,7 +991,7 @@ test "std.enums.EnumSet" { |
| 986 | testing.expectEqual(@as(?E, null), it.next()); | 991 | testing.expectEqual(@as(?E, null), it.next()); |
| 987 | } | 992 | } |
| 988 | 993 | ||
| 989 | mut.toggleSet(Set.init(.{ .a=true, .b=true })); | 994 | mut.toggleSet(Set.init(.{ .a = true, .b = true })); |
| 990 | testing.expectEqual(@as(usize, 2), mut.count()); | 995 | testing.expectEqual(@as(usize, 2), mut.count()); |
| 991 | testing.expectEqual(true, mut.contains(.a)); | 996 | testing.expectEqual(true, mut.contains(.a)); |
| 992 | testing.expectEqual(false, mut.contains(.b)); | 997 | testing.expectEqual(false, mut.contains(.b)); |
| ... | @@ -994,7 +999,7 @@ test "std.enums.EnumSet" { | ... | @@ -994,7 +999,7 @@ test "std.enums.EnumSet" { |
| 994 | testing.expectEqual(true, mut.contains(.d)); | 999 | testing.expectEqual(true, mut.contains(.d)); |
| 995 | testing.expectEqual(true, mut.contains(.e)); // aliases a | 1000 | testing.expectEqual(true, mut.contains(.e)); // aliases a |
| 996 | 1001 | ||
| 997 | mut.setUnion(Set.init(.{ .a=true, .b=true })); | 1002 | mut.setUnion(Set.init(.{ .a = true, .b = true })); |
| 998 | testing.expectEqual(@as(usize, 3), mut.count()); | 1003 | testing.expectEqual(@as(usize, 3), mut.count()); |
| 999 | testing.expectEqual(true, mut.contains(.a)); | 1004 | testing.expectEqual(true, mut.contains(.a)); |
| 1000 | testing.expectEqual(true, mut.contains(.b)); | 1005 | testing.expectEqual(true, mut.contains(.b)); |
| ... | @@ -1009,7 +1014,7 @@ test "std.enums.EnumSet" { | ... | @@ -1009,7 +1014,7 @@ test "std.enums.EnumSet" { |
| 1009 | testing.expectEqual(false, mut.contains(.c)); | 1014 | testing.expectEqual(false, mut.contains(.c)); |
| 1010 | testing.expectEqual(true, mut.contains(.d)); | 1015 | testing.expectEqual(true, mut.contains(.d)); |
| 1011 | 1016 | ||
| 1012 | mut.setIntersection(Set.init(.{ .a=true, .b=true })); | 1017 | mut.setIntersection(Set.init(.{ .a = true, .b = true })); |
| 1013 | testing.expectEqual(@as(usize, 1), mut.count()); | 1018 | testing.expectEqual(@as(usize, 1), mut.count()); |
| 1014 | testing.expectEqual(true, mut.contains(.a)); | 1019 | testing.expectEqual(true, mut.contains(.a)); |
| 1015 | testing.expectEqual(false, mut.contains(.b)); | 1020 | testing.expectEqual(false, mut.contains(.b)); |
| ... | @@ -1072,7 +1077,7 @@ test "std.enums.EnumArray sized" { | ... | @@ -1072,7 +1077,7 @@ test "std.enums.EnumArray sized" { |
| 1072 | const undef = Array.initUndefined(); | 1077 | const undef = Array.initUndefined(); |
| 1073 | var inst = Array.initFill(5); | 1078 | var inst = Array.initFill(5); |
| 1074 | const inst2 = Array.init(.{ .a = 1, .b = 2, .c = 3, .d = 4 }); | 1079 | const inst2 = Array.init(.{ .a = 1, .b = 2, .c = 3, .d = 4 }); |
| 1075 | const inst3 = Array.initDefault(6, .{.b = 4, .c = 2}); | 1080 | const inst3 = Array.initDefault(6, .{ .b = 4, .c = 2 }); |
| 1076 | 1081 | ||
| 1077 | testing.expectEqual(@as(usize, 5), inst.get(.a)); | 1082 | testing.expectEqual(@as(usize, 5), inst.get(.a)); |
| 1078 | testing.expectEqual(@as(usize, 5), inst.get(.b)); | 1083 | testing.expectEqual(@as(usize, 5), inst.get(.b)); |
| ... | @@ -1272,10 +1277,12 @@ test "std.enums.EnumMap sized" { | ... | @@ -1272,10 +1277,12 @@ test "std.enums.EnumMap sized" { |
| 1272 | var iter = a.iterator(); | 1277 | var iter = a.iterator(); |
| 1273 | const Entry = Map.Entry; | 1278 | const Entry = Map.Entry; |
| 1274 | testing.expectEqual(@as(?Entry, Entry{ | 1279 | testing.expectEqual(@as(?Entry, Entry{ |
| 1275 | .key = .b, .value = &a.values[1], | 1280 | .key = .b, |
| 1281 | .value = &a.values[1], | ||
| 1276 | }), iter.next()); | 1282 | }), iter.next()); |
| 1277 | testing.expectEqual(@as(?Entry, Entry{ | 1283 | testing.expectEqual(@as(?Entry, Entry{ |
| 1278 | .key = .d, .value = &a.values[3], | 1284 | .key = .d, |
| 1285 | .value = &a.values[3], | ||
| 1279 | }), iter.next()); | 1286 | }), iter.next()); |
| 1280 | testing.expectEqual(@as(?Entry, null), iter.next()); | 1287 | testing.expectEqual(@as(?Entry, null), iter.next()); |
| 1281 | } | 1288 | } |
src/Module.zig+50-48| ... | @@ -914,16 +914,16 @@ pub const Scope = struct { | ... | @@ -914,16 +914,16 @@ pub const Scope = struct { |
| 914 | parent: *Scope, | 914 | parent: *Scope, |
| 915 | /// All `GenZir` scopes for the same ZIR share this. | 915 | /// All `GenZir` scopes for the same ZIR share this. |
| 916 | zir_code: *WipZirCode, | 916 | zir_code: *WipZirCode, |
| 917 | /// Keeps track of the list of instructions in this scope only. References | 917 | /// Keeps track of the list of instructions in this scope only. Indexes |
| 918 | /// to instructions in `zir_code`. | 918 | /// to instructions in `zir_code`. |
| 919 | instructions: std.ArrayListUnmanaged(zir.Inst.Ref) = .{}, | 919 | instructions: std.ArrayListUnmanaged(zir.Inst.Index) = .{}, |
| 920 | label: ?Label = null, | 920 | label: ?Label = null, |
| 921 | break_block: zir.Inst.Index = 0, | 921 | break_block: zir.Inst.Index = 0, |
| 922 | continue_block: zir.Inst.Index = 0, | 922 | continue_block: zir.Inst.Index = 0, |
| 923 | /// Only valid when setBlockResultLoc is called. | 923 | /// Only valid when setBlockResultLoc is called. |
| 924 | break_result_loc: astgen.ResultLoc = undefined, | 924 | break_result_loc: astgen.ResultLoc = undefined, |
| 925 | /// When a block has a pointer result location, here it is. | 925 | /// When a block has a pointer result location, here it is. |
| 926 | rl_ptr: zir.Inst.Ref = 0, | 926 | rl_ptr: zir.Inst.Ref = .none, |
| 927 | /// Keeps track of how many branches of a block did not actually | 927 | /// Keeps track of how many branches of a block did not actually |
| 928 | /// consume the result location. astgen uses this to figure out | 928 | /// consume the result location. astgen uses this to figure out |
| 929 | /// whether to rely on break instructions or writing to the result | 929 | /// whether to rely on break instructions or writing to the result |
| ... | @@ -1001,8 +1001,8 @@ pub const Scope = struct { | ... | @@ -1001,8 +1001,8 @@ pub const Scope = struct { |
| 1001 | ret_ty: zir.Inst.Ref, | 1001 | ret_ty: zir.Inst.Ref, |
| 1002 | cc: zir.Inst.Ref, | 1002 | cc: zir.Inst.Ref, |
| 1003 | }) !zir.Inst.Ref { | 1003 | }) !zir.Inst.Ref { |
| 1004 | assert(args.ret_ty != 0); | 1004 | assert(args.ret_ty != .none); |
| 1005 | assert(args.cc != 0); | 1005 | assert(args.cc != .none); |
| 1006 | const gpa = gz.zir_code.gpa; | 1006 | const gpa = gz.zir_code.gpa; |
| 1007 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | 1007 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); |
| 1008 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); | 1008 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); |
| ... | @@ -1013,7 +1013,7 @@ pub const Scope = struct { | ... | @@ -1013,7 +1013,7 @@ pub const Scope = struct { |
| 1013 | .cc = args.cc, | 1013 | .cc = args.cc, |
| 1014 | .param_types_len = @intCast(u32, args.param_types.len), | 1014 | .param_types_len = @intCast(u32, args.param_types.len), |
| 1015 | }); | 1015 | }); |
| 1016 | gz.zir_code.extra.appendSliceAssumeCapacity(args.param_types); | 1016 | gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args.param_types))); |
| 1017 | 1017 | ||
| 1018 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1018 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1019 | gz.zir_code.instructions.appendAssumeCapacity(.{ | 1019 | gz.zir_code.instructions.appendAssumeCapacity(.{ |
| ... | @@ -1024,7 +1024,7 @@ pub const Scope = struct { | ... | @@ -1024,7 +1024,7 @@ pub const Scope = struct { |
| 1024 | } }, | 1024 | } }, |
| 1025 | }); | 1025 | }); |
| 1026 | gz.instructions.appendAssumeCapacity(new_index); | 1026 | gz.instructions.appendAssumeCapacity(new_index); |
| 1027 | return new_index + gz.zir_code.ref_start_index; | 1027 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1028 | } | 1028 | } |
| 1029 | 1029 | ||
| 1030 | pub fn addFnType( | 1030 | pub fn addFnType( |
| ... | @@ -1033,7 +1033,7 @@ pub const Scope = struct { | ... | @@ -1033,7 +1033,7 @@ pub const Scope = struct { |
| 1033 | ret_ty: zir.Inst.Ref, | 1033 | ret_ty: zir.Inst.Ref, |
| 1034 | param_types: []const zir.Inst.Ref, | 1034 | param_types: []const zir.Inst.Ref, |
| 1035 | ) !zir.Inst.Ref { | 1035 | ) !zir.Inst.Ref { |
| 1036 | assert(ret_ty != 0); | 1036 | assert(ret_ty != .none); |
| 1037 | const gpa = gz.zir_code.gpa; | 1037 | const gpa = gz.zir_code.gpa; |
| 1038 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | 1038 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); |
| 1039 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); | 1039 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); |
| ... | @@ -1043,7 +1043,7 @@ pub const Scope = struct { | ... | @@ -1043,7 +1043,7 @@ pub const Scope = struct { |
| 1043 | const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.FnType{ | 1043 | const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.FnType{ |
| 1044 | .param_types_len = @intCast(u32, param_types.len), | 1044 | .param_types_len = @intCast(u32, param_types.len), |
| 1045 | }); | 1045 | }); |
| 1046 | gz.zir_code.extra.appendSliceAssumeCapacity(param_types); | 1046 | gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(param_types))); |
| 1047 | 1047 | ||
| 1048 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1048 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1049 | gz.zir_code.instructions.appendAssumeCapacity(.{ | 1049 | gz.zir_code.instructions.appendAssumeCapacity(.{ |
| ... | @@ -1054,7 +1054,7 @@ pub const Scope = struct { | ... | @@ -1054,7 +1054,7 @@ pub const Scope = struct { |
| 1054 | } }, | 1054 | } }, |
| 1055 | }); | 1055 | }); |
| 1056 | gz.instructions.appendAssumeCapacity(new_index); | 1056 | gz.instructions.appendAssumeCapacity(new_index); |
| 1057 | return new_index + gz.zir_code.ref_start_index; | 1057 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1058 | } | 1058 | } |
| 1059 | 1059 | ||
| 1060 | pub fn addCall( | 1060 | pub fn addCall( |
| ... | @@ -1065,7 +1065,7 @@ pub const Scope = struct { | ... | @@ -1065,7 +1065,7 @@ pub const Scope = struct { |
| 1065 | /// Absolute node index. This function does the conversion to offset from Decl. | 1065 | /// Absolute node index. This function does the conversion to offset from Decl. |
| 1066 | src_node: ast.Node.Index, | 1066 | src_node: ast.Node.Index, |
| 1067 | ) !zir.Inst.Ref { | 1067 | ) !zir.Inst.Ref { |
| 1068 | assert(callee != 0); | 1068 | assert(callee != .none); |
| 1069 | assert(src_node != 0); | 1069 | assert(src_node != 0); |
| 1070 | const gpa = gz.zir_code.gpa; | 1070 | const gpa = gz.zir_code.gpa; |
| 1071 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | 1071 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); |
| ... | @@ -1077,7 +1077,7 @@ pub const Scope = struct { | ... | @@ -1077,7 +1077,7 @@ pub const Scope = struct { |
| 1077 | .callee = callee, | 1077 | .callee = callee, |
| 1078 | .args_len = @intCast(u32, args.len), | 1078 | .args_len = @intCast(u32, args.len), |
| 1079 | }); | 1079 | }); |
| 1080 | gz.zir_code.extra.appendSliceAssumeCapacity(args); | 1080 | gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args))); |
| 1081 | 1081 | ||
| 1082 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1082 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1083 | gz.zir_code.instructions.appendAssumeCapacity(.{ | 1083 | gz.zir_code.instructions.appendAssumeCapacity(.{ |
| ... | @@ -1088,7 +1088,7 @@ pub const Scope = struct { | ... | @@ -1088,7 +1088,7 @@ pub const Scope = struct { |
| 1088 | } }, | 1088 | } }, |
| 1089 | }); | 1089 | }); |
| 1090 | gz.instructions.appendAssumeCapacity(new_index); | 1090 | gz.instructions.appendAssumeCapacity(new_index); |
| 1091 | return new_index + gz.zir_code.ref_start_index; | 1091 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1092 | } | 1092 | } |
| 1093 | 1093 | ||
| 1094 | /// Note that this returns a `zir.Inst.Index` not a ref. | 1094 | /// Note that this returns a `zir.Inst.Index` not a ref. |
| ... | @@ -1098,7 +1098,7 @@ pub const Scope = struct { | ... | @@ -1098,7 +1098,7 @@ pub const Scope = struct { |
| 1098 | tag: zir.Inst.Tag, | 1098 | tag: zir.Inst.Tag, |
| 1099 | lhs: zir.Inst.Ref, | 1099 | lhs: zir.Inst.Ref, |
| 1100 | ) !zir.Inst.Index { | 1100 | ) !zir.Inst.Index { |
| 1101 | assert(lhs != 0); | 1101 | assert(lhs != .none); |
| 1102 | const gpa = gz.zir_code.gpa; | 1102 | const gpa = gz.zir_code.gpa; |
| 1103 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); | 1103 | try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); |
| 1104 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); | 1104 | try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1); |
| ... | @@ -1129,7 +1129,7 @@ pub const Scope = struct { | ... | @@ -1129,7 +1129,7 @@ pub const Scope = struct { |
| 1129 | /// Absolute node index. This function does the conversion to offset from Decl. | 1129 | /// Absolute node index. This function does the conversion to offset from Decl. |
| 1130 | src_node: ast.Node.Index, | 1130 | src_node: ast.Node.Index, |
| 1131 | ) !zir.Inst.Ref { | 1131 | ) !zir.Inst.Ref { |
| 1132 | assert(operand != 0); | 1132 | assert(operand != .none); |
| 1133 | return gz.add(.{ | 1133 | return gz.add(.{ |
| 1134 | .tag = tag, | 1134 | .tag = tag, |
| 1135 | .data = .{ .un_node = .{ | 1135 | .data = .{ .un_node = .{ |
| ... | @@ -1160,7 +1160,7 @@ pub const Scope = struct { | ... | @@ -1160,7 +1160,7 @@ pub const Scope = struct { |
| 1160 | } }, | 1160 | } }, |
| 1161 | }); | 1161 | }); |
| 1162 | gz.instructions.appendAssumeCapacity(new_index); | 1162 | gz.instructions.appendAssumeCapacity(new_index); |
| 1163 | return new_index + gz.zir_code.ref_start_index; | 1163 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1164 | } | 1164 | } |
| 1165 | 1165 | ||
| 1166 | pub fn addArrayTypeSentinel( | 1166 | pub fn addArrayTypeSentinel( |
| ... | @@ -1186,7 +1186,7 @@ pub const Scope = struct { | ... | @@ -1186,7 +1186,7 @@ pub const Scope = struct { |
| 1186 | } }, | 1186 | } }, |
| 1187 | }); | 1187 | }); |
| 1188 | gz.instructions.appendAssumeCapacity(new_index); | 1188 | gz.instructions.appendAssumeCapacity(new_index); |
| 1189 | return new_index + gz.zir_code.ref_start_index; | 1189 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1190 | } | 1190 | } |
| 1191 | 1191 | ||
| 1192 | pub fn addUnTok( | 1192 | pub fn addUnTok( |
| ... | @@ -1196,7 +1196,7 @@ pub const Scope = struct { | ... | @@ -1196,7 +1196,7 @@ pub const Scope = struct { |
| 1196 | /// Absolute token index. This function does the conversion to Decl offset. | 1196 | /// Absolute token index. This function does the conversion to Decl offset. |
| 1197 | abs_tok_index: ast.TokenIndex, | 1197 | abs_tok_index: ast.TokenIndex, |
| 1198 | ) !zir.Inst.Ref { | 1198 | ) !zir.Inst.Ref { |
| 1199 | assert(operand != 0); | 1199 | assert(operand != .none); |
| 1200 | return gz.add(.{ | 1200 | return gz.add(.{ |
| 1201 | .tag = tag, | 1201 | .tag = tag, |
| 1202 | .data = .{ .un_tok = .{ | 1202 | .data = .{ .un_tok = .{ |
| ... | @@ -1228,8 +1228,8 @@ pub const Scope = struct { | ... | @@ -1228,8 +1228,8 @@ pub const Scope = struct { |
| 1228 | lhs: zir.Inst.Ref, | 1228 | lhs: zir.Inst.Ref, |
| 1229 | rhs: zir.Inst.Ref, | 1229 | rhs: zir.Inst.Ref, |
| 1230 | ) !zir.Inst.Ref { | 1230 | ) !zir.Inst.Ref { |
| 1231 | assert(lhs != 0); | 1231 | assert(lhs != .none); |
| 1232 | assert(rhs != 0); | 1232 | assert(rhs != .none); |
| 1233 | return gz.add(.{ | 1233 | return gz.add(.{ |
| 1234 | .tag = tag, | 1234 | .tag = tag, |
| 1235 | .data = .{ .bin = .{ | 1235 | .data = .{ .bin = .{ |
| ... | @@ -1317,7 +1317,7 @@ pub const Scope = struct { | ... | @@ -1317,7 +1317,7 @@ pub const Scope = struct { |
| 1317 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1317 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1318 | gz.zir_code.instructions.appendAssumeCapacity(inst); | 1318 | gz.zir_code.instructions.appendAssumeCapacity(inst); |
| 1319 | gz.instructions.appendAssumeCapacity(new_index); | 1319 | gz.instructions.appendAssumeCapacity(new_index); |
| 1320 | return gz.zir_code.ref_start_index + new_index; | 1320 | return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1321 | } | 1321 | } |
| 1322 | }; | 1322 | }; |
| 1323 | 1323 | ||
| ... | @@ -1331,7 +1331,7 @@ pub const Scope = struct { | ... | @@ -1331,7 +1331,7 @@ pub const Scope = struct { |
| 1331 | parent: *Scope, | 1331 | parent: *Scope, |
| 1332 | gen_zir: *GenZir, | 1332 | gen_zir: *GenZir, |
| 1333 | name: []const u8, | 1333 | name: []const u8, |
| 1334 | inst: zir.Inst.Index, | 1334 | inst: zir.Inst.Ref, |
| 1335 | /// Source location of the corresponding variable declaration. | 1335 | /// Source location of the corresponding variable declaration. |
| 1336 | src: LazySrcLoc, | 1336 | src: LazySrcLoc, |
| 1337 | }; | 1337 | }; |
| ... | @@ -1346,7 +1346,7 @@ pub const Scope = struct { | ... | @@ -1346,7 +1346,7 @@ pub const Scope = struct { |
| 1346 | parent: *Scope, | 1346 | parent: *Scope, |
| 1347 | gen_zir: *GenZir, | 1347 | gen_zir: *GenZir, |
| 1348 | name: []const u8, | 1348 | name: []const u8, |
| 1349 | ptr: zir.Inst.Index, | 1349 | ptr: zir.Inst.Ref, |
| 1350 | /// Source location of the corresponding variable declaration. | 1350 | /// Source location of the corresponding variable declaration. |
| 1351 | src: LazySrcLoc, | 1351 | src: LazySrcLoc, |
| 1352 | }; | 1352 | }; |
| ... | @@ -1366,9 +1366,9 @@ pub const WipZirCode = struct { | ... | @@ -1366,9 +1366,9 @@ pub const WipZirCode = struct { |
| 1366 | instructions: std.MultiArrayList(zir.Inst) = .{}, | 1366 | instructions: std.MultiArrayList(zir.Inst) = .{}, |
| 1367 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, | 1367 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 1368 | extra: std.ArrayListUnmanaged(u32) = .{}, | 1368 | extra: std.ArrayListUnmanaged(u32) = .{}, |
| 1369 | /// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert | 1369 | /// We need to keep track of this count in order to convert between |
| 1370 | /// to `zir.Inst.Index`. The default here is correct if there are 0 parameters. | 1370 | /// `zir.Inst.Ref` and `zir.Inst.Index` types. |
| 1371 | ref_start_index: u32 = zir.const_inst_list.len, | 1371 | param_count: u32 = 0, |
| 1372 | decl: *Decl, | 1372 | decl: *Decl, |
| 1373 | gpa: *Allocator, | 1373 | gpa: *Allocator, |
| 1374 | arena: *Allocator, | 1374 | arena: *Allocator, |
| ... | @@ -1383,15 +1383,18 @@ pub const WipZirCode = struct { | ... | @@ -1383,15 +1383,18 @@ pub const WipZirCode = struct { |
| 1383 | const fields = std.meta.fields(@TypeOf(extra)); | 1383 | const fields = std.meta.fields(@TypeOf(extra)); |
| 1384 | const result = @intCast(u32, wzc.extra.items.len); | 1384 | const result = @intCast(u32, wzc.extra.items.len); |
| 1385 | inline for (fields) |field| { | 1385 | inline for (fields) |field| { |
| 1386 | comptime assert(field.field_type == u32); | 1386 | wzc.extra.appendAssumeCapacity(switch (field.field_type) { |
| 1387 | wzc.extra.appendAssumeCapacity(@field(extra, field.name)); | 1387 | u32 => @field(extra, field.name), |
| 1388 | zir.Inst.Ref => @enumToInt(@field(extra, field.name)), | ||
| 1389 | else => unreachable, | ||
| 1390 | }); | ||
| 1388 | } | 1391 | } |
| 1389 | return result; | 1392 | return result; |
| 1390 | } | 1393 | } |
| 1391 | 1394 | ||
| 1392 | pub fn refIsNoReturn(wzc: WipZirCode, zir_inst_ref: zir.Inst.Ref) bool { | 1395 | pub fn refIsNoReturn(wzc: WipZirCode, zir_inst_ref: zir.Inst.Ref) bool { |
| 1393 | if (zir_inst_ref >= wzc.ref_start_index) { | 1396 | if (zir_inst_ref == .unreachable_value) return true; |
| 1394 | const zir_inst = zir_inst_ref - wzc.ref_start_index; | 1397 | if (zir_inst_ref.toIndex(wzc.param_count)) |zir_inst| { |
| 1395 | return wzc.instructions.items(.tag)[zir_inst].isNoReturn(); | 1398 | return wzc.instructions.items(.tag)[zir_inst].isNoReturn(); |
| 1396 | } | 1399 | } |
| 1397 | return false; | 1400 | return false; |
| ... | @@ -2072,7 +2075,7 @@ fn astgenAndSemaFn( | ... | @@ -2072,7 +2075,7 @@ fn astgenAndSemaFn( |
| 2072 | // The AST params array does not contain anytype and ... parameters. | 2075 | // The AST params array does not contain anytype and ... parameters. |
| 2073 | // We must iterate to count how many param types to allocate. | 2076 | // We must iterate to count how many param types to allocate. |
| 2074 | const param_count = blk: { | 2077 | const param_count = blk: { |
| 2075 | var count: usize = 0; | 2078 | var count: u32 = 0; |
| 2076 | var it = fn_proto.iterate(tree); | 2079 | var it = fn_proto.iterate(tree); |
| 2077 | while (it.next()) |param| { | 2080 | while (it.next()) |param| { |
| 2078 | if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break; | 2081 | if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break; |
| ... | @@ -2081,7 +2084,6 @@ fn astgenAndSemaFn( | ... | @@ -2081,7 +2084,6 @@ fn astgenAndSemaFn( |
| 2081 | break :blk count; | 2084 | break :blk count; |
| 2082 | }; | 2085 | }; |
| 2083 | const param_types = try fn_type_scope_arena.allocator.alloc(zir.Inst.Ref, param_count); | 2086 | const param_types = try fn_type_scope_arena.allocator.alloc(zir.Inst.Ref, param_count); |
| 2084 | const type_type_rl: astgen.ResultLoc = .{ .ty = @enumToInt(zir.Const.type_type) }; | ||
| 2085 | 2087 | ||
| 2086 | var is_var_args = false; | 2088 | var is_var_args = false; |
| 2087 | { | 2089 | { |
| ... | @@ -2106,7 +2108,7 @@ fn astgenAndSemaFn( | ... | @@ -2106,7 +2108,7 @@ fn astgenAndSemaFn( |
| 2106 | const param_type_node = param.type_expr; | 2108 | const param_type_node = param.type_expr; |
| 2107 | assert(param_type_node != 0); | 2109 | assert(param_type_node != 0); |
| 2108 | param_types[param_type_i] = | 2110 | param_types[param_type_i] = |
| 2109 | try astgen.expr(mod, &fn_type_scope.base, type_type_rl, param_type_node); | 2111 | try astgen.expr(mod, &fn_type_scope.base, .{ .ty = .type_type }, param_type_node); |
| 2110 | } | 2112 | } |
| 2111 | assert(param_type_i == param_count); | 2113 | assert(param_type_i == param_count); |
| 2112 | } | 2114 | } |
| ... | @@ -2178,7 +2180,7 @@ fn astgenAndSemaFn( | ... | @@ -2178,7 +2180,7 @@ fn astgenAndSemaFn( |
| 2178 | const return_type_inst = try astgen.expr( | 2180 | const return_type_inst = try astgen.expr( |
| 2179 | mod, | 2181 | mod, |
| 2180 | &fn_type_scope.base, | 2182 | &fn_type_scope.base, |
| 2181 | type_type_rl, | 2183 | .{ .ty = .type_type }, |
| 2182 | fn_proto.ast.return_type, | 2184 | fn_proto.ast.return_type, |
| 2183 | ); | 2185 | ); |
| 2184 | 2186 | ||
| ... | @@ -2187,19 +2189,22 @@ fn astgenAndSemaFn( | ... | @@ -2187,19 +2189,22 @@ fn astgenAndSemaFn( |
| 2187 | else | 2189 | else |
| 2188 | false; | 2190 | false; |
| 2189 | 2191 | ||
| 2190 | const cc: zir.Inst.Index = if (fn_proto.ast.callconv_expr != 0) | 2192 | const cc: zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) |
| 2191 | // TODO instead of enum literal type, this needs to be the | 2193 | // TODO instead of enum literal type, this needs to be the |
| 2192 | // std.builtin.CallingConvention enum. We need to implement importing other files | 2194 | // std.builtin.CallingConvention enum. We need to implement importing other files |
| 2193 | // and enums in order to fix this. | 2195 | // and enums in order to fix this. |
| 2194 | try astgen.comptimeExpr(mod, &fn_type_scope.base, .{ | 2196 | try astgen.comptimeExpr( |
| 2195 | .ty = @enumToInt(zir.Const.enum_literal_type), | 2197 | mod, |
| 2196 | }, fn_proto.ast.callconv_expr) | 2198 | &fn_type_scope.base, |
| 2199 | .{ .ty = .enum_literal_type }, | ||
| 2200 | fn_proto.ast.callconv_expr, | ||
| 2201 | ) | ||
| 2197 | else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269 | 2202 | else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269 |
| 2198 | try fn_type_scope.addSmallStr(.enum_literal_small, "C") | 2203 | try fn_type_scope.addSmallStr(.enum_literal_small, "C") |
| 2199 | else | 2204 | else |
| 2200 | 0; | 2205 | .none; |
| 2201 | 2206 | ||
| 2202 | const fn_type_inst: zir.Inst.Ref = if (cc != 0) fn_type: { | 2207 | const fn_type_inst: zir.Inst.Ref = if (cc != .none) fn_type: { |
| 2203 | const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc; | 2208 | const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc; |
| 2204 | break :fn_type try fn_type_scope.addFnTypeCc(tag, .{ | 2209 | break :fn_type try fn_type_scope.addFnTypeCc(tag, .{ |
| 2205 | .ret_ty = return_type_inst, | 2210 | .ret_ty = return_type_inst, |
| ... | @@ -2292,7 +2297,7 @@ fn astgenAndSemaFn( | ... | @@ -2292,7 +2297,7 @@ fn astgenAndSemaFn( |
| 2292 | .decl = decl, | 2297 | .decl = decl, |
| 2293 | .arena = &decl_arena.allocator, | 2298 | .arena = &decl_arena.allocator, |
| 2294 | .gpa = mod.gpa, | 2299 | .gpa = mod.gpa, |
| 2295 | .ref_start_index = @intCast(u32, zir.const_inst_list.len + param_count), | 2300 | .param_count = param_count, |
| 2296 | }; | 2301 | }; |
| 2297 | defer wip_zir_code.deinit(); | 2302 | defer wip_zir_code.deinit(); |
| 2298 | 2303 | ||
| ... | @@ -2309,7 +2314,7 @@ fn astgenAndSemaFn( | ... | @@ -2309,7 +2314,7 @@ fn astgenAndSemaFn( |
| 2309 | try wip_zir_code.extra.ensureCapacity(mod.gpa, param_count); | 2314 | try wip_zir_code.extra.ensureCapacity(mod.gpa, param_count); |
| 2310 | 2315 | ||
| 2311 | var params_scope = &gen_scope.base; | 2316 | var params_scope = &gen_scope.base; |
| 2312 | var i: usize = 0; | 2317 | var i: u32 = 0; |
| 2313 | var it = fn_proto.iterate(tree); | 2318 | var it = fn_proto.iterate(tree); |
| 2314 | while (it.next()) |param| : (i += 1) { | 2319 | while (it.next()) |param| : (i += 1) { |
| 2315 | const name_token = param.name_token.?; | 2320 | const name_token = param.name_token.?; |
| ... | @@ -2320,7 +2325,7 @@ fn astgenAndSemaFn( | ... | @@ -2320,7 +2325,7 @@ fn astgenAndSemaFn( |
| 2320 | .gen_zir = &gen_scope, | 2325 | .gen_zir = &gen_scope, |
| 2321 | .name = param_name, | 2326 | .name = param_name, |
| 2322 | // Implicit const list first, then implicit arg list. | 2327 | // Implicit const list first, then implicit arg list. |
| 2323 | .inst = @intCast(u32, zir.const_inst_list.len + i), | 2328 | .inst = zir.Inst.Ref.fromParam(i), |
| 2324 | .src = decl.tokSrcLoc(name_token), | 2329 | .src = decl.tokSrcLoc(name_token), |
| 2325 | }; | 2330 | }; |
| 2326 | params_scope = &sub_scope.base; | 2331 | params_scope = &sub_scope.base; |
| ... | @@ -2344,8 +2349,7 @@ fn astgenAndSemaFn( | ... | @@ -2344,8 +2349,7 @@ fn astgenAndSemaFn( |
| 2344 | // astgen uses result location semantics to coerce return operands. | 2349 | // astgen uses result location semantics to coerce return operands. |
| 2345 | // Since we are adding the return instruction here, we must handle the coercion. | 2350 | // Since we are adding the return instruction here, we must handle the coercion. |
| 2346 | // We do this by using the `ret_coerce` instruction. | 2351 | // We do this by using the `ret_coerce` instruction. |
| 2347 | const void_inst: zir.Inst.Ref = @enumToInt(zir.Const.void_value); | 2352 | _ = try gen_scope.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| 2348 | _ = try gen_scope.addUnTok(.ret_coerce, void_inst, tree.lastToken(body_node)); | ||
| 2349 | } | 2353 | } |
| 2350 | 2354 | ||
| 2351 | const code = try gen_scope.finish(); | 2355 | const code = try gen_scope.finish(); |
| ... | @@ -2514,9 +2518,7 @@ fn astgenAndSemaVarDecl( | ... | @@ -2514,9 +2518,7 @@ fn astgenAndSemaVarDecl( |
| 2514 | defer gen_scope.instructions.deinit(mod.gpa); | 2518 | defer gen_scope.instructions.deinit(mod.gpa); |
| 2515 | 2519 | ||
| 2516 | const init_result_loc: astgen.ResultLoc = if (var_decl.ast.type_node != 0) .{ | 2520 | const init_result_loc: astgen.ResultLoc = if (var_decl.ast.type_node != 0) .{ |
| 2517 | .ty = try astgen.expr(mod, &gen_scope.base, .{ | 2521 | .ty = try astgen.expr(mod, &gen_scope.base, .{ .ty = .type_type }, var_decl.ast.type_node), |
| 2518 | .ty = @enumToInt(zir.Const.type_type), | ||
| 2519 | }, var_decl.ast.type_node), | ||
| 2520 | } else .none; | 2522 | } else .none; |
| 2521 | 2523 | ||
| 2522 | const init_inst = try astgen.comptimeExpr( | 2524 | const init_inst = try astgen.comptimeExpr( |
src/Sema.zig+32-34| ... | @@ -78,7 +78,7 @@ pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type { | ... | @@ -78,7 +78,7 @@ pub fn rootAsType(sema: *Sema, root_block: *Scope.Block) !Type { |
| 78 | /// return type of `analyzeBody` so that we can tail call them. | 78 | /// return type of `analyzeBody` so that we can tail call them. |
| 79 | /// Only appropriate to return when the instruction is known to be NoReturn | 79 | /// Only appropriate to return when the instruction is known to be NoReturn |
| 80 | /// solely based on the ZIR tag. | 80 | /// solely based on the ZIR tag. |
| 81 | const always_noreturn: InnerError!zir.Inst.Ref = @as(zir.Inst.Index, 0); | 81 | const always_noreturn: InnerError!zir.Inst.Ref = .none; |
| 82 | 82 | ||
| 83 | /// This function is the main loop of `Sema` and it can be used in two different ways: | 83 | /// This function is the main loop of `Sema` and it can be used in two different ways: |
| 84 | /// * The traditional way where there are N breaks out of the block and peer type | 84 | /// * The traditional way where there are N breaks out of the block and peer type |
| ... | @@ -88,7 +88,7 @@ const always_noreturn: InnerError!zir.Inst.Ref = @as(zir.Inst.Index, 0); | ... | @@ -88,7 +88,7 @@ const always_noreturn: InnerError!zir.Inst.Ref = @as(zir.Inst.Index, 0); |
| 88 | /// * The "flat" way. There is only 1 break out of the block, and it is with a `break_flat` | 88 | /// * The "flat" way. There is only 1 break out of the block, and it is with a `break_flat` |
| 89 | /// instruction. In this case, the `zir.Inst.Index` part of the return value will be | 89 | /// instruction. In this case, the `zir.Inst.Index` part of the return value will be |
| 90 | /// the block result value. No block scope needs to be created for this strategy. | 90 | /// the block result value. No block scope needs to be created for this strategy. |
| 91 | pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) !zir.Inst.Index { | 91 | pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) !zir.Inst.Ref { |
| 92 | // No tracy calls here, to avoid interfering with the tail call mechanism. | 92 | // No tracy calls here, to avoid interfering with the tail call mechanism. |
| 93 | 93 | ||
| 94 | const map = block.sema.inst_map; | 94 | const map = block.sema.inst_map; |
| ... | @@ -300,28 +300,18 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde | ... | @@ -300,28 +300,18 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | /// TODO when we rework TZIR memory layout, this function will no longer have a possible error. | 302 | /// TODO when we rework TZIR memory layout, this function will no longer have a possible error. |
| 303 | /// Until then we allocate memory for a new, mutable `ir.Inst` to match what TZIR expects. | ||
| 303 | pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst { | 304 | pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst { |
| 304 | var i: usize = zir_ref; | 305 | if (zir_ref.toTypedValue()) |typed_value| { |
| 305 | 306 | return sema.mod.constInst(sema.arena, .unneeded, typed_value); | |
| 306 | // First section of indexes correspond to a set number of constant values. | ||
| 307 | if (i < zir.const_inst_list.len) { | ||
| 308 | // TODO when we rework TZIR memory layout, this function can be as simple as: | ||
| 309 | // if (zir_ref < zir.const_inst_list.len + sema.param_count) | ||
| 310 | // return zir_ref; | ||
| 311 | // Until then we allocate memory for a new, mutable `ir.Inst` to match what | ||
| 312 | // TZIR expects. | ||
| 313 | return sema.mod.constInst(sema.arena, .unneeded, zir.const_inst_list[i]); | ||
| 314 | } | 307 | } |
| 315 | i -= zir.const_inst_list.len; | ||
| 316 | 308 | ||
| 317 | // Next section of indexes correspond to function parameters, if any. | 309 | const param_count = @intCast(u32, sema.param_inst_list.len); |
| 318 | if (i < sema.param_inst_list.len) { | 310 | if (zir_ref.toParam(param_count)) |param| { |
| 319 | return sema.param_inst_list[i]; | 311 | return sema.param_inst_list[param]; |
| 320 | } | 312 | } |
| 321 | i -= sema.param_inst_list.len; | ||
| 322 | 313 | ||
| 323 | // Finally, the last section of indexes refers to the map of ZIR=>TZIR. | 314 | return sema.inst_map[zir_ref.toIndex(param_count).?]; |
| 324 | return sema.inst_map[i]; | ||
| 325 | } | 315 | } |
| 326 | 316 | ||
| 327 | fn resolveConstString( | 317 | fn resolveConstString( |
| ... | @@ -745,7 +735,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In | ... | @@ -745,7 +735,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In |
| 745 | return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int); | 735 | return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int); |
| 746 | } | 736 | } |
| 747 | 737 | ||
| 748 | fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index { | 738 | fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref { |
| 749 | const tracy = trace(@src()); | 739 | const tracy = trace(@src()); |
| 750 | defer tracy.end(); | 740 | defer tracy.end(); |
| 751 | 741 | ||
| ... | @@ -763,7 +753,10 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr | ... | @@ -763,7 +753,10 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr |
| 763 | 753 | ||
| 764 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 754 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 765 | const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index); | 755 | const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index); |
| 766 | for (sema.code.extra[extra.end..][0..extra.data.operands_len]) |arg_ref, i| { | 756 | const raw_args = sema.code.extra[extra.end..][0..extra.data.operands_len]; |
| 757 | const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args)); | ||
| 758 | |||
| 759 | for (args) |arg_ref, i| { | ||
| 767 | if (i != 0) try writer.print(", ", .{}); | 760 | if (i != 0) try writer.print(", ", .{}); |
| 768 | 761 | ||
| 769 | const arg = try sema.resolveInst(arg_ref); | 762 | const arg = try sema.resolveInst(arg_ref); |
| ... | @@ -998,7 +991,7 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr | ... | @@ -998,7 +991,7 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr |
| 998 | _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint); | 991 | _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint); |
| 999 | } | 992 | } |
| 1000 | 993 | ||
| 1001 | fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index { | 994 | fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref { |
| 1002 | const tracy = trace(@src()); | 995 | const tracy = trace(@src()); |
| 1003 | defer tracy.end(); | 996 | defer tracy.end(); |
| 1004 | 997 | ||
| ... | @@ -1007,7 +1000,7 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!z | ... | @@ -1007,7 +1000,7 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!z |
| 1007 | return sema.analyzeBreak(block, sema.src, inst_data.block_inst, operand); | 1000 | return sema.analyzeBreak(block, sema.src, inst_data.block_inst, operand); |
| 1008 | } | 1001 | } |
| 1009 | 1002 | ||
| 1010 | fn zirBreakVoidNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index { | 1003 | fn zirBreakVoidNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Ref { |
| 1011 | const tracy = trace(@src()); | 1004 | const tracy = trace(@src()); |
| 1012 | defer tracy.end(); | 1005 | defer tracy.end(); |
| 1013 | 1006 | ||
| ... | @@ -1112,7 +1105,8 @@ fn zirCall( | ... | @@ -1112,7 +1105,8 @@ fn zirCall( |
| 1112 | const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; | 1105 | const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node }; |
| 1113 | const call_src = inst_data.src(); | 1106 | const call_src = inst_data.src(); |
| 1114 | const extra = sema.code.extraData(zir.Inst.Call, inst_data.payload_index); | 1107 | const extra = sema.code.extraData(zir.Inst.Call, inst_data.payload_index); |
| 1115 | const args = sema.code.extra[extra.end..][0..extra.data.args_len]; | 1108 | const raw_args = sema.code.extra[extra.end..][0..extra.data.args_len]; |
| 1109 | const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args)); | ||
| 1116 | 1110 | ||
| 1117 | return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args); | 1111 | return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args); |
| 1118 | } | 1112 | } |
| ... | @@ -1739,7 +1733,8 @@ fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: b | ... | @@ -1739,7 +1733,8 @@ fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: b |
| 1739 | 1733 | ||
| 1740 | const inst_data = sema.code.instructions.items(.data)[inst].fn_type; | 1734 | const inst_data = sema.code.instructions.items(.data)[inst].fn_type; |
| 1741 | const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index); | 1735 | const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index); |
| 1742 | const param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len]; | 1736 | const raw_param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len]; |
| 1737 | const param_types = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_param_types)); | ||
| 1743 | 1738 | ||
| 1744 | return sema.fnTypeCommon( | 1739 | return sema.fnTypeCommon( |
| 1745 | block, | 1740 | block, |
| ... | @@ -1757,7 +1752,8 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: | ... | @@ -1757,7 +1752,8 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: |
| 1757 | 1752 | ||
| 1758 | const inst_data = sema.code.instructions.items(.data)[inst].fn_type; | 1753 | const inst_data = sema.code.instructions.items(.data)[inst].fn_type; |
| 1759 | const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index); | 1754 | const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index); |
| 1760 | const param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len]; | 1755 | const raw_param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len]; |
| 1756 | const param_types = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_param_types)); | ||
| 1761 | 1757 | ||
| 1762 | const cc_tv = try sema.resolveInstConst(block, .todo, extra.data.cc); | 1758 | const cc_tv = try sema.resolveInstConst(block, .todo, extra.data.cc); |
| 1763 | // TODO once we're capable of importing and analyzing decls from | 1759 | // TODO once we're capable of importing and analyzing decls from |
| ... | @@ -2487,7 +2483,7 @@ fn zirNegate( | ... | @@ -2487,7 +2483,7 @@ fn zirNegate( |
| 2487 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 2483 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 2488 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 2484 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 2489 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 2485 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 2490 | const lhs = try sema.resolveInst(@enumToInt(zir.Const.zero)); | 2486 | const lhs = try sema.resolveInst(.zero); |
| 2491 | const rhs = try sema.resolveInst(inst_data.operand); | 2487 | const rhs = try sema.resolveInst(inst_data.operand); |
| 2492 | 2488 | ||
| 2493 | return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src); | 2489 | return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src); |
| ... | @@ -2641,7 +2637,7 @@ fn zirAsm( | ... | @@ -2641,7 +2637,7 @@ fn zirAsm( |
| 2641 | 2637 | ||
| 2642 | var extra_i = extra.end; | 2638 | var extra_i = extra.end; |
| 2643 | const Output = struct { name: []const u8, inst: *Inst }; | 2639 | const Output = struct { name: []const u8, inst: *Inst }; |
| 2644 | const output: ?Output = if (extra.data.output != 0) blk: { | 2640 | const output: ?Output = if (extra.data.output != .none) blk: { |
| 2645 | const name = sema.code.nullTerminatedString(sema.code.extra[extra_i]); | 2641 | const name = sema.code.nullTerminatedString(sema.code.extra[extra_i]); |
| 2646 | extra_i += 1; | 2642 | extra_i += 1; |
| 2647 | break :blk Output{ | 2643 | break :blk Output{ |
| ... | @@ -2655,7 +2651,7 @@ fn zirAsm( | ... | @@ -2655,7 +2651,7 @@ fn zirAsm( |
| 2655 | const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len); | 2651 | const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len); |
| 2656 | 2652 | ||
| 2657 | for (args) |*arg| { | 2653 | for (args) |*arg| { |
| 2658 | arg.* = try sema.resolveInst(sema.code.extra[extra_i]); | 2654 | arg.* = try sema.resolveInst(@intToEnum(zir.Inst.Ref, sema.code.extra[extra_i])); |
| 2659 | extra_i += 1; | 2655 | extra_i += 1; |
| 2660 | } | 2656 | } |
| 2661 | for (inputs) |*name| { | 2657 | for (inputs) |*name| { |
| ... | @@ -2772,11 +2768,13 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr | ... | @@ -2772,11 +2768,13 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr |
| 2772 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 2768 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 2773 | const src = inst_data.src(); | 2769 | const src = inst_data.src(); |
| 2774 | const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index); | 2770 | const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index); |
| 2771 | const raw_args = sema.code.extra[extra.end..][0..extra.data.operands_len]; | ||
| 2772 | const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args)); | ||
| 2775 | 2773 | ||
| 2776 | const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len); | 2774 | const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len); |
| 2777 | defer sema.gpa.free(inst_list); | 2775 | defer sema.gpa.free(inst_list); |
| 2778 | 2776 | ||
| 2779 | for (sema.code.extra[extra.end..][0..extra.data.operands_len]) |arg_ref, i| { | 2777 | for (args) |arg_ref, i| { |
| 2780 | inst_list[i] = try sema.resolveInst(arg_ref); | 2778 | inst_list[i] = try sema.resolveInst(arg_ref); |
| 2781 | } | 2779 | } |
| 2782 | 2780 | ||
| ... | @@ -3115,25 +3113,25 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError | ... | @@ -3115,25 +3113,25 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError |
| 3115 | var extra_i = extra.end; | 3113 | var extra_i = extra.end; |
| 3116 | 3114 | ||
| 3117 | const sentinel = if (inst_data.flags.has_sentinel) blk: { | 3115 | const sentinel = if (inst_data.flags.has_sentinel) blk: { |
| 3118 | const ref = sema.code.extra[extra_i]; | 3116 | const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]); |
| 3119 | extra_i += 1; | 3117 | extra_i += 1; |
| 3120 | break :blk (try sema.resolveInstConst(block, .unneeded, ref)).val; | 3118 | break :blk (try sema.resolveInstConst(block, .unneeded, ref)).val; |
| 3121 | } else null; | 3119 | } else null; |
| 3122 | 3120 | ||
| 3123 | const abi_align = if (inst_data.flags.has_align) blk: { | 3121 | const abi_align = if (inst_data.flags.has_align) blk: { |
| 3124 | const ref = sema.code.extra[extra_i]; | 3122 | const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]); |
| 3125 | extra_i += 1; | 3123 | extra_i += 1; |
| 3126 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32); | 3124 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32); |
| 3127 | } else 0; | 3125 | } else 0; |
| 3128 | 3126 | ||
| 3129 | const bit_start = if (inst_data.flags.has_bit_range) blk: { | 3127 | const bit_start = if (inst_data.flags.has_bit_range) blk: { |
| 3130 | const ref = sema.code.extra[extra_i]; | 3128 | const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]); |
| 3131 | extra_i += 1; | 3129 | extra_i += 1; |
| 3132 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16); | 3130 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16); |
| 3133 | } else 0; | 3131 | } else 0; |
| 3134 | 3132 | ||
| 3135 | const bit_end = if (inst_data.flags.has_bit_range) blk: { | 3133 | const bit_end = if (inst_data.flags.has_bit_range) blk: { |
| 3136 | const ref = sema.code.extra[extra_i]; | 3134 | const ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_i]); |
| 3137 | extra_i += 1; | 3135 | extra_i += 1; |
| 3138 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16); | 3136 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16); |
| 3139 | } else 0; | 3137 | } else 0; |
src/astgen.zig+85-106| ... | @@ -58,11 +58,8 @@ pub const ResultLoc = union(enum) { | ... | @@ -58,11 +58,8 @@ pub const ResultLoc = union(enum) { |
| 58 | }; | 58 | }; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | const void_inst: zir.Inst.Ref = @enumToInt(zir.Const.void_value); | ||
| 62 | |||
| 63 | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!zir.Inst.Ref { | 61 | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 64 | const type_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.type_type) }; | 62 | return expr(mod, scope, .{ .ty = .type_type }, type_node); |
| 65 | return expr(mod, scope, type_rl, type_node); | ||
| 66 | } | 63 | } |
| 67 | 64 | ||
| 68 | fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref { | 65 | fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| ... | @@ -291,59 +288,59 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -291,59 +288,59 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 291 | 288 | ||
| 292 | .assign => { | 289 | .assign => { |
| 293 | try assign(mod, scope, node); | 290 | try assign(mod, scope, node); |
| 294 | return rvalue(mod, scope, rl, void_inst, node); | 291 | return rvalue(mod, scope, rl, .void_value, node); |
| 295 | }, | 292 | }, |
| 296 | .assign_bit_and => { | 293 | .assign_bit_and => { |
| 297 | try assignOp(mod, scope, node, .bit_and); | 294 | try assignOp(mod, scope, node, .bit_and); |
| 298 | return rvalue(mod, scope, rl, void_inst, node); | 295 | return rvalue(mod, scope, rl, .void_value, node); |
| 299 | }, | 296 | }, |
| 300 | .assign_bit_or => { | 297 | .assign_bit_or => { |
| 301 | try assignOp(mod, scope, node, .bit_or); | 298 | try assignOp(mod, scope, node, .bit_or); |
| 302 | return rvalue(mod, scope, rl, void_inst, node); | 299 | return rvalue(mod, scope, rl, .void_value, node); |
| 303 | }, | 300 | }, |
| 304 | .assign_bit_shift_left => { | 301 | .assign_bit_shift_left => { |
| 305 | try assignOp(mod, scope, node, .shl); | 302 | try assignOp(mod, scope, node, .shl); |
| 306 | return rvalue(mod, scope, rl, void_inst, node); | 303 | return rvalue(mod, scope, rl, .void_value, node); |
| 307 | }, | 304 | }, |
| 308 | .assign_bit_shift_right => { | 305 | .assign_bit_shift_right => { |
| 309 | try assignOp(mod, scope, node, .shr); | 306 | try assignOp(mod, scope, node, .shr); |
| 310 | return rvalue(mod, scope, rl, void_inst, node); | 307 | return rvalue(mod, scope, rl, .void_value, node); |
| 311 | }, | 308 | }, |
| 312 | .assign_bit_xor => { | 309 | .assign_bit_xor => { |
| 313 | try assignOp(mod, scope, node, .xor); | 310 | try assignOp(mod, scope, node, .xor); |
| 314 | return rvalue(mod, scope, rl, void_inst, node); | 311 | return rvalue(mod, scope, rl, .void_value, node); |
| 315 | }, | 312 | }, |
| 316 | .assign_div => { | 313 | .assign_div => { |
| 317 | try assignOp(mod, scope, node, .div); | 314 | try assignOp(mod, scope, node, .div); |
| 318 | return rvalue(mod, scope, rl, void_inst, node); | 315 | return rvalue(mod, scope, rl, .void_value, node); |
| 319 | }, | 316 | }, |
| 320 | .assign_sub => { | 317 | .assign_sub => { |
| 321 | try assignOp(mod, scope, node, .sub); | 318 | try assignOp(mod, scope, node, .sub); |
| 322 | return rvalue(mod, scope, rl, void_inst, node); | 319 | return rvalue(mod, scope, rl, .void_value, node); |
| 323 | }, | 320 | }, |
| 324 | .assign_sub_wrap => { | 321 | .assign_sub_wrap => { |
| 325 | try assignOp(mod, scope, node, .subwrap); | 322 | try assignOp(mod, scope, node, .subwrap); |
| 326 | return rvalue(mod, scope, rl, void_inst, node); | 323 | return rvalue(mod, scope, rl, .void_value, node); |
| 327 | }, | 324 | }, |
| 328 | .assign_mod => { | 325 | .assign_mod => { |
| 329 | try assignOp(mod, scope, node, .mod_rem); | 326 | try assignOp(mod, scope, node, .mod_rem); |
| 330 | return rvalue(mod, scope, rl, void_inst, node); | 327 | return rvalue(mod, scope, rl, .void_value, node); |
| 331 | }, | 328 | }, |
| 332 | .assign_add => { | 329 | .assign_add => { |
| 333 | try assignOp(mod, scope, node, .add); | 330 | try assignOp(mod, scope, node, .add); |
| 334 | return rvalue(mod, scope, rl, void_inst, node); | 331 | return rvalue(mod, scope, rl, .void_value, node); |
| 335 | }, | 332 | }, |
| 336 | .assign_add_wrap => { | 333 | .assign_add_wrap => { |
| 337 | try assignOp(mod, scope, node, .addwrap); | 334 | try assignOp(mod, scope, node, .addwrap); |
| 338 | return rvalue(mod, scope, rl, void_inst, node); | 335 | return rvalue(mod, scope, rl, .void_value, node); |
| 339 | }, | 336 | }, |
| 340 | .assign_mul => { | 337 | .assign_mul => { |
| 341 | try assignOp(mod, scope, node, .mul); | 338 | try assignOp(mod, scope, node, .mul); |
| 342 | return rvalue(mod, scope, rl, void_inst, node); | 339 | return rvalue(mod, scope, rl, .void_value, node); |
| 343 | }, | 340 | }, |
| 344 | .assign_mul_wrap => { | 341 | .assign_mul_wrap => { |
| 345 | try assignOp(mod, scope, node, .mulwrap); | 342 | try assignOp(mod, scope, node, .mulwrap); |
| 346 | return rvalue(mod, scope, rl, void_inst, node); | 343 | return rvalue(mod, scope, rl, .void_value, node); |
| 347 | }, | 344 | }, |
| 348 | 345 | ||
| 349 | .add => return simpleBinOp(mod, scope, rl, node, .add), | 346 | .add => return simpleBinOp(mod, scope, rl, node, .add), |
| ... | @@ -450,22 +447,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -450,22 +447,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 450 | const result = try expr(mod, scope, .ref, node_datas[node].lhs); | 447 | const result = try expr(mod, scope, .ref, node_datas[node].lhs); |
| 451 | return rvalue(mod, scope, rl, result, node); | 448 | return rvalue(mod, scope, rl, result, node); |
| 452 | }, | 449 | }, |
| 453 | .undefined_literal => { | 450 | .undefined_literal => return rvalue(mod, scope, rl, .undef, node), |
| 454 | const result = @enumToInt(zir.Const.undef); | 451 | .true_literal => return rvalue(mod, scope, rl, .bool_true, node), |
| 455 | return rvalue(mod, scope, rl, result, node); | 452 | .false_literal => return rvalue(mod, scope, rl, .bool_false, node), |
| 456 | }, | 453 | .null_literal => return rvalue(mod, scope, rl, .null_value, node), |
| 457 | .true_literal => { | ||
| 458 | const result = @enumToInt(zir.Const.bool_true); | ||
| 459 | return rvalue(mod, scope, rl, result, node); | ||
| 460 | }, | ||
| 461 | .false_literal => { | ||
| 462 | const result = @enumToInt(zir.Const.bool_false); | ||
| 463 | return rvalue(mod, scope, rl, result, node); | ||
| 464 | }, | ||
| 465 | .null_literal => { | ||
| 466 | const result = @enumToInt(zir.Const.null_value); | ||
| 467 | return rvalue(mod, scope, rl, result, node); | ||
| 468 | }, | ||
| 469 | .optional_type => { | 454 | .optional_type => { |
| 470 | const operand = try typeExpr(mod, scope, node_datas[node].lhs); | 455 | const operand = try typeExpr(mod, scope, node_datas[node].lhs); |
| 471 | const result = try gz.addUnNode(.optional_type, operand, node); | 456 | const result = try gz.addUnNode(.optional_type, operand, node); |
| ... | @@ -830,7 +815,7 @@ pub fn blockExpr( | ... | @@ -830,7 +815,7 @@ pub fn blockExpr( |
| 830 | } | 815 | } |
| 831 | 816 | ||
| 832 | try blockExprStmts(mod, scope, block_node, statements); | 817 | try blockExprStmts(mod, scope, block_node, statements); |
| 833 | return rvalue(mod, scope, rl, void_inst, block_node); | 818 | return rvalue(mod, scope, rl, .void_value, block_node); |
| 834 | } | 819 | } |
| 835 | 820 | ||
| 836 | fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIndex) !void { | 821 | fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIndex) !void { |
| ... | @@ -935,13 +920,13 @@ fn labeledBlockExpr( | ... | @@ -935,13 +920,13 @@ fn labeledBlockExpr( |
| 935 | // The code took advantage of the result location as a pointer. | 920 | // The code took advantage of the result location as a pointer. |
| 936 | // Turn the break instruction operands into void. | 921 | // Turn the break instruction operands into void. |
| 937 | for (block_scope.labeled_breaks.items) |br| { | 922 | for (block_scope.labeled_breaks.items) |br| { |
| 938 | zir_datas[br].@"break".operand = @enumToInt(zir.Const.void_value); | 923 | zir_datas[br].@"break".operand = .void_value; |
| 939 | } | 924 | } |
| 940 | // TODO technically not needed since we changed the tag to break_void but | 925 | // TODO technically not needed since we changed the tag to break_void but |
| 941 | // would be better still to elide the ones that are in this list. | 926 | // would be better still to elide the ones that are in this list. |
| 942 | try block_scope.setBlockBody(block_inst); | 927 | try block_scope.setBlockBody(block_inst); |
| 943 | 928 | ||
| 944 | return gz.zir_code.ref_start_index + block_inst; | 929 | return zir.Inst.Ref.fromIndex(block_inst, gz.zir_code.param_count); |
| 945 | }, | 930 | }, |
| 946 | .break_operand => { | 931 | .break_operand => { |
| 947 | // All break operands are values that did not use the result location pointer. | 932 | // All break operands are values that did not use the result location pointer. |
| ... | @@ -954,7 +939,7 @@ fn labeledBlockExpr( | ... | @@ -954,7 +939,7 @@ fn labeledBlockExpr( |
| 954 | // would be better still to elide the ones that are in this list. | 939 | // would be better still to elide the ones that are in this list. |
| 955 | } | 940 | } |
| 956 | try block_scope.setBlockBody(block_inst); | 941 | try block_scope.setBlockBody(block_inst); |
| 957 | const block_ref = gz.zir_code.ref_start_index + block_inst; | 942 | const block_ref = zir.Inst.Ref.fromIndex(block_inst, gz.zir_code.param_count); |
| 958 | switch (rl) { | 943 | switch (rl) { |
| 959 | .ref => return block_ref, | 944 | .ref => return block_ref, |
| 960 | else => return rvalue(mod, parent_scope, rl, block_ref, block_node), | 945 | else => return rvalue(mod, parent_scope, rl, block_ref, block_node), |
| ... | @@ -1006,8 +991,7 @@ fn blockExprStmts( | ... | @@ -1006,8 +991,7 @@ fn blockExprStmts( |
| 1006 | // We need to emit an error if the result is not `noreturn` or `void`, but | 991 | // We need to emit an error if the result is not `noreturn` or `void`, but |
| 1007 | // we want to avoid adding the ZIR instruction if possible for performance. | 992 | // we want to avoid adding the ZIR instruction if possible for performance. |
| 1008 | const maybe_unused_result = try expr(mod, scope, .none, statement); | 993 | const maybe_unused_result = try expr(mod, scope, .none, statement); |
| 1009 | const elide_check = if (maybe_unused_result >= gz.zir_code.ref_start_index) b: { | 994 | const elide_check = if (maybe_unused_result.toIndex(gz.zir_code.param_count)) |inst| b: { |
| 1010 | const inst = maybe_unused_result - gz.zir_code.ref_start_index; | ||
| 1011 | // Note that this array becomes invalid after appending more items to it | 995 | // Note that this array becomes invalid after appending more items to it |
| 1012 | // in the above while loop. | 996 | // in the above while loop. |
| 1013 | const zir_tags = gz.zir_code.instructions.items(.tag); | 997 | const zir_tags = gz.zir_code.instructions.items(.tag); |
| ... | @@ -1167,10 +1151,10 @@ fn blockExprStmts( | ... | @@ -1167,10 +1151,10 @@ fn blockExprStmts( |
| 1167 | => break :b true, | 1151 | => break :b true, |
| 1168 | } | 1152 | } |
| 1169 | } else switch (maybe_unused_result) { | 1153 | } else switch (maybe_unused_result) { |
| 1170 | @enumToInt(zir.Const.unused) => unreachable, | 1154 | .none => unreachable, |
| 1171 | 1155 | ||
| 1172 | @enumToInt(zir.Const.void_value), | 1156 | .void_value, |
| 1173 | @enumToInt(zir.Const.unreachable_value), | 1157 | .unreachable_value, |
| 1174 | => true, | 1158 | => true, |
| 1175 | 1159 | ||
| 1176 | else => false, | 1160 | else => false, |
| ... | @@ -1283,8 +1267,8 @@ fn varDecl( | ... | @@ -1283,8 +1267,8 @@ fn varDecl( |
| 1283 | }; | 1267 | }; |
| 1284 | defer init_scope.instructions.deinit(mod.gpa); | 1268 | defer init_scope.instructions.deinit(mod.gpa); |
| 1285 | 1269 | ||
| 1286 | var resolve_inferred_alloc: zir.Inst.Ref = 0; | 1270 | var resolve_inferred_alloc: zir.Inst.Ref = .none; |
| 1287 | var opt_type_inst: zir.Inst.Ref = 0; | 1271 | var opt_type_inst: zir.Inst.Ref = .none; |
| 1288 | if (var_decl.ast.type_node != 0) { | 1272 | if (var_decl.ast.type_node != 0) { |
| 1289 | const type_inst = try typeExpr(mod, &init_scope.base, var_decl.ast.type_node); | 1273 | const type_inst = try typeExpr(mod, &init_scope.base, var_decl.ast.type_node); |
| 1290 | opt_type_inst = type_inst; | 1274 | opt_type_inst = type_inst; |
| ... | @@ -1308,14 +1292,14 @@ fn varDecl( | ... | @@ -1308,14 +1292,14 @@ fn varDecl( |
| 1308 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2; | 1292 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2; |
| 1309 | try parent_zir.ensureCapacity(mod.gpa, expected_len); | 1293 | try parent_zir.ensureCapacity(mod.gpa, expected_len); |
| 1310 | for (init_scope.instructions.items) |src_inst| { | 1294 | for (init_scope.instructions.items) |src_inst| { |
| 1311 | if (wzc.ref_start_index + src_inst == init_scope.rl_ptr) continue; | 1295 | if (zir.Inst.Ref.fromIndex(src_inst, wzc.param_count) == init_scope.rl_ptr) continue; |
| 1312 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 1296 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 1313 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; | 1297 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; |
| 1314 | } | 1298 | } |
| 1315 | parent_zir.appendAssumeCapacity(src_inst); | 1299 | parent_zir.appendAssumeCapacity(src_inst); |
| 1316 | } | 1300 | } |
| 1317 | assert(parent_zir.items.len == expected_len); | 1301 | assert(parent_zir.items.len == expected_len); |
| 1318 | const casted_init = if (opt_type_inst != 0) | 1302 | const casted_init = if (opt_type_inst != .none) |
| 1319 | try gz.addPlNode(.as_node, var_decl.ast.type_node, zir.Inst.As{ | 1303 | try gz.addPlNode(.as_node, var_decl.ast.type_node, zir.Inst.As{ |
| 1320 | .dest_type = opt_type_inst, | 1304 | .dest_type = opt_type_inst, |
| 1321 | .operand = init_inst, | 1305 | .operand = init_inst, |
| ... | @@ -1348,7 +1332,7 @@ fn varDecl( | ... | @@ -1348,7 +1332,7 @@ fn varDecl( |
| 1348 | parent_zir.appendAssumeCapacity(src_inst); | 1332 | parent_zir.appendAssumeCapacity(src_inst); |
| 1349 | } | 1333 | } |
| 1350 | assert(parent_zir.items.len == expected_len); | 1334 | assert(parent_zir.items.len == expected_len); |
| 1351 | if (resolve_inferred_alloc != 0) { | 1335 | if (resolve_inferred_alloc != .none) { |
| 1352 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 1336 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 1353 | } | 1337 | } |
| 1354 | const sub_scope = try block_arena.create(Scope.LocalPtr); | 1338 | const sub_scope = try block_arena.create(Scope.LocalPtr); |
| ... | @@ -1362,7 +1346,7 @@ fn varDecl( | ... | @@ -1362,7 +1346,7 @@ fn varDecl( |
| 1362 | return &sub_scope.base; | 1346 | return &sub_scope.base; |
| 1363 | }, | 1347 | }, |
| 1364 | .keyword_var => { | 1348 | .keyword_var => { |
| 1365 | var resolve_inferred_alloc: zir.Inst.Ref = 0; | 1349 | var resolve_inferred_alloc: zir.Inst.Ref = .none; |
| 1366 | const var_data: struct { | 1350 | const var_data: struct { |
| 1367 | result_loc: ResultLoc, | 1351 | result_loc: ResultLoc, |
| 1368 | alloc: zir.Inst.Ref, | 1352 | alloc: zir.Inst.Ref, |
| ... | @@ -1377,7 +1361,7 @@ fn varDecl( | ... | @@ -1377,7 +1361,7 @@ fn varDecl( |
| 1377 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; | 1361 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; |
| 1378 | }; | 1362 | }; |
| 1379 | const init_inst = try expr(mod, scope, var_data.result_loc, var_decl.ast.init_node); | 1363 | const init_inst = try expr(mod, scope, var_data.result_loc, var_decl.ast.init_node); |
| 1380 | if (resolve_inferred_alloc != 0) { | 1364 | if (resolve_inferred_alloc != .none) { |
| 1381 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 1365 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 1382 | } | 1366 | } |
| 1383 | const sub_scope = try block_arena.create(Scope.LocalPtr); | 1367 | const sub_scope = try block_arena.create(Scope.LocalPtr); |
| ... | @@ -1440,7 +1424,7 @@ fn boolNot(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn | ... | @@ -1440,7 +1424,7 @@ fn boolNot(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn |
| 1440 | const tree = scope.tree(); | 1424 | const tree = scope.tree(); |
| 1441 | const node_datas = tree.nodes.items(.data); | 1425 | const node_datas = tree.nodes.items(.data); |
| 1442 | 1426 | ||
| 1443 | const operand = try expr(mod, scope, .{ .ty = @enumToInt(zir.Const.bool_type) }, node_datas[node].lhs); | 1427 | const operand = try expr(mod, scope, .{ .ty = .bool_type }, node_datas[node].lhs); |
| 1444 | const gz = scope.getGenZir(); | 1428 | const gz = scope.getGenZir(); |
| 1445 | const result = try gz.addUnNode(.bool_not, operand, node); | 1429 | const result = try gz.addUnNode(.bool_not, operand, node); |
| 1446 | return rvalue(mod, scope, rl, result, node); | 1430 | return rvalue(mod, scope, rl, result, node); |
| ... | @@ -1501,10 +1485,10 @@ fn ptrType( | ... | @@ -1501,10 +1485,10 @@ fn ptrType( |
| 1501 | return rvalue(mod, scope, rl, result, node); | 1485 | return rvalue(mod, scope, rl, result, node); |
| 1502 | } | 1486 | } |
| 1503 | 1487 | ||
| 1504 | var sentinel_ref: zir.Inst.Ref = 0; | 1488 | var sentinel_ref: zir.Inst.Ref = .none; |
| 1505 | var align_ref: zir.Inst.Ref = 0; | 1489 | var align_ref: zir.Inst.Ref = .none; |
| 1506 | var bit_start_ref: zir.Inst.Ref = 0; | 1490 | var bit_start_ref: zir.Inst.Ref = .none; |
| 1507 | var bit_end_ref: zir.Inst.Ref = 0; | 1491 | var bit_end_ref: zir.Inst.Ref = .none; |
| 1508 | var trailing_count: u32 = 0; | 1492 | var trailing_count: u32 = 0; |
| 1509 | 1493 | ||
| 1510 | if (ptr_info.ast.sentinel != 0) { | 1494 | if (ptr_info.ast.sentinel != 0) { |
| ... | @@ -1529,24 +1513,28 @@ fn ptrType( | ... | @@ -1529,24 +1513,28 @@ fn ptrType( |
| 1529 | @typeInfo(zir.Inst.PtrType).Struct.fields.len + trailing_count); | 1513 | @typeInfo(zir.Inst.PtrType).Struct.fields.len + trailing_count); |
| 1530 | 1514 | ||
| 1531 | const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.PtrType{ .elem_type = elem_type }); | 1515 | const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.PtrType{ .elem_type = elem_type }); |
| 1532 | if (sentinel_ref != 0) gz.zir_code.extra.appendAssumeCapacity(sentinel_ref); | 1516 | if (sentinel_ref != .none) { |
| 1533 | if (align_ref != 0) gz.zir_code.extra.appendAssumeCapacity(align_ref); | 1517 | gz.zir_code.extra.appendAssumeCapacity(@enumToInt(sentinel_ref)); |
| 1534 | if (bit_start_ref != 0) { | 1518 | } |
| 1535 | gz.zir_code.extra.appendAssumeCapacity(bit_start_ref); | 1519 | if (align_ref != .none) { |
| 1536 | gz.zir_code.extra.appendAssumeCapacity(bit_end_ref); | 1520 | gz.zir_code.extra.appendAssumeCapacity(@enumToInt(align_ref)); |
| 1521 | } | ||
| 1522 | if (bit_start_ref != .none) { | ||
| 1523 | gz.zir_code.extra.appendAssumeCapacity(@enumToInt(bit_start_ref)); | ||
| 1524 | gz.zir_code.extra.appendAssumeCapacity(@enumToInt(bit_end_ref)); | ||
| 1537 | } | 1525 | } |
| 1538 | 1526 | ||
| 1539 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1527 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1540 | const result = new_index + gz.zir_code.ref_start_index; | 1528 | const result = zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count); |
| 1541 | gz.zir_code.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{ | 1529 | gz.zir_code.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{ |
| 1542 | .ptr_type = .{ | 1530 | .ptr_type = .{ |
| 1543 | .flags = .{ | 1531 | .flags = .{ |
| 1544 | .is_allowzero = ptr_info.allowzero_token != null, | 1532 | .is_allowzero = ptr_info.allowzero_token != null, |
| 1545 | .is_mutable = ptr_info.const_token == null, | 1533 | .is_mutable = ptr_info.const_token == null, |
| 1546 | .is_volatile = ptr_info.volatile_token != null, | 1534 | .is_volatile = ptr_info.volatile_token != null, |
| 1547 | .has_sentinel = sentinel_ref != 0, | 1535 | .has_sentinel = sentinel_ref != .none, |
| 1548 | .has_align = align_ref != 0, | 1536 | .has_align = align_ref != .none, |
| 1549 | .has_bit_range = bit_start_ref != 0, | 1537 | .has_bit_range = bit_start_ref != .none, |
| 1550 | }, | 1538 | }, |
| 1551 | .size = ptr_info.size, | 1539 | .size = ptr_info.size, |
| 1552 | .payload_index = payload_index, | 1540 | .payload_index = payload_index, |
| ... | @@ -1561,10 +1549,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) ! | ... | @@ -1561,10 +1549,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) ! |
| 1561 | const tree = scope.tree(); | 1549 | const tree = scope.tree(); |
| 1562 | const node_datas = tree.nodes.items(.data); | 1550 | const node_datas = tree.nodes.items(.data); |
| 1563 | const gz = scope.getGenZir(); | 1551 | const gz = scope.getGenZir(); |
| 1564 | const usize_type = @enumToInt(zir.Const.usize_type); | ||
| 1565 | 1552 | ||
| 1566 | // TODO check for [_]T | 1553 | // TODO check for [_]T |
| 1567 | const len = try expr(mod, scope, .{ .ty = usize_type }, node_datas[node].lhs); | 1554 | const len = try expr(mod, scope, .{ .ty = .usize_type }, node_datas[node].lhs); |
| 1568 | const elem_type = try typeExpr(mod, scope, node_datas[node].rhs); | 1555 | const elem_type = try typeExpr(mod, scope, node_datas[node].rhs); |
| 1569 | 1556 | ||
| 1570 | const result = try gz.addBin(.array_type, len, elem_type); | 1557 | const result = try gz.addBin(.array_type, len, elem_type); |
| ... | @@ -1576,10 +1563,9 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node. | ... | @@ -1576,10 +1563,9 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node. |
| 1576 | const node_datas = tree.nodes.items(.data); | 1563 | const node_datas = tree.nodes.items(.data); |
| 1577 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); | 1564 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); |
| 1578 | const gz = scope.getGenZir(); | 1565 | const gz = scope.getGenZir(); |
| 1579 | const usize_type = @enumToInt(zir.Const.usize_type); | ||
| 1580 | 1566 | ||
| 1581 | // TODO check for [_]T | 1567 | // TODO check for [_]T |
| 1582 | const len = try expr(mod, scope, .{ .ty = usize_type }, node_datas[node].lhs); | 1568 | const len = try expr(mod, scope, .{ .ty = .usize_type }, node_datas[node].lhs); |
| 1583 | const elem_type = try typeExpr(mod, scope, extra.elem_type); | 1569 | const elem_type = try typeExpr(mod, scope, extra.elem_type); |
| 1584 | const sentinel = try expr(mod, scope, .{ .ty = elem_type }, extra.sentinel); | 1570 | const sentinel = try expr(mod, scope, .{ .ty = elem_type }, extra.sentinel); |
| 1585 | 1571 | ||
| ... | @@ -1784,7 +1770,7 @@ fn finishThenElseBlock( | ... | @@ -1784,7 +1770,7 @@ fn finishThenElseBlock( |
| 1784 | } }, | 1770 | } }, |
| 1785 | }); | 1771 | }); |
| 1786 | } | 1772 | } |
| 1787 | const elide_else = if (else_result != 0) wzc.refIsNoReturn(else_result) else false; | 1773 | const elide_else = if (else_result != .none) wzc.refIsNoReturn(else_result) else false; |
| 1788 | if (!elide_else) { | 1774 | if (!elide_else) { |
| 1789 | _ = try else_scope.add(.{ | 1775 | _ = try else_scope.add(.{ |
| 1790 | .tag = .break_void_node, | 1776 | .tag = .break_void_node, |
| ... | @@ -1796,7 +1782,7 @@ fn finishThenElseBlock( | ... | @@ -1796,7 +1782,7 @@ fn finishThenElseBlock( |
| 1796 | } | 1782 | } |
| 1797 | assert(!strat.elide_store_to_block_ptr_instructions); | 1783 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 1798 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 1784 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 1799 | return wzc.ref_start_index + main_block; | 1785 | return zir.Inst.Ref.fromIndex(main_block, wzc.param_count); |
| 1800 | }, | 1786 | }, |
| 1801 | .break_operand => { | 1787 | .break_operand => { |
| 1802 | if (!wzc.refIsNoReturn(then_result)) { | 1788 | if (!wzc.refIsNoReturn(then_result)) { |
| ... | @@ -1808,7 +1794,7 @@ fn finishThenElseBlock( | ... | @@ -1808,7 +1794,7 @@ fn finishThenElseBlock( |
| 1808 | } }, | 1794 | } }, |
| 1809 | }); | 1795 | }); |
| 1810 | } | 1796 | } |
| 1811 | if (else_result != 0) { | 1797 | if (else_result != .none) { |
| 1812 | if (!wzc.refIsNoReturn(else_result)) { | 1798 | if (!wzc.refIsNoReturn(else_result)) { |
| 1813 | _ = try else_scope.add(.{ | 1799 | _ = try else_scope.add(.{ |
| 1814 | .tag = .@"break", | 1800 | .tag = .@"break", |
| ... | @@ -1832,7 +1818,7 @@ fn finishThenElseBlock( | ... | @@ -1832,7 +1818,7 @@ fn finishThenElseBlock( |
| 1832 | } else { | 1818 | } else { |
| 1833 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 1819 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 1834 | } | 1820 | } |
| 1835 | const block_ref = wzc.ref_start_index + main_block; | 1821 | const block_ref = zir.Inst.Ref.fromIndex(main_block, wzc.param_count); |
| 1836 | switch (rl) { | 1822 | switch (rl) { |
| 1837 | .ref => return block_ref, | 1823 | .ref => return block_ref, |
| 1838 | else => return rvalue(mod, parent_scope, rl, block_ref, node), | 1824 | else => return rvalue(mod, parent_scope, rl, block_ref, node), |
| ... | @@ -1981,9 +1967,8 @@ fn boolBinOp( | ... | @@ -1981,9 +1967,8 @@ fn boolBinOp( |
| 1981 | ) InnerError!zir.Inst.Ref { | 1967 | ) InnerError!zir.Inst.Ref { |
| 1982 | const gz = scope.getGenZir(); | 1968 | const gz = scope.getGenZir(); |
| 1983 | const node_datas = gz.tree().nodes.items(.data); | 1969 | const node_datas = gz.tree().nodes.items(.data); |
| 1984 | const bool_type = @enumToInt(zir.Const.bool_type); | ||
| 1985 | 1970 | ||
| 1986 | const lhs = try expr(mod, scope, .{ .ty = bool_type }, node_datas[node].lhs); | 1971 | const lhs = try expr(mod, scope, .{ .ty = .bool_type }, node_datas[node].lhs); |
| 1987 | const bool_br = try gz.addBoolBr(zir_tag, lhs); | 1972 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 1988 | 1973 | ||
| 1989 | var rhs_scope: Scope.GenZir = .{ | 1974 | var rhs_scope: Scope.GenZir = .{ |
| ... | @@ -1992,11 +1977,11 @@ fn boolBinOp( | ... | @@ -1992,11 +1977,11 @@ fn boolBinOp( |
| 1992 | .force_comptime = gz.force_comptime, | 1977 | .force_comptime = gz.force_comptime, |
| 1993 | }; | 1978 | }; |
| 1994 | defer rhs_scope.instructions.deinit(mod.gpa); | 1979 | defer rhs_scope.instructions.deinit(mod.gpa); |
| 1995 | const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, node_datas[node].rhs); | 1980 | const rhs = try expr(mod, &rhs_scope.base, .{ .ty = .bool_type }, node_datas[node].rhs); |
| 1996 | _ = try rhs_scope.addUnNode(.break_flat, rhs, node); | 1981 | _ = try rhs_scope.addUnNode(.break_flat, rhs, node); |
| 1997 | try rhs_scope.setBoolBrBody(bool_br); | 1982 | try rhs_scope.setBoolBrBody(bool_br); |
| 1998 | 1983 | ||
| 1999 | const block_ref = gz.zir_code.ref_start_index + bool_br; | 1984 | const block_ref = zir.Inst.Ref.fromIndex(bool_br, gz.zir_code.param_count); |
| 2000 | return rvalue(mod, scope, rl, block_ref, node); | 1985 | return rvalue(mod, scope, rl, block_ref, node); |
| 2001 | } | 1986 | } |
| 2002 | 1987 | ||
| ... | @@ -2024,8 +2009,7 @@ fn ifExpr( | ... | @@ -2024,8 +2009,7 @@ fn ifExpr( |
| 2024 | } else if (if_full.payload_token) |payload_token| { | 2009 | } else if (if_full.payload_token) |payload_token| { |
| 2025 | return mod.failTok(scope, payload_token, "TODO implement if optional", .{}); | 2010 | return mod.failTok(scope, payload_token, "TODO implement if optional", .{}); |
| 2026 | } else { | 2011 | } else { |
| 2027 | const bool_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.bool_type) }; | 2012 | break :c try expr(mod, &block_scope.base, .{ .ty = .bool_type }, if_full.ast.cond_expr); |
| 2028 | break :c try expr(mod, &block_scope.base, bool_rl, if_full.ast.cond_expr); | ||
| 2029 | } | 2013 | } |
| 2030 | }; | 2014 | }; |
| 2031 | 2015 | ||
| ... | @@ -2073,7 +2057,7 @@ fn ifExpr( | ... | @@ -2073,7 +2057,7 @@ fn ifExpr( |
| 2073 | }; | 2057 | }; |
| 2074 | } else .{ | 2058 | } else .{ |
| 2075 | .src = if_full.ast.then_expr, | 2059 | .src = if_full.ast.then_expr, |
| 2076 | .result = 0, | 2060 | .result = .none, |
| 2077 | }; | 2061 | }; |
| 2078 | 2062 | ||
| 2079 | return finishThenElseBlock( | 2063 | return finishThenElseBlock( |
| ... | @@ -2185,7 +2169,7 @@ fn whileExpr( | ... | @@ -2185,7 +2169,7 @@ fn whileExpr( |
| 2185 | } else if (while_full.payload_token) |payload_token| { | 2169 | } else if (while_full.payload_token) |payload_token| { |
| 2186 | return mod.failTok(scope, payload_token, "TODO implement while optional", .{}); | 2170 | return mod.failTok(scope, payload_token, "TODO implement while optional", .{}); |
| 2187 | } else { | 2171 | } else { |
| 2188 | const bool_type_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.bool_type) }; | 2172 | const bool_type_rl: ResultLoc = .{ .ty = .bool_type }; |
| 2189 | break :c try expr(mod, &continue_scope.base, bool_type_rl, while_full.ast.cond_expr); | 2173 | break :c try expr(mod, &continue_scope.base, bool_type_rl, while_full.ast.cond_expr); |
| 2190 | } | 2174 | } |
| 2191 | }; | 2175 | }; |
| ... | @@ -2200,8 +2184,7 @@ fn whileExpr( | ... | @@ -2200,8 +2184,7 @@ fn whileExpr( |
| 2200 | // and there are no `continue` statements. | 2184 | // and there are no `continue` statements. |
| 2201 | // The "repeat" at the end of a loop body is implied. | 2185 | // The "repeat" at the end of a loop body is implied. |
| 2202 | if (while_full.ast.cont_expr != 0) { | 2186 | if (while_full.ast.cont_expr != 0) { |
| 2203 | const void_type_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.void_type) }; | 2187 | _ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr); |
| 2204 | _ = try expr(mod, &loop_scope.base, void_type_rl, while_full.ast.cont_expr); | ||
| 2205 | } | 2188 | } |
| 2206 | const is_inline = while_full.inline_token != null; | 2189 | const is_inline = while_full.inline_token != null; |
| 2207 | const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; | 2190 | const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; |
| ... | @@ -2251,7 +2234,7 @@ fn whileExpr( | ... | @@ -2251,7 +2234,7 @@ fn whileExpr( |
| 2251 | }; | 2234 | }; |
| 2252 | } else .{ | 2235 | } else .{ |
| 2253 | .src = while_full.ast.then_expr, | 2236 | .src = while_full.ast.then_expr, |
| 2254 | .result = 0, | 2237 | .result = .none, |
| 2255 | }; | 2238 | }; |
| 2256 | 2239 | ||
| 2257 | if (loop_scope.label) |some| { | 2240 | if (loop_scope.label) |some| { |
| ... | @@ -2838,7 +2821,7 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Re | ... | @@ -2838,7 +2821,7 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Re |
| 2838 | .ty = try gz.addNode(.ret_type, node), | 2821 | .ty = try gz.addNode(.ret_type, node), |
| 2839 | }; | 2822 | }; |
| 2840 | break :operand try expr(mod, scope, rl, operand_node); | 2823 | break :operand try expr(mod, scope, rl, operand_node); |
| 2841 | } else void_inst; | 2824 | } else .void_value; |
| 2842 | return gz.addUnNode(.ret_node, operand, node); | 2825 | return gz.addUnNode(.ret_node, operand, node); |
| 2843 | } | 2826 | } |
| 2844 | 2827 | ||
| ... | @@ -2862,8 +2845,8 @@ fn identifier( | ... | @@ -2862,8 +2845,8 @@ fn identifier( |
| 2862 | return mod.failNode(scope, ident, "TODO implement '_' identifier", .{}); | 2845 | return mod.failNode(scope, ident, "TODO implement '_' identifier", .{}); |
| 2863 | } | 2846 | } |
| 2864 | 2847 | ||
| 2865 | if (simple_types.get(ident_name)) |zir_const_tag| { | 2848 | if (simple_types.get(ident_name)) |zir_const_ref| { |
| 2866 | return rvalue(mod, scope, rl, @enumToInt(zir_const_tag), ident); | 2849 | return rvalue(mod, scope, rl, zir_const_ref, ident); |
| 2867 | } | 2850 | } |
| 2868 | 2851 | ||
| 2869 | if (ident_name.len >= 2) integer: { | 2852 | if (ident_name.len >= 2) integer: { |
| ... | @@ -3028,9 +3011,9 @@ fn integerLiteral( | ... | @@ -3028,9 +3011,9 @@ fn integerLiteral( |
| 3028 | const prefixed_bytes = tree.tokenSlice(int_token); | 3011 | const prefixed_bytes = tree.tokenSlice(int_token); |
| 3029 | const gz = scope.getGenZir(); | 3012 | const gz = scope.getGenZir(); |
| 3030 | if (std.fmt.parseInt(u64, prefixed_bytes, 0)) |small_int| { | 3013 | if (std.fmt.parseInt(u64, prefixed_bytes, 0)) |small_int| { |
| 3031 | const result: zir.Inst.Index = switch (small_int) { | 3014 | const result: zir.Inst.Ref = switch (small_int) { |
| 3032 | 0 => @enumToInt(zir.Const.zero), | 3015 | 0 => .zero, |
| 3033 | 1 => @enumToInt(zir.Const.one), | 3016 | 1 => .one, |
| 3034 | else => try gz.addInt(small_int), | 3017 | else => try gz.addInt(small_int), |
| 3035 | }; | 3018 | }; |
| 3036 | return rvalue(mod, scope, rl, result, node); | 3019 | return rvalue(mod, scope, rl, result, node); |
| ... | @@ -3078,14 +3061,11 @@ fn asmExpr( | ... | @@ -3078,14 +3061,11 @@ fn asmExpr( |
| 3078 | const node_datas = tree.nodes.items(.data); | 3061 | const node_datas = tree.nodes.items(.data); |
| 3079 | const gz = scope.getGenZir(); | 3062 | const gz = scope.getGenZir(); |
| 3080 | 3063 | ||
| 3081 | const str_type = @enumToInt(zir.Const.const_slice_u8_type); | 3064 | const asm_source = try expr(mod, scope, .{ .ty = .const_slice_u8_type }, full.ast.template); |
| 3082 | const str_type_rl: ResultLoc = .{ .ty = str_type }; | ||
| 3083 | const asm_source = try expr(mod, scope, str_type_rl, full.ast.template); | ||
| 3084 | 3065 | ||
| 3085 | if (full.outputs.len != 0) { | 3066 | if (full.outputs.len != 0) { |
| 3086 | return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{}); | 3067 | return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{}); |
| 3087 | } | 3068 | } |
| 3088 | const return_type = @enumToInt(zir.Const.void_type); | ||
| 3089 | 3069 | ||
| 3090 | const constraints = try arena.alloc(u32, full.inputs.len); | 3070 | const constraints = try arena.alloc(u32, full.inputs.len); |
| 3091 | const args = try arena.alloc(zir.Inst.Ref, full.inputs.len); | 3071 | const args = try arena.alloc(zir.Inst.Ref, full.inputs.len); |
| ... | @@ -3098,22 +3078,21 @@ fn asmExpr( | ... | @@ -3098,22 +3078,21 @@ fn asmExpr( |
| 3098 | try mod.parseStrLit(scope, constraint_token, string_bytes, token_bytes, 0); | 3078 | try mod.parseStrLit(scope, constraint_token, string_bytes, token_bytes, 0); |
| 3099 | try string_bytes.append(mod.gpa, 0); | 3079 | try string_bytes.append(mod.gpa, 0); |
| 3100 | 3080 | ||
| 3101 | const usize_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.usize_type) }; | 3081 | args[i] = try expr(mod, scope, .{ .ty = .usize_type }, node_datas[input].lhs); |
| 3102 | args[i] = try expr(mod, scope, usize_rl, node_datas[input].lhs); | ||
| 3103 | } | 3082 | } |
| 3104 | 3083 | ||
| 3105 | const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm"; | 3084 | const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm"; |
| 3106 | const result = try gz.addPlNode(tag, node, zir.Inst.Asm{ | 3085 | const result = try gz.addPlNode(tag, node, zir.Inst.Asm{ |
| 3107 | .asm_source = asm_source, | 3086 | .asm_source = asm_source, |
| 3108 | .return_type = return_type, | 3087 | .return_type = .void_type, |
| 3109 | .output = 0, | 3088 | .output = .none, |
| 3110 | .args_len = @intCast(u32, full.inputs.len), | 3089 | .args_len = @intCast(u32, full.inputs.len), |
| 3111 | .clobbers_len = 0, // TODO implement asm clobbers | 3090 | .clobbers_len = 0, // TODO implement asm clobbers |
| 3112 | }); | 3091 | }); |
| 3113 | 3092 | ||
| 3114 | try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len + | 3093 | try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len + |
| 3115 | args.len + constraints.len); | 3094 | args.len + constraints.len); |
| 3116 | gz.zir_code.extra.appendSliceAssumeCapacity(args); | 3095 | gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args))); |
| 3117 | gz.zir_code.extra.appendSliceAssumeCapacity(constraints); | 3096 | gz.zir_code.extra.appendSliceAssumeCapacity(constraints); |
| 3118 | 3097 | ||
| 3119 | return rvalue(mod, scope, rl, result, node); | 3098 | return rvalue(mod, scope, rl, result, node); |
| ... | @@ -3185,7 +3164,7 @@ fn asRlPtr( | ... | @@ -3185,7 +3164,7 @@ fn asRlPtr( |
| 3185 | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; | 3164 | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; |
| 3186 | try parent_zir.ensureCapacity(mod.gpa, expected_len); | 3165 | try parent_zir.ensureCapacity(mod.gpa, expected_len); |
| 3187 | for (as_scope.instructions.items) |src_inst| { | 3166 | for (as_scope.instructions.items) |src_inst| { |
| 3188 | if (wzc.ref_start_index + src_inst == as_scope.rl_ptr) continue; | 3167 | if (zir.Inst.Ref.fromIndex(src_inst, wzc.param_count) == as_scope.rl_ptr) continue; |
| 3189 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 3168 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 3190 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; | 3169 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; |
| 3191 | } | 3170 | } |
| ... | @@ -3272,11 +3251,12 @@ fn typeOf( | ... | @@ -3272,11 +3251,12 @@ fn typeOf( |
| 3272 | } | 3251 | } |
| 3273 | const arena = scope.arena(); | 3252 | const arena = scope.arena(); |
| 3274 | var items = try arena.alloc(zir.Inst.Ref, params.len); | 3253 | var items = try arena.alloc(zir.Inst.Ref, params.len); |
| 3275 | for (params) |param, param_i| | 3254 | for (params) |param, param_i| { |
| 3276 | items[param_i] = try expr(mod, scope, .none, param); | 3255 | items[param_i] = try expr(mod, scope, .none, param); |
| 3256 | } | ||
| 3277 | 3257 | ||
| 3278 | const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{ .operands_len = @intCast(u32, params.len) }); | 3258 | const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{ .operands_len = @intCast(u32, params.len) }); |
| 3279 | try gz.zir_code.extra.appendSlice(gz.zir_code.gpa, items); | 3259 | try gz.zir_code.extra.appendSlice(gz.zir_code.gpa, mem.bytesAsSlice(u32, mem.sliceAsBytes(items))); |
| 3280 | 3260 | ||
| 3281 | return rvalue(mod, scope, rl, result, node); | 3261 | return rvalue(mod, scope, rl, result, node); |
| 3282 | } | 3262 | } |
| ... | @@ -3351,8 +3331,7 @@ fn builtinCall( | ... | @@ -3351,8 +3331,7 @@ fn builtinCall( |
| 3351 | return rvalue(mod, scope, rl, result, node); | 3331 | return rvalue(mod, scope, rl, result, node); |
| 3352 | }, | 3332 | }, |
| 3353 | .set_eval_branch_quota => { | 3333 | .set_eval_branch_quota => { |
| 3354 | const u32_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.u32_type) }; | 3334 | const quota = try expr(mod, scope, .{ .ty = .u32_type }, params[0]); |
| 3355 | const quota = try expr(mod, scope, u32_rl, params[0]); | ||
| 3356 | const result = try gz.addUnNode(.set_eval_branch_quota, quota, node); | 3335 | const result = try gz.addUnNode(.set_eval_branch_quota, quota, node); |
| 3357 | return rvalue(mod, scope, rl, result, node); | 3336 | return rvalue(mod, scope, rl, result, node); |
| 3358 | }, | 3337 | }, |
| ... | @@ -3498,7 +3477,7 @@ fn callExpr( | ... | @@ -3498,7 +3477,7 @@ fn callExpr( |
| 3498 | } | 3477 | } |
| 3499 | const lhs = try expr(mod, scope, .none, call.ast.fn_expr); | 3478 | const lhs = try expr(mod, scope, .none, call.ast.fn_expr); |
| 3500 | 3479 | ||
| 3501 | const args = try mod.gpa.alloc(zir.Inst.Index, call.ast.params.len); | 3480 | const args = try mod.gpa.alloc(zir.Inst.Ref, call.ast.params.len); |
| 3502 | defer mod.gpa.free(args); | 3481 | defer mod.gpa.free(args); |
| 3503 | 3482 | ||
| 3504 | const gz = scope.getGenZir(); | 3483 | const gz = scope.getGenZir(); |
| ... | @@ -3517,7 +3496,7 @@ fn callExpr( | ... | @@ -3517,7 +3496,7 @@ fn callExpr( |
| 3517 | true => .async_kw, | 3496 | true => .async_kw, |
| 3518 | false => .auto, | 3497 | false => .auto, |
| 3519 | }; | 3498 | }; |
| 3520 | const result: zir.Inst.Index = res: { | 3499 | const result: zir.Inst.Ref = res: { |
| 3521 | const tag: zir.Inst.Tag = switch (modifier) { | 3500 | const tag: zir.Inst.Tag = switch (modifier) { |
| 3522 | .auto => switch (args.len == 0) { | 3501 | .auto => switch (args.len == 0) { |
| 3523 | true => break :res try gz.addUnNode(.call_none, lhs, node), | 3502 | true => break :res try gz.addUnNode(.call_none, lhs, node), |
| ... | @@ -3536,7 +3515,7 @@ fn callExpr( | ... | @@ -3536,7 +3515,7 @@ fn callExpr( |
| 3536 | return rvalue(mod, scope, rl, result, node); // TODO function call with result location | 3515 | return rvalue(mod, scope, rl, result, node); // TODO function call with result location |
| 3537 | } | 3516 | } |
| 3538 | 3517 | ||
| 3539 | pub const simple_types = std.ComptimeStringMap(zir.Const, .{ | 3518 | pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{ |
| 3540 | .{ "u8", .u8_type }, | 3519 | .{ "u8", .u8_type }, |
| 3541 | .{ "i8", .i8_type }, | 3520 | .{ "i8", .i8_type }, |
| 3542 | .{ "u16", .u16_type }, | 3521 | .{ "u16", .u16_type }, |
src/zir.zig+333-300| ... | @@ -48,8 +48,11 @@ pub const Code = struct { | ... | @@ -48,8 +48,11 @@ pub const Code = struct { |
| 48 | var i: usize = index; | 48 | var i: usize = index; |
| 49 | var result: T = undefined; | 49 | var result: T = undefined; |
| 50 | inline for (fields) |field| { | 50 | inline for (fields) |field| { |
| 51 | comptime assert(field.field_type == u32); | 51 | @field(result, field.name) = switch (field.field_type) { |
| 52 | @field(result, field.name) = code.extra[i]; | 52 | u32 => code.extra[i], |
| 53 | Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]), | ||
| 54 | else => unreachable, | ||
| 55 | }; | ||
| 53 | i += 1; | 56 | i += 1; |
| 54 | } | 57 | } |
| 55 | return .{ | 58 | return .{ |
| ... | @@ -105,284 +108,6 @@ pub const Code = struct { | ... | @@ -105,284 +108,6 @@ pub const Code = struct { |
| 105 | } | 108 | } |
| 106 | }; | 109 | }; |
| 107 | 110 | ||
| 108 | /// These correspond to the first N tags of Value. | ||
| 109 | /// A ZIR instruction refers to another one by index. However the first N indexes | ||
| 110 | /// correspond to this enum, and the next M indexes correspond to the parameters | ||
| 111 | /// of the current function. After that, they refer to other instructions in the | ||
| 112 | /// instructions array for the function. | ||
| 113 | /// When adding to this, consider adding a corresponding entry o `simple_types` | ||
| 114 | /// in astgen. | ||
| 115 | pub const Const = enum { | ||
| 116 | /// The 0 value is reserved so that ZIR instruction indexes can use it to | ||
| 117 | /// mean "null". | ||
| 118 | unused, | ||
| 119 | |||
| 120 | u8_type, | ||
| 121 | i8_type, | ||
| 122 | u16_type, | ||
| 123 | i16_type, | ||
| 124 | u32_type, | ||
| 125 | i32_type, | ||
| 126 | u64_type, | ||
| 127 | i64_type, | ||
| 128 | u128_type, | ||
| 129 | i128_type, | ||
| 130 | usize_type, | ||
| 131 | isize_type, | ||
| 132 | c_short_type, | ||
| 133 | c_ushort_type, | ||
| 134 | c_int_type, | ||
| 135 | c_uint_type, | ||
| 136 | c_long_type, | ||
| 137 | c_ulong_type, | ||
| 138 | c_longlong_type, | ||
| 139 | c_ulonglong_type, | ||
| 140 | c_longdouble_type, | ||
| 141 | f16_type, | ||
| 142 | f32_type, | ||
| 143 | f64_type, | ||
| 144 | f128_type, | ||
| 145 | c_void_type, | ||
| 146 | bool_type, | ||
| 147 | void_type, | ||
| 148 | type_type, | ||
| 149 | anyerror_type, | ||
| 150 | comptime_int_type, | ||
| 151 | comptime_float_type, | ||
| 152 | noreturn_type, | ||
| 153 | null_type, | ||
| 154 | undefined_type, | ||
| 155 | fn_noreturn_no_args_type, | ||
| 156 | fn_void_no_args_type, | ||
| 157 | fn_naked_noreturn_no_args_type, | ||
| 158 | fn_ccc_void_no_args_type, | ||
| 159 | single_const_pointer_to_comptime_int_type, | ||
| 160 | const_slice_u8_type, | ||
| 161 | enum_literal_type, | ||
| 162 | |||
| 163 | /// `undefined` (untyped) | ||
| 164 | undef, | ||
| 165 | /// `0` (comptime_int) | ||
| 166 | zero, | ||
| 167 | /// `1` (comptime_int) | ||
| 168 | one, | ||
| 169 | /// `{}` | ||
| 170 | void_value, | ||
| 171 | /// `unreachable` (noreturn type) | ||
| 172 | unreachable_value, | ||
| 173 | /// `null` (untyped) | ||
| 174 | null_value, | ||
| 175 | /// `true` | ||
| 176 | bool_true, | ||
| 177 | /// `false` | ||
| 178 | bool_false, | ||
| 179 | }; | ||
| 180 | |||
| 181 | pub const const_inst_list = std.enums.directEnumArray(Const, TypedValue, 0, .{ | ||
| 182 | .unused = undefined, | ||
| 183 | .u8_type = .{ | ||
| 184 | .ty = Type.initTag(.type), | ||
| 185 | .val = Value.initTag(.u8_type), | ||
| 186 | }, | ||
| 187 | .i8_type = .{ | ||
| 188 | .ty = Type.initTag(.type), | ||
| 189 | .val = Value.initTag(.i8_type), | ||
| 190 | }, | ||
| 191 | .u16_type = .{ | ||
| 192 | .ty = Type.initTag(.type), | ||
| 193 | .val = Value.initTag(.u16_type), | ||
| 194 | }, | ||
| 195 | .i16_type = .{ | ||
| 196 | .ty = Type.initTag(.type), | ||
| 197 | .val = Value.initTag(.i16_type), | ||
| 198 | }, | ||
| 199 | .u32_type = .{ | ||
| 200 | .ty = Type.initTag(.type), | ||
| 201 | .val = Value.initTag(.u32_type), | ||
| 202 | }, | ||
| 203 | .i32_type = .{ | ||
| 204 | .ty = Type.initTag(.type), | ||
| 205 | .val = Value.initTag(.i32_type), | ||
| 206 | }, | ||
| 207 | .u64_type = .{ | ||
| 208 | .ty = Type.initTag(.type), | ||
| 209 | .val = Value.initTag(.u64_type), | ||
| 210 | }, | ||
| 211 | .i64_type = .{ | ||
| 212 | .ty = Type.initTag(.type), | ||
| 213 | .val = Value.initTag(.i64_type), | ||
| 214 | }, | ||
| 215 | .u128_type = .{ | ||
| 216 | .ty = Type.initTag(.type), | ||
| 217 | .val = Value.initTag(.u128_type), | ||
| 218 | }, | ||
| 219 | .i128_type = .{ | ||
| 220 | .ty = Type.initTag(.type), | ||
| 221 | .val = Value.initTag(.i128_type), | ||
| 222 | }, | ||
| 223 | .usize_type = .{ | ||
| 224 | .ty = Type.initTag(.type), | ||
| 225 | .val = Value.initTag(.usize_type), | ||
| 226 | }, | ||
| 227 | .isize_type = .{ | ||
| 228 | .ty = Type.initTag(.type), | ||
| 229 | .val = Value.initTag(.isize_type), | ||
| 230 | }, | ||
| 231 | .c_short_type = .{ | ||
| 232 | .ty = Type.initTag(.type), | ||
| 233 | .val = Value.initTag(.c_short_type), | ||
| 234 | }, | ||
| 235 | .c_ushort_type = .{ | ||
| 236 | .ty = Type.initTag(.type), | ||
| 237 | .val = Value.initTag(.c_ushort_type), | ||
| 238 | }, | ||
| 239 | .c_int_type = .{ | ||
| 240 | .ty = Type.initTag(.type), | ||
| 241 | .val = Value.initTag(.c_int_type), | ||
| 242 | }, | ||
| 243 | .c_uint_type = .{ | ||
| 244 | .ty = Type.initTag(.type), | ||
| 245 | .val = Value.initTag(.c_uint_type), | ||
| 246 | }, | ||
| 247 | .c_long_type = .{ | ||
| 248 | .ty = Type.initTag(.type), | ||
| 249 | .val = Value.initTag(.c_long_type), | ||
| 250 | }, | ||
| 251 | .c_ulong_type = .{ | ||
| 252 | .ty = Type.initTag(.type), | ||
| 253 | .val = Value.initTag(.c_ulong_type), | ||
| 254 | }, | ||
| 255 | .c_longlong_type = .{ | ||
| 256 | .ty = Type.initTag(.type), | ||
| 257 | .val = Value.initTag(.c_longlong_type), | ||
| 258 | }, | ||
| 259 | .c_ulonglong_type = .{ | ||
| 260 | .ty = Type.initTag(.type), | ||
| 261 | .val = Value.initTag(.c_ulonglong_type), | ||
| 262 | }, | ||
| 263 | .c_longdouble_type = .{ | ||
| 264 | .ty = Type.initTag(.type), | ||
| 265 | .val = Value.initTag(.c_longdouble_type), | ||
| 266 | }, | ||
| 267 | .f16_type = .{ | ||
| 268 | .ty = Type.initTag(.type), | ||
| 269 | .val = Value.initTag(.f16_type), | ||
| 270 | }, | ||
| 271 | .f32_type = .{ | ||
| 272 | .ty = Type.initTag(.type), | ||
| 273 | .val = Value.initTag(.f32_type), | ||
| 274 | }, | ||
| 275 | .f64_type = .{ | ||
| 276 | .ty = Type.initTag(.type), | ||
| 277 | .val = Value.initTag(.f64_type), | ||
| 278 | }, | ||
| 279 | .f128_type = .{ | ||
| 280 | .ty = Type.initTag(.type), | ||
| 281 | .val = Value.initTag(.f128_type), | ||
| 282 | }, | ||
| 283 | .c_void_type = .{ | ||
| 284 | .ty = Type.initTag(.type), | ||
| 285 | .val = Value.initTag(.c_void_type), | ||
| 286 | }, | ||
| 287 | .bool_type = .{ | ||
| 288 | .ty = Type.initTag(.type), | ||
| 289 | .val = Value.initTag(.bool_type), | ||
| 290 | }, | ||
| 291 | .void_type = .{ | ||
| 292 | .ty = Type.initTag(.type), | ||
| 293 | .val = Value.initTag(.void_type), | ||
| 294 | }, | ||
| 295 | .type_type = .{ | ||
| 296 | .ty = Type.initTag(.type), | ||
| 297 | .val = Value.initTag(.type_type), | ||
| 298 | }, | ||
| 299 | .anyerror_type = .{ | ||
| 300 | .ty = Type.initTag(.type), | ||
| 301 | .val = Value.initTag(.anyerror_type), | ||
| 302 | }, | ||
| 303 | .comptime_int_type = .{ | ||
| 304 | .ty = Type.initTag(.type), | ||
| 305 | .val = Value.initTag(.comptime_int_type), | ||
| 306 | }, | ||
| 307 | .comptime_float_type = .{ | ||
| 308 | .ty = Type.initTag(.type), | ||
| 309 | .val = Value.initTag(.comptime_float_type), | ||
| 310 | }, | ||
| 311 | .noreturn_type = .{ | ||
| 312 | .ty = Type.initTag(.type), | ||
| 313 | .val = Value.initTag(.noreturn_type), | ||
| 314 | }, | ||
| 315 | .null_type = .{ | ||
| 316 | .ty = Type.initTag(.type), | ||
| 317 | .val = Value.initTag(.null_type), | ||
| 318 | }, | ||
| 319 | .undefined_type = .{ | ||
| 320 | .ty = Type.initTag(.type), | ||
| 321 | .val = Value.initTag(.undefined_type), | ||
| 322 | }, | ||
| 323 | .fn_noreturn_no_args_type = .{ | ||
| 324 | .ty = Type.initTag(.type), | ||
| 325 | .val = Value.initTag(.fn_noreturn_no_args_type), | ||
| 326 | }, | ||
| 327 | .fn_void_no_args_type = .{ | ||
| 328 | .ty = Type.initTag(.type), | ||
| 329 | .val = Value.initTag(.fn_void_no_args_type), | ||
| 330 | }, | ||
| 331 | .fn_naked_noreturn_no_args_type = .{ | ||
| 332 | .ty = Type.initTag(.type), | ||
| 333 | .val = Value.initTag(.fn_naked_noreturn_no_args_type), | ||
| 334 | }, | ||
| 335 | .fn_ccc_void_no_args_type = .{ | ||
| 336 | .ty = Type.initTag(.type), | ||
| 337 | .val = Value.initTag(.fn_ccc_void_no_args_type), | ||
| 338 | }, | ||
| 339 | .single_const_pointer_to_comptime_int_type = .{ | ||
| 340 | .ty = Type.initTag(.type), | ||
| 341 | .val = Value.initTag(.single_const_pointer_to_comptime_int_type), | ||
| 342 | }, | ||
| 343 | .const_slice_u8_type = .{ | ||
| 344 | .ty = Type.initTag(.type), | ||
| 345 | .val = Value.initTag(.const_slice_u8_type), | ||
| 346 | }, | ||
| 347 | .enum_literal_type = .{ | ||
| 348 | .ty = Type.initTag(.type), | ||
| 349 | .val = Value.initTag(.enum_literal_type), | ||
| 350 | }, | ||
| 351 | |||
| 352 | .undef = .{ | ||
| 353 | .ty = Type.initTag(.@"undefined"), | ||
| 354 | .val = Value.initTag(.undef), | ||
| 355 | }, | ||
| 356 | .zero = .{ | ||
| 357 | .ty = Type.initTag(.comptime_int), | ||
| 358 | .val = Value.initTag(.zero), | ||
| 359 | }, | ||
| 360 | .one = .{ | ||
| 361 | .ty = Type.initTag(.comptime_int), | ||
| 362 | .val = Value.initTag(.one), | ||
| 363 | }, | ||
| 364 | .void_value = .{ | ||
| 365 | .ty = Type.initTag(.void), | ||
| 366 | .val = Value.initTag(.void_value), | ||
| 367 | }, | ||
| 368 | .unreachable_value = .{ | ||
| 369 | .ty = Type.initTag(.noreturn), | ||
| 370 | .val = Value.initTag(.unreachable_value), | ||
| 371 | }, | ||
| 372 | .null_value = .{ | ||
| 373 | .ty = Type.initTag(.@"null"), | ||
| 374 | .val = Value.initTag(.null_value), | ||
| 375 | }, | ||
| 376 | .bool_true = .{ | ||
| 377 | .ty = Type.initTag(.bool), | ||
| 378 | .val = Value.initTag(.bool_true), | ||
| 379 | }, | ||
| 380 | .bool_false = .{ | ||
| 381 | .ty = Type.initTag(.bool), | ||
| 382 | .val = Value.initTag(.bool_false), | ||
| 383 | }, | ||
| 384 | }); | ||
| 385 | |||
| 386 | /// These are untyped instructions generated from an Abstract Syntax Tree. | 111 | /// These are untyped instructions generated from an Abstract Syntax Tree. |
| 387 | /// The data here is immutable because it is possible to have multiple | 112 | /// The data here is immutable because it is possible to have multiple |
| 388 | /// analyses on the same ZIR happening at the same time. | 113 | /// analyses on the same ZIR happening at the same time. |
| ... | @@ -1032,14 +757,319 @@ pub const Inst = struct { | ... | @@ -1032,14 +757,319 @@ pub const Inst = struct { |
| 1032 | /// The position of a ZIR instruction within the `Code` instructions array. | 757 | /// The position of a ZIR instruction within the `Code` instructions array. |
| 1033 | pub const Index = u32; | 758 | pub const Index = u32; |
| 1034 | 759 | ||
| 1035 | /// A reference to another ZIR instruction. If this value is below a certain | 760 | /// A reference to a TypedValue, parameter of the current function, |
| 1036 | /// threshold, it implicitly refers to a constant-known value from the `Const` enum. | 761 | /// or ZIR instruction. |
| 1037 | /// Below a second threshold, it implicitly refers to a parameter of the current | 762 | /// |
| 1038 | /// function. | 763 | /// If the Ref has a tag in this enum, it refers to a TypedValue which may be |
| 1039 | /// Finally, after subtracting that offset, it refers to another instruction in | 764 | /// retrieved with Ref.toTypedValue(). |
| 1040 | /// the instruction array. | 765 | /// |
| 1041 | /// This logic is implemented in `Sema.resolveRef`. | 766 | /// If the value of a Ref does not have a tag, it referes to either a parameter |
| 1042 | pub const Ref = u32; | 767 | /// of the current function or a ZIR instruction. |
| 768 | /// | ||
| 769 | /// The first values after the the last tag refer to parameters which may be | ||
| 770 | /// derived by subtracting typed_value_count. | ||
| 771 | /// | ||
| 772 | /// All further values refer to ZIR instructions which may be derived by | ||
| 773 | /// subtracting typed_value_count and the number of parameters. | ||
| 774 | /// | ||
| 775 | /// When adding a tag to this enum, consider adding a corresponding entry to | ||
| 776 | /// `simple_types` in astgen. | ||
| 777 | /// | ||
| 778 | /// This is packed so that it is safe to cast between `[]u32` and `[]Ref`. | ||
| 779 | pub const Ref = packed enum(u32) { | ||
| 780 | /// This Ref does not correspond to any ZIR instruction or constant | ||
| 781 | /// value and may instead be used as a sentinel to indicate null. | ||
| 782 | none, | ||
| 783 | |||
| 784 | u8_type, | ||
| 785 | i8_type, | ||
| 786 | u16_type, | ||
| 787 | i16_type, | ||
| 788 | u32_type, | ||
| 789 | i32_type, | ||
| 790 | u64_type, | ||
| 791 | i64_type, | ||
| 792 | usize_type, | ||
| 793 | isize_type, | ||
| 794 | c_short_type, | ||
| 795 | c_ushort_type, | ||
| 796 | c_int_type, | ||
| 797 | c_uint_type, | ||
| 798 | c_long_type, | ||
| 799 | c_ulong_type, | ||
| 800 | c_longlong_type, | ||
| 801 | c_ulonglong_type, | ||
| 802 | c_longdouble_type, | ||
| 803 | f16_type, | ||
| 804 | f32_type, | ||
| 805 | f64_type, | ||
| 806 | f128_type, | ||
| 807 | c_void_type, | ||
| 808 | bool_type, | ||
| 809 | void_type, | ||
| 810 | type_type, | ||
| 811 | anyerror_type, | ||
| 812 | comptime_int_type, | ||
| 813 | comptime_float_type, | ||
| 814 | noreturn_type, | ||
| 815 | null_type, | ||
| 816 | undefined_type, | ||
| 817 | fn_noreturn_no_args_type, | ||
| 818 | fn_void_no_args_type, | ||
| 819 | fn_naked_noreturn_no_args_type, | ||
| 820 | fn_ccc_void_no_args_type, | ||
| 821 | single_const_pointer_to_comptime_int_type, | ||
| 822 | const_slice_u8_type, | ||
| 823 | enum_literal_type, | ||
| 824 | |||
| 825 | /// `undefined` (untyped) | ||
| 826 | undef, | ||
| 827 | /// `0` (comptime_int) | ||
| 828 | zero, | ||
| 829 | /// `1` (comptime_int) | ||
| 830 | one, | ||
| 831 | /// `{}` | ||
| 832 | void_value, | ||
| 833 | /// `unreachable` (noreturn type) | ||
| 834 | unreachable_value, | ||
| 835 | /// `null` (untyped) | ||
| 836 | null_value, | ||
| 837 | /// `true` | ||
| 838 | bool_true, | ||
| 839 | /// `false` | ||
| 840 | bool_false, | ||
| 841 | |||
| 842 | _, | ||
| 843 | |||
| 844 | pub const typed_value_count = @as(u32, typed_value_map.len); | ||
| 845 | const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{ | ||
| 846 | .none = undefined, | ||
| 847 | |||
| 848 | .u8_type = .{ | ||
| 849 | .ty = Type.initTag(.type), | ||
| 850 | .val = Value.initTag(.u8_type), | ||
| 851 | }, | ||
| 852 | .i8_type = .{ | ||
| 853 | .ty = Type.initTag(.type), | ||
| 854 | .val = Value.initTag(.i8_type), | ||
| 855 | }, | ||
| 856 | .u16_type = .{ | ||
| 857 | .ty = Type.initTag(.type), | ||
| 858 | .val = Value.initTag(.u16_type), | ||
| 859 | }, | ||
| 860 | .i16_type = .{ | ||
| 861 | .ty = Type.initTag(.type), | ||
| 862 | .val = Value.initTag(.i16_type), | ||
| 863 | }, | ||
| 864 | .u32_type = .{ | ||
| 865 | .ty = Type.initTag(.type), | ||
| 866 | .val = Value.initTag(.u32_type), | ||
| 867 | }, | ||
| 868 | .i32_type = .{ | ||
| 869 | .ty = Type.initTag(.type), | ||
| 870 | .val = Value.initTag(.i32_type), | ||
| 871 | }, | ||
| 872 | .u64_type = .{ | ||
| 873 | .ty = Type.initTag(.type), | ||
| 874 | .val = Value.initTag(.u64_type), | ||
| 875 | }, | ||
| 876 | .i64_type = .{ | ||
| 877 | .ty = Type.initTag(.type), | ||
| 878 | .val = Value.initTag(.i64_type), | ||
| 879 | }, | ||
| 880 | .usize_type = .{ | ||
| 881 | .ty = Type.initTag(.type), | ||
| 882 | .val = Value.initTag(.usize_type), | ||
| 883 | }, | ||
| 884 | .isize_type = .{ | ||
| 885 | .ty = Type.initTag(.type), | ||
| 886 | .val = Value.initTag(.isize_type), | ||
| 887 | }, | ||
| 888 | .c_short_type = .{ | ||
| 889 | .ty = Type.initTag(.type), | ||
| 890 | .val = Value.initTag(.c_short_type), | ||
| 891 | }, | ||
| 892 | .c_ushort_type = .{ | ||
| 893 | .ty = Type.initTag(.type), | ||
| 894 | .val = Value.initTag(.c_ushort_type), | ||
| 895 | }, | ||
| 896 | .c_int_type = .{ | ||
| 897 | .ty = Type.initTag(.type), | ||
| 898 | .val = Value.initTag(.c_int_type), | ||
| 899 | }, | ||
| 900 | .c_uint_type = .{ | ||
| 901 | .ty = Type.initTag(.type), | ||
| 902 | .val = Value.initTag(.c_uint_type), | ||
| 903 | }, | ||
| 904 | .c_long_type = .{ | ||
| 905 | .ty = Type.initTag(.type), | ||
| 906 | .val = Value.initTag(.c_long_type), | ||
| 907 | }, | ||
| 908 | .c_ulong_type = .{ | ||
| 909 | .ty = Type.initTag(.type), | ||
| 910 | .val = Value.initTag(.c_ulong_type), | ||
| 911 | }, | ||
| 912 | .c_longlong_type = .{ | ||
| 913 | .ty = Type.initTag(.type), | ||
| 914 | .val = Value.initTag(.c_longlong_type), | ||
| 915 | }, | ||
| 916 | .c_ulonglong_type = .{ | ||
| 917 | .ty = Type.initTag(.type), | ||
| 918 | .val = Value.initTag(.c_ulonglong_type), | ||
| 919 | }, | ||
| 920 | .c_longdouble_type = .{ | ||
| 921 | .ty = Type.initTag(.type), | ||
| 922 | .val = Value.initTag(.c_longdouble_type), | ||
| 923 | }, | ||
| 924 | .f16_type = .{ | ||
| 925 | .ty = Type.initTag(.type), | ||
| 926 | .val = Value.initTag(.f16_type), | ||
| 927 | }, | ||
| 928 | .f32_type = .{ | ||
| 929 | .ty = Type.initTag(.type), | ||
| 930 | .val = Value.initTag(.f32_type), | ||
| 931 | }, | ||
| 932 | .f64_type = .{ | ||
| 933 | .ty = Type.initTag(.type), | ||
| 934 | .val = Value.initTag(.f64_type), | ||
| 935 | }, | ||
| 936 | .f128_type = .{ | ||
| 937 | .ty = Type.initTag(.type), | ||
| 938 | .val = Value.initTag(.f128_type), | ||
| 939 | }, | ||
| 940 | .c_void_type = .{ | ||
| 941 | .ty = Type.initTag(.type), | ||
| 942 | .val = Value.initTag(.c_void_type), | ||
| 943 | }, | ||
| 944 | .bool_type = .{ | ||
| 945 | .ty = Type.initTag(.type), | ||
| 946 | .val = Value.initTag(.bool_type), | ||
| 947 | }, | ||
| 948 | .void_type = .{ | ||
| 949 | .ty = Type.initTag(.type), | ||
| 950 | .val = Value.initTag(.void_type), | ||
| 951 | }, | ||
| 952 | .type_type = .{ | ||
| 953 | .ty = Type.initTag(.type), | ||
| 954 | .val = Value.initTag(.type_type), | ||
| 955 | }, | ||
| 956 | .anyerror_type = .{ | ||
| 957 | .ty = Type.initTag(.type), | ||
| 958 | .val = Value.initTag(.anyerror_type), | ||
| 959 | }, | ||
| 960 | .comptime_int_type = .{ | ||
| 961 | .ty = Type.initTag(.type), | ||
| 962 | .val = Value.initTag(.comptime_int_type), | ||
| 963 | }, | ||
| 964 | .comptime_float_type = .{ | ||
| 965 | .ty = Type.initTag(.type), | ||
| 966 | .val = Value.initTag(.comptime_float_type), | ||
| 967 | }, | ||
| 968 | .noreturn_type = .{ | ||
| 969 | .ty = Type.initTag(.type), | ||
| 970 | .val = Value.initTag(.noreturn_type), | ||
| 971 | }, | ||
| 972 | .null_type = .{ | ||
| 973 | .ty = Type.initTag(.type), | ||
| 974 | .val = Value.initTag(.null_type), | ||
| 975 | }, | ||
| 976 | .undefined_type = .{ | ||
| 977 | .ty = Type.initTag(.type), | ||
| 978 | .val = Value.initTag(.undefined_type), | ||
| 979 | }, | ||
| 980 | .fn_noreturn_no_args_type = .{ | ||
| 981 | .ty = Type.initTag(.type), | ||
| 982 | .val = Value.initTag(.fn_noreturn_no_args_type), | ||
| 983 | }, | ||
| 984 | .fn_void_no_args_type = .{ | ||
| 985 | .ty = Type.initTag(.type), | ||
| 986 | .val = Value.initTag(.fn_void_no_args_type), | ||
| 987 | }, | ||
| 988 | .fn_naked_noreturn_no_args_type = .{ | ||
| 989 | .ty = Type.initTag(.type), | ||
| 990 | .val = Value.initTag(.fn_naked_noreturn_no_args_type), | ||
| 991 | }, | ||
| 992 | .fn_ccc_void_no_args_type = .{ | ||
| 993 | .ty = Type.initTag(.type), | ||
| 994 | .val = Value.initTag(.fn_ccc_void_no_args_type), | ||
| 995 | }, | ||
| 996 | .single_const_pointer_to_comptime_int_type = .{ | ||
| 997 | .ty = Type.initTag(.type), | ||
| 998 | .val = Value.initTag(.single_const_pointer_to_comptime_int_type), | ||
| 999 | }, | ||
| 1000 | .const_slice_u8_type = .{ | ||
| 1001 | .ty = Type.initTag(.type), | ||
| 1002 | .val = Value.initTag(.const_slice_u8_type), | ||
| 1003 | }, | ||
| 1004 | .enum_literal_type = .{ | ||
| 1005 | .ty = Type.initTag(.type), | ||
| 1006 | .val = Value.initTag(.enum_literal_type), | ||
| 1007 | }, | ||
| 1008 | |||
| 1009 | .undef = .{ | ||
| 1010 | .ty = Type.initTag(.@"undefined"), | ||
| 1011 | .val = Value.initTag(.undef), | ||
| 1012 | }, | ||
| 1013 | .zero = .{ | ||
| 1014 | .ty = Type.initTag(.comptime_int), | ||
| 1015 | .val = Value.initTag(.zero), | ||
| 1016 | }, | ||
| 1017 | .one = .{ | ||
| 1018 | .ty = Type.initTag(.comptime_int), | ||
| 1019 | .val = Value.initTag(.one), | ||
| 1020 | }, | ||
| 1021 | .void_value = .{ | ||
| 1022 | .ty = Type.initTag(.void), | ||
| 1023 | .val = Value.initTag(.void_value), | ||
| 1024 | }, | ||
| 1025 | .unreachable_value = .{ | ||
| 1026 | .ty = Type.initTag(.noreturn), | ||
| 1027 | .val = Value.initTag(.unreachable_value), | ||
| 1028 | }, | ||
| 1029 | .null_value = .{ | ||
| 1030 | .ty = Type.initTag(.@"null"), | ||
| 1031 | .val = Value.initTag(.null_value), | ||
| 1032 | }, | ||
| 1033 | .bool_true = .{ | ||
| 1034 | .ty = Type.initTag(.bool), | ||
| 1035 | .val = Value.initTag(.bool_true), | ||
| 1036 | }, | ||
| 1037 | .bool_false = .{ | ||
| 1038 | .ty = Type.initTag(.bool), | ||
| 1039 | .val = Value.initTag(.bool_false), | ||
| 1040 | }, | ||
| 1041 | }); | ||
| 1042 | |||
| 1043 | pub fn fromParam(param: u32) Ref { | ||
| 1044 | return @intToEnum(Ref, typed_value_count + param); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | pub fn fromIndex(index: Index, param_count: u32) Ref { | ||
| 1048 | return @intToEnum(Ref, typed_value_count + param_count + index); | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | pub fn toTypedValue(ref: Ref) ?TypedValue { | ||
| 1052 | assert(ref != .none); | ||
| 1053 | if (@enumToInt(ref) >= typed_value_count) return null; | ||
| 1054 | return typed_value_map[@enumToInt(ref)]; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | pub fn toParam(ref: Ref, param_count: u32) ?u32 { | ||
| 1058 | assert(ref != .none); | ||
| 1059 | if (@enumToInt(ref) < typed_value_count or | ||
| 1060 | @enumToInt(ref) >= typed_value_count + param_count) | ||
| 1061 | { | ||
| 1062 | return null; | ||
| 1063 | } | ||
| 1064 | return @enumToInt(ref) - typed_value_count; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | pub fn toIndex(ref: Ref, param_count: u32) ?Index { | ||
| 1068 | assert(ref != .none); | ||
| 1069 | if (@enumToInt(ref) < typed_value_count + param_count) return null; | ||
| 1070 | return @enumToInt(ref) - typed_value_count - param_count; | ||
| 1071 | } | ||
| 1072 | }; | ||
| 1043 | 1073 | ||
| 1044 | /// All instructions have an 8-byte payload, which is contained within | 1074 | /// All instructions have an 8-byte payload, which is contained within |
| 1045 | /// this union. `Tag` determines which union field is active, as well as | 1075 | /// this union. `Tag` determines which union field is active, as well as |
| ... | @@ -1642,7 +1672,9 @@ const Writer = struct { | ... | @@ -1642,7 +1672,9 @@ const Writer = struct { |
| 1642 | fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 1672 | fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 1643 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 1673 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1644 | const extra = self.code.extraData(Inst.Call, inst_data.payload_index); | 1674 | const extra = self.code.extraData(Inst.Call, inst_data.payload_index); |
| 1645 | const args = self.code.extra[extra.end..][0..extra.data.args_len]; | 1675 | const raw_args = self.code.extra[extra.end..][0..extra.data.args_len]; |
| 1676 | const args = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_args)); | ||
| 1677 | |||
| 1646 | try self.writeInstRef(stream, extra.data.callee); | 1678 | try self.writeInstRef(stream, extra.data.callee); |
| 1647 | try stream.writeAll(", ["); | 1679 | try stream.writeAll(", ["); |
| 1648 | for (args) |arg, i| { | 1680 | for (args) |arg, i| { |
| ... | @@ -1735,9 +1767,9 @@ const Writer = struct { | ... | @@ -1735,9 +1767,9 @@ const Writer = struct { |
| 1735 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | 1767 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 1736 | const inst_data = self.code.instructions.items(.data)[inst].fn_type; | 1768 | const inst_data = self.code.instructions.items(.data)[inst].fn_type; |
| 1737 | const extra = self.code.extraData(Inst.FnType, inst_data.payload_index); | 1769 | const extra = self.code.extraData(Inst.FnType, inst_data.payload_index); |
| 1738 | const param_types = self.code.extra[extra.end..][0..extra.data.param_types_len]; | 1770 | const raw_param_types = self.code.extra[extra.end..][0..extra.data.param_types_len]; |
| 1739 | const cc: Inst.Ref = 0; | 1771 | const param_types = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_param_types)); |
| 1740 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); | 1772 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, .none); |
| 1741 | } | 1773 | } |
| 1742 | 1774 | ||
| 1743 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 1775 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| ... | @@ -1761,7 +1793,8 @@ const Writer = struct { | ... | @@ -1761,7 +1793,8 @@ const Writer = struct { |
| 1761 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | 1793 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 1762 | const inst_data = self.code.instructions.items(.data)[inst].fn_type; | 1794 | const inst_data = self.code.instructions.items(.data)[inst].fn_type; |
| 1763 | const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index); | 1795 | const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index); |
| 1764 | const param_types = self.code.extra[extra.end..][0..extra.data.param_types_len]; | 1796 | const raw_param_types = self.code.extra[extra.end..][0..extra.data.param_types_len]; |
| 1797 | const param_types = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_param_types)); | ||
| 1765 | const cc = extra.data.cc; | 1798 | const cc = extra.data.cc; |
| 1766 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); | 1799 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); |
| 1767 | } | 1800 | } |
| ... | @@ -1828,13 +1861,13 @@ const Writer = struct { | ... | @@ -1828,13 +1861,13 @@ const Writer = struct { |
| 1828 | try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)}); | 1861 | try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)}); |
| 1829 | } | 1862 | } |
| 1830 | 1863 | ||
| 1831 | fn writeInstRef(self: *Writer, stream: anytype, inst: Inst.Ref) !void { | 1864 | fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void { |
| 1832 | var i: usize = inst; | 1865 | var i: usize = @enumToInt(ref); |
| 1833 | 1866 | ||
| 1834 | if (i < const_inst_list.len) { | 1867 | if (i < Inst.Ref.typed_value_count) { |
| 1835 | return stream.print("@{d}", .{i}); | 1868 | return stream.print("@{}", .{ref}); |
| 1836 | } | 1869 | } |
| 1837 | i -= const_inst_list.len; | 1870 | i -= Inst.Ref.typed_value_count; |
| 1838 | 1871 | ||
| 1839 | if (i < self.param_count) { | 1872 | if (i < self.param_count) { |
| 1840 | return stream.print("${d}", .{i}); | 1873 | return stream.print("${d}", .{i}); |
| ... | @@ -1852,9 +1885,9 @@ const Writer = struct { | ... | @@ -1852,9 +1885,9 @@ const Writer = struct { |
| 1852 | self: *Writer, | 1885 | self: *Writer, |
| 1853 | stream: anytype, | 1886 | stream: anytype, |
| 1854 | prefix: []const u8, | 1887 | prefix: []const u8, |
| 1855 | inst: Inst.Index, | 1888 | inst: Inst.Ref, |
| 1856 | ) !void { | 1889 | ) !void { |
| 1857 | if (inst == 0) return; | 1890 | if (inst == .none) return; |
| 1858 | try stream.writeAll(prefix); | 1891 | try stream.writeAll(prefix); |
| 1859 | try self.writeInstRef(stream, inst); | 1892 | try self.writeInstRef(stream, inst); |
| 1860 | } | 1893 | } |