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