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
3232 .fields = fields,
3333 .decls = &[_]std.builtin.TypeInfo.Declaration{},
3434 .is_tuple = false,
35 }});
35 } });
3636}
3737
3838/// Looks up the supplied fields in the given enum type.
......@@ -70,7 +70,7 @@ pub fn values(comptime E: type) []const E {
7070
7171test "std.enum.values" {
7272 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));
7474}
7575
7676/// 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 {
8282
8383test "std.enum.uniqueValues" {
8484 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
8787 const F = enum { a, b, c };
88 testing.expectEqualSlices(F, &.{.a, .b, .c}, uniqueValues(F));
88 testing.expectEqualSlices(F, &.{ .a, .b, .c }, uniqueValues(F));
8989}
9090
9191/// 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 {
102102 }
103103
104104 var unique_fields: []const EnumField = &[_]EnumField{};
105 outer:
106 for (raw_fields) |candidate| {
105 outer: for (raw_fields) |candidate| {
107106 for (unique_fields) |u| {
108107 if (u.value == candidate.value)
109108 continue :outer;
......@@ -116,28 +115,25 @@ pub fn uniqueFields(comptime E: type) []const EnumField {
116115}
117116
118117/// 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.
120121/// If the enum contains any fields with values that cannot be represented
121122/// by usize, a compile error is issued. The max_unused_slots parameter limits
122123/// the total number of items which have no matching enum key (holes in the enum
123124/// numbering). So for example, if an enum has values 1, 2, 5, and 6, max_unused_slots
124125/// must be at least 3, to allow unused slots 0, 3, and 4.
125126fn 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
131127 var max_value: comptime_int = -1;
132128 const max_usize: comptime_int = ~@as(usize, 0);
133129 const fields = uniqueFields(E);
134130 for (fields) |f| {
135131 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.");
137133 }
138134 if (f.value > max_value) {
139135 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.");
141137 }
142138 max_value = f.value;
143139 }
......@@ -147,14 +143,16 @@ fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int)
147143 if (unused_slots > max_unused_slots) {
148144 const unused_str = std.fmt.comptimePrint("{d}", .{unused_slots});
149145 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.");
151147 }
152148
153149 return max_value + 1;
154150}
155151
156152/// 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.
158156/// If the enum contains any fields with values that cannot be represented
159157/// by usize, a compile error is issued. The max_unused_slots parameter limits
160158/// 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 {
243241 if (@hasField(E, n)) {
244242 return @field(E, n);
245243 }
246 @compileError("Enum "++@typeName(E)++" has no field named "++n);
244 @compileError("Enum " ++ @typeName(E) ++ " has no field named " ++ n);
247245 }
248 @compileError("Cannot cast from "++@typeName(@TypeOf(value))++" to "++@typeName(E));
246 @compileError("Cannot cast from " ++ @typeName(@TypeOf(value)) ++ " to " ++ @typeName(E));
249247 }
250248}
251249
......@@ -256,7 +254,7 @@ test "std.enums.nameCast" {
256254 testing.expectEqual(A.a, nameCast(A, A.a));
257255 testing.expectEqual(A.a, nameCast(A, B.a));
258256 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")));
260258 testing.expectEqual(A.a, nameCast(A, @as([:0]const u8, "a")));
261259 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 {
398396pub fn NoExtension(comptime Self: type) type {
399397 return NoExt;
400398}
401const NoExt = struct{};
399const NoExt = struct {};
402400
403401/// A set type with an Indexer mapping from keys to indices.
404402/// Presence or absence is stored as a dense bitfield. This
405403/// 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 {
407405 comptime ensureIndexer(I);
408406 return struct {
409407 const Self = @This();
......@@ -422,7 +420,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type {
422420
423421 bits: BitSet = BitSet.initEmpty(),
424422
425 /// Returns a set containing all possible keys.
423 /// Returns a set containing all possible keys.
426424 pub fn initFull() Self {
427425 return .{ .bits = BitSet.initFull() };
428426 }
......@@ -492,7 +490,8 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type {
492490 pub fn next(self: *Iterator) ?Key {
493491 return if (self.inner.next()) |index|
494492 Indexer.keyForIndex(index)
495 else null;
493 else
494 null;
496495 }
497496 };
498497 };
......@@ -501,7 +500,7 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn(type)type) type {
501500/// A map from keys to values, using an index lookup. Uses a
502501/// bitfield to track presence and a dense array of values.
503502/// 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 {
505504 comptime ensureIndexer(I);
506505 return struct {
507506 const Self = @This();
......@@ -652,7 +651,8 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type
652651 .key = Indexer.keyForIndex(index),
653652 .value = &self.values[index],
654653 }
655 else null;
654 else
655 null;
656656 }
657657 };
658658 };
......@@ -660,7 +660,7 @@ pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: fn(type)type
660660
661661/// A dense array of values, using an indexed lookup.
662662/// 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 {
664664 comptime ensureIndexer(I);
665665 return struct {
666666 const Self = @This();
......@@ -769,9 +769,9 @@ pub fn ensureIndexer(comptime T: type) void {
769769 if (!@hasDecl(T, "count")) @compileError("Indexer must have decl count: usize.");
770770 if (@TypeOf(T.count) != usize) @compileError("Indexer.count must be a usize.");
771771 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.");
773773 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.");
775775 }
776776}
777777
......@@ -802,14 +802,18 @@ pub fn EnumIndexer(comptime E: type) type {
802802 return struct {
803803 pub const Key = E;
804804 pub const count: usize = 0;
805 pub fn indexOf(e: E) usize { unreachable; }
806 pub fn keyForIndex(i: usize) E { unreachable; }
805 pub fn indexOf(e: E) usize {
806 unreachable;
807 }
808 pub fn keyForIndex(i: usize) E {
809 unreachable;
810 }
807811 };
808812 }
809813 std.sort.sort(EnumField, &fields, {}, ascByValue);
810814 const min = fields[0].value;
811 const max = fields[fields.len-1].value;
812 if (max - min == fields.len-1) {
815 const max = fields[fields.len - 1].value;
816 if (max - min == fields.len - 1) {
813817 return struct {
814818 pub const Key = E;
815819 pub const count = fields.len;
......@@ -844,7 +848,7 @@ pub fn EnumIndexer(comptime E: type) type {
844848}
845849
846850test "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 };
848852 const Indexer = EnumIndexer(E);
849853 ensureIndexer(Indexer);
850854 testing.expectEqual(E, Indexer.Key);
......@@ -908,7 +912,7 @@ test "std.enums.EnumIndexer sparse" {
908912}
909913
910914test "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 };
912916 const Indexer = EnumIndexer(E);
913917 ensureIndexer(Indexer);
914918 testing.expectEqual(E, Indexer.Key);
......@@ -957,7 +961,8 @@ test "std.enums.EnumSet" {
957961 }
958962
959963 var mut = Set.init(.{
960 .a=true, .c=true,
964 .a = true,
965 .c = true,
961966 });
962967 testing.expectEqual(@as(usize, 2), mut.count());
963968 testing.expectEqual(true, mut.contains(.a));
......@@ -986,7 +991,7 @@ test "std.enums.EnumSet" {
986991 testing.expectEqual(@as(?E, null), it.next());
987992 }
988993
989 mut.toggleSet(Set.init(.{ .a=true, .b=true }));
994 mut.toggleSet(Set.init(.{ .a = true, .b = true }));
990995 testing.expectEqual(@as(usize, 2), mut.count());
991996 testing.expectEqual(true, mut.contains(.a));
992997 testing.expectEqual(false, mut.contains(.b));
......@@ -994,7 +999,7 @@ test "std.enums.EnumSet" {
994999 testing.expectEqual(true, mut.contains(.d));
9951000 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 }));
9981003 testing.expectEqual(@as(usize, 3), mut.count());
9991004 testing.expectEqual(true, mut.contains(.a));
10001005 testing.expectEqual(true, mut.contains(.b));
......@@ -1009,7 +1014,7 @@ test "std.enums.EnumSet" {
10091014 testing.expectEqual(false, mut.contains(.c));
10101015 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 }));
10131018 testing.expectEqual(@as(usize, 1), mut.count());
10141019 testing.expectEqual(true, mut.contains(.a));
10151020 testing.expectEqual(false, mut.contains(.b));
......@@ -1072,7 +1077,7 @@ test "std.enums.EnumArray sized" {
10721077 const undef = Array.initUndefined();
10731078 var inst = Array.initFill(5);
10741079 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
10771082 testing.expectEqual(@as(usize, 5), inst.get(.a));
10781083 testing.expectEqual(@as(usize, 5), inst.get(.b));
......@@ -1272,10 +1277,12 @@ test "std.enums.EnumMap sized" {
12721277 var iter = a.iterator();
12731278 const Entry = Map.Entry;
12741279 testing.expectEqual(@as(?Entry, Entry{
1275 .key = .b, .value = &a.values[1],
1280 .key = .b,
1281 .value = &a.values[1],
12761282 }), iter.next());
12771283 testing.expectEqual(@as(?Entry, Entry{
1278 .key = .d, .value = &a.values[3],
1284 .key = .d,
1285 .value = &a.values[3],
12791286 }), iter.next());
12801287 testing.expectEqual(@as(?Entry, null), iter.next());
12811288}
src/Module.zig+50-48
......@@ -914,16 +914,16 @@ pub const Scope = struct {
914914 parent: *Scope,
915915 /// All `GenZir` scopes for the same ZIR share this.
916916 zir_code: *WipZirCode,
917 /// Keeps track of the list of instructions in this scope only. References
917 /// Keeps track of the list of instructions in this scope only. Indexes
918918 /// to instructions in `zir_code`.
919 instructions: std.ArrayListUnmanaged(zir.Inst.Ref) = .{},
919 instructions: std.ArrayListUnmanaged(zir.Inst.Index) = .{},
920920 label: ?Label = null,
921921 break_block: zir.Inst.Index = 0,
922922 continue_block: zir.Inst.Index = 0,
923923 /// Only valid when setBlockResultLoc is called.
924924 break_result_loc: astgen.ResultLoc = undefined,
925925 /// 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,
927927 /// Keeps track of how many branches of a block did not actually
928928 /// consume the result location. astgen uses this to figure out
929929 /// whether to rely on break instructions or writing to the result
......@@ -1001,8 +1001,8 @@ pub const Scope = struct {
10011001 ret_ty: zir.Inst.Ref,
10021002 cc: zir.Inst.Ref,
10031003 }) !zir.Inst.Ref {
1004 assert(args.ret_ty != 0);
1005 assert(args.cc != 0);
1004 assert(args.ret_ty != .none);
1005 assert(args.cc != .none);
10061006 const gpa = gz.zir_code.gpa;
10071007 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
10081008 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
......@@ -1013,7 +1013,7 @@ pub const Scope = struct {
10131013 .cc = args.cc,
10141014 .param_types_len = @intCast(u32, args.param_types.len),
10151015 });
1016 gz.zir_code.extra.appendSliceAssumeCapacity(args.param_types);
1016 gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args.param_types)));
10171017
10181018 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
10191019 gz.zir_code.instructions.appendAssumeCapacity(.{
......@@ -1024,7 +1024,7 @@ pub const Scope = struct {
10241024 } },
10251025 });
10261026 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);
10281028 }
10291029
10301030 pub fn addFnType(
......@@ -1033,7 +1033,7 @@ pub const Scope = struct {
10331033 ret_ty: zir.Inst.Ref,
10341034 param_types: []const zir.Inst.Ref,
10351035 ) !zir.Inst.Ref {
1036 assert(ret_ty != 0);
1036 assert(ret_ty != .none);
10371037 const gpa = gz.zir_code.gpa;
10381038 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
10391039 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
......@@ -1043,7 +1043,7 @@ pub const Scope = struct {
10431043 const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.FnType{
10441044 .param_types_len = @intCast(u32, param_types.len),
10451045 });
1046 gz.zir_code.extra.appendSliceAssumeCapacity(param_types);
1046 gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(param_types)));
10471047
10481048 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
10491049 gz.zir_code.instructions.appendAssumeCapacity(.{
......@@ -1054,7 +1054,7 @@ pub const Scope = struct {
10541054 } },
10551055 });
10561056 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);
10581058 }
10591059
10601060 pub fn addCall(
......@@ -1065,7 +1065,7 @@ pub const Scope = struct {
10651065 /// Absolute node index. This function does the conversion to offset from Decl.
10661066 src_node: ast.Node.Index,
10671067 ) !zir.Inst.Ref {
1068 assert(callee != 0);
1068 assert(callee != .none);
10691069 assert(src_node != 0);
10701070 const gpa = gz.zir_code.gpa;
10711071 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
......@@ -1077,7 +1077,7 @@ pub const Scope = struct {
10771077 .callee = callee,
10781078 .args_len = @intCast(u32, args.len),
10791079 });
1080 gz.zir_code.extra.appendSliceAssumeCapacity(args);
1080 gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args)));
10811081
10821082 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
10831083 gz.zir_code.instructions.appendAssumeCapacity(.{
......@@ -1088,7 +1088,7 @@ pub const Scope = struct {
10881088 } },
10891089 });
10901090 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);
10921092 }
10931093
10941094 /// Note that this returns a `zir.Inst.Index` not a ref.
......@@ -1098,7 +1098,7 @@ pub const Scope = struct {
10981098 tag: zir.Inst.Tag,
10991099 lhs: zir.Inst.Ref,
11001100 ) !zir.Inst.Index {
1101 assert(lhs != 0);
1101 assert(lhs != .none);
11021102 const gpa = gz.zir_code.gpa;
11031103 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
11041104 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
......@@ -1129,7 +1129,7 @@ pub const Scope = struct {
11291129 /// Absolute node index. This function does the conversion to offset from Decl.
11301130 src_node: ast.Node.Index,
11311131 ) !zir.Inst.Ref {
1132 assert(operand != 0);
1132 assert(operand != .none);
11331133 return gz.add(.{
11341134 .tag = tag,
11351135 .data = .{ .un_node = .{
......@@ -1160,7 +1160,7 @@ pub const Scope = struct {
11601160 } },
11611161 });
11621162 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);
11641164 }
11651165
11661166 pub fn addArrayTypeSentinel(
......@@ -1186,7 +1186,7 @@ pub const Scope = struct {
11861186 } },
11871187 });
11881188 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);
11901190 }
11911191
11921192 pub fn addUnTok(
......@@ -1196,7 +1196,7 @@ pub const Scope = struct {
11961196 /// Absolute token index. This function does the conversion to Decl offset.
11971197 abs_tok_index: ast.TokenIndex,
11981198 ) !zir.Inst.Ref {
1199 assert(operand != 0);
1199 assert(operand != .none);
12001200 return gz.add(.{
12011201 .tag = tag,
12021202 .data = .{ .un_tok = .{
......@@ -1228,8 +1228,8 @@ pub const Scope = struct {
12281228 lhs: zir.Inst.Ref,
12291229 rhs: zir.Inst.Ref,
12301230 ) !zir.Inst.Ref {
1231 assert(lhs != 0);
1232 assert(rhs != 0);
1231 assert(lhs != .none);
1232 assert(rhs != .none);
12331233 return gz.add(.{
12341234 .tag = tag,
12351235 .data = .{ .bin = .{
......@@ -1317,7 +1317,7 @@ pub const Scope = struct {
13171317 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
13181318 gz.zir_code.instructions.appendAssumeCapacity(inst);
13191319 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);
13211321 }
13221322 };
13231323
......@@ -1331,7 +1331,7 @@ pub const Scope = struct {
13311331 parent: *Scope,
13321332 gen_zir: *GenZir,
13331333 name: []const u8,
1334 inst: zir.Inst.Index,
1334 inst: zir.Inst.Ref,
13351335 /// Source location of the corresponding variable declaration.
13361336 src: LazySrcLoc,
13371337 };
......@@ -1346,7 +1346,7 @@ pub const Scope = struct {
13461346 parent: *Scope,
13471347 gen_zir: *GenZir,
13481348 name: []const u8,
1349 ptr: zir.Inst.Index,
1349 ptr: zir.Inst.Ref,
13501350 /// Source location of the corresponding variable declaration.
13511351 src: LazySrcLoc,
13521352 };
......@@ -1366,9 +1366,9 @@ pub const WipZirCode = struct {
13661366 instructions: std.MultiArrayList(zir.Inst) = .{},
13671367 string_bytes: std.ArrayListUnmanaged(u8) = .{},
13681368 extra: std.ArrayListUnmanaged(u32) = .{},
1369 /// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert
1370 /// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.
1371 ref_start_index: u32 = zir.const_inst_list.len,
1369 /// We need to keep track of this count in order to convert between
1370 /// `zir.Inst.Ref` and `zir.Inst.Index` types.
1371 param_count: u32 = 0,
13721372 decl: *Decl,
13731373 gpa: *Allocator,
13741374 arena: *Allocator,
......@@ -1383,15 +1383,18 @@ pub const WipZirCode = struct {
13831383 const fields = std.meta.fields(@TypeOf(extra));
13841384 const result = @intCast(u32, wzc.extra.items.len);
13851385 inline for (fields) |field| {
1386 comptime assert(field.field_type == u32);
1387 wzc.extra.appendAssumeCapacity(@field(extra, field.name));
1386 wzc.extra.appendAssumeCapacity(switch (field.field_type) {
1387 u32 => @field(extra, field.name),
1388 zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
1389 else => unreachable,
1390 });
13881391 }
13891392 return result;
13901393 }
13911394
13921395 pub fn refIsNoReturn(wzc: WipZirCode, zir_inst_ref: zir.Inst.Ref) bool {
1393 if (zir_inst_ref >= wzc.ref_start_index) {
1394 const zir_inst = zir_inst_ref - wzc.ref_start_index;
1396 if (zir_inst_ref == .unreachable_value) return true;
1397 if (zir_inst_ref.toIndex(wzc.param_count)) |zir_inst| {
13951398 return wzc.instructions.items(.tag)[zir_inst].isNoReturn();
13961399 }
13971400 return false;
......@@ -2072,7 +2075,7 @@ fn astgenAndSemaFn(
20722075 // The AST params array does not contain anytype and ... parameters.
20732076 // We must iterate to count how many param types to allocate.
20742077 const param_count = blk: {
2075 var count: usize = 0;
2078 var count: u32 = 0;
20762079 var it = fn_proto.iterate(tree);
20772080 while (it.next()) |param| {
20782081 if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break;
......@@ -2081,7 +2084,6 @@ fn astgenAndSemaFn(
20812084 break :blk count;
20822085 };
20832086 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
20862088 var is_var_args = false;
20872089 {
......@@ -2106,7 +2108,7 @@ fn astgenAndSemaFn(
21062108 const param_type_node = param.type_expr;
21072109 assert(param_type_node != 0);
21082110 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);
21102112 }
21112113 assert(param_type_i == param_count);
21122114 }
......@@ -2178,7 +2180,7 @@ fn astgenAndSemaFn(
21782180 const return_type_inst = try astgen.expr(
21792181 mod,
21802182 &fn_type_scope.base,
2181 type_type_rl,
2183 .{ .ty = .type_type },
21822184 fn_proto.ast.return_type,
21832185 );
21842186
......@@ -2187,19 +2189,22 @@ fn astgenAndSemaFn(
21872189 else
21882190 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)
21912193 // TODO instead of enum literal type, this needs to be the
21922194 // std.builtin.CallingConvention enum. We need to implement importing other files
21932195 // and enums in order to fix this.
2194 try astgen.comptimeExpr(mod, &fn_type_scope.base, .{
2195 .ty = @enumToInt(zir.Const.enum_literal_type),
2196 }, fn_proto.ast.callconv_expr)
2196 try astgen.comptimeExpr(
2197 mod,
2198 &fn_type_scope.base,
2199 .{ .ty = .enum_literal_type },
2200 fn_proto.ast.callconv_expr,
2201 )
21972202 else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269
21982203 try fn_type_scope.addSmallStr(.enum_literal_small, "C")
21992204 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: {
22032208 const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc;
22042209 break :fn_type try fn_type_scope.addFnTypeCc(tag, .{
22052210 .ret_ty = return_type_inst,
......@@ -2292,7 +2297,7 @@ fn astgenAndSemaFn(
22922297 .decl = decl,
22932298 .arena = &decl_arena.allocator,
22942299 .gpa = mod.gpa,
2295 .ref_start_index = @intCast(u32, zir.const_inst_list.len + param_count),
2300 .param_count = param_count,
22962301 };
22972302 defer wip_zir_code.deinit();
22982303
......@@ -2309,7 +2314,7 @@ fn astgenAndSemaFn(
23092314 try wip_zir_code.extra.ensureCapacity(mod.gpa, param_count);
23102315
23112316 var params_scope = &gen_scope.base;
2312 var i: usize = 0;
2317 var i: u32 = 0;
23132318 var it = fn_proto.iterate(tree);
23142319 while (it.next()) |param| : (i += 1) {
23152320 const name_token = param.name_token.?;
......@@ -2320,7 +2325,7 @@ fn astgenAndSemaFn(
23202325 .gen_zir = &gen_scope,
23212326 .name = param_name,
23222327 // 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),
23242329 .src = decl.tokSrcLoc(name_token),
23252330 };
23262331 params_scope = &sub_scope.base;
......@@ -2344,8 +2349,7 @@ fn astgenAndSemaFn(
23442349 // astgen uses result location semantics to coerce return operands.
23452350 // Since we are adding the return instruction here, we must handle the coercion.
23462351 // We do this by using the `ret_coerce` instruction.
2347 const void_inst: zir.Inst.Ref = @enumToInt(zir.Const.void_value);
2348 _ = try gen_scope.addUnTok(.ret_coerce, void_inst, tree.lastToken(body_node));
2352 _ = try gen_scope.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
23492353 }
23502354
23512355 const code = try gen_scope.finish();
......@@ -2514,9 +2518,7 @@ fn astgenAndSemaVarDecl(
25142518 defer gen_scope.instructions.deinit(mod.gpa);
25152519
25162520 const init_result_loc: astgen.ResultLoc = if (var_decl.ast.type_node != 0) .{
2517 .ty = try astgen.expr(mod, &gen_scope.base, .{
2518 .ty = @enumToInt(zir.Const.type_type),
2519 }, var_decl.ast.type_node),
2521 .ty = try astgen.expr(mod, &gen_scope.base, .{ .ty = .type_type }, var_decl.ast.type_node),
25202522 } else .none;
25212523
25222524 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 {
7878/// return type of `analyzeBody` so that we can tail call them.
7979/// Only appropriate to return when the instruction is known to be NoReturn
8080/// 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
8383/// This function is the main loop of `Sema` and it can be used in two different ways:
8484/// * 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);
8888/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_flat`
8989/// instruction. In this case, the `zir.Inst.Index` part of the return value will be
9090/// 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 {
9292 // No tracy calls here, to avoid interfering with the tail call mechanism.
9393
9494 const map = block.sema.inst_map;
......@@ -300,28 +300,18 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde
300300}
301301
302302/// 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.
303304pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {
304 var i: usize = zir_ref;
305
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]);
305 if (zir_ref.toTypedValue()) |typed_value| {
306 return sema.mod.constInst(sema.arena, .unneeded, typed_value);
314307 }
315 i -= zir.const_inst_list.len;
316308
317 // Next section of indexes correspond to function parameters, if any.
318 if (i < sema.param_inst_list.len) {
319 return sema.param_inst_list[i];
309 const param_count = @intCast(u32, sema.param_inst_list.len);
310 if (zir_ref.toParam(param_count)) |param| {
311 return sema.param_inst_list[param];
320312 }
321 i -= sema.param_inst_list.len;
322313
323 // Finally, the last section of indexes refers to the map of ZIR=>TZIR.
324 return sema.inst_map[i];
314 return sema.inst_map[zir_ref.toIndex(param_count).?];
325315}
326316
327317fn resolveConstString(
......@@ -745,7 +735,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
745735 return sema.mod.constIntUnsigned(sema.arena, .unneeded, Type.initTag(.comptime_int), int);
746736}
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 {
749739 const tracy = trace(@src());
750740 defer tracy.end();
751741
......@@ -763,7 +753,10 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
763753
764754 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
765755 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| {
767760 if (i != 0) try writer.print(", ", .{});
768761
769762 const arg = try sema.resolveInst(arg_ref);
......@@ -998,7 +991,7 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
998991 _ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
999992}
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 {
1002995 const tracy = trace(@src());
1003996 defer tracy.end();
1004997
......@@ -1007,7 +1000,7 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!z
10071000 return sema.analyzeBreak(block, sema.src, inst_data.block_inst, operand);
10081001}
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 {
10111004 const tracy = trace(@src());
10121005 defer tracy.end();
10131006
......@@ -1112,7 +1105,8 @@ fn zirCall(
11121105 const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
11131106 const call_src = inst_data.src();
11141107 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
11171111 return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args);
11181112}
......@@ -1739,7 +1733,8 @@ fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: b
17391733
17401734 const inst_data = sema.code.instructions.items(.data)[inst].fn_type;
17411735 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
17441739 return sema.fnTypeCommon(
17451740 block,
......@@ -1757,7 +1752,8 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args:
17571752
17581753 const inst_data = sema.code.instructions.items(.data)[inst].fn_type;
17591754 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
17621758 const cc_tv = try sema.resolveInstConst(block, .todo, extra.data.cc);
17631759 // TODO once we're capable of importing and analyzing decls from
......@@ -2487,7 +2483,7 @@ fn zirNegate(
24872483 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
24882484 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
24892485 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);
24912487 const rhs = try sema.resolveInst(inst_data.operand);
24922488
24932489 return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src);
......@@ -2641,7 +2637,7 @@ fn zirAsm(
26412637
26422638 var extra_i = extra.end;
26432639 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: {
26452641 const name = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
26462642 extra_i += 1;
26472643 break :blk Output{
......@@ -2655,7 +2651,7 @@ fn zirAsm(
26552651 const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len);
26562652
26572653 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]));
26592655 extra_i += 1;
26602656 }
26612657 for (inputs) |*name| {
......@@ -2772,11 +2768,13 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
27722768 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
27732769 const src = inst_data.src();
27742770 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
27762774 const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len);
27772775 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| {
27802778 inst_list[i] = try sema.resolveInst(arg_ref);
27812779 }
27822780
......@@ -3115,25 +3113,25 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
31153113 var extra_i = extra.end;
31163114
31173115 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]);
31193117 extra_i += 1;
31203118 break :blk (try sema.resolveInstConst(block, .unneeded, ref)).val;
31213119 } else null;
31223120
31233121 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]);
31253123 extra_i += 1;
31263124 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32);
31273125 } else 0;
31283126
31293127 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]);
31313129 extra_i += 1;
31323130 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
31333131 } else 0;
31343132
31353133 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]);
31373135 extra_i += 1;
31383136 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
31393137 } else 0;
src/astgen.zig+85-106
......@@ -58,11 +58,8 @@ pub const ResultLoc = union(enum) {
5858 };
5959};
6060
61const void_inst: zir.Inst.Ref = @enumToInt(zir.Const.void_value);
62
6361pub 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) };
65 return expr(mod, scope, type_rl, type_node);
62 return expr(mod, scope, .{ .ty = .type_type }, type_node);
6663}
6764
6865fn 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
291288
292289 .assign => {
293290 try assign(mod, scope, node);
294 return rvalue(mod, scope, rl, void_inst, node);
291 return rvalue(mod, scope, rl, .void_value, node);
295292 },
296293 .assign_bit_and => {
297294 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);
299296 },
300297 .assign_bit_or => {
301298 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);
303300 },
304301 .assign_bit_shift_left => {
305302 try assignOp(mod, scope, node, .shl);
306 return rvalue(mod, scope, rl, void_inst, node);
303 return rvalue(mod, scope, rl, .void_value, node);
307304 },
308305 .assign_bit_shift_right => {
309306 try assignOp(mod, scope, node, .shr);
310 return rvalue(mod, scope, rl, void_inst, node);
307 return rvalue(mod, scope, rl, .void_value, node);
311308 },
312309 .assign_bit_xor => {
313310 try assignOp(mod, scope, node, .xor);
314 return rvalue(mod, scope, rl, void_inst, node);
311 return rvalue(mod, scope, rl, .void_value, node);
315312 },
316313 .assign_div => {
317314 try assignOp(mod, scope, node, .div);
318 return rvalue(mod, scope, rl, void_inst, node);
315 return rvalue(mod, scope, rl, .void_value, node);
319316 },
320317 .assign_sub => {
321318 try assignOp(mod, scope, node, .sub);
322 return rvalue(mod, scope, rl, void_inst, node);
319 return rvalue(mod, scope, rl, .void_value, node);
323320 },
324321 .assign_sub_wrap => {
325322 try assignOp(mod, scope, node, .subwrap);
326 return rvalue(mod, scope, rl, void_inst, node);
323 return rvalue(mod, scope, rl, .void_value, node);
327324 },
328325 .assign_mod => {
329326 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);
331328 },
332329 .assign_add => {
333330 try assignOp(mod, scope, node, .add);
334 return rvalue(mod, scope, rl, void_inst, node);
331 return rvalue(mod, scope, rl, .void_value, node);
335332 },
336333 .assign_add_wrap => {
337334 try assignOp(mod, scope, node, .addwrap);
338 return rvalue(mod, scope, rl, void_inst, node);
335 return rvalue(mod, scope, rl, .void_value, node);
339336 },
340337 .assign_mul => {
341338 try assignOp(mod, scope, node, .mul);
342 return rvalue(mod, scope, rl, void_inst, node);
339 return rvalue(mod, scope, rl, .void_value, node);
343340 },
344341 .assign_mul_wrap => {
345342 try assignOp(mod, scope, node, .mulwrap);
346 return rvalue(mod, scope, rl, void_inst, node);
343 return rvalue(mod, scope, rl, .void_value, node);
347344 },
348345
349346 .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
450447 const result = try expr(mod, scope, .ref, node_datas[node].lhs);
451448 return rvalue(mod, scope, rl, result, node);
452449 },
453 .undefined_literal => {
454 const result = @enumToInt(zir.Const.undef);
455 return rvalue(mod, scope, rl, result, node);
456 },
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 },
450 .undefined_literal => return rvalue(mod, scope, rl, .undef, node),
451 .true_literal => return rvalue(mod, scope, rl, .bool_true, node),
452 .false_literal => return rvalue(mod, scope, rl, .bool_false, node),
453 .null_literal => return rvalue(mod, scope, rl, .null_value, node),
469454 .optional_type => {
470455 const operand = try typeExpr(mod, scope, node_datas[node].lhs);
471456 const result = try gz.addUnNode(.optional_type, operand, node);
......@@ -830,7 +815,7 @@ pub fn blockExpr(
830815 }
831816
832817 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);
834819}
835820
836821fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIndex) !void {
......@@ -935,13 +920,13 @@ fn labeledBlockExpr(
935920 // The code took advantage of the result location as a pointer.
936921 // Turn the break instruction operands into void.
937922 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;
939924 }
940925 // TODO technically not needed since we changed the tag to break_void but
941926 // would be better still to elide the ones that are in this list.
942927 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);
945930 },
946931 .break_operand => {
947932 // All break operands are values that did not use the result location pointer.
......@@ -954,7 +939,7 @@ fn labeledBlockExpr(
954939 // would be better still to elide the ones that are in this list.
955940 }
956941 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);
958943 switch (rl) {
959944 .ref => return block_ref,
960945 else => return rvalue(mod, parent_scope, rl, block_ref, block_node),
......@@ -1006,8 +991,7 @@ fn blockExprStmts(
1006991 // We need to emit an error if the result is not `noreturn` or `void`, but
1007992 // we want to avoid adding the ZIR instruction if possible for performance.
1008993 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: {
1010 const inst = maybe_unused_result - gz.zir_code.ref_start_index;
994 const elide_check = if (maybe_unused_result.toIndex(gz.zir_code.param_count)) |inst| b: {
1011995 // Note that this array becomes invalid after appending more items to it
1012996 // in the above while loop.
1013997 const zir_tags = gz.zir_code.instructions.items(.tag);
......@@ -1167,10 +1151,10 @@ fn blockExprStmts(
11671151 => break :b true,
11681152 }
11691153 } else switch (maybe_unused_result) {
1170 @enumToInt(zir.Const.unused) => unreachable,
1154 .none => unreachable,
11711155
1172 @enumToInt(zir.Const.void_value),
1173 @enumToInt(zir.Const.unreachable_value),
1156 .void_value,
1157 .unreachable_value,
11741158 => true,
11751159
11761160 else => false,
......@@ -1283,8 +1267,8 @@ fn varDecl(
12831267 };
12841268 defer init_scope.instructions.deinit(mod.gpa);
12851269
1286 var resolve_inferred_alloc: zir.Inst.Ref = 0;
1287 var opt_type_inst: zir.Inst.Ref = 0;
1270 var resolve_inferred_alloc: zir.Inst.Ref = .none;
1271 var opt_type_inst: zir.Inst.Ref = .none;
12881272 if (var_decl.ast.type_node != 0) {
12891273 const type_inst = try typeExpr(mod, &init_scope.base, var_decl.ast.type_node);
12901274 opt_type_inst = type_inst;
......@@ -1308,14 +1292,14 @@ fn varDecl(
13081292 const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2;
13091293 try parent_zir.ensureCapacity(mod.gpa, expected_len);
13101294 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;
13121296 if (zir_tags[src_inst] == .store_to_block_ptr) {
13131297 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;
13141298 }
13151299 parent_zir.appendAssumeCapacity(src_inst);
13161300 }
13171301 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)
13191303 try gz.addPlNode(.as_node, var_decl.ast.type_node, zir.Inst.As{
13201304 .dest_type = opt_type_inst,
13211305 .operand = init_inst,
......@@ -1348,7 +1332,7 @@ fn varDecl(
13481332 parent_zir.appendAssumeCapacity(src_inst);
13491333 }
13501334 assert(parent_zir.items.len == expected_len);
1351 if (resolve_inferred_alloc != 0) {
1335 if (resolve_inferred_alloc != .none) {
13521336 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
13531337 }
13541338 const sub_scope = try block_arena.create(Scope.LocalPtr);
......@@ -1362,7 +1346,7 @@ fn varDecl(
13621346 return &sub_scope.base;
13631347 },
13641348 .keyword_var => {
1365 var resolve_inferred_alloc: zir.Inst.Ref = 0;
1349 var resolve_inferred_alloc: zir.Inst.Ref = .none;
13661350 const var_data: struct {
13671351 result_loc: ResultLoc,
13681352 alloc: zir.Inst.Ref,
......@@ -1377,7 +1361,7 @@ fn varDecl(
13771361 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
13781362 };
13791363 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) {
13811365 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
13821366 }
13831367 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
14401424 const tree = scope.tree();
14411425 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);
14441428 const gz = scope.getGenZir();
14451429 const result = try gz.addUnNode(.bool_not, operand, node);
14461430 return rvalue(mod, scope, rl, result, node);
......@@ -1501,10 +1485,10 @@ fn ptrType(
15011485 return rvalue(mod, scope, rl, result, node);
15021486 }
15031487
1504 var sentinel_ref: zir.Inst.Ref = 0;
1505 var align_ref: zir.Inst.Ref = 0;
1506 var bit_start_ref: zir.Inst.Ref = 0;
1507 var bit_end_ref: zir.Inst.Ref = 0;
1488 var sentinel_ref: zir.Inst.Ref = .none;
1489 var align_ref: zir.Inst.Ref = .none;
1490 var bit_start_ref: zir.Inst.Ref = .none;
1491 var bit_end_ref: zir.Inst.Ref = .none;
15081492 var trailing_count: u32 = 0;
15091493
15101494 if (ptr_info.ast.sentinel != 0) {
......@@ -1529,24 +1513,28 @@ fn ptrType(
15291513 @typeInfo(zir.Inst.PtrType).Struct.fields.len + trailing_count);
15301514
15311515 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);
1533 if (align_ref != 0) gz.zir_code.extra.appendAssumeCapacity(align_ref);
1534 if (bit_start_ref != 0) {
1535 gz.zir_code.extra.appendAssumeCapacity(bit_start_ref);
1536 gz.zir_code.extra.appendAssumeCapacity(bit_end_ref);
1516 if (sentinel_ref != .none) {
1517 gz.zir_code.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));
1518 }
1519 if (align_ref != .none) {
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));
15371525 }
15381526
15391527 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);
15411529 gz.zir_code.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{
15421530 .ptr_type = .{
15431531 .flags = .{
15441532 .is_allowzero = ptr_info.allowzero_token != null,
15451533 .is_mutable = ptr_info.const_token == null,
15461534 .is_volatile = ptr_info.volatile_token != null,
1547 .has_sentinel = sentinel_ref != 0,
1548 .has_align = align_ref != 0,
1549 .has_bit_range = bit_start_ref != 0,
1535 .has_sentinel = sentinel_ref != .none,
1536 .has_align = align_ref != .none,
1537 .has_bit_range = bit_start_ref != .none,
15501538 },
15511539 .size = ptr_info.size,
15521540 .payload_index = payload_index,
......@@ -1561,10 +1549,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !
15611549 const tree = scope.tree();
15621550 const node_datas = tree.nodes.items(.data);
15631551 const gz = scope.getGenZir();
1564 const usize_type = @enumToInt(zir.Const.usize_type);
15651552
15661553 // 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);
15681555 const elem_type = try typeExpr(mod, scope, node_datas[node].rhs);
15691556
15701557 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.
15761563 const node_datas = tree.nodes.items(.data);
15771564 const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
15781565 const gz = scope.getGenZir();
1579 const usize_type = @enumToInt(zir.Const.usize_type);
15801566
15811567 // 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);
15831569 const elem_type = try typeExpr(mod, scope, extra.elem_type);
15841570 const sentinel = try expr(mod, scope, .{ .ty = elem_type }, extra.sentinel);
15851571
......@@ -1784,7 +1770,7 @@ fn finishThenElseBlock(
17841770 } },
17851771 });
17861772 }
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;
17881774 if (!elide_else) {
17891775 _ = try else_scope.add(.{
17901776 .tag = .break_void_node,
......@@ -1796,7 +1782,7 @@ fn finishThenElseBlock(
17961782 }
17971783 assert(!strat.elide_store_to_block_ptr_instructions);
17981784 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);
18001786 },
18011787 .break_operand => {
18021788 if (!wzc.refIsNoReturn(then_result)) {
......@@ -1808,7 +1794,7 @@ fn finishThenElseBlock(
18081794 } },
18091795 });
18101796 }
1811 if (else_result != 0) {
1797 if (else_result != .none) {
18121798 if (!wzc.refIsNoReturn(else_result)) {
18131799 _ = try else_scope.add(.{
18141800 .tag = .@"break",
......@@ -1832,7 +1818,7 @@ fn finishThenElseBlock(
18321818 } else {
18331819 try setCondBrPayload(condbr, cond, then_scope, else_scope);
18341820 }
1835 const block_ref = wzc.ref_start_index + main_block;
1821 const block_ref = zir.Inst.Ref.fromIndex(main_block, wzc.param_count);
18361822 switch (rl) {
18371823 .ref => return block_ref,
18381824 else => return rvalue(mod, parent_scope, rl, block_ref, node),
......@@ -1981,9 +1967,8 @@ fn boolBinOp(
19811967) InnerError!zir.Inst.Ref {
19821968 const gz = scope.getGenZir();
19831969 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);
19871972 const bool_br = try gz.addBoolBr(zir_tag, lhs);
19881973
19891974 var rhs_scope: Scope.GenZir = .{
......@@ -1992,11 +1977,11 @@ fn boolBinOp(
19921977 .force_comptime = gz.force_comptime,
19931978 };
19941979 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);
19961981 _ = try rhs_scope.addUnNode(.break_flat, rhs, node);
19971982 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);
20001985 return rvalue(mod, scope, rl, block_ref, node);
20011986}
20021987
......@@ -2024,8 +2009,7 @@ fn ifExpr(
20242009 } else if (if_full.payload_token) |payload_token| {
20252010 return mod.failTok(scope, payload_token, "TODO implement if optional", .{});
20262011 } else {
2027 const bool_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.bool_type) };
2028 break :c try expr(mod, &block_scope.base, bool_rl, if_full.ast.cond_expr);
2012 break :c try expr(mod, &block_scope.base, .{ .ty = .bool_type }, if_full.ast.cond_expr);
20292013 }
20302014 };
20312015
......@@ -2073,7 +2057,7 @@ fn ifExpr(
20732057 };
20742058 } else .{
20752059 .src = if_full.ast.then_expr,
2076 .result = 0,
2060 .result = .none,
20772061 };
20782062
20792063 return finishThenElseBlock(
......@@ -2185,7 +2169,7 @@ fn whileExpr(
21852169 } else if (while_full.payload_token) |payload_token| {
21862170 return mod.failTok(scope, payload_token, "TODO implement while optional", .{});
21872171 } else {
2188 const bool_type_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.bool_type) };
2172 const bool_type_rl: ResultLoc = .{ .ty = .bool_type };
21892173 break :c try expr(mod, &continue_scope.base, bool_type_rl, while_full.ast.cond_expr);
21902174 }
21912175 };
......@@ -2200,8 +2184,7 @@ fn whileExpr(
22002184 // and there are no `continue` statements.
22012185 // The "repeat" at the end of a loop body is implied.
22022186 if (while_full.ast.cont_expr != 0) {
2203 const void_type_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.void_type) };
2204 _ = try expr(mod, &loop_scope.base, void_type_rl, while_full.ast.cont_expr);
2187 _ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);
22052188 }
22062189 const is_inline = while_full.inline_token != null;
22072190 const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
......@@ -2251,7 +2234,7 @@ fn whileExpr(
22512234 };
22522235 } else .{
22532236 .src = while_full.ast.then_expr,
2254 .result = 0,
2237 .result = .none,
22552238 };
22562239
22572240 if (loop_scope.label) |some| {
......@@ -2838,7 +2821,7 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Re
28382821 .ty = try gz.addNode(.ret_type, node),
28392822 };
28402823 break :operand try expr(mod, scope, rl, operand_node);
2841 } else void_inst;
2824 } else .void_value;
28422825 return gz.addUnNode(.ret_node, operand, node);
28432826}
28442827
......@@ -2862,8 +2845,8 @@ fn identifier(
28622845 return mod.failNode(scope, ident, "TODO implement '_' identifier", .{});
28632846 }
28642847
2865 if (simple_types.get(ident_name)) |zir_const_tag| {
2866 return rvalue(mod, scope, rl, @enumToInt(zir_const_tag), ident);
2848 if (simple_types.get(ident_name)) |zir_const_ref| {
2849 return rvalue(mod, scope, rl, zir_const_ref, ident);
28672850 }
28682851
28692852 if (ident_name.len >= 2) integer: {
......@@ -3028,9 +3011,9 @@ fn integerLiteral(
30283011 const prefixed_bytes = tree.tokenSlice(int_token);
30293012 const gz = scope.getGenZir();
30303013 if (std.fmt.parseInt(u64, prefixed_bytes, 0)) |small_int| {
3031 const result: zir.Inst.Index = switch (small_int) {
3032 0 => @enumToInt(zir.Const.zero),
3033 1 => @enumToInt(zir.Const.one),
3014 const result: zir.Inst.Ref = switch (small_int) {
3015 0 => .zero,
3016 1 => .one,
30343017 else => try gz.addInt(small_int),
30353018 };
30363019 return rvalue(mod, scope, rl, result, node);
......@@ -3078,14 +3061,11 @@ fn asmExpr(
30783061 const node_datas = tree.nodes.items(.data);
30793062 const gz = scope.getGenZir();
30803063
3081 const str_type = @enumToInt(zir.Const.const_slice_u8_type);
3082 const str_type_rl: ResultLoc = .{ .ty = str_type };
3083 const asm_source = try expr(mod, scope, str_type_rl, full.ast.template);
3064 const asm_source = try expr(mod, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);
30843065
30853066 if (full.outputs.len != 0) {
30863067 return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{});
30873068 }
3088 const return_type = @enumToInt(zir.Const.void_type);
30893069
30903070 const constraints = try arena.alloc(u32, full.inputs.len);
30913071 const args = try arena.alloc(zir.Inst.Ref, full.inputs.len);
......@@ -3098,22 +3078,21 @@ fn asmExpr(
30983078 try mod.parseStrLit(scope, constraint_token, string_bytes, token_bytes, 0);
30993079 try string_bytes.append(mod.gpa, 0);
31003080
3101 const usize_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.usize_type) };
3102 args[i] = try expr(mod, scope, usize_rl, node_datas[input].lhs);
3081 args[i] = try expr(mod, scope, .{ .ty = .usize_type }, node_datas[input].lhs);
31033082 }
31043083
31053084 const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm";
31063085 const result = try gz.addPlNode(tag, node, zir.Inst.Asm{
31073086 .asm_source = asm_source,
3108 .return_type = return_type,
3109 .output = 0,
3087 .return_type = .void_type,
3088 .output = .none,
31103089 .args_len = @intCast(u32, full.inputs.len),
31113090 .clobbers_len = 0, // TODO implement asm clobbers
31123091 });
31133092
31143093 try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len +
31153094 args.len + constraints.len);
3116 gz.zir_code.extra.appendSliceAssumeCapacity(args);
3095 gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args)));
31173096 gz.zir_code.extra.appendSliceAssumeCapacity(constraints);
31183097
31193098 return rvalue(mod, scope, rl, result, node);
......@@ -3185,7 +3164,7 @@ fn asRlPtr(
31853164 const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2;
31863165 try parent_zir.ensureCapacity(mod.gpa, expected_len);
31873166 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;
31893168 if (zir_tags[src_inst] == .store_to_block_ptr) {
31903169 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;
31913170 }
......@@ -3272,11 +3251,12 @@ fn typeOf(
32723251 }
32733252 const arena = scope.arena();
32743253 var items = try arena.alloc(zir.Inst.Ref, params.len);
3275 for (params) |param, param_i|
3254 for (params) |param, param_i| {
32763255 items[param_i] = try expr(mod, scope, .none, param);
3256 }
32773257
32783258 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
32813261 return rvalue(mod, scope, rl, result, node);
32823262}
......@@ -3351,8 +3331,7 @@ fn builtinCall(
33513331 return rvalue(mod, scope, rl, result, node);
33523332 },
33533333 .set_eval_branch_quota => {
3354 const u32_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.u32_type) };
3355 const quota = try expr(mod, scope, u32_rl, params[0]);
3334 const quota = try expr(mod, scope, .{ .ty = .u32_type }, params[0]);
33563335 const result = try gz.addUnNode(.set_eval_branch_quota, quota, node);
33573336 return rvalue(mod, scope, rl, result, node);
33583337 },
......@@ -3498,7 +3477,7 @@ fn callExpr(
34983477 }
34993478 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);
35023481 defer mod.gpa.free(args);
35033482
35043483 const gz = scope.getGenZir();
......@@ -3517,7 +3496,7 @@ fn callExpr(
35173496 true => .async_kw,
35183497 false => .auto,
35193498 };
3520 const result: zir.Inst.Index = res: {
3499 const result: zir.Inst.Ref = res: {
35213500 const tag: zir.Inst.Tag = switch (modifier) {
35223501 .auto => switch (args.len == 0) {
35233502 true => break :res try gz.addUnNode(.call_none, lhs, node),
......@@ -3536,7 +3515,7 @@ fn callExpr(
35363515 return rvalue(mod, scope, rl, result, node); // TODO function call with result location
35373516}
35383517
3539pub const simple_types = std.ComptimeStringMap(zir.Const, .{
3518pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{
35403519 .{ "u8", .u8_type },
35413520 .{ "i8", .i8_type },
35423521 .{ "u16", .u16_type },
src/zir.zig+333-300
......@@ -48,8 +48,11 @@ pub const Code = struct {
4848 var i: usize = index;
4949 var result: T = undefined;
5050 inline for (fields) |field| {
51 comptime assert(field.field_type == u32);
52 @field(result, field.name) = code.extra[i];
51 @field(result, field.name) = switch (field.field_type) {
52 u32 => code.extra[i],
53 Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
54 else => unreachable,
55 };
5356 i += 1;
5457 }
5558 return .{
......@@ -105,284 +108,6 @@ pub const Code = struct {
105108 }
106109};
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
386111/// These are untyped instructions generated from an Abstract Syntax Tree.
387112/// The data here is immutable because it is possible to have multiple
388113/// analyses on the same ZIR happening at the same time.
......@@ -1032,14 +757,319 @@ pub const Inst = struct {
1032757 /// The position of a ZIR instruction within the `Code` instructions array.
1033758 pub const Index = u32;
1034759
1035 /// A reference to another ZIR instruction. If this value is below a certain
1036 /// threshold, it implicitly refers to a constant-known value from the `Const` enum.
1037 /// Below a second threshold, it implicitly refers to a parameter of the current
1038 /// function.
1039 /// Finally, after subtracting that offset, it refers to another instruction in
1040 /// the instruction array.
1041 /// This logic is implemented in `Sema.resolveRef`.
1042 pub const Ref = u32;
760 /// A reference to a TypedValue, parameter of the current function,
761 /// or ZIR instruction.
762 ///
763 /// If the Ref has a tag in this enum, it refers to a TypedValue which may be
764 /// retrieved with Ref.toTypedValue().
765 ///
766 /// If the value of a Ref does not have a tag, it referes to either a parameter
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
10441074 /// All instructions have an 8-byte payload, which is contained within
10451075 /// this union. `Tag` determines which union field is active, as well as
......@@ -1642,7 +1672,9 @@ const Writer = struct {
16421672 fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void {
16431673 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
16441674 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
16461678 try self.writeInstRef(stream, extra.data.callee);
16471679 try stream.writeAll(", [");
16481680 for (args) |arg, i| {
......@@ -1735,9 +1767,9 @@ const Writer = struct {
17351767 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
17361768 const inst_data = self.code.instructions.items(.data)[inst].fn_type;
17371769 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];
1739 const cc: Inst.Ref = 0;
1740 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
1770 const raw_param_types = self.code.extra[extra.end..][0..extra.data.param_types_len];
1771 const param_types = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_param_types));
1772 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, .none);
17411773 }
17421774
17431775 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
......@@ -1761,7 +1793,8 @@ const Writer = struct {
17611793 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
17621794 const inst_data = self.code.instructions.items(.data)[inst].fn_type;
17631795 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));
17651798 const cc = extra.data.cc;
17661799 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
17671800 }
......@@ -1828,13 +1861,13 @@ const Writer = struct {
18281861 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
18291862 }
18301863
1831 fn writeInstRef(self: *Writer, stream: anytype, inst: Inst.Ref) !void {
1832 var i: usize = inst;
1864 fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {
1865 var i: usize = @enumToInt(ref);
18331866
1834 if (i < const_inst_list.len) {
1835 return stream.print("@{d}", .{i});
1867 if (i < Inst.Ref.typed_value_count) {
1868 return stream.print("@{}", .{ref});
18361869 }
1837 i -= const_inst_list.len;
1870 i -= Inst.Ref.typed_value_count;
18381871
18391872 if (i < self.param_count) {
18401873 return stream.print("${d}", .{i});
......@@ -1852,9 +1885,9 @@ const Writer = struct {
18521885 self: *Writer,
18531886 stream: anytype,
18541887 prefix: []const u8,
1855 inst: Inst.Index,
1888 inst: Inst.Ref,
18561889 ) !void {
1857 if (inst == 0) return;
1890 if (inst == .none) return;
18581891 try stream.writeAll(prefix);
18591892 try self.writeInstRef(stream, inst);
18601893 }