authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-03-24 01:17:38+01:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-03-24 19:11:44+01:00
log0c601965ab6600fdaf5be3c017176a6871413026
tree12c797047baf1bbc87a89c4b513bc2227b9f177f
parenta1afe693951f6d2ad06961c06b3a2cc14ad6efd9
signature Commit is signed but in an unrecognized format.

stage2: make zir.Inst.Ref a non-exhaustive enum

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}
3737
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 {
7070
71test "std.enum.values" {71test "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}
7575
76/// Returns the set of all unique named values in the given enum, in76/// 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 {
8282
83test "std.enum.uniqueValues" {83test "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));
8686
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}
9090
91/// Returns the set of all unique field values in the given enum, in91/// 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 }
103103
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}
117116
118/// Determines the length of a direct-mapped enum array, indexed by117/// 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 represented121/// 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 limits122/// 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 enum123/// 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_slots124/// 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.
125fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int {126fn 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 }
152148
153 return max_value + 1;149 return max_value + 1;
154}150}
155151
156/// Initializes an array of Data which can be indexed by152/// 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 represented156/// 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 limits157/// 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 enum158/// 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}
251249
...@@ -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")));
262260
...@@ -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 {
398pub fn NoExtension(comptime Self: type) type {396pub fn NoExtension(comptime Self: type) type {
399 return NoExt;397 return NoExt;
400}398}
401const NoExt = struct{};399const NoExt = struct {};
402400
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. This402/// 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.
406pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type {404pub 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 {
422420
423 bits: BitSet = BitSet.initEmpty(),421 bits: BitSet = BitSet.initEmpty(),
424422
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 a500/// 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.
504pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type) type {503pub 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
660660
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.
663pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: fn(type)type) type {663pub 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}
777777
...@@ -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}
845849
846test "std.enums.EnumIndexer dense zeroed" {850test "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}
909913
910test "std.enums.EnumIndexer repeats" {914test "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 }
958962
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 }
988993
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 a1000 testing.expectEqual(true, mut.contains(.e)); // aliases a
9961001
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));
10111016
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 });
10761081
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. References917 /// 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 actually927 /// Keeps track of how many branches of a block did not actually
928 /// consume the result location. astgen uses this to figure out928 /// consume the result location. astgen uses this to figure out
929 /// whether to rely on break instructions or writing to the result929 /// 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)));
10171017
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 }
10291029
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)));
10471047
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 }
10591059
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)));
10811081
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 }
10931093
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 }
11651165
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 }
11911191
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 };
13231323
...@@ -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 convert1369 /// 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 }
13911394
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) };
20852087
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 );
21842186
...@@ -2187,19 +2189,22 @@ fn astgenAndSemaFn(...@@ -2187,19 +2189,22 @@ fn astgenAndSemaFn(
2187 else2189 else
2188 false;2190 false;
21892191
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 the2193 // TODO instead of enum literal type, this needs to be the
2192 // std.builtin.CallingConvention enum. We need to implement importing other files2194 // 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/52692202 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 else2204 else
2200 0;2205 .none;
22012206
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();
22982303
...@@ -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);
23102315
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 }
23502354
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);
25152519
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;
25212523
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 NoReturn79/// 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.
81const always_noreturn: InnerError!zir.Inst.Ref = @as(zir.Inst.Index, 0);81const always_noreturn: InnerError!zir.Inst.Ref = .none;
8282
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 type84/// * 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 be89/// 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.
91pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Index) !zir.Inst.Index {91pub 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.
9393
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}
301301
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.
303pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {304pub 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| {
305306 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;
316308
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;
322313
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}
326316
327fn resolveConstString(317fn 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}
747737
748fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {738fn 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();
751741
...@@ -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
763753
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(", ", .{});
768761
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}
1000993
1001fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {994fn 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();
1004997
...@@ -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}
10091002
1010fn zirBreakVoidNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index {1003fn 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();
10131006
...@@ -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));
11161110
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
17391733
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));
17431738
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:
17571752
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));
17611757
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 from1759 // 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);
24922488
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(
26412637
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);
26562652
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));
27752773
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);
27782776
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 }
27822780
...@@ -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;
31163114
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;
31223120
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;
31283126
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;
31343132
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};
6060
61const void_inst: zir.Inst.Ref = @enumToInt(zir.Const.void_value);
62
63pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!zir.Inst.Ref {61pub 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}
6764
68fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {65fn 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
291288
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 },
348345
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 }
831816
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}
835820
836fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIndex) !void {821fn 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 but925 // 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);
943928
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`, but991 // 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 it995 // 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,
11711155
1172 @enumToInt(zir.Const.void_value),1156 .void_value,
1173 @enumToInt(zir.Const.unreachable_value),1157 .unreachable_value,
1174 => true,1158 => true,
11751159
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);
12851269
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);
14421426
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 }
15031487
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;
15091493
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);
15301514
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 }
15381526
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);
15651552
1566 // TODO check for [_]T1553 // 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);
15691556
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);
15801566
1581 // TODO check for [_]T1567 // 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);
15851571
...@@ -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);
19851970
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);
19881973
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);
19981983
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}
20021987
...@@ -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 };
20312015
...@@ -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 };
20782062
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 };
22562239
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}
28442827
...@@ -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 }
28642847
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 }
28682851
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();
30803063
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);
30843065
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);
30893069
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);
31003080
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 }
31043083
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 clobbers3090 .clobbers_len = 0, // TODO implement asm clobbers
3112 });3091 });
31133092
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);
31183097
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 }
32773257
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)));
32803260
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);
35003479
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);
35033482
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 location3515 return rvalue(mod, scope, rl, result, node); // TODO function call with result location
3537}3516}
35383517
3539pub const simple_types = std.ComptimeStringMap(zir.Const, .{3518pub 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};
107110
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.
115pub 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
181pub 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 multiple112/// 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;
1034759
1035 /// A reference to another ZIR instruction. If this value is below a certain760 /// 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 current762 ///
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 in764 /// 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 };
10431073
1044 /// All instructions have an 8-byte payload, which is contained within1074 /// All instructions have an 8-byte payload, which is contained within
1045 /// this union. `Tag` determines which union field is active, as well as1075 /// 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 }
17421774
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 }
18301863
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);
18331866
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;
18381871
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 }