authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-02 17:08:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-02 17:08:19-07:00
loga973c362e5de460bf44bf513d97daa2c79570733
tree9fe122773ac29cf54878ead7011941330551b83e
parentd5f77c0babb83e5e9d651fa96b84f374dd3f0c57

AstGen: decouple from Module/Compilation

AstGen is now completely independent from the rest of the compiler. It ingests an AST tree and produces ZIR code as the output, without depending on any of the glue code of the compiler.

6 files changed, 1164 insertions(+), 1203 deletions(-)

BRANCH_TODO-1
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1 * implement lazy struct field resolution; don't resolve struct fields until1 * implement lazy struct field resolution; don't resolve struct fields until
2 they are needed.2 they are needed.
3 * decouple AstGen from Module, Compilation
4 * AstGen threadlocal3 * AstGen threadlocal
5 * extern "foo" for vars and for functions4 * extern "foo" for vars and for functions
6 * namespace decls table can't reference ZIR memory because it can get modified on updates5 * namespace decls table can't reference ZIR memory because it can get modified on updates
src/AstGen.zig+1056-247
...@@ -13,17 +13,11 @@ const assert = std.debug.assert;...@@ -13,17 +13,11 @@ const assert = std.debug.assert;
13const ArrayListUnmanaged = std.ArrayListUnmanaged;13const ArrayListUnmanaged = std.ArrayListUnmanaged;
1414
15const Zir = @import("Zir.zig");15const Zir = @import("Zir.zig");
16const Module = @import("Module.zig");
17const trace = @import("tracy.zig").trace;16const trace = @import("tracy.zig").trace;
18const Scope = Module.Scope;
19const GenZir = Scope.GenZir;
20const InnerError = Module.InnerError;
21const Decl = Module.Decl;
22const LazySrcLoc = Module.LazySrcLoc;
23const BuiltinFn = @import("BuiltinFn.zig");17const BuiltinFn = @import("BuiltinFn.zig");
2418
25gpa: *Allocator,19gpa: *Allocator,
26file: *Scope.File,20tree: *const ast.Tree,
27instructions: std.MultiArrayList(Zir.Inst) = .{},21instructions: std.MultiArrayList(Zir.Inst) = .{},
28extra: ArrayListUnmanaged(u32) = .{},22extra: ArrayListUnmanaged(u32) = .{},
29string_bytes: ArrayListUnmanaged(u8) = .{},23string_bytes: ArrayListUnmanaged(u8) = .{},
...@@ -37,13 +31,15 @@ fn_block: ?*GenZir = null,...@@ -37,13 +31,15 @@ fn_block: ?*GenZir = null,
37/// String table indexes, keeps track of all `@import` operands.31/// String table indexes, keeps track of all `@import` operands.
38imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},32imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
3933
40pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {34const InnerError = error{ OutOfMemory, AnalysisFail };
35
36fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
41 const fields = std.meta.fields(@TypeOf(extra));37 const fields = std.meta.fields(@TypeOf(extra));
42 try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len);38 try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len);
43 return addExtraAssumeCapacity(astgen, extra);39 return addExtraAssumeCapacity(astgen, extra);
44}40}
4541
46pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {42fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
47 const fields = std.meta.fields(@TypeOf(extra));43 const fields = std.meta.fields(@TypeOf(extra));
48 const result = @intCast(u32, astgen.extra.items.len);44 const result = @intCast(u32, astgen.extra.items.len);
49 inline for (fields) |field| {45 inline for (fields) |field| {
...@@ -57,24 +53,24 @@ pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {...@@ -57,24 +53,24 @@ pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
57 return result;53 return result;
58}54}
5955
60pub fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void {56fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void {
61 const coerced = @bitCast([]const u32, refs);57 const coerced = @bitCast([]const u32, refs);
62 return astgen.extra.appendSlice(astgen.gpa, coerced);58 return astgen.extra.appendSlice(astgen.gpa, coerced);
63}59}
6460
65pub fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void {61fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void {
66 const coerced = @bitCast([]const u32, refs);62 const coerced = @bitCast([]const u32, refs);
67 astgen.extra.appendSliceAssumeCapacity(coerced);63 astgen.extra.appendSliceAssumeCapacity(coerced);
68}64}
6965
70pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {66pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
71 var arena = std.heap.ArenaAllocator.init(gpa);67 var arena = std.heap.ArenaAllocator.init(gpa);
72 defer arena.deinit();68 defer arena.deinit();
7369
74 var astgen: AstGen = .{70 var astgen: AstGen = .{
75 .gpa = gpa,71 .gpa = gpa,
76 .arena = &arena.allocator,72 .arena = &arena.allocator,
77 .file = file,73 .tree = &tree,
78 };74 };
79 defer astgen.deinit(gpa);75 defer astgen.deinit(gpa);
8076
...@@ -83,16 +79,16 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {...@@ -83,16 +79,16 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
8379
84 // We expect at least as many ZIR instructions and extra data items80 // We expect at least as many ZIR instructions and extra data items
85 // as AST nodes.81 // as AST nodes.
86 try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len);82 try astgen.instructions.ensureTotalCapacity(gpa, tree.nodes.len);
8783
88 // First few indexes of extra are reserved and set at the end.84 // First few indexes of extra are reserved and set at the end.
89 const reserved_count = @typeInfo(Zir.ExtraIndex).Enum.fields.len;85 const reserved_count = @typeInfo(Zir.ExtraIndex).Enum.fields.len;
90 try astgen.extra.ensureTotalCapacity(gpa, file.tree.nodes.len + reserved_count);86 try astgen.extra.ensureTotalCapacity(gpa, tree.nodes.len + reserved_count);
91 astgen.extra.items.len += reserved_count;87 astgen.extra.items.len += reserved_count;
9288
93 var gen_scope: GenZir = .{89 var gen_scope: GenZir = .{
94 .force_comptime = true,90 .force_comptime = true,
95 .parent = &file.base,91 .parent = null,
96 .decl_node_index = 0,92 .decl_node_index = 0,
97 .decl_line = 0,93 .decl_line = 0,
98 .astgen = &astgen,94 .astgen = &astgen,
...@@ -104,7 +100,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {...@@ -104,7 +100,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
104 .ast = .{100 .ast = .{
105 .main_token = undefined,101 .main_token = undefined,
106 .enum_token = null,102 .enum_token = null,
107 .members = file.tree.rootDecls(),103 .members = tree.rootDecls(),
108 .arg = 0,104 .arg = 0,
109 },105 },
110 };106 };
...@@ -250,7 +246,7 @@ pub const ResultLoc = union(enum) {...@@ -250,7 +246,7 @@ pub const ResultLoc = union(enum) {
250pub const align_rl: ResultLoc = .{ .ty = .u16_type };246pub const align_rl: ResultLoc = .{ .ty = .u16_type };
251pub const bool_rl: ResultLoc = .{ .ty = .bool_type };247pub const bool_rl: ResultLoc = .{ .ty = .bool_type };
252248
253pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref {249fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref {
254 const prev_force_comptime = gz.force_comptime;250 const prev_force_comptime = gz.force_comptime;
255 gz.force_comptime = true;251 gz.force_comptime = true;
256 const e = expr(gz, scope, .{ .ty = .type_type }, type_node);252 const e = expr(gz, scope, .{ .ty = .type_type }, type_node);
...@@ -260,7 +256,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro...@@ -260,7 +256,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro
260256
261fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {257fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
262 const astgen = gz.astgen;258 const astgen = gz.astgen;
263 const tree = &astgen.file.tree;259 const tree = astgen.tree;
264 const node_tags = tree.nodes.items(.tag);260 const node_tags = tree.nodes.items(.tag);
265 const main_tokens = tree.nodes.items(.main_token);261 const main_tokens = tree.nodes.items(.main_token);
266 switch (node_tags[node]) {262 switch (node_tags[node]) {
...@@ -453,9 +449,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Ins...@@ -453,9 +449,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Ins
453/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the449/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
454/// result instruction can be used to inspect whether it is isNoReturn() but that is it,450/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
455/// it must otherwise not be used.451/// it must otherwise not be used.
456pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {452fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
457 const astgen = gz.astgen;453 const astgen = gz.astgen;
458 const tree = &astgen.file.tree;454 const tree = astgen.tree;
459 const main_tokens = tree.nodes.items(.main_token);455 const main_tokens = tree.nodes.items(.main_token);
460 const token_tags = tree.tokens.items(.tag);456 const token_tags = tree.tokens.items(.tag);
461 const node_datas = tree.nodes.items(.data);457 const node_datas = tree.nodes.items(.data);
...@@ -888,7 +884,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -888,7 +884,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
888 }884 }
889}885}
890886
891pub fn nosuspendExpr(887fn nosuspendExpr(
892 gz: *GenZir,888 gz: *GenZir,
893 scope: *Scope,889 scope: *Scope,
894 rl: ResultLoc,890 rl: ResultLoc,
...@@ -896,7 +892,7 @@ pub fn nosuspendExpr(...@@ -896,7 +892,7 @@ pub fn nosuspendExpr(
896) InnerError!Zir.Inst.Ref {892) InnerError!Zir.Inst.Ref {
897 const astgen = gz.astgen;893 const astgen = gz.astgen;
898 const gpa = astgen.gpa;894 const gpa = astgen.gpa;
899 const tree = &astgen.file.tree;895 const tree = astgen.tree;
900 const node_datas = tree.nodes.items(.data);896 const node_datas = tree.nodes.items(.data);
901 const body_node = node_datas[node].lhs;897 const body_node = node_datas[node].lhs;
902 assert(body_node != 0);898 assert(body_node != 0);
...@@ -911,7 +907,7 @@ pub fn nosuspendExpr(...@@ -911,7 +907,7 @@ pub fn nosuspendExpr(
911 return rvalue(gz, scope, rl, result, node);907 return rvalue(gz, scope, rl, result, node);
912}908}
913909
914pub fn suspendExpr(910fn suspendExpr(
915 gz: *GenZir,911 gz: *GenZir,
916 scope: *Scope,912 scope: *Scope,
917 rl: ResultLoc,913 rl: ResultLoc,
...@@ -919,7 +915,7 @@ pub fn suspendExpr(...@@ -919,7 +915,7 @@ pub fn suspendExpr(
919) InnerError!Zir.Inst.Ref {915) InnerError!Zir.Inst.Ref {
920 const astgen = gz.astgen;916 const astgen = gz.astgen;
921 const gpa = astgen.gpa;917 const gpa = astgen.gpa;
922 const tree = &astgen.file.tree;918 const tree = astgen.tree;
923 const node_datas = tree.nodes.items(.data);919 const node_datas = tree.nodes.items(.data);
924 const body_node = node_datas[node].lhs;920 const body_node = node_datas[node].lhs;
925921
...@@ -951,14 +947,14 @@ pub fn suspendExpr(...@@ -951,14 +947,14 @@ pub fn suspendExpr(
951 return gz.indexToRef(suspend_inst);947 return gz.indexToRef(suspend_inst);
952}948}
953949
954pub fn awaitExpr(950fn awaitExpr(
955 gz: *GenZir,951 gz: *GenZir,
956 scope: *Scope,952 scope: *Scope,
957 rl: ResultLoc,953 rl: ResultLoc,
958 node: ast.Node.Index,954 node: ast.Node.Index,
959) InnerError!Zir.Inst.Ref {955) InnerError!Zir.Inst.Ref {
960 const astgen = gz.astgen;956 const astgen = gz.astgen;
961 const tree = &astgen.file.tree;957 const tree = astgen.tree;
962 const node_datas = tree.nodes.items(.data);958 const node_datas = tree.nodes.items(.data);
963 const rhs_node = node_datas[node].lhs;959 const rhs_node = node_datas[node].lhs;
964960
...@@ -973,14 +969,14 @@ pub fn awaitExpr(...@@ -973,14 +969,14 @@ pub fn awaitExpr(
973 return rvalue(gz, scope, rl, result, node);969 return rvalue(gz, scope, rl, result, node);
974}970}
975971
976pub fn resumeExpr(972fn resumeExpr(
977 gz: *GenZir,973 gz: *GenZir,
978 scope: *Scope,974 scope: *Scope,
979 rl: ResultLoc,975 rl: ResultLoc,
980 node: ast.Node.Index,976 node: ast.Node.Index,
981) InnerError!Zir.Inst.Ref {977) InnerError!Zir.Inst.Ref {
982 const astgen = gz.astgen;978 const astgen = gz.astgen;
983 const tree = &astgen.file.tree;979 const tree = astgen.tree;
984 const node_datas = tree.nodes.items(.data);980 const node_datas = tree.nodes.items(.data);
985 const rhs_node = node_datas[node].lhs;981 const rhs_node = node_datas[node].lhs;
986 const operand = try expr(gz, scope, .none, rhs_node);982 const operand = try expr(gz, scope, .none, rhs_node);
...@@ -988,7 +984,7 @@ pub fn resumeExpr(...@@ -988,7 +984,7 @@ pub fn resumeExpr(
988 return rvalue(gz, scope, rl, result, node);984 return rvalue(gz, scope, rl, result, node);
989}985}
990986
991pub fn fnProtoExpr(987fn fnProtoExpr(
992 gz: *GenZir,988 gz: *GenZir,
993 scope: *Scope,989 scope: *Scope,
994 rl: ResultLoc,990 rl: ResultLoc,
...@@ -996,7 +992,7 @@ pub fn fnProtoExpr(...@@ -996,7 +992,7 @@ pub fn fnProtoExpr(
996) InnerError!Zir.Inst.Ref {992) InnerError!Zir.Inst.Ref {
997 const astgen = gz.astgen;993 const astgen = gz.astgen;
998 const gpa = astgen.gpa;994 const gpa = astgen.gpa;
999 const tree = &astgen.file.tree;995 const tree = astgen.tree;
1000 const token_tags = tree.tokens.items(.tag);996 const token_tags = tree.tokens.items(.tag);
1001997
1002 const is_extern = blk: {998 const is_extern = blk: {
...@@ -1093,7 +1089,7 @@ pub fn fnProtoExpr(...@@ -1093,7 +1089,7 @@ pub fn fnProtoExpr(
1093 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);1089 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);
1094}1090}
10951091
1096pub fn arrayInitExpr(1092fn arrayInitExpr(
1097 gz: *GenZir,1093 gz: *GenZir,
1098 scope: *Scope,1094 scope: *Scope,
1099 rl: ResultLoc,1095 rl: ResultLoc,
...@@ -1101,7 +1097,7 @@ pub fn arrayInitExpr(...@@ -1101,7 +1097,7 @@ pub fn arrayInitExpr(
1101 array_init: ast.full.ArrayInit,1097 array_init: ast.full.ArrayInit,
1102) InnerError!Zir.Inst.Ref {1098) InnerError!Zir.Inst.Ref {
1103 const astgen = gz.astgen;1099 const astgen = gz.astgen;
1104 const tree = &astgen.file.tree;1100 const tree = astgen.tree;
1105 const gpa = astgen.gpa;1101 const gpa = astgen.gpa;
1106 const node_tags = tree.nodes.items(.tag);1102 const node_tags = tree.nodes.items(.tag);
1107 const main_tokens = tree.nodes.items(.main_token);1103 const main_tokens = tree.nodes.items(.main_token);
...@@ -1192,7 +1188,7 @@ pub fn arrayInitExpr(...@@ -1192,7 +1188,7 @@ pub fn arrayInitExpr(
1192 }1188 }
1193}1189}
11941190
1195pub fn arrayInitExprRlNone(1191fn arrayInitExprRlNone(
1196 gz: *GenZir,1192 gz: *GenZir,
1197 scope: *Scope,1193 scope: *Scope,
1198 rl: ResultLoc,1194 rl: ResultLoc,
...@@ -1215,7 +1211,7 @@ pub fn arrayInitExprRlNone(...@@ -1215,7 +1211,7 @@ pub fn arrayInitExprRlNone(
1215 return init_inst;1211 return init_inst;
1216}1212}
12171213
1218pub fn arrayInitExprRlTy(1214fn arrayInitExprRlTy(
1219 gz: *GenZir,1215 gz: *GenZir,
1220 scope: *Scope,1216 scope: *Scope,
1221 rl: ResultLoc,1217 rl: ResultLoc,
...@@ -1243,7 +1239,7 @@ pub fn arrayInitExprRlTy(...@@ -1243,7 +1239,7 @@ pub fn arrayInitExprRlTy(
1243 return init_inst;1239 return init_inst;
1244}1240}
12451241
1246pub fn arrayInitExprRlPtr(1242fn arrayInitExprRlPtr(
1247 gz: *GenZir,1243 gz: *GenZir,
1248 scope: *Scope,1244 scope: *Scope,
1249 rl: ResultLoc,1245 rl: ResultLoc,
...@@ -1273,7 +1269,7 @@ pub fn arrayInitExprRlPtr(...@@ -1273,7 +1269,7 @@ pub fn arrayInitExprRlPtr(
1273 return .void_value;1269 return .void_value;
1274}1270}
12751271
1276pub fn structInitExpr(1272fn structInitExpr(
1277 gz: *GenZir,1273 gz: *GenZir,
1278 scope: *Scope,1274 scope: *Scope,
1279 rl: ResultLoc,1275 rl: ResultLoc,
...@@ -1281,7 +1277,7 @@ pub fn structInitExpr(...@@ -1281,7 +1277,7 @@ pub fn structInitExpr(
1281 struct_init: ast.full.StructInit,1277 struct_init: ast.full.StructInit,
1282) InnerError!Zir.Inst.Ref {1278) InnerError!Zir.Inst.Ref {
1283 const astgen = gz.astgen;1279 const astgen = gz.astgen;
1284 const tree = &astgen.file.tree;1280 const tree = astgen.tree;
1285 const gpa = astgen.gpa;1281 const gpa = astgen.gpa;
12861282
1287 if (struct_init.ast.fields.len == 0) {1283 if (struct_init.ast.fields.len == 0) {
...@@ -1351,7 +1347,7 @@ pub fn structInitExpr(...@@ -1351,7 +1347,7 @@ pub fn structInitExpr(
1351 }1347 }
1352}1348}
13531349
1354pub fn structInitExprRlNone(1350fn structInitExprRlNone(
1355 gz: *GenZir,1351 gz: *GenZir,
1356 scope: *Scope,1352 scope: *Scope,
1357 rl: ResultLoc,1353 rl: ResultLoc,
...@@ -1361,7 +1357,7 @@ pub fn structInitExprRlNone(...@@ -1361,7 +1357,7 @@ pub fn structInitExprRlNone(
1361) InnerError!Zir.Inst.Ref {1357) InnerError!Zir.Inst.Ref {
1362 const astgen = gz.astgen;1358 const astgen = gz.astgen;
1363 const gpa = astgen.gpa;1359 const gpa = astgen.gpa;
1364 const tree = &astgen.file.tree;1360 const tree = astgen.tree;
13651361
1366 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);1362 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);
1367 defer gpa.free(fields_list);1363 defer gpa.free(fields_list);
...@@ -1386,7 +1382,7 @@ pub fn structInitExprRlNone(...@@ -1386,7 +1382,7 @@ pub fn structInitExprRlNone(
1386 return init_inst;1382 return init_inst;
1387}1383}
13881384
1389pub fn structInitExprRlPtr(1385fn structInitExprRlPtr(
1390 gz: *GenZir,1386 gz: *GenZir,
1391 scope: *Scope,1387 scope: *Scope,
1392 rl: ResultLoc,1388 rl: ResultLoc,
...@@ -1396,7 +1392,7 @@ pub fn structInitExprRlPtr(...@@ -1396,7 +1392,7 @@ pub fn structInitExprRlPtr(
1396) InnerError!Zir.Inst.Ref {1392) InnerError!Zir.Inst.Ref {
1397 const astgen = gz.astgen;1393 const astgen = gz.astgen;
1398 const gpa = astgen.gpa;1394 const gpa = astgen.gpa;
1399 const tree = &astgen.file.tree;1395 const tree = astgen.tree;
14001396
1401 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);1397 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);
1402 defer gpa.free(field_ptr_list);1398 defer gpa.free(field_ptr_list);
...@@ -1418,7 +1414,7 @@ pub fn structInitExprRlPtr(...@@ -1418,7 +1414,7 @@ pub fn structInitExprRlPtr(
1418 return .void_value;1414 return .void_value;
1419}1415}
14201416
1421pub fn structInitExprRlTy(1417fn structInitExprRlTy(
1422 gz: *GenZir,1418 gz: *GenZir,
1423 scope: *Scope,1419 scope: *Scope,
1424 rl: ResultLoc,1420 rl: ResultLoc,
...@@ -1429,7 +1425,7 @@ pub fn structInitExprRlTy(...@@ -1429,7 +1425,7 @@ pub fn structInitExprRlTy(
1429) InnerError!Zir.Inst.Ref {1425) InnerError!Zir.Inst.Ref {
1430 const astgen = gz.astgen;1426 const astgen = gz.astgen;
1431 const gpa = astgen.gpa;1427 const gpa = astgen.gpa;
1432 const tree = &astgen.file.tree;1428 const tree = astgen.tree;
14331429
1434 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);1430 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);
1435 defer gpa.free(fields_list);1431 defer gpa.free(fields_list);
...@@ -1486,7 +1482,7 @@ fn comptimeExprAst(...@@ -1486,7 +1482,7 @@ fn comptimeExprAst(
1486 if (gz.force_comptime) {1482 if (gz.force_comptime) {
1487 return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{});1483 return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{});
1488 }1484 }
1489 const tree = &astgen.file.tree;1485 const tree = astgen.tree;
1490 const node_datas = tree.nodes.items(.data);1486 const node_datas = tree.nodes.items(.data);
1491 const body_node = node_datas[node].lhs;1487 const body_node = node_datas[node].lhs;
1492 gz.force_comptime = true;1488 gz.force_comptime = true;
...@@ -1497,7 +1493,7 @@ fn comptimeExprAst(...@@ -1497,7 +1493,7 @@ fn comptimeExprAst(
14971493
1498fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {1494fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
1499 const astgen = parent_gz.astgen;1495 const astgen = parent_gz.astgen;
1500 const tree = &astgen.file.tree;1496 const tree = astgen.tree;
1501 const node_datas = tree.nodes.items(.data);1497 const node_datas = tree.nodes.items(.data);
1502 const break_label = node_datas[node].lhs;1498 const break_label = node_datas[node].lhs;
1503 const rhs = node_datas[node].rhs;1499 const rhs = node_datas[node].rhs;
...@@ -1520,7 +1516,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn...@@ -1520,7 +1516,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
1520 } else if (block_gz.break_block != 0) {1516 } else if (block_gz.break_block != 0) {
1521 break :blk block_gz.break_block;1517 break :blk block_gz.break_block;
1522 }1518 }
1523 scope = block_gz.parent;1519 scope = block_gz.parent orelse break;
1524 continue;1520 continue;
1525 };1521 };
15261522
...@@ -1558,19 +1554,19 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn...@@ -1558,19 +1554,19 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
1558 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);1554 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1559 },1555 },
1560 .defer_error => scope = scope.cast(Scope.Defer).?.parent,1556 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1561 else => if (break_label != 0) {
1562 const label_name = try astgen.identifierTokenString(break_label);
1563 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1564 } else {
1565 return astgen.failNode(node, "break expression outside loop", .{});
1566 },
1567 }1557 }
1568 }1558 }
1559 if (break_label != 0) {
1560 const label_name = try astgen.identifierTokenString(break_label);
1561 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1562 } else {
1563 return astgen.failNode(node, "break expression outside loop", .{});
1564 }
1569}1565}
15701566
1571fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {1567fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
1572 const astgen = parent_gz.astgen;1568 const astgen = parent_gz.astgen;
1573 const tree = &astgen.file.tree;1569 const tree = astgen.tree;
1574 const node_datas = tree.nodes.items(.data);1570 const node_datas = tree.nodes.items(.data);
1575 const break_label = node_datas[node].lhs;1571 const break_label = node_datas[node].lhs;
15761572
...@@ -1582,7 +1578,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)...@@ -1582,7 +1578,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
1582 const gen_zir = scope.cast(GenZir).?;1578 const gen_zir = scope.cast(GenZir).?;
1583 const continue_block = gen_zir.continue_block;1579 const continue_block = gen_zir.continue_block;
1584 if (continue_block == 0) {1580 if (continue_block == 0) {
1585 scope = gen_zir.parent;1581 scope = gen_zir.parent orelse break;
1586 continue;1582 continue;
1587 }1583 }
1588 if (break_label != 0) blk: {1584 if (break_label != 0) blk: {
...@@ -1593,7 +1589,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)...@@ -1593,7 +1589,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
1593 }1589 }
1594 }1590 }
1595 // found continue but either it has a different label, or no label1591 // found continue but either it has a different label, or no label
1596 scope = gen_zir.parent;1592 scope = gen_zir.parent orelse break;
1597 continue;1593 continue;
1598 }1594 }
15991595
...@@ -1610,17 +1606,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)...@@ -1610,17 +1606,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
1610 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);1606 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1611 },1607 },
1612 .defer_error => scope = scope.cast(Scope.Defer).?.parent,1608 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1613 else => if (break_label != 0) {
1614 const label_name = try astgen.identifierTokenString(break_label);
1615 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1616 } else {
1617 return astgen.failNode(node, "continue expression outside loop", .{});
1618 },
1619 }1609 }
1620 }1610 }
1611 if (break_label != 0) {
1612 const label_name = try astgen.identifierTokenString(break_label);
1613 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
1614 } else {
1615 return astgen.failNode(node, "continue expression outside loop", .{});
1616 }
1621}1617}
16221618
1623pub fn blockExpr(1619fn blockExpr(
1624 gz: *GenZir,1620 gz: *GenZir,
1625 scope: *Scope,1621 scope: *Scope,
1626 rl: ResultLoc,1622 rl: ResultLoc,
...@@ -1631,7 +1627,7 @@ pub fn blockExpr(...@@ -1631,7 +1627,7 @@ pub fn blockExpr(
1631 defer tracy.end();1627 defer tracy.end();
16321628
1633 const astgen = gz.astgen;1629 const astgen = gz.astgen;
1634 const tree = &astgen.file.tree;1630 const tree = astgen.tree;
1635 const main_tokens = tree.nodes.items(.main_token);1631 const main_tokens = tree.nodes.items(.main_token);
1636 const token_tags = tree.tokens.items(.tag);1632 const token_tags = tree.tokens.items(.tag);
16371633
...@@ -1655,7 +1651,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke...@@ -1655,7 +1651,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
1655 const gen_zir = scope.cast(GenZir).?;1651 const gen_zir = scope.cast(GenZir).?;
1656 if (gen_zir.label) |prev_label| {1652 if (gen_zir.label) |prev_label| {
1657 if (try astgen.tokenIdentEql(label, prev_label.token)) {1653 if (try astgen.tokenIdentEql(label, prev_label.token)) {
1658 const tree = &astgen.file.tree;1654 const tree = astgen.tree;
1659 const main_tokens = tree.nodes.items(.main_token);1655 const main_tokens = tree.nodes.items(.main_token);
16601656
1661 const label_name = try astgen.identifierTokenString(label);1657 const label_name = try astgen.identifierTokenString(label);
...@@ -1670,12 +1666,11 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke...@@ -1670,12 +1666,11 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
1670 });1666 });
1671 }1667 }
1672 }1668 }
1673 scope = gen_zir.parent;1669 scope = gen_zir.parent orelse return;
1674 },1670 },
1675 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,1671 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
1676 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,1672 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
1677 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,1673 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1678 else => return,
1679 }1674 }
1680 }1675 }
1681}1676}
...@@ -1694,7 +1689,7 @@ fn labeledBlockExpr(...@@ -1694,7 +1689,7 @@ fn labeledBlockExpr(
1694 assert(zir_tag == .block);1689 assert(zir_tag == .block);
16951690
1696 const astgen = gz.astgen;1691 const astgen = gz.astgen;
1697 const tree = &astgen.file.tree;1692 const tree = astgen.tree;
1698 const main_tokens = tree.nodes.items(.main_token);1693 const main_tokens = tree.nodes.items(.main_token);
1699 const token_tags = tree.tokens.items(.tag);1694 const token_tags = tree.tokens.items(.tag);
17001695
...@@ -1768,7 +1763,7 @@ fn blockExprStmts(...@@ -1768,7 +1763,7 @@ fn blockExprStmts(
1768 statements: []const ast.Node.Index,1763 statements: []const ast.Node.Index,
1769) !void {1764) !void {
1770 const astgen = gz.astgen;1765 const astgen = gz.astgen;
1771 const tree = &astgen.file.tree;1766 const tree = astgen.tree;
1772 const main_tokens = tree.nodes.items(.main_token);1767 const main_tokens = tree.nodes.items(.main_token);
1773 const node_tags = tree.nodes.items(.tag);1768 const node_tags = tree.nodes.items(.tag);
17741769
...@@ -2108,13 +2103,13 @@ fn genDefers(...@@ -2108,13 +2103,13 @@ fn genDefers(
2108 err_code: Zir.Inst.Ref,2103 err_code: Zir.Inst.Ref,
2109) InnerError!void {2104) InnerError!void {
2110 const astgen = gz.astgen;2105 const astgen = gz.astgen;
2111 const tree = &astgen.file.tree;2106 const tree = astgen.tree;
2112 const node_datas = tree.nodes.items(.data);2107 const node_datas = tree.nodes.items(.data);
21132108
2114 var scope = inner_scope;2109 var scope = inner_scope;
2115 while (scope != outer_scope) {2110 while (scope != outer_scope) {
2116 switch (scope.tag) {2111 switch (scope.tag) {
2117 .gen_zir => scope = scope.cast(GenZir).?.parent,2112 .gen_zir => scope = scope.cast(GenZir).?.parent.?,
2118 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2113 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2119 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2114 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2120 .defer_normal => {2115 .defer_normal => {
...@@ -2130,7 +2125,6 @@ fn genDefers(...@@ -2130,7 +2125,6 @@ fn genDefers(
2130 const expr_node = node_datas[defer_scope.defer_node].rhs;2125 const expr_node = node_datas[defer_scope.defer_node].rhs;
2131 try unusedResultExpr(gz, defer_scope.parent, expr_node);2126 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2132 },2127 },
2133 else => unreachable,
2134 }2128 }
2135 }2129 }
2136}2130}
...@@ -2161,7 +2155,7 @@ fn varDecl(...@@ -2161,7 +2155,7 @@ fn varDecl(
2161 try emitDbgNode(gz, node);2155 try emitDbgNode(gz, node);
2162 const astgen = gz.astgen;2156 const astgen = gz.astgen;
2163 const gpa = astgen.gpa;2157 const gpa = astgen.gpa;
2164 const tree = &astgen.file.tree;2158 const tree = astgen.tree;
2165 const token_tags = tree.tokens.items(.tag);2159 const token_tags = tree.tokens.items(.tag);
21662160
2167 const name_token = var_decl.ast.mut_token + 1;2161 const name_token = var_decl.ast.mut_token + 1;
...@@ -2201,10 +2195,8 @@ fn varDecl(...@@ -2201,10 +2195,8 @@ fn varDecl(
2201 }2195 }
2202 s = local_ptr.parent;2196 s = local_ptr.parent;
2203 },2197 },
2204 .gen_zir => s = s.cast(GenZir).?.parent,2198 .gen_zir => s = s.cast(GenZir).?.parent orelse break,
2205 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,2199 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
2206 .file => break,
2207 else => unreachable,
2208 };2200 };
2209 }2201 }
22102202
...@@ -2402,7 +2394,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {...@@ -2402,7 +2394,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
2402 if (gz.force_comptime) return;2394 if (gz.force_comptime) return;
24032395
2404 const astgen = gz.astgen;2396 const astgen = gz.astgen;
2405 const tree = &astgen.file.tree;2397 const tree = astgen.tree;
2406 const node_tags = tree.nodes.items(.tag);2398 const node_tags = tree.nodes.items(.tag);
2407 const token_starts = tree.tokens.items(.start);2399 const token_starts = tree.tokens.items(.start);
2408 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];2400 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
...@@ -2420,7 +2412,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {...@@ -2420,7 +2412,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
2420fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {2412fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
2421 try emitDbgNode(gz, infix_node);2413 try emitDbgNode(gz, infix_node);
2422 const astgen = gz.astgen;2414 const astgen = gz.astgen;
2423 const tree = &astgen.file.tree;2415 const tree = astgen.tree;
2424 const node_datas = tree.nodes.items(.data);2416 const node_datas = tree.nodes.items(.data);
2425 const main_tokens = tree.nodes.items(.main_token);2417 const main_tokens = tree.nodes.items(.main_token);
2426 const node_tags = tree.nodes.items(.tag);2418 const node_tags = tree.nodes.items(.tag);
...@@ -2447,7 +2439,7 @@ fn assignOp(...@@ -2447,7 +2439,7 @@ fn assignOp(
2447) InnerError!void {2439) InnerError!void {
2448 try emitDbgNode(gz, infix_node);2440 try emitDbgNode(gz, infix_node);
2449 const astgen = gz.astgen;2441 const astgen = gz.astgen;
2450 const tree = &astgen.file.tree;2442 const tree = astgen.tree;
2451 const node_datas = tree.nodes.items(.data);2443 const node_datas = tree.nodes.items(.data);
24522444
2453 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);2445 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
...@@ -2470,7 +2462,7 @@ fn assignShift(...@@ -2470,7 +2462,7 @@ fn assignShift(
2470) InnerError!void {2462) InnerError!void {
2471 try emitDbgNode(gz, infix_node);2463 try emitDbgNode(gz, infix_node);
2472 const astgen = gz.astgen;2464 const astgen = gz.astgen;
2473 const tree = &astgen.file.tree;2465 const tree = astgen.tree;
2474 const node_datas = tree.nodes.items(.data);2466 const node_datas = tree.nodes.items(.data);
24752467
2476 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);2468 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
...@@ -2487,7 +2479,7 @@ fn assignShift(...@@ -2487,7 +2479,7 @@ fn assignShift(
24872479
2488fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {2480fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
2489 const astgen = gz.astgen;2481 const astgen = gz.astgen;
2490 const tree = &astgen.file.tree;2482 const tree = astgen.tree;
2491 const node_datas = tree.nodes.items(.data);2483 const node_datas = tree.nodes.items(.data);
24922484
2493 const operand = try expr(gz, scope, bool_rl, node_datas[node].lhs);2485 const operand = try expr(gz, scope, bool_rl, node_datas[node].lhs);
...@@ -2497,7 +2489,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne...@@ -2497,7 +2489,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne
24972489
2498fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {2490fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
2499 const astgen = gz.astgen;2491 const astgen = gz.astgen;
2500 const tree = &astgen.file.tree;2492 const tree = astgen.tree;
2501 const node_datas = tree.nodes.items(.data);2493 const node_datas = tree.nodes.items(.data);
25022494
2503 const operand = try expr(gz, scope, .none, node_datas[node].lhs);2495 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
...@@ -2513,7 +2505,7 @@ fn negation(...@@ -2513,7 +2505,7 @@ fn negation(
2513 tag: Zir.Inst.Tag,2505 tag: Zir.Inst.Tag,
2514) InnerError!Zir.Inst.Ref {2506) InnerError!Zir.Inst.Ref {
2515 const astgen = gz.astgen;2507 const astgen = gz.astgen;
2516 const tree = &astgen.file.tree;2508 const tree = astgen.tree;
2517 const node_datas = tree.nodes.items(.data);2509 const node_datas = tree.nodes.items(.data);
25182510
2519 const operand = try expr(gz, scope, .none, node_datas[node].lhs);2511 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
...@@ -2529,7 +2521,7 @@ fn ptrType(...@@ -2529,7 +2521,7 @@ fn ptrType(
2529 ptr_info: ast.full.PtrType,2521 ptr_info: ast.full.PtrType,
2530) InnerError!Zir.Inst.Ref {2522) InnerError!Zir.Inst.Ref {
2531 const astgen = gz.astgen;2523 const astgen = gz.astgen;
2532 const tree = &astgen.file.tree;2524 const tree = astgen.tree;
25332525
2534 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);2526 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
25352527
...@@ -2612,7 +2604,7 @@ fn ptrType(...@@ -2612,7 +2604,7 @@ fn ptrType(
26122604
2613fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {2605fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
2614 const astgen = gz.astgen;2606 const astgen = gz.astgen;
2615 const tree = &astgen.file.tree;2607 const tree = astgen.tree;
2616 const node_datas = tree.nodes.items(.data);2608 const node_datas = tree.nodes.items(.data);
2617 const node_tags = tree.nodes.items(.tag);2609 const node_tags = tree.nodes.items(.tag);
2618 const main_tokens = tree.nodes.items(.main_token);2610 const main_tokens = tree.nodes.items(.main_token);
...@@ -2632,7 +2624,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z...@@ -2632,7 +2624,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z
26322624
2633fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {2625fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
2634 const astgen = gz.astgen;2626 const astgen = gz.astgen;
2635 const tree = &astgen.file.tree;2627 const tree = astgen.tree;
2636 const node_datas = tree.nodes.items(.data);2628 const node_datas = tree.nodes.items(.data);
2637 const node_tags = tree.nodes.items(.tag);2629 const node_tags = tree.nodes.items(.tag);
2638 const main_tokens = tree.nodes.items(.main_token);2630 const main_tokens = tree.nodes.items(.main_token);
...@@ -2696,7 +2688,7 @@ fn fnDecl(...@@ -2696,7 +2688,7 @@ fn fnDecl(
2696 fn_proto: ast.full.FnProto,2688 fn_proto: ast.full.FnProto,
2697) InnerError!void {2689) InnerError!void {
2698 const gpa = astgen.gpa;2690 const gpa = astgen.gpa;
2699 const tree = &astgen.file.tree;2691 const tree = astgen.tree;
2700 const token_tags = tree.tokens.items(.tag);2692 const token_tags = tree.tokens.items(.tag);
27012693
2702 // We insert this at the beginning so that its instruction index marks the2694 // We insert this at the beginning so that its instruction index marks the
...@@ -2937,7 +2929,7 @@ fn globalVarDecl(...@@ -2937,7 +2929,7 @@ fn globalVarDecl(
2937 var_decl: ast.full.VarDecl,2929 var_decl: ast.full.VarDecl,
2938) InnerError!void {2930) InnerError!void {
2939 const gpa = astgen.gpa;2931 const gpa = astgen.gpa;
2940 const tree = &astgen.file.tree;2932 const tree = astgen.tree;
2941 const token_tags = tree.tokens.items(.tag);2933 const token_tags = tree.tokens.items(.tag);
29422934
2943 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;2935 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
...@@ -3076,7 +3068,7 @@ fn comptimeDecl(...@@ -3076,7 +3068,7 @@ fn comptimeDecl(
3076 node: ast.Node.Index,3068 node: ast.Node.Index,
3077) InnerError!void {3069) InnerError!void {
3078 const gpa = astgen.gpa;3070 const gpa = astgen.gpa;
3079 const tree = &astgen.file.tree;3071 const tree = astgen.tree;
3080 const node_datas = tree.nodes.items(.data);3072 const node_datas = tree.nodes.items(.data);
3081 const body_node = node_datas[node].lhs;3073 const body_node = node_datas[node].lhs;
30823074
...@@ -3122,7 +3114,7 @@ fn usingnamespaceDecl(...@@ -3122,7 +3114,7 @@ fn usingnamespaceDecl(
3122 node: ast.Node.Index,3114 node: ast.Node.Index,
3123) InnerError!void {3115) InnerError!void {
3124 const gpa = astgen.gpa;3116 const gpa = astgen.gpa;
3125 const tree = &astgen.file.tree;3117 const tree = astgen.tree;
3126 const node_datas = tree.nodes.items(.data);3118 const node_datas = tree.nodes.items(.data);
31273119
3128 const type_expr = node_datas[node].lhs;3120 const type_expr = node_datas[node].lhs;
...@@ -3172,7 +3164,7 @@ fn testDecl(...@@ -3172,7 +3164,7 @@ fn testDecl(
3172 node: ast.Node.Index,3164 node: ast.Node.Index,
3173) InnerError!void {3165) InnerError!void {
3174 const gpa = astgen.gpa;3166 const gpa = astgen.gpa;
3175 const tree = &astgen.file.tree;3167 const tree = astgen.tree;
3176 const node_datas = tree.nodes.items(.data);3168 const node_datas = tree.nodes.items(.data);
3177 const body_node = node_datas[node].rhs;3169 const body_node = node_datas[node].rhs;
31783170
...@@ -3271,7 +3263,7 @@ fn structDeclInner(...@@ -3271,7 +3263,7 @@ fn structDeclInner(
32713263
3272 const astgen = gz.astgen;3264 const astgen = gz.astgen;
3273 const gpa = astgen.gpa;3265 const gpa = astgen.gpa;
3274 const tree = &astgen.file.tree;3266 const tree = astgen.tree;
3275 const node_tags = tree.nodes.items(.tag);3267 const node_tags = tree.nodes.items(.tag);
3276 const node_datas = tree.nodes.items(.data);3268 const node_datas = tree.nodes.items(.data);
32773269
...@@ -3483,7 +3475,7 @@ fn unionDeclInner(...@@ -3483,7 +3475,7 @@ fn unionDeclInner(
3483) InnerError!Zir.Inst.Ref {3475) InnerError!Zir.Inst.Ref {
3484 const astgen = gz.astgen;3476 const astgen = gz.astgen;
3485 const gpa = astgen.gpa;3477 const gpa = astgen.gpa;
3486 const tree = &astgen.file.tree;3478 const tree = astgen.tree;
3487 const node_tags = tree.nodes.items(.tag);3479 const node_tags = tree.nodes.items(.tag);
3488 const node_datas = tree.nodes.items(.data);3480 const node_datas = tree.nodes.items(.data);
34893481
...@@ -3705,7 +3697,7 @@ fn containerDecl(...@@ -3705,7 +3697,7 @@ fn containerDecl(
3705) InnerError!Zir.Inst.Ref {3697) InnerError!Zir.Inst.Ref {
3706 const astgen = gz.astgen;3698 const astgen = gz.astgen;
3707 const gpa = astgen.gpa;3699 const gpa = astgen.gpa;
3708 const tree = &astgen.file.tree;3700 const tree = astgen.tree;
3709 const token_tags = tree.tokens.items(.tag);3701 const token_tags = tree.tokens.items(.tag);
3710 const node_tags = tree.nodes.items(.tag);3702 const node_tags = tree.nodes.items(.tag);
3711 const node_datas = tree.nodes.items(.data);3703 const node_datas = tree.nodes.items(.data);
...@@ -4149,7 +4141,7 @@ fn errorSetDecl(...@@ -4149,7 +4141,7 @@ fn errorSetDecl(
4149) InnerError!Zir.Inst.Ref {4141) InnerError!Zir.Inst.Ref {
4150 const astgen = gz.astgen;4142 const astgen = gz.astgen;
4151 const gpa = astgen.gpa;4143 const gpa = astgen.gpa;
4152 const tree = &astgen.file.tree;4144 const tree = astgen.tree;
4153 const main_tokens = tree.nodes.items(.main_token);4145 const main_tokens = tree.nodes.items(.main_token);
4154 const token_tags = tree.tokens.items(.tag);4146 const token_tags = tree.tokens.items(.tag);
41554147
...@@ -4189,7 +4181,7 @@ fn tryExpr(...@@ -4189,7 +4181,7 @@ fn tryExpr(
4189 operand_node: ast.Node.Index,4181 operand_node: ast.Node.Index,
4190) InnerError!Zir.Inst.Ref {4182) InnerError!Zir.Inst.Ref {
4191 const astgen = parent_gz.astgen;4183 const astgen = parent_gz.astgen;
4192 const tree = &astgen.file.tree;4184 const tree = astgen.tree;
41934185
4194 const fn_block = astgen.fn_block orelse {4186 const fn_block = astgen.fn_block orelse {
4195 return astgen.failNode(node, "invalid 'try' outside function scope", .{});4187 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
...@@ -4272,7 +4264,7 @@ fn orelseCatchExpr(...@@ -4272,7 +4264,7 @@ fn orelseCatchExpr(
4272 payload_token: ?ast.TokenIndex,4264 payload_token: ?ast.TokenIndex,
4273) InnerError!Zir.Inst.Ref {4265) InnerError!Zir.Inst.Ref {
4274 const astgen = parent_gz.astgen;4266 const astgen = parent_gz.astgen;
4275 const tree = &astgen.file.tree;4267 const tree = astgen.tree;
42764268
4277 var block_scope = parent_gz.makeSubBlock(scope);4269 var block_scope = parent_gz.makeSubBlock(scope);
4278 block_scope.setBreakResultLoc(rl);4270 block_scope.setBreakResultLoc(rl);
...@@ -4421,14 +4413,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: ast.TokenIndex, token2: ast.TokenIndex...@@ -4421,14 +4413,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: ast.TokenIndex, token2: ast.TokenIndex
4421 return mem.eql(u8, ident_name_1, ident_name_2);4413 return mem.eql(u8, ident_name_1, ident_name_2);
4422}4414}
44234415
4424pub fn fieldAccess(4416fn fieldAccess(
4425 gz: *GenZir,4417 gz: *GenZir,
4426 scope: *Scope,4418 scope: *Scope,
4427 rl: ResultLoc,4419 rl: ResultLoc,
4428 node: ast.Node.Index,4420 node: ast.Node.Index,
4429) InnerError!Zir.Inst.Ref {4421) InnerError!Zir.Inst.Ref {
4430 const astgen = gz.astgen;4422 const astgen = gz.astgen;
4431 const tree = &astgen.file.tree;4423 const tree = astgen.tree;
4432 const main_tokens = tree.nodes.items(.main_token);4424 const main_tokens = tree.nodes.items(.main_token);
4433 const node_datas = tree.nodes.items(.data);4425 const node_datas = tree.nodes.items(.data);
44344426
...@@ -4455,7 +4447,7 @@ fn arrayAccess(...@@ -4455,7 +4447,7 @@ fn arrayAccess(
4455 node: ast.Node.Index,4447 node: ast.Node.Index,
4456) InnerError!Zir.Inst.Ref {4448) InnerError!Zir.Inst.Ref {
4457 const astgen = gz.astgen;4449 const astgen = gz.astgen;
4458 const tree = &astgen.file.tree;4450 const tree = astgen.tree;
4459 const main_tokens = tree.nodes.items(.main_token);4451 const main_tokens = tree.nodes.items(.main_token);
4460 const node_datas = tree.nodes.items(.data);4452 const node_datas = tree.nodes.items(.data);
4461 switch (rl) {4453 switch (rl) {
...@@ -4480,7 +4472,7 @@ fn simpleBinOp(...@@ -4480,7 +4472,7 @@ fn simpleBinOp(
4480 op_inst_tag: Zir.Inst.Tag,4472 op_inst_tag: Zir.Inst.Tag,
4481) InnerError!Zir.Inst.Ref {4473) InnerError!Zir.Inst.Ref {
4482 const astgen = gz.astgen;4474 const astgen = gz.astgen;
4483 const tree = &astgen.file.tree;4475 const tree = astgen.tree;
4484 const node_datas = tree.nodes.items(.data);4476 const node_datas = tree.nodes.items(.data);
44854477
4486 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{4478 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
...@@ -4512,7 +4504,7 @@ fn boolBinOp(...@@ -4512,7 +4504,7 @@ fn boolBinOp(
4512 zir_tag: Zir.Inst.Tag,4504 zir_tag: Zir.Inst.Tag,
4513) InnerError!Zir.Inst.Ref {4505) InnerError!Zir.Inst.Ref {
4514 const astgen = gz.astgen;4506 const astgen = gz.astgen;
4515 const tree = &astgen.file.tree;4507 const tree = astgen.tree;
4516 const node_datas = tree.nodes.items(.data);4508 const node_datas = tree.nodes.items(.data);
45174509
4518 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);4510 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
...@@ -4538,7 +4530,7 @@ fn ifExpr(...@@ -4538,7 +4530,7 @@ fn ifExpr(
4538 if_full: ast.full.If,4530 if_full: ast.full.If,
4539) InnerError!Zir.Inst.Ref {4531) InnerError!Zir.Inst.Ref {
4540 const astgen = parent_gz.astgen;4532 const astgen = parent_gz.astgen;
4541 const tree = &astgen.file.tree;4533 const tree = astgen.tree;
4542 const token_tags = tree.tokens.items(.tag);4534 const token_tags = tree.tokens.items(.tag);
45434535
4544 var block_scope = parent_gz.makeSubBlock(scope);4536 var block_scope = parent_gz.makeSubBlock(scope);
...@@ -4765,7 +4757,7 @@ fn whileExpr(...@@ -4765,7 +4757,7 @@ fn whileExpr(
4765 while_full: ast.full.While,4757 while_full: ast.full.While,
4766) InnerError!Zir.Inst.Ref {4758) InnerError!Zir.Inst.Ref {
4767 const astgen = parent_gz.astgen;4759 const astgen = parent_gz.astgen;
4768 const tree = &astgen.file.tree;4760 const tree = astgen.tree;
4769 const token_tags = tree.tokens.items(.tag);4761 const token_tags = tree.tokens.items(.tag);
47704762
4771 if (while_full.label_token) |label_token| {4763 if (while_full.label_token) |label_token| {
...@@ -4967,7 +4959,7 @@ fn forExpr(...@@ -4967,7 +4959,7 @@ fn forExpr(
4967 }4959 }
4968 // Set up variables and constants.4960 // Set up variables and constants.
4969 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;4961 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
4970 const tree = &astgen.file.tree;4962 const tree = astgen.tree;
4971 const token_tags = tree.tokens.items(.tag);4963 const token_tags = tree.tokens.items(.tag);
49724964
4973 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);4965 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);
...@@ -5123,111 +5115,6 @@ fn forExpr(...@@ -5123,111 +5115,6 @@ fn forExpr(
5123 );5115 );
5124}5116}
51255117
5126fn getRangeNode(
5127 node_tags: []const ast.Node.Tag,
5128 node_datas: []const ast.Node.Data,
5129 node: ast.Node.Index,
5130) ?ast.Node.Index {
5131 switch (node_tags[node]) {
5132 .switch_range => return node,
5133 .grouped_expression => unreachable,
5134 else => return null,
5135 }
5136}
5137
5138pub const SwitchProngSrc = union(enum) {
5139 scalar: u32,
5140 multi: Multi,
5141 range: Multi,
5142
5143 pub const Multi = struct {
5144 prong: u32,
5145 item: u32,
5146 };
5147
5148 pub const RangeExpand = enum { none, first, last };
5149
5150 /// This function is intended to be called only when it is certain that we need
5151 /// the LazySrcLoc in order to emit a compile error.
5152 pub fn resolve(
5153 prong_src: SwitchProngSrc,
5154 decl: *Decl,
5155 switch_node_offset: i32,
5156 range_expand: RangeExpand,
5157 ) LazySrcLoc {
5158 @setCold(true);
5159 const switch_node = decl.relativeToNodeIndex(switch_node_offset);
5160 const tree = decl.namespace.file_scope.tree;
5161 const main_tokens = tree.nodes.items(.main_token);
5162 const node_datas = tree.nodes.items(.data);
5163 const node_tags = tree.nodes.items(.tag);
5164 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
5165 const case_nodes = tree.extra_data[extra.start..extra.end];
5166
5167 var multi_i: u32 = 0;
5168 var scalar_i: u32 = 0;
5169 for (case_nodes) |case_node| {
5170 const case = switch (node_tags[case_node]) {
5171 .switch_case_one => tree.switchCaseOne(case_node),
5172 .switch_case => tree.switchCase(case_node),
5173 else => unreachable,
5174 };
5175 if (case.ast.values.len == 0)
5176 continue;
5177 if (case.ast.values.len == 1 and
5178 node_tags[case.ast.values[0]] == .identifier and
5179 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
5180 {
5181 continue;
5182 }
5183 const is_multi = case.ast.values.len != 1 or
5184 getRangeNode(node_tags, node_datas, case.ast.values[0]) != null;
5185
5186 switch (prong_src) {
5187 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc{
5188 .node_offset = decl.nodeIndexToRelative(case.ast.values[0]),
5189 },
5190 .multi => |s| if (is_multi and s.prong == multi_i) {
5191 var item_i: u32 = 0;
5192 for (case.ast.values) |item_node| {
5193 if (getRangeNode(node_tags, node_datas, item_node) != null)
5194 continue;
5195
5196 if (item_i == s.item) return LazySrcLoc{
5197 .node_offset = decl.nodeIndexToRelative(item_node),
5198 };
5199 item_i += 1;
5200 } else unreachable;
5201 },
5202 .range => |s| if (is_multi and s.prong == multi_i) {
5203 var range_i: u32 = 0;
5204 for (case.ast.values) |item_node| {
5205 const range = getRangeNode(node_tags, node_datas, item_node) orelse continue;
5206
5207 if (range_i == s.item) switch (range_expand) {
5208 .none => return LazySrcLoc{
5209 .node_offset = decl.nodeIndexToRelative(item_node),
5210 },
5211 .first => return LazySrcLoc{
5212 .node_offset = decl.nodeIndexToRelative(node_datas[range].lhs),
5213 },
5214 .last => return LazySrcLoc{
5215 .node_offset = decl.nodeIndexToRelative(node_datas[range].rhs),
5216 },
5217 };
5218 range_i += 1;
5219 } else unreachable;
5220 },
5221 }
5222 if (is_multi) {
5223 multi_i += 1;
5224 } else {
5225 scalar_i += 1;
5226 }
5227 } else unreachable;
5228 }
5229};
5230
5231fn switchExpr(5118fn switchExpr(
5232 parent_gz: *GenZir,5119 parent_gz: *GenZir,
5233 scope: *Scope,5120 scope: *Scope,
...@@ -5236,7 +5123,7 @@ fn switchExpr(...@@ -5236,7 +5123,7 @@ fn switchExpr(
5236) InnerError!Zir.Inst.Ref {5123) InnerError!Zir.Inst.Ref {
5237 const astgen = parent_gz.astgen;5124 const astgen = parent_gz.astgen;
5238 const gpa = astgen.gpa;5125 const gpa = astgen.gpa;
5239 const tree = &astgen.file.tree;5126 const tree = astgen.tree;
5240 const node_datas = tree.nodes.items(.data);5127 const node_datas = tree.nodes.items(.data);
5241 const node_tags = tree.nodes.items(.tag);5128 const node_tags = tree.nodes.items(.tag);
5242 const main_tokens = tree.nodes.items(.main_token);5129 const main_tokens = tree.nodes.items(.main_token);
...@@ -5348,9 +5235,7 @@ fn switchExpr(...@@ -5348,9 +5235,7 @@ fn switchExpr(
5348 continue;5235 continue;
5349 }5236 }
53505237
5351 if (case.ast.values.len == 1 and5238 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
5352 getRangeNode(node_tags, node_datas, case.ast.values[0]) == null)
5353 {
5354 scalar_cases_len += 1;5239 scalar_cases_len += 1;
5355 } else {5240 } else {
5356 multi_cases_len += 1;5241 multi_cases_len += 1;
...@@ -5472,7 +5357,7 @@ fn switchExpr(...@@ -5472,7 +5357,7 @@ fn switchExpr(
5472 case_scope.instructions.shrinkRetainingCapacity(0);5357 case_scope.instructions.shrinkRetainingCapacity(0);
54735358
5474 const is_multi_case = case.ast.values.len != 1 or5359 const is_multi_case = case.ast.values.len != 1 or
5475 getRangeNode(node_tags, node_datas, case.ast.values[0]) != null;5360 node_tags[case.ast.values[0]] == .switch_range;
54765361
5477 const sub_scope = blk: {5362 const sub_scope = blk: {
5478 const payload_token = case.payload_token orelse break :blk &case_scope.base;5363 const payload_token = case.payload_token orelse break :blk &case_scope.base;
...@@ -5528,7 +5413,7 @@ fn switchExpr(...@@ -5528,7 +5413,7 @@ fn switchExpr(
5528 // items5413 // items
5529 var items_len: u32 = 0;5414 var items_len: u32 = 0;
5530 for (case.ast.values) |item_node| {5415 for (case.ast.values) |item_node| {
5531 if (getRangeNode(node_tags, node_datas, item_node) != null) continue;5416 if (node_tags[item_node] == .switch_range) continue;
5532 items_len += 1;5417 items_len += 1;
55335418
5534 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);5419 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
...@@ -5537,8 +5422,8 @@ fn switchExpr(...@@ -5537,8 +5422,8 @@ fn switchExpr(
55375422
5538 // ranges5423 // ranges
5539 var ranges_len: u32 = 0;5424 var ranges_len: u32 = 0;
5540 for (case.ast.values) |item_node| {5425 for (case.ast.values) |range| {
5541 const range = getRangeNode(node_tags, node_datas, item_node) orelse continue;5426 if (node_tags[range] != .switch_range) continue;
5542 ranges_len += 1;5427 ranges_len += 1;
55435428
5544 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);5429 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
...@@ -5824,7 +5709,7 @@ fn switchExpr(...@@ -5824,7 +5709,7 @@ fn switchExpr(
58245709
5825fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {5710fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
5826 const astgen = gz.astgen;5711 const astgen = gz.astgen;
5827 const tree = &astgen.file.tree;5712 const tree = astgen.tree;
5828 const node_datas = tree.nodes.items(.data);5713 const node_datas = tree.nodes.items(.data);
5829 const main_tokens = tree.nodes.items(.main_token);5714 const main_tokens = tree.nodes.items(.main_token);
58305715
...@@ -5857,7 +5742,7 @@ fn identifier(...@@ -5857,7 +5742,7 @@ fn identifier(
5857 defer tracy.end();5742 defer tracy.end();
58585743
5859 const astgen = gz.astgen;5744 const astgen = gz.astgen;
5860 const tree = &astgen.file.tree;5745 const tree = astgen.tree;
5861 const main_tokens = tree.nodes.items(.main_token);5746 const main_tokens = tree.nodes.items(.main_token);
58625747
5863 const ident_token = main_tokens[ident];5748 const ident_token = main_tokens[ident];
...@@ -5922,8 +5807,8 @@ fn identifier(...@@ -5922,8 +5807,8 @@ fn identifier(
5922 }5807 }
5923 s = local_ptr.parent;5808 s = local_ptr.parent;
5924 },5809 },
5925 .gen_zir => s = s.cast(GenZir).?.parent,5810 .gen_zir => s = s.cast(GenZir).?.parent orelse break,
5926 else => break,5811 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
5927 };5812 };
5928 }5813 }
59295814
...@@ -5946,7 +5831,7 @@ fn stringLiteral(...@@ -5946,7 +5831,7 @@ fn stringLiteral(
5946 node: ast.Node.Index,5831 node: ast.Node.Index,
5947) InnerError!Zir.Inst.Ref {5832) InnerError!Zir.Inst.Ref {
5948 const astgen = gz.astgen;5833 const astgen = gz.astgen;
5949 const tree = astgen.file.tree;5834 const tree = astgen.tree;
5950 const main_tokens = tree.nodes.items(.main_token);5835 const main_tokens = tree.nodes.items(.main_token);
5951 const str_lit_token = main_tokens[node];5836 const str_lit_token = main_tokens[node];
5952 const str = try astgen.strLitAsString(str_lit_token);5837 const str = try astgen.strLitAsString(str_lit_token);
...@@ -5967,7 +5852,7 @@ fn multilineStringLiteral(...@@ -5967,7 +5852,7 @@ fn multilineStringLiteral(
5967 node: ast.Node.Index,5852 node: ast.Node.Index,
5968) InnerError!Zir.Inst.Ref {5853) InnerError!Zir.Inst.Ref {
5969 const astgen = gz.astgen;5854 const astgen = gz.astgen;
5970 const tree = &astgen.file.tree;5855 const tree = astgen.tree;
5971 const node_datas = tree.nodes.items(.data);5856 const node_datas = tree.nodes.items(.data);
5972 const main_tokens = tree.nodes.items(.main_token);5857 const main_tokens = tree.nodes.items(.main_token);
59735858
...@@ -6006,7 +5891,7 @@ fn multilineStringLiteral(...@@ -6006,7 +5891,7 @@ fn multilineStringLiteral(
60065891
6007fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {5892fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
6008 const astgen = gz.astgen;5893 const astgen = gz.astgen;
6009 const tree = &astgen.file.tree;5894 const tree = astgen.tree;
6010 const main_tokens = tree.nodes.items(.main_token);5895 const main_tokens = tree.nodes.items(.main_token);
6011 const main_token = main_tokens[node];5896 const main_token = main_tokens[node];
6012 const slice = tree.tokenSlice(main_token);5897 const slice = tree.tokenSlice(main_token);
...@@ -6035,7 +5920,7 @@ fn integerLiteral(...@@ -6035,7 +5920,7 @@ fn integerLiteral(
6035 node: ast.Node.Index,5920 node: ast.Node.Index,
6036) InnerError!Zir.Inst.Ref {5921) InnerError!Zir.Inst.Ref {
6037 const astgen = gz.astgen;5922 const astgen = gz.astgen;
6038 const tree = &astgen.file.tree;5923 const tree = astgen.tree;
6039 const main_tokens = tree.nodes.items(.main_token);5924 const main_tokens = tree.nodes.items(.main_token);
6040 const int_token = main_tokens[node];5925 const int_token = main_tokens[node];
6041 const prefixed_bytes = tree.tokenSlice(int_token);5926 const prefixed_bytes = tree.tokenSlice(int_token);
...@@ -6087,7 +5972,7 @@ fn floatLiteral(...@@ -6087,7 +5972,7 @@ fn floatLiteral(
6087) InnerError!Zir.Inst.Ref {5972) InnerError!Zir.Inst.Ref {
6088 const astgen = gz.astgen;5973 const astgen = gz.astgen;
6089 const arena = astgen.arena;5974 const arena = astgen.arena;
6090 const tree = &astgen.file.tree;5975 const tree = astgen.tree;
6091 const main_tokens = tree.nodes.items(.main_token);5976 const main_tokens = tree.nodes.items(.main_token);
60925977
6093 const main_token = main_tokens[node];5978 const main_token = main_tokens[node];
...@@ -6130,7 +6015,7 @@ fn asmExpr(...@@ -6130,7 +6015,7 @@ fn asmExpr(
6130) InnerError!Zir.Inst.Ref {6015) InnerError!Zir.Inst.Ref {
6131 const astgen = gz.astgen;6016 const astgen = gz.astgen;
6132 const arena = astgen.arena;6017 const arena = astgen.arena;
6133 const tree = &astgen.file.tree;6018 const tree = astgen.tree;
6134 const main_tokens = tree.nodes.items(.main_token);6019 const main_tokens = tree.nodes.items(.main_token);
6135 const node_datas = tree.nodes.items(.data);6020 const node_datas = tree.nodes.items(.data);
6136 const token_tags = tree.tokens.items(.tag);6021 const token_tags = tree.tokens.items(.tag);
...@@ -6426,7 +6311,7 @@ fn builtinCall(...@@ -6426,7 +6311,7 @@ fn builtinCall(
6426 params: []const ast.Node.Index,6311 params: []const ast.Node.Index,
6427) InnerError!Zir.Inst.Ref {6312) InnerError!Zir.Inst.Ref {
6428 const astgen = gz.astgen;6313 const astgen = gz.astgen;
6429 const tree = &astgen.file.tree;6314 const tree = astgen.tree;
6430 const main_tokens = tree.nodes.items(.main_token);6315 const main_tokens = tree.nodes.items(.main_token);
64316316
6432 const builtin_token = main_tokens[node];6317 const builtin_token = main_tokens[node];
...@@ -7406,7 +7291,7 @@ fn rvalue(...@@ -7406,7 +7291,7 @@ fn rvalue(
7406 },7291 },
7407 .ref => {7292 .ref => {
7408 // We need a pointer but we have a value.7293 // We need a pointer but we have a value.
7409 const tree = &gz.astgen.file.tree;7294 const tree = gz.astgen.tree;
7410 const src_token = tree.firstToken(src_node);7295 const src_token = tree.firstToken(src_node);
7411 return gz.addUnTok(.ref, result, src_token);7296 return gz.addUnTok(.ref, result, src_token);
7412 },7297 },
...@@ -7498,8 +7383,8 @@ fn rvalue(...@@ -7498,8 +7383,8 @@ fn rvalue(
7498/// and allocates the result within `astgen.arena`.7383/// and allocates the result within `astgen.arena`.
7499/// Otherwise, returns a reference to the source code bytes directly.7384/// Otherwise, returns a reference to the source code bytes directly.
7500/// See also `appendIdentStr` and `parseStrLit`.7385/// See also `appendIdentStr` and `parseStrLit`.
7501pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {7386fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
7502 const tree = &astgen.file.tree;7387 const tree = astgen.tree;
7503 const token_tags = tree.tokens.items(.tag);7388 const token_tags = tree.tokens.items(.tag);
7504 assert(token_tags[token] == .identifier);7389 assert(token_tags[token] == .identifier);
7505 const ident_name = tree.tokenSlice(token);7390 const ident_name = tree.tokenSlice(token);
...@@ -7516,12 +7401,12 @@ pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError!...@@ -7516,12 +7401,12 @@ pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError!
7516/// Given an identifier token, obtain the string for it (possibly parsing as a string7401/// Given an identifier token, obtain the string for it (possibly parsing as a string
7517/// literal if it is @"" syntax), and append the string to `buf`.7402/// literal if it is @"" syntax), and append the string to `buf`.
7518/// See also `identifierTokenString` and `parseStrLit`.7403/// See also `identifierTokenString` and `parseStrLit`.
7519pub fn appendIdentStr(7404fn appendIdentStr(
7520 astgen: *AstGen,7405 astgen: *AstGen,
7521 token: ast.TokenIndex,7406 token: ast.TokenIndex,
7522 buf: *ArrayListUnmanaged(u8),7407 buf: *ArrayListUnmanaged(u8),
7523) InnerError!void {7408) InnerError!void {
7524 const tree = &astgen.file.tree;7409 const tree = astgen.tree;
7525 const token_tags = tree.tokens.items(.tag);7410 const token_tags = tree.tokens.items(.tag);
7526 assert(token_tags[token] == .identifier);7411 assert(token_tags[token] == .identifier);
7527 const ident_name = tree.tokenSlice(token);7412 const ident_name = tree.tokenSlice(token);
...@@ -7533,14 +7418,14 @@ pub fn appendIdentStr(...@@ -7533,14 +7418,14 @@ pub fn appendIdentStr(
7533}7418}
75347419
7535/// Appends the result to `buf`.7420/// Appends the result to `buf`.
7536pub fn parseStrLit(7421fn parseStrLit(
7537 astgen: *AstGen,7422 astgen: *AstGen,
7538 token: ast.TokenIndex,7423 token: ast.TokenIndex,
7539 buf: *ArrayListUnmanaged(u8),7424 buf: *ArrayListUnmanaged(u8),
7540 bytes: []const u8,7425 bytes: []const u8,
7541 offset: u32,7426 offset: u32,
7542) InnerError!void {7427) InnerError!void {
7543 const tree = &astgen.file.tree;7428 const tree = astgen.tree;
7544 const raw_string = bytes[offset..];7429 const raw_string = bytes[offset..];
7545 var buf_managed = buf.toManaged(astgen.gpa);7430 var buf_managed = buf.toManaged(astgen.gpa);
7546 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);7431 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);
...@@ -7598,7 +7483,7 @@ pub fn parseStrLit(...@@ -7598,7 +7483,7 @@ pub fn parseStrLit(
7598 }7483 }
7599}7484}
76007485
7601pub fn failNode(7486fn failNode(
7602 astgen: *AstGen,7487 astgen: *AstGen,
7603 node: ast.Node.Index,7488 node: ast.Node.Index,
7604 comptime format: []const u8,7489 comptime format: []const u8,
...@@ -7607,7 +7492,7 @@ pub fn failNode(...@@ -7607,7 +7492,7 @@ pub fn failNode(
7607 return astgen.failNodeNotes(node, format, args, &[0]u32{});7492 return astgen.failNodeNotes(node, format, args, &[0]u32{});
7608}7493}
76097494
7610pub fn failNodeNotes(7495fn failNodeNotes(
7611 astgen: *AstGen,7496 astgen: *AstGen,
7612 node: ast.Node.Index,7497 node: ast.Node.Index,
7613 comptime format: []const u8,7498 comptime format: []const u8,
...@@ -7639,7 +7524,7 @@ pub fn failNodeNotes(...@@ -7639,7 +7524,7 @@ pub fn failNodeNotes(
7639 return error.AnalysisFail;7524 return error.AnalysisFail;
7640}7525}
76417526
7642pub fn failTok(7527fn failTok(
7643 astgen: *AstGen,7528 astgen: *AstGen,
7644 token: ast.TokenIndex,7529 token: ast.TokenIndex,
7645 comptime format: []const u8,7530 comptime format: []const u8,
...@@ -7648,7 +7533,7 @@ pub fn failTok(...@@ -7648,7 +7533,7 @@ pub fn failTok(
7648 return astgen.failTokNotes(token, format, args, &[0]u32{});7533 return astgen.failTokNotes(token, format, args, &[0]u32{});
7649}7534}
76507535
7651pub fn failTokNotes(7536fn failTokNotes(
7652 astgen: *AstGen,7537 astgen: *AstGen,
7653 token: ast.TokenIndex,7538 token: ast.TokenIndex,
7654 comptime format: []const u8,7539 comptime format: []const u8,
...@@ -7680,9 +7565,8 @@ pub fn failTokNotes(...@@ -7680,9 +7565,8 @@ pub fn failTokNotes(
7680 return error.AnalysisFail;7565 return error.AnalysisFail;
7681}7566}
76827567
7683/// Same as `fail`, except given an absolute byte offset, and the function sets up the `LazySrcLoc`7568/// Same as `fail`, except given an absolute byte offset.
7684/// for pointing at it relatively by subtracting from the containing `Decl`.7569fn failOff(
7685pub fn failOff(
7686 astgen: *AstGen,7570 astgen: *AstGen,
7687 token: ast.TokenIndex,7571 token: ast.TokenIndex,
7688 byte_offset: u32,7572 byte_offset: u32,
...@@ -7707,7 +7591,7 @@ pub fn failOff(...@@ -7707,7 +7591,7 @@ pub fn failOff(
7707 return error.AnalysisFail;7591 return error.AnalysisFail;
7708}7592}
77097593
7710pub fn errNoteTok(7594fn errNoteTok(
7711 astgen: *AstGen,7595 astgen: *AstGen,
7712 token: ast.TokenIndex,7596 token: ast.TokenIndex,
7713 comptime format: []const u8,7597 comptime format: []const u8,
...@@ -7730,7 +7614,7 @@ pub fn errNoteTok(...@@ -7730,7 +7614,7 @@ pub fn errNoteTok(
7730 });7614 });
7731}7615}
77327616
7733pub fn errNoteNode(7617fn errNoteNode(
7734 astgen: *AstGen,7618 astgen: *AstGen,
7735 node: ast.Node.Index,7619 node: ast.Node.Index,
7736 comptime format: []const u8,7620 comptime format: []const u8,
...@@ -7780,7 +7664,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {...@@ -7780,7 +7664,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
7780 const gpa = astgen.gpa;7664 const gpa = astgen.gpa;
7781 const string_bytes = &astgen.string_bytes;7665 const string_bytes = &astgen.string_bytes;
7782 const str_index = @intCast(u32, string_bytes.items.len);7666 const str_index = @intCast(u32, string_bytes.items.len);
7783 const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);7667 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
7784 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);7668 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7785 const key = string_bytes.items[str_index..];7669 const key = string_bytes.items[str_index..];
7786 const gop = try astgen.string_table.getOrPut(gpa, key);7670 const gop = try astgen.string_table.getOrPut(gpa, key);
...@@ -7811,9 +7695,934 @@ fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {...@@ -7811,9 +7695,934 @@ fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
7811 const gpa = astgen.gpa;7695 const gpa = astgen.gpa;
7812 const string_bytes = &astgen.string_bytes;7696 const string_bytes = &astgen.string_bytes;
7813 const str_index = @intCast(u32, string_bytes.items.len);7697 const str_index = @intCast(u32, string_bytes.items.len);
7814 const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);7698 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
7815 try string_bytes.append(gpa, 0); // Indicates this is a test.7699 try string_bytes.append(gpa, 0); // Indicates this is a test.
7816 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);7700 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7817 try string_bytes.append(gpa, 0);7701 try string_bytes.append(gpa, 0);
7818 return str_index;7702 return str_index;
7819}7703}
7704
7705const Scope = struct {
7706 tag: Tag,
7707
7708 fn cast(base: *Scope, comptime T: type) ?*T {
7709 if (T == Defer) {
7710 switch (base.tag) {
7711 .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base),
7712 else => return null,
7713 }
7714 }
7715 if (base.tag != T.base_tag)
7716 return null;
7717
7718 return @fieldParentPtr(T, "base", base);
7719 }
7720
7721 const Tag = enum {
7722 gen_zir,
7723 local_val,
7724 local_ptr,
7725 defer_normal,
7726 defer_error,
7727 };
7728
7729 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.
7730 /// This structure lives as long as the AST generation of the Block
7731 /// node that contains the variable.
7732 const LocalVal = struct {
7733 const base_tag: Tag = .local_val;
7734 base: Scope = Scope{ .tag = base_tag },
7735 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
7736 parent: *Scope,
7737 gen_zir: *GenZir,
7738 inst: Zir.Inst.Ref,
7739 /// Source location of the corresponding variable declaration.
7740 token_src: ast.TokenIndex,
7741 /// String table index.
7742 name: u32,
7743 };
7744
7745 /// This could be a `const` or `var` local. It has a pointer instead of a value.
7746 /// This structure lives as long as the AST generation of the Block
7747 /// node that contains the variable.
7748 const LocalPtr = struct {
7749 const base_tag: Tag = .local_ptr;
7750 base: Scope = Scope{ .tag = base_tag },
7751 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
7752 parent: *Scope,
7753 gen_zir: *GenZir,
7754 ptr: Zir.Inst.Ref,
7755 /// Source location of the corresponding variable declaration.
7756 token_src: ast.TokenIndex,
7757 /// String table index.
7758 name: u32,
7759 };
7760
7761 const Defer = struct {
7762 base: Scope,
7763 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
7764 parent: *Scope,
7765 defer_node: ast.Node.Index,
7766 };
7767};
7768
7769/// This is a temporary structure; references to it are valid only
7770/// while constructing a `Zir`.
7771const GenZir = struct {
7772 const base_tag: Scope.Tag = .gen_zir;
7773 base: Scope = Scope{ .tag = base_tag },
7774 force_comptime: bool,
7775 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
7776 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.
7777 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
7778 /// The containing decl AST node.
7779 decl_node_index: ast.Node.Index,
7780 /// The containing decl line index, absolute.
7781 decl_line: u32,
7782 parent: ?*Scope,
7783 /// All `GenZir` scopes for the same ZIR share this.
7784 astgen: *AstGen,
7785 /// Keeps track of the list of instructions in this scope only. Indexes
7786 /// to instructions in `astgen`.
7787 instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{},
7788 label: ?Label = null,
7789 break_block: Zir.Inst.Index = 0,
7790 continue_block: Zir.Inst.Index = 0,
7791 /// Only valid when setBreakResultLoc is called.
7792 break_result_loc: AstGen.ResultLoc = undefined,
7793 /// When a block has a pointer result location, here it is.
7794 rl_ptr: Zir.Inst.Ref = .none,
7795 /// When a block has a type result location, here it is.
7796 rl_ty_inst: Zir.Inst.Ref = .none,
7797 /// Keeps track of how many branches of a block did not actually
7798 /// consume the result location. astgen uses this to figure out
7799 /// whether to rely on break instructions or writing to the result
7800 /// pointer for the result instruction.
7801 rvalue_rl_count: usize = 0,
7802 /// Keeps track of how many break instructions there are. When astgen is finished
7803 /// with a block, it can check this against rvalue_rl_count to find out whether
7804 /// the break instructions should be downgraded to break_void.
7805 break_count: usize = 0,
7806 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
7807 /// the labeled block ends up not needing a result location pointer.
7808 labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{},
7809 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
7810 /// so they can possibly be elided later if the labeled block ends up not needing
7811 /// a result location pointer.
7812 labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{},
7813
7814 suspend_node: ast.Node.Index = 0,
7815 nosuspend_node: ast.Node.Index = 0,
7816
7817 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
7818 return .{
7819 .force_comptime = gz.force_comptime,
7820 .ref_start_index = gz.ref_start_index,
7821 .decl_node_index = gz.decl_node_index,
7822 .decl_line = gz.decl_line,
7823 .parent = scope,
7824 .astgen = gz.astgen,
7825 .suspend_node = gz.suspend_node,
7826 .nosuspend_node = gz.nosuspend_node,
7827 };
7828 }
7829
7830 const Label = struct {
7831 token: ast.TokenIndex,
7832 block_inst: Zir.Inst.Index,
7833 used: bool = false,
7834 };
7835
7836 fn refIsNoReturn(gz: GenZir, inst_ref: Zir.Inst.Ref) bool {
7837 if (inst_ref == .unreachable_value) return true;
7838 if (gz.refToIndex(inst_ref)) |inst_index| {
7839 return gz.astgen.instructions.items(.tag)[inst_index].isNoReturn();
7840 }
7841 return false;
7842 }
7843
7844 fn calcLine(gz: GenZir, node: ast.Node.Index) u32 {
7845 const astgen = gz.astgen;
7846 const tree = astgen.tree;
7847 const node_tags = tree.nodes.items(.tag);
7848 const token_starts = tree.tokens.items(.start);
7849 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
7850 const node_start = token_starts[tree.firstToken(node)];
7851 const source = tree.source[decl_start..node_start];
7852 const loc = std.zig.findLineColumn(source, source.len);
7853 return @intCast(u32, gz.decl_line + loc.line);
7854 }
7855
7856 fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {
7857 return .{ .token_offset = token_index - gz.srcToken() };
7858 }
7859
7860 fn nodeSrcLoc(gz: GenZir, node_index: ast.Node.Index) LazySrcLoc {
7861 return .{ .node_offset = gz.nodeIndexToRelative(node_index) };
7862 }
7863
7864 fn nodeIndexToRelative(gz: GenZir, node_index: ast.Node.Index) i32 {
7865 return @bitCast(i32, node_index) - @bitCast(i32, gz.decl_node_index);
7866 }
7867
7868 fn tokenIndexToRelative(gz: GenZir, token: ast.TokenIndex) u32 {
7869 return token - gz.srcToken();
7870 }
7871
7872 fn srcToken(gz: GenZir) ast.TokenIndex {
7873 return gz.astgen.tree.firstToken(gz.decl_node_index);
7874 }
7875
7876 fn indexToRef(gz: GenZir, inst: Zir.Inst.Index) Zir.Inst.Ref {
7877 return @intToEnum(Zir.Inst.Ref, gz.ref_start_index + inst);
7878 }
7879
7880 fn refToIndex(gz: GenZir, inst: Zir.Inst.Ref) ?Zir.Inst.Index {
7881 const ref_int = @enumToInt(inst);
7882 if (ref_int >= gz.ref_start_index) {
7883 return ref_int - gz.ref_start_index;
7884 } else {
7885 return null;
7886 }
7887 }
7888
7889 fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {
7890 // Depending on whether the result location is a pointer or value, different
7891 // ZIR needs to be generated. In the former case we rely on storing to the
7892 // pointer to communicate the result, and use breakvoid; in the latter case
7893 // the block break instructions will have the result values.
7894 // One more complication: when the result location is a pointer, we detect
7895 // the scenario where the result location is not consumed. In this case
7896 // we emit ZIR for the block break instructions to have the result values,
7897 // and then rvalue() on that to pass the value to the result location.
7898 switch (parent_rl) {
7899 .ty => |ty_inst| {
7900 gz.rl_ty_inst = ty_inst;
7901 gz.break_result_loc = parent_rl;
7902 },
7903 .none_or_ref => {
7904 gz.break_result_loc = .ref;
7905 },
7906 .discard, .none, .ptr, .ref => {
7907 gz.break_result_loc = parent_rl;
7908 },
7909
7910 .inferred_ptr => |ptr| {
7911 gz.rl_ptr = ptr;
7912 gz.break_result_loc = .{ .block_ptr = gz };
7913 },
7914
7915 .block_ptr => |parent_block_scope| {
7916 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
7917 gz.rl_ptr = parent_block_scope.rl_ptr;
7918 gz.break_result_loc = .{ .block_ptr = gz };
7919 },
7920 }
7921 }
7922
7923 fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void {
7924 const gpa = gz.astgen.gpa;
7925 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
7926 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
7927 const zir_datas = gz.astgen.instructions.items(.data);
7928 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
7929 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
7930 );
7931 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
7932 }
7933
7934 fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void {
7935 const gpa = gz.astgen.gpa;
7936 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
7937 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
7938 const zir_datas = gz.astgen.instructions.items(.data);
7939 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
7940 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
7941 );
7942 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
7943 }
7944
7945 /// Same as `setBlockBody` except we don't copy instructions which are
7946 /// `store_to_block_ptr` instructions with lhs set to .none.
7947 fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
7948 const gpa = gz.astgen.gpa;
7949 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
7950 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
7951 const zir_datas = gz.astgen.instructions.items(.data);
7952 const zir_tags = gz.astgen.instructions.items(.tag);
7953 const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
7954 .body_len = @intCast(u32, gz.instructions.items.len),
7955 });
7956 zir_datas[inst].pl_node.payload_index = block_pl_index;
7957 for (gz.instructions.items) |sub_inst| {
7958 if (zir_tags[sub_inst] == .store_to_block_ptr and
7959 zir_datas[sub_inst].bin.lhs == .none)
7960 {
7961 // Decrement `body_len`.
7962 gz.astgen.extra.items[block_pl_index] -= 1;
7963 continue;
7964 }
7965 gz.astgen.extra.appendAssumeCapacity(sub_inst);
7966 }
7967 }
7968
7969 fn addFunc(gz: *GenZir, args: struct {
7970 src_node: ast.Node.Index,
7971 param_types: []const Zir.Inst.Ref,
7972 body: []const Zir.Inst.Index,
7973 ret_ty: Zir.Inst.Ref,
7974 cc: Zir.Inst.Ref,
7975 align_inst: Zir.Inst.Ref,
7976 lib_name: u32,
7977 is_var_args: bool,
7978 is_inferred_error: bool,
7979 is_test: bool,
7980 }) !Zir.Inst.Ref {
7981 assert(args.src_node != 0);
7982 assert(args.ret_ty != .none);
7983 const astgen = gz.astgen;
7984 const gpa = astgen.gpa;
7985
7986 try gz.instructions.ensureUnusedCapacity(gpa, 1);
7987 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
7988
7989 var src_locs_buffer: [3]u32 = undefined;
7990 var src_locs: []u32 = src_locs_buffer[0..0];
7991 if (args.body.len != 0) {
7992 const tree = astgen.tree;
7993 const node_tags = tree.nodes.items(.tag);
7994 const node_datas = tree.nodes.items(.data);
7995 const token_starts = tree.tokens.items(.start);
7996 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
7997 const fn_decl = args.src_node;
7998 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
7999 const block = node_datas[fn_decl].rhs;
8000 const lbrace_start = token_starts[tree.firstToken(block)];
8001 const rbrace_start = token_starts[tree.lastToken(block)];
8002 const lbrace_source = tree.source[decl_start..lbrace_start];
8003 const lbrace_loc = std.zig.findLineColumn(lbrace_source, lbrace_source.len);
8004 const rbrace_source = tree.source[lbrace_start..rbrace_start];
8005 const rbrace_loc = std.zig.findLineColumn(rbrace_source, rbrace_source.len);
8006 const lbrace_line = @intCast(u32, lbrace_loc.line);
8007 const rbrace_line = lbrace_line + @intCast(u32, rbrace_loc.line);
8008 const columns = @intCast(u32, lbrace_loc.column) |
8009 (@intCast(u32, rbrace_loc.column) << 16);
8010 src_locs_buffer[0] = lbrace_line;
8011 src_locs_buffer[1] = rbrace_line;
8012 src_locs_buffer[2] = columns;
8013 src_locs = &src_locs_buffer;
8014 }
8015
8016 if (args.cc != .none or args.lib_name != 0 or
8017 args.is_var_args or args.is_test or args.align_inst != .none)
8018 {
8019 try astgen.extra.ensureUnusedCapacity(
8020 gpa,
8021 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
8022 args.param_types.len + args.body.len + src_locs.len +
8023 @boolToInt(args.lib_name != 0) +
8024 @boolToInt(args.align_inst != .none) +
8025 @boolToInt(args.cc != .none),
8026 );
8027 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
8028 .src_node = gz.nodeIndexToRelative(args.src_node),
8029 .return_type = args.ret_ty,
8030 .param_types_len = @intCast(u32, args.param_types.len),
8031 .body_len = @intCast(u32, args.body.len),
8032 });
8033 if (args.lib_name != 0) {
8034 astgen.extra.appendAssumeCapacity(args.lib_name);
8035 }
8036 if (args.cc != .none) {
8037 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
8038 }
8039 if (args.align_inst != .none) {
8040 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8041 }
8042 astgen.appendRefsAssumeCapacity(args.param_types);
8043 astgen.extra.appendSliceAssumeCapacity(args.body);
8044 astgen.extra.appendSliceAssumeCapacity(src_locs);
8045
8046 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8047 astgen.instructions.appendAssumeCapacity(.{
8048 .tag = .extended,
8049 .data = .{ .extended = .{
8050 .opcode = .func,
8051 .small = @bitCast(u16, Zir.Inst.ExtendedFunc.Small{
8052 .is_var_args = args.is_var_args,
8053 .is_inferred_error = args.is_inferred_error,
8054 .has_lib_name = args.lib_name != 0,
8055 .has_cc = args.cc != .none,
8056 .has_align = args.align_inst != .none,
8057 .is_test = args.is_test,
8058 }),
8059 .operand = payload_index,
8060 } },
8061 });
8062 gz.instructions.appendAssumeCapacity(new_index);
8063 return gz.indexToRef(new_index);
8064 } else {
8065 try gz.astgen.extra.ensureUnusedCapacity(
8066 gpa,
8067 @typeInfo(Zir.Inst.Func).Struct.fields.len +
8068 args.param_types.len + args.body.len + src_locs.len,
8069 );
8070
8071 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
8072 .return_type = args.ret_ty,
8073 .param_types_len = @intCast(u32, args.param_types.len),
8074 .body_len = @intCast(u32, args.body.len),
8075 });
8076 gz.astgen.appendRefsAssumeCapacity(args.param_types);
8077 gz.astgen.extra.appendSliceAssumeCapacity(args.body);
8078 gz.astgen.extra.appendSliceAssumeCapacity(src_locs);
8079
8080 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
8081 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8082 gz.astgen.instructions.appendAssumeCapacity(.{
8083 .tag = tag,
8084 .data = .{ .pl_node = .{
8085 .src_node = gz.nodeIndexToRelative(args.src_node),
8086 .payload_index = payload_index,
8087 } },
8088 });
8089 gz.instructions.appendAssumeCapacity(new_index);
8090 return gz.indexToRef(new_index);
8091 }
8092 }
8093
8094 fn addVar(gz: *GenZir, args: struct {
8095 align_inst: Zir.Inst.Ref,
8096 lib_name: u32,
8097 var_type: Zir.Inst.Ref,
8098 init: Zir.Inst.Ref,
8099 is_extern: bool,
8100 }) !Zir.Inst.Ref {
8101 const astgen = gz.astgen;
8102 const gpa = astgen.gpa;
8103
8104 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8105 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8106
8107 try astgen.extra.ensureUnusedCapacity(
8108 gpa,
8109 @typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
8110 @boolToInt(args.lib_name != 0) +
8111 @boolToInt(args.align_inst != .none) +
8112 @boolToInt(args.init != .none),
8113 );
8114 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
8115 .var_type = args.var_type,
8116 });
8117 if (args.lib_name != 0) {
8118 astgen.extra.appendAssumeCapacity(args.lib_name);
8119 }
8120 if (args.align_inst != .none) {
8121 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8122 }
8123 if (args.init != .none) {
8124 astgen.extra.appendAssumeCapacity(@enumToInt(args.init));
8125 }
8126
8127 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8128 astgen.instructions.appendAssumeCapacity(.{
8129 .tag = .extended,
8130 .data = .{ .extended = .{
8131 .opcode = .variable,
8132 .small = @bitCast(u16, Zir.Inst.ExtendedVar.Small{
8133 .has_lib_name = args.lib_name != 0,
8134 .has_align = args.align_inst != .none,
8135 .has_init = args.init != .none,
8136 .is_extern = args.is_extern,
8137 }),
8138 .operand = payload_index,
8139 } },
8140 });
8141 gz.instructions.appendAssumeCapacity(new_index);
8142 return gz.indexToRef(new_index);
8143 }
8144
8145 fn addCall(
8146 gz: *GenZir,
8147 tag: Zir.Inst.Tag,
8148 callee: Zir.Inst.Ref,
8149 args: []const Zir.Inst.Ref,
8150 /// Absolute node index. This function does the conversion to offset from Decl.
8151 src_node: ast.Node.Index,
8152 ) !Zir.Inst.Ref {
8153 assert(callee != .none);
8154 assert(src_node != 0);
8155 const gpa = gz.astgen.gpa;
8156 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8157 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8158 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
8159 @typeInfo(Zir.Inst.Call).Struct.fields.len + args.len);
8160
8161 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Call{
8162 .callee = callee,
8163 .args_len = @intCast(u32, args.len),
8164 });
8165 gz.astgen.appendRefsAssumeCapacity(args);
8166
8167 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8168 gz.astgen.instructions.appendAssumeCapacity(.{
8169 .tag = tag,
8170 .data = .{ .pl_node = .{
8171 .src_node = gz.nodeIndexToRelative(src_node),
8172 .payload_index = payload_index,
8173 } },
8174 });
8175 gz.instructions.appendAssumeCapacity(new_index);
8176 return gz.indexToRef(new_index);
8177 }
8178
8179 /// Note that this returns a `Zir.Inst.Index` not a ref.
8180 /// Leaves the `payload_index` field undefined.
8181 fn addBoolBr(
8182 gz: *GenZir,
8183 tag: Zir.Inst.Tag,
8184 lhs: Zir.Inst.Ref,
8185 ) !Zir.Inst.Index {
8186 assert(lhs != .none);
8187 const gpa = gz.astgen.gpa;
8188 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8189 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8190
8191 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8192 gz.astgen.instructions.appendAssumeCapacity(.{
8193 .tag = tag,
8194 .data = .{ .bool_br = .{
8195 .lhs = lhs,
8196 .payload_index = undefined,
8197 } },
8198 });
8199 gz.instructions.appendAssumeCapacity(new_index);
8200 return new_index;
8201 }
8202
8203 fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
8204 return gz.add(.{
8205 .tag = .int,
8206 .data = .{ .int = integer },
8207 });
8208 }
8209
8210 fn addIntBig(gz: *GenZir, limbs: []const std.math.big.Limb) !Zir.Inst.Ref {
8211 const astgen = gz.astgen;
8212 const gpa = astgen.gpa;
8213 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8214 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8215 try astgen.string_bytes.ensureUnusedCapacity(gpa, @sizeOf(std.math.big.Limb) * limbs.len);
8216
8217 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8218 astgen.instructions.appendAssumeCapacity(.{
8219 .tag = .int_big,
8220 .data = .{ .str = .{
8221 .start = @intCast(u32, astgen.string_bytes.items.len),
8222 .len = @intCast(u32, limbs.len),
8223 } },
8224 });
8225 gz.instructions.appendAssumeCapacity(new_index);
8226 astgen.string_bytes.appendSliceAssumeCapacity(mem.sliceAsBytes(limbs));
8227 return gz.indexToRef(new_index);
8228 }
8229
8230 fn addFloat(gz: *GenZir, number: f32, src_node: ast.Node.Index) !Zir.Inst.Ref {
8231 return gz.add(.{
8232 .tag = .float,
8233 .data = .{ .float = .{
8234 .src_node = gz.nodeIndexToRelative(src_node),
8235 .number = number,
8236 } },
8237 });
8238 }
8239
8240 fn addUnNode(
8241 gz: *GenZir,
8242 tag: Zir.Inst.Tag,
8243 operand: Zir.Inst.Ref,
8244 /// Absolute node index. This function does the conversion to offset from Decl.
8245 src_node: ast.Node.Index,
8246 ) !Zir.Inst.Ref {
8247 assert(operand != .none);
8248 return gz.add(.{
8249 .tag = tag,
8250 .data = .{ .un_node = .{
8251 .operand = operand,
8252 .src_node = gz.nodeIndexToRelative(src_node),
8253 } },
8254 });
8255 }
8256
8257 fn addPlNode(
8258 gz: *GenZir,
8259 tag: Zir.Inst.Tag,
8260 /// Absolute node index. This function does the conversion to offset from Decl.
8261 src_node: ast.Node.Index,
8262 extra: anytype,
8263 ) !Zir.Inst.Ref {
8264 const gpa = gz.astgen.gpa;
8265 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8266 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8267
8268 const payload_index = try gz.astgen.addExtra(extra);
8269 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8270 gz.astgen.instructions.appendAssumeCapacity(.{
8271 .tag = tag,
8272 .data = .{ .pl_node = .{
8273 .src_node = gz.nodeIndexToRelative(src_node),
8274 .payload_index = payload_index,
8275 } },
8276 });
8277 gz.instructions.appendAssumeCapacity(new_index);
8278 return gz.indexToRef(new_index);
8279 }
8280
8281 fn addExtendedPayload(
8282 gz: *GenZir,
8283 opcode: Zir.Inst.Extended,
8284 extra: anytype,
8285 ) !Zir.Inst.Ref {
8286 const gpa = gz.astgen.gpa;
8287
8288 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8289 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8290
8291 const payload_index = try gz.astgen.addExtra(extra);
8292 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8293 gz.astgen.instructions.appendAssumeCapacity(.{
8294 .tag = .extended,
8295 .data = .{ .extended = .{
8296 .opcode = opcode,
8297 .small = undefined,
8298 .operand = payload_index,
8299 } },
8300 });
8301 gz.instructions.appendAssumeCapacity(new_index);
8302 return gz.indexToRef(new_index);
8303 }
8304
8305 fn addExtendedMultiOp(
8306 gz: *GenZir,
8307 opcode: Zir.Inst.Extended,
8308 node: ast.Node.Index,
8309 operands: []const Zir.Inst.Ref,
8310 ) !Zir.Inst.Ref {
8311 const astgen = gz.astgen;
8312 const gpa = astgen.gpa;
8313
8314 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8315 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8316 try astgen.extra.ensureUnusedCapacity(
8317 gpa,
8318 @typeInfo(Zir.Inst.NodeMultiOp).Struct.fields.len + operands.len,
8319 );
8320
8321 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.NodeMultiOp{
8322 .src_node = gz.nodeIndexToRelative(node),
8323 });
8324 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8325 astgen.instructions.appendAssumeCapacity(.{
8326 .tag = .extended,
8327 .data = .{ .extended = .{
8328 .opcode = opcode,
8329 .small = @intCast(u16, operands.len),
8330 .operand = payload_index,
8331 } },
8332 });
8333 gz.instructions.appendAssumeCapacity(new_index);
8334 astgen.appendRefsAssumeCapacity(operands);
8335 return gz.indexToRef(new_index);
8336 }
8337
8338 fn addArrayTypeSentinel(
8339 gz: *GenZir,
8340 len: Zir.Inst.Ref,
8341 sentinel: Zir.Inst.Ref,
8342 elem_type: Zir.Inst.Ref,
8343 ) !Zir.Inst.Ref {
8344 const gpa = gz.astgen.gpa;
8345 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8346 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8347
8348 const payload_index = try gz.astgen.addExtra(Zir.Inst.ArrayTypeSentinel{
8349 .sentinel = sentinel,
8350 .elem_type = elem_type,
8351 });
8352 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8353 gz.astgen.instructions.appendAssumeCapacity(.{
8354 .tag = .array_type_sentinel,
8355 .data = .{ .array_type_sentinel = .{
8356 .len = len,
8357 .payload_index = payload_index,
8358 } },
8359 });
8360 gz.instructions.appendAssumeCapacity(new_index);
8361 return gz.indexToRef(new_index);
8362 }
8363
8364 fn addUnTok(
8365 gz: *GenZir,
8366 tag: Zir.Inst.Tag,
8367 operand: Zir.Inst.Ref,
8368 /// Absolute token index. This function does the conversion to Decl offset.
8369 abs_tok_index: ast.TokenIndex,
8370 ) !Zir.Inst.Ref {
8371 assert(operand != .none);
8372 return gz.add(.{
8373 .tag = tag,
8374 .data = .{ .un_tok = .{
8375 .operand = operand,
8376 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
8377 } },
8378 });
8379 }
8380
8381 fn addStrTok(
8382 gz: *GenZir,
8383 tag: Zir.Inst.Tag,
8384 str_index: u32,
8385 /// Absolute token index. This function does the conversion to Decl offset.
8386 abs_tok_index: ast.TokenIndex,
8387 ) !Zir.Inst.Ref {
8388 return gz.add(.{
8389 .tag = tag,
8390 .data = .{ .str_tok = .{
8391 .start = str_index,
8392 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
8393 } },
8394 });
8395 }
8396
8397 fn addBreak(
8398 gz: *GenZir,
8399 tag: Zir.Inst.Tag,
8400 break_block: Zir.Inst.Index,
8401 operand: Zir.Inst.Ref,
8402 ) !Zir.Inst.Index {
8403 return gz.addAsIndex(.{
8404 .tag = tag,
8405 .data = .{ .@"break" = .{
8406 .block_inst = break_block,
8407 .operand = operand,
8408 } },
8409 });
8410 }
8411
8412 fn addBin(
8413 gz: *GenZir,
8414 tag: Zir.Inst.Tag,
8415 lhs: Zir.Inst.Ref,
8416 rhs: Zir.Inst.Ref,
8417 ) !Zir.Inst.Ref {
8418 assert(lhs != .none);
8419 assert(rhs != .none);
8420 return gz.add(.{
8421 .tag = tag,
8422 .data = .{ .bin = .{
8423 .lhs = lhs,
8424 .rhs = rhs,
8425 } },
8426 });
8427 }
8428
8429 fn addDecl(
8430 gz: *GenZir,
8431 tag: Zir.Inst.Tag,
8432 decl_index: u32,
8433 src_node: ast.Node.Index,
8434 ) !Zir.Inst.Ref {
8435 return gz.add(.{
8436 .tag = tag,
8437 .data = .{ .pl_node = .{
8438 .src_node = gz.nodeIndexToRelative(src_node),
8439 .payload_index = decl_index,
8440 } },
8441 });
8442 }
8443
8444 fn addNode(
8445 gz: *GenZir,
8446 tag: Zir.Inst.Tag,
8447 /// Absolute node index. This function does the conversion to offset from Decl.
8448 src_node: ast.Node.Index,
8449 ) !Zir.Inst.Ref {
8450 return gz.add(.{
8451 .tag = tag,
8452 .data = .{ .node = gz.nodeIndexToRelative(src_node) },
8453 });
8454 }
8455
8456 fn addNodeExtended(
8457 gz: *GenZir,
8458 opcode: Zir.Inst.Extended,
8459 /// Absolute node index. This function does the conversion to offset from Decl.
8460 src_node: ast.Node.Index,
8461 ) !Zir.Inst.Ref {
8462 return gz.add(.{
8463 .tag = .extended,
8464 .data = .{ .extended = .{
8465 .opcode = opcode,
8466 .small = undefined,
8467 .operand = @bitCast(u32, gz.nodeIndexToRelative(src_node)),
8468 } },
8469 });
8470 }
8471
8472 fn addAllocExtended(
8473 gz: *GenZir,
8474 args: struct {
8475 /// Absolute node index. This function does the conversion to offset from Decl.
8476 node: ast.Node.Index,
8477 type_inst: Zir.Inst.Ref,
8478 align_inst: Zir.Inst.Ref,
8479 is_const: bool,
8480 is_comptime: bool,
8481 },
8482 ) !Zir.Inst.Ref {
8483 const astgen = gz.astgen;
8484 const gpa = astgen.gpa;
8485
8486 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8487 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8488 try astgen.extra.ensureUnusedCapacity(
8489 gpa,
8490 @typeInfo(Zir.Inst.AllocExtended).Struct.fields.len +
8491 @as(usize, @boolToInt(args.type_inst != .none)) +
8492 @as(usize, @boolToInt(args.align_inst != .none)),
8493 );
8494 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{
8495 .src_node = gz.nodeIndexToRelative(args.node),
8496 });
8497 if (args.type_inst != .none) {
8498 astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst));
8499 }
8500 if (args.align_inst != .none) {
8501 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
8502 }
8503
8504 const has_type: u4 = @boolToInt(args.type_inst != .none);
8505 const has_align: u4 = @boolToInt(args.align_inst != .none);
8506 const is_const: u4 = @boolToInt(args.is_const);
8507 const is_comptime: u4 = @boolToInt(args.is_comptime);
8508 const small: u16 = has_type | (has_align << 1) | (is_const << 2) | (is_comptime << 3);
8509
8510 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8511 astgen.instructions.appendAssumeCapacity(.{
8512 .tag = .extended,
8513 .data = .{ .extended = .{
8514 .opcode = .alloc,
8515 .small = small,
8516 .operand = payload_index,
8517 } },
8518 });
8519 gz.instructions.appendAssumeCapacity(new_index);
8520 return gz.indexToRef(new_index);
8521 }
8522
8523 fn addAsm(
8524 gz: *GenZir,
8525 args: struct {
8526 /// Absolute node index. This function does the conversion to offset from Decl.
8527 node: ast.Node.Index,
8528 asm_source: Zir.Inst.Ref,
8529 output_type_bits: u32,
8530 is_volatile: bool,
8531 outputs: []const Zir.Inst.Asm.Output,
8532 inputs: []const Zir.Inst.Asm.Input,
8533 clobbers: []const u32,
8534 },
8535 ) !Zir.Inst.Ref {
8536 const astgen = gz.astgen;
8537 const gpa = astgen.gpa;
8538
8539 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8540 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
8541 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len +
8542 args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len +
8543 args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len +
8544 args.clobbers.len);
8545
8546 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{
8547 .src_node = gz.nodeIndexToRelative(args.node),
8548 .asm_source = args.asm_source,
8549 .output_type_bits = args.output_type_bits,
8550 });
8551 for (args.outputs) |output| {
8552 _ = gz.astgen.addExtraAssumeCapacity(output);
8553 }
8554 for (args.inputs) |input| {
8555 _ = gz.astgen.addExtraAssumeCapacity(input);
8556 }
8557 gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers);
8558
8559 // * 0b00000000_000XXXXX - `outputs_len`.
8560 // * 0b000000XX_XXX00000 - `inputs_len`.
8561 // * 0b0XXXXX00_00000000 - `clobbers_len`.
8562 // * 0bX0000000_00000000 - is volatile
8563 const small: u16 = @intCast(u16, args.outputs.len) |
8564 @intCast(u16, args.inputs.len << 5) |
8565 @intCast(u16, args.clobbers.len << 10) |
8566 (@as(u16, @boolToInt(args.is_volatile)) << 15);
8567
8568 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
8569 astgen.instructions.appendAssumeCapacity(.{
8570 .tag = .extended,
8571 .data = .{ .extended = .{
8572 .opcode = .@"asm",
8573 .small = small,
8574 .operand = payload_index,
8575 } },
8576 });
8577 gz.instructions.appendAssumeCapacity(new_index);
8578 return gz.indexToRef(new_index);
8579 }
8580
8581 /// Note that this returns a `Zir.Inst.Index` not a ref.
8582 /// Does *not* append the block instruction to the scope.
8583 /// Leaves the `payload_index` field undefined.
8584 fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
8585 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8586 const gpa = gz.astgen.gpa;
8587 try gz.astgen.instructions.append(gpa, .{
8588 .tag = tag,
8589 .data = .{ .pl_node = .{
8590 .src_node = gz.nodeIndexToRelative(node),
8591 .payload_index = undefined,
8592 } },
8593 });
8594 return new_index;
8595 }
8596
8597 /// Note that this returns a `Zir.Inst.Index` not a ref.
8598 /// Leaves the `payload_index` field undefined.
8599 fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
8600 const gpa = gz.astgen.gpa;
8601 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8602 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8603 try gz.astgen.instructions.append(gpa, .{
8604 .tag = tag,
8605 .data = .{ .pl_node = .{
8606 .src_node = gz.nodeIndexToRelative(node),
8607 .payload_index = undefined,
8608 } },
8609 });
8610 gz.instructions.appendAssumeCapacity(new_index);
8611 return new_index;
8612 }
8613
8614 fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {
8615 return gz.indexToRef(try gz.addAsIndex(inst));
8616 }
8617
8618 fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {
8619 const gpa = gz.astgen.gpa;
8620 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8621 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8622
8623 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8624 gz.astgen.instructions.appendAssumeCapacity(inst);
8625 gz.instructions.appendAssumeCapacity(new_index);
8626 return new_index;
8627 }
8628};
src/Module.zig+93-939
...@@ -628,12 +628,6 @@ pub const Scope = struct {...@@ -628,12 +628,6 @@ pub const Scope = struct {
628 pub const NameHash = [16]u8;628 pub const NameHash = [16]u8;
629629
630 pub fn cast(base: *Scope, comptime T: type) ?*T {630 pub fn cast(base: *Scope, comptime T: type) ?*T {
631 if (T == Defer) {
632 switch (base.tag) {
633 .defer_normal, .defer_error => return @fieldParentPtr(T, "base", base),
634 else => return null,
635 }
636 }
637 if (base.tag != T.base_tag)631 if (base.tag != T.base_tag)
638 return null;632 return null;
639633
...@@ -643,11 +637,6 @@ pub const Scope = struct {...@@ -643,11 +637,6 @@ pub const Scope = struct {
643 pub fn ownerDecl(scope: *Scope) ?*Decl {637 pub fn ownerDecl(scope: *Scope) ?*Decl {
644 return switch (scope.tag) {638 return switch (scope.tag) {
645 .block => scope.cast(Block).?.sema.owner_decl,639 .block => scope.cast(Block).?.sema.owner_decl,
646 .gen_zir => unreachable,
647 .local_val => unreachable,
648 .local_ptr => unreachable,
649 .defer_normal => unreachable,
650 .defer_error => unreachable,
651 .file => null,640 .file => null,
652 .namespace => null,641 .namespace => null,
653 .decl_ref => scope.cast(DeclRef).?.decl,642 .decl_ref => scope.cast(DeclRef).?.decl,
...@@ -657,11 +646,6 @@ pub const Scope = struct {...@@ -657,11 +646,6 @@ pub const Scope = struct {
657 pub fn srcDecl(scope: *Scope) ?*Decl {646 pub fn srcDecl(scope: *Scope) ?*Decl {
658 return switch (scope.tag) {647 return switch (scope.tag) {
659 .block => scope.cast(Block).?.src_decl,648 .block => scope.cast(Block).?.src_decl,
660 .gen_zir => unreachable,
661 .local_val => unreachable,
662 .local_ptr => unreachable,
663 .defer_normal => unreachable,
664 .defer_error => unreachable,
665 .file => null,649 .file => null,
666 .namespace => null,650 .namespace => null,
667 .decl_ref => scope.cast(DeclRef).?.decl,651 .decl_ref => scope.cast(DeclRef).?.decl,
...@@ -672,11 +656,6 @@ pub const Scope = struct {...@@ -672,11 +656,6 @@ pub const Scope = struct {
672 pub fn namespace(scope: *Scope) *Namespace {656 pub fn namespace(scope: *Scope) *Namespace {
673 switch (scope.tag) {657 switch (scope.tag) {
674 .block => return scope.cast(Block).?.sema.owner_decl.namespace,658 .block => return scope.cast(Block).?.sema.owner_decl.namespace,
675 .gen_zir => unreachable,
676 .local_val => unreachable,
677 .local_ptr => unreachable,
678 .defer_normal => unreachable,
679 .defer_error => unreachable,
680 .file => return scope.cast(File).?.namespace,659 .file => return scope.cast(File).?.namespace,
681 .namespace => return scope.cast(Namespace).?,660 .namespace => return scope.cast(Namespace).?,
682 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,661 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,
...@@ -690,11 +669,6 @@ pub const Scope = struct {...@@ -690,11 +669,6 @@ pub const Scope = struct {
690 .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path,669 .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path,
691 .file => return @fieldParentPtr(File, "base", base).sub_file_path,670 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
692 .block => unreachable,671 .block => unreachable,
693 .gen_zir => unreachable,
694 .local_val => unreachable,
695 .local_ptr => unreachable,
696 .defer_normal => unreachable,
697 .defer_error => unreachable,
698 .decl_ref => unreachable,672 .decl_ref => unreachable,
699 }673 }
700 }674 }
...@@ -706,11 +680,6 @@ pub const Scope = struct {...@@ -706,11 +680,6 @@ pub const Scope = struct {
706 cur = switch (cur.tag) {680 cur = switch (cur.tag) {
707 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,681 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,
708 .file => return @fieldParentPtr(File, "base", cur),682 .file => return @fieldParentPtr(File, "base", cur),
709 .gen_zir => return @fieldParentPtr(GenZir, "base", cur).astgen.file,
710 .local_val => return @fieldParentPtr(LocalVal, "base", cur).gen_zir.astgen.file,
711 .local_ptr => return @fieldParentPtr(LocalPtr, "base", cur).gen_zir.astgen.file,
712 .defer_normal => @fieldParentPtr(Defer, "base", cur).parent,
713 .defer_error => @fieldParentPtr(Defer, "base", cur).parent,
714 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,683 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,
715 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,684 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,
716 };685 };
...@@ -723,15 +692,10 @@ pub const Scope = struct {...@@ -723,15 +692,10 @@ pub const Scope = struct {
723 /// Namespace owned by structs, enums, unions, and opaques for decls.692 /// Namespace owned by structs, enums, unions, and opaques for decls.
724 namespace,693 namespace,
725 block,694 block,
726 gen_zir,
727 local_val,
728 local_ptr,
729 /// Used for simple error reporting. Only contains a reference to a695 /// Used for simple error reporting. Only contains a reference to a
730 /// `Decl` for use with `srcDecl` and `ownerDecl`.696 /// `Decl` for use with `srcDecl` and `ownerDecl`.
731 /// Has no parents or children.697 /// Has no parents or children.
732 decl_ref,698 decl_ref,
733 defer_normal,
734 defer_error,
735 };699 };
736700
737 /// The container that structs, enums, unions, and opaques have.701 /// The container that structs, enums, unions, and opaques have.
...@@ -1183,907 +1147,6 @@ pub const Scope = struct {...@@ -1183,907 +1147,6 @@ pub const Scope = struct {
1183 }1147 }
1184 };1148 };
11851149
1186 /// This is a temporary structure; references to it are valid only
1187 /// while constructing a `Zir`.
1188 pub const GenZir = struct {
1189 pub const base_tag: Tag = .gen_zir;
1190 base: Scope = Scope{ .tag = base_tag },
1191 force_comptime: bool,
1192 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
1193 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.
1194 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
1195 /// The containing decl AST node.
1196 decl_node_index: ast.Node.Index,
1197 /// The containing decl line index, absolute.
1198 decl_line: u32,
1199 /// Parents can be: `GenZir`, `File`
1200 parent: *Scope,
1201 /// All `GenZir` scopes for the same ZIR share this.
1202 astgen: *AstGen,
1203 /// Keeps track of the list of instructions in this scope only. Indexes
1204 /// to instructions in `astgen`.
1205 instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{},
1206 label: ?Label = null,
1207 break_block: Zir.Inst.Index = 0,
1208 continue_block: Zir.Inst.Index = 0,
1209 /// Only valid when setBreakResultLoc is called.
1210 break_result_loc: AstGen.ResultLoc = undefined,
1211 /// When a block has a pointer result location, here it is.
1212 rl_ptr: Zir.Inst.Ref = .none,
1213 /// When a block has a type result location, here it is.
1214 rl_ty_inst: Zir.Inst.Ref = .none,
1215 /// Keeps track of how many branches of a block did not actually
1216 /// consume the result location. astgen uses this to figure out
1217 /// whether to rely on break instructions or writing to the result
1218 /// pointer for the result instruction.
1219 rvalue_rl_count: usize = 0,
1220 /// Keeps track of how many break instructions there are. When astgen is finished
1221 /// with a block, it can check this against rvalue_rl_count to find out whether
1222 /// the break instructions should be downgraded to break_void.
1223 break_count: usize = 0,
1224 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
1225 /// the labeled block ends up not needing a result location pointer.
1226 labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{},
1227 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
1228 /// so they can possibly be elided later if the labeled block ends up not needing
1229 /// a result location pointer.
1230 labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{},
1231
1232 suspend_node: ast.Node.Index = 0,
1233 nosuspend_node: ast.Node.Index = 0,
1234
1235 pub fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
1236 return .{
1237 .force_comptime = gz.force_comptime,
1238 .ref_start_index = gz.ref_start_index,
1239 .decl_node_index = gz.decl_node_index,
1240 .decl_line = gz.decl_line,
1241 .parent = scope,
1242 .astgen = gz.astgen,
1243 .suspend_node = gz.suspend_node,
1244 .nosuspend_node = gz.nosuspend_node,
1245 };
1246 }
1247
1248 pub const Label = struct {
1249 token: ast.TokenIndex,
1250 block_inst: Zir.Inst.Index,
1251 used: bool = false,
1252 };
1253
1254 pub fn refIsNoReturn(gz: GenZir, inst_ref: Zir.Inst.Ref) bool {
1255 if (inst_ref == .unreachable_value) return true;
1256 if (gz.refToIndex(inst_ref)) |inst_index| {
1257 return gz.astgen.instructions.items(.tag)[inst_index].isNoReturn();
1258 }
1259 return false;
1260 }
1261
1262 pub fn calcLine(gz: GenZir, node: ast.Node.Index) u32 {
1263 const astgen = gz.astgen;
1264 const tree = &astgen.file.tree;
1265 const node_tags = tree.nodes.items(.tag);
1266 const token_starts = tree.tokens.items(.start);
1267 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
1268 const node_start = token_starts[tree.firstToken(node)];
1269 const source = tree.source[decl_start..node_start];
1270 const loc = std.zig.findLineColumn(source, source.len);
1271 return @intCast(u32, gz.decl_line + loc.line);
1272 }
1273
1274 pub fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {
1275 return .{ .token_offset = token_index - gz.srcToken() };
1276 }
1277
1278 pub fn nodeSrcLoc(gz: GenZir, node_index: ast.Node.Index) LazySrcLoc {
1279 return .{ .node_offset = gz.nodeIndexToRelative(node_index) };
1280 }
1281
1282 pub fn nodeIndexToRelative(gz: GenZir, node_index: ast.Node.Index) i32 {
1283 return @bitCast(i32, node_index) - @bitCast(i32, gz.decl_node_index);
1284 }
1285
1286 pub fn tokenIndexToRelative(gz: GenZir, token: ast.TokenIndex) u32 {
1287 return token - gz.srcToken();
1288 }
1289
1290 pub fn srcToken(gz: GenZir) ast.TokenIndex {
1291 return gz.astgen.file.tree.firstToken(gz.decl_node_index);
1292 }
1293
1294 pub fn indexToRef(gz: GenZir, inst: Zir.Inst.Index) Zir.Inst.Ref {
1295 return @intToEnum(Zir.Inst.Ref, gz.ref_start_index + inst);
1296 }
1297
1298 pub fn refToIndex(gz: GenZir, inst: Zir.Inst.Ref) ?Zir.Inst.Index {
1299 const ref_int = @enumToInt(inst);
1300 if (ref_int >= gz.ref_start_index) {
1301 return ref_int - gz.ref_start_index;
1302 } else {
1303 return null;
1304 }
1305 }
1306
1307 pub fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void {
1308 // Depending on whether the result location is a pointer or value, different
1309 // ZIR needs to be generated. In the former case we rely on storing to the
1310 // pointer to communicate the result, and use breakvoid; in the latter case
1311 // the block break instructions will have the result values.
1312 // One more complication: when the result location is a pointer, we detect
1313 // the scenario where the result location is not consumed. In this case
1314 // we emit ZIR for the block break instructions to have the result values,
1315 // and then rvalue() on that to pass the value to the result location.
1316 switch (parent_rl) {
1317 .ty => |ty_inst| {
1318 gz.rl_ty_inst = ty_inst;
1319 gz.break_result_loc = parent_rl;
1320 },
1321 .none_or_ref => {
1322 gz.break_result_loc = .ref;
1323 },
1324 .discard, .none, .ptr, .ref => {
1325 gz.break_result_loc = parent_rl;
1326 },
1327
1328 .inferred_ptr => |ptr| {
1329 gz.rl_ptr = ptr;
1330 gz.break_result_loc = .{ .block_ptr = gz };
1331 },
1332
1333 .block_ptr => |parent_block_scope| {
1334 gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
1335 gz.rl_ptr = parent_block_scope.rl_ptr;
1336 gz.break_result_loc = .{ .block_ptr = gz };
1337 },
1338 }
1339 }
1340
1341 pub fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void {
1342 const gpa = gz.astgen.gpa;
1343 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1344 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1345 const zir_datas = gz.astgen.instructions.items(.data);
1346 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
1347 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
1348 );
1349 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
1350 }
1351
1352 pub fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void {
1353 const gpa = gz.astgen.gpa;
1354 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1355 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1356 const zir_datas = gz.astgen.instructions.items(.data);
1357 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
1358 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
1359 );
1360 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
1361 }
1362
1363 /// Same as `setBlockBody` except we don't copy instructions which are
1364 /// `store_to_block_ptr` instructions with lhs set to .none.
1365 pub fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
1366 const gpa = gz.astgen.gpa;
1367 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1368 @typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
1369 const zir_datas = gz.astgen.instructions.items(.data);
1370 const zir_tags = gz.astgen.instructions.items(.tag);
1371 const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
1372 .body_len = @intCast(u32, gz.instructions.items.len),
1373 });
1374 zir_datas[inst].pl_node.payload_index = block_pl_index;
1375 for (gz.instructions.items) |sub_inst| {
1376 if (zir_tags[sub_inst] == .store_to_block_ptr and
1377 zir_datas[sub_inst].bin.lhs == .none)
1378 {
1379 // Decrement `body_len`.
1380 gz.astgen.extra.items[block_pl_index] -= 1;
1381 continue;
1382 }
1383 gz.astgen.extra.appendAssumeCapacity(sub_inst);
1384 }
1385 }
1386
1387 pub fn addFunc(gz: *GenZir, args: struct {
1388 src_node: ast.Node.Index,
1389 param_types: []const Zir.Inst.Ref,
1390 body: []const Zir.Inst.Index,
1391 ret_ty: Zir.Inst.Ref,
1392 cc: Zir.Inst.Ref,
1393 align_inst: Zir.Inst.Ref,
1394 lib_name: u32,
1395 is_var_args: bool,
1396 is_inferred_error: bool,
1397 is_test: bool,
1398 }) !Zir.Inst.Ref {
1399 assert(args.src_node != 0);
1400 assert(args.ret_ty != .none);
1401 const astgen = gz.astgen;
1402 const gpa = astgen.gpa;
1403
1404 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1405 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1406
1407 var src_locs_buffer: [3]u32 = undefined;
1408 var src_locs: []u32 = src_locs_buffer[0..0];
1409 if (args.body.len != 0) {
1410 const tree = &astgen.file.tree;
1411 const node_tags = tree.nodes.items(.tag);
1412 const node_datas = tree.nodes.items(.data);
1413 const token_starts = tree.tokens.items(.start);
1414 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
1415 const fn_decl = args.src_node;
1416 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
1417 const block = node_datas[fn_decl].rhs;
1418 const lbrace_start = token_starts[tree.firstToken(block)];
1419 const rbrace_start = token_starts[tree.lastToken(block)];
1420 const lbrace_source = tree.source[decl_start..lbrace_start];
1421 const lbrace_loc = std.zig.findLineColumn(lbrace_source, lbrace_source.len);
1422 const rbrace_source = tree.source[lbrace_start..rbrace_start];
1423 const rbrace_loc = std.zig.findLineColumn(rbrace_source, rbrace_source.len);
1424 const lbrace_line = @intCast(u32, lbrace_loc.line);
1425 const rbrace_line = lbrace_line + @intCast(u32, rbrace_loc.line);
1426 const columns = @intCast(u32, lbrace_loc.column) |
1427 (@intCast(u32, rbrace_loc.column) << 16);
1428 src_locs_buffer[0] = lbrace_line;
1429 src_locs_buffer[1] = rbrace_line;
1430 src_locs_buffer[2] = columns;
1431 src_locs = &src_locs_buffer;
1432 }
1433
1434 if (args.cc != .none or args.lib_name != 0 or
1435 args.is_var_args or args.is_test or args.align_inst != .none)
1436 {
1437 try astgen.extra.ensureUnusedCapacity(
1438 gpa,
1439 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
1440 args.param_types.len + args.body.len + src_locs.len +
1441 @boolToInt(args.lib_name != 0) +
1442 @boolToInt(args.align_inst != .none) +
1443 @boolToInt(args.cc != .none),
1444 );
1445 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
1446 .src_node = gz.nodeIndexToRelative(args.src_node),
1447 .return_type = args.ret_ty,
1448 .param_types_len = @intCast(u32, args.param_types.len),
1449 .body_len = @intCast(u32, args.body.len),
1450 });
1451 if (args.lib_name != 0) {
1452 astgen.extra.appendAssumeCapacity(args.lib_name);
1453 }
1454 if (args.cc != .none) {
1455 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
1456 }
1457 if (args.align_inst != .none) {
1458 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
1459 }
1460 astgen.appendRefsAssumeCapacity(args.param_types);
1461 astgen.extra.appendSliceAssumeCapacity(args.body);
1462 astgen.extra.appendSliceAssumeCapacity(src_locs);
1463
1464 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1465 astgen.instructions.appendAssumeCapacity(.{
1466 .tag = .extended,
1467 .data = .{ .extended = .{
1468 .opcode = .func,
1469 .small = @bitCast(u16, Zir.Inst.ExtendedFunc.Small{
1470 .is_var_args = args.is_var_args,
1471 .is_inferred_error = args.is_inferred_error,
1472 .has_lib_name = args.lib_name != 0,
1473 .has_cc = args.cc != .none,
1474 .has_align = args.align_inst != .none,
1475 .is_test = args.is_test,
1476 }),
1477 .operand = payload_index,
1478 } },
1479 });
1480 gz.instructions.appendAssumeCapacity(new_index);
1481 return gz.indexToRef(new_index);
1482 } else {
1483 try gz.astgen.extra.ensureUnusedCapacity(
1484 gpa,
1485 @typeInfo(Zir.Inst.Func).Struct.fields.len +
1486 args.param_types.len + args.body.len + src_locs.len,
1487 );
1488
1489 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
1490 .return_type = args.ret_ty,
1491 .param_types_len = @intCast(u32, args.param_types.len),
1492 .body_len = @intCast(u32, args.body.len),
1493 });
1494 gz.astgen.appendRefsAssumeCapacity(args.param_types);
1495 gz.astgen.extra.appendSliceAssumeCapacity(args.body);
1496 gz.astgen.extra.appendSliceAssumeCapacity(src_locs);
1497
1498 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
1499 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1500 gz.astgen.instructions.appendAssumeCapacity(.{
1501 .tag = tag,
1502 .data = .{ .pl_node = .{
1503 .src_node = gz.nodeIndexToRelative(args.src_node),
1504 .payload_index = payload_index,
1505 } },
1506 });
1507 gz.instructions.appendAssumeCapacity(new_index);
1508 return gz.indexToRef(new_index);
1509 }
1510 }
1511
1512 pub fn addVar(gz: *GenZir, args: struct {
1513 align_inst: Zir.Inst.Ref,
1514 lib_name: u32,
1515 var_type: Zir.Inst.Ref,
1516 init: Zir.Inst.Ref,
1517 is_extern: bool,
1518 }) !Zir.Inst.Ref {
1519 const astgen = gz.astgen;
1520 const gpa = astgen.gpa;
1521
1522 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1523 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1524
1525 try astgen.extra.ensureUnusedCapacity(
1526 gpa,
1527 @typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
1528 @boolToInt(args.lib_name != 0) +
1529 @boolToInt(args.align_inst != .none) +
1530 @boolToInt(args.init != .none),
1531 );
1532 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
1533 .var_type = args.var_type,
1534 });
1535 if (args.lib_name != 0) {
1536 astgen.extra.appendAssumeCapacity(args.lib_name);
1537 }
1538 if (args.align_inst != .none) {
1539 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
1540 }
1541 if (args.init != .none) {
1542 astgen.extra.appendAssumeCapacity(@enumToInt(args.init));
1543 }
1544
1545 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1546 astgen.instructions.appendAssumeCapacity(.{
1547 .tag = .extended,
1548 .data = .{ .extended = .{
1549 .opcode = .variable,
1550 .small = @bitCast(u16, Zir.Inst.ExtendedVar.Small{
1551 .has_lib_name = args.lib_name != 0,
1552 .has_align = args.align_inst != .none,
1553 .has_init = args.init != .none,
1554 .is_extern = args.is_extern,
1555 }),
1556 .operand = payload_index,
1557 } },
1558 });
1559 gz.instructions.appendAssumeCapacity(new_index);
1560 return gz.indexToRef(new_index);
1561 }
1562
1563 pub fn addCall(
1564 gz: *GenZir,
1565 tag: Zir.Inst.Tag,
1566 callee: Zir.Inst.Ref,
1567 args: []const Zir.Inst.Ref,
1568 /// Absolute node index. This function does the conversion to offset from Decl.
1569 src_node: ast.Node.Index,
1570 ) !Zir.Inst.Ref {
1571 assert(callee != .none);
1572 assert(src_node != 0);
1573 const gpa = gz.astgen.gpa;
1574 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1575 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1576 try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
1577 @typeInfo(Zir.Inst.Call).Struct.fields.len + args.len);
1578
1579 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Call{
1580 .callee = callee,
1581 .args_len = @intCast(u32, args.len),
1582 });
1583 gz.astgen.appendRefsAssumeCapacity(args);
1584
1585 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1586 gz.astgen.instructions.appendAssumeCapacity(.{
1587 .tag = tag,
1588 .data = .{ .pl_node = .{
1589 .src_node = gz.nodeIndexToRelative(src_node),
1590 .payload_index = payload_index,
1591 } },
1592 });
1593 gz.instructions.appendAssumeCapacity(new_index);
1594 return gz.indexToRef(new_index);
1595 }
1596
1597 /// Note that this returns a `Zir.Inst.Index` not a ref.
1598 /// Leaves the `payload_index` field undefined.
1599 pub fn addBoolBr(
1600 gz: *GenZir,
1601 tag: Zir.Inst.Tag,
1602 lhs: Zir.Inst.Ref,
1603 ) !Zir.Inst.Index {
1604 assert(lhs != .none);
1605 const gpa = gz.astgen.gpa;
1606 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1607 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1608
1609 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1610 gz.astgen.instructions.appendAssumeCapacity(.{
1611 .tag = tag,
1612 .data = .{ .bool_br = .{
1613 .lhs = lhs,
1614 .payload_index = undefined,
1615 } },
1616 });
1617 gz.instructions.appendAssumeCapacity(new_index);
1618 return new_index;
1619 }
1620
1621 pub fn addInt(gz: *GenZir, integer: u64) !Zir.Inst.Ref {
1622 return gz.add(.{
1623 .tag = .int,
1624 .data = .{ .int = integer },
1625 });
1626 }
1627
1628 pub fn addIntBig(gz: *GenZir, limbs: []const std.math.big.Limb) !Zir.Inst.Ref {
1629 const astgen = gz.astgen;
1630 const gpa = astgen.gpa;
1631 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1632 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1633 try astgen.string_bytes.ensureUnusedCapacity(gpa, @sizeOf(std.math.big.Limb) * limbs.len);
1634
1635 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1636 astgen.instructions.appendAssumeCapacity(.{
1637 .tag = .int_big,
1638 .data = .{ .str = .{
1639 .start = @intCast(u32, astgen.string_bytes.items.len),
1640 .len = @intCast(u32, limbs.len),
1641 } },
1642 });
1643 gz.instructions.appendAssumeCapacity(new_index);
1644 astgen.string_bytes.appendSliceAssumeCapacity(mem.sliceAsBytes(limbs));
1645 return gz.indexToRef(new_index);
1646 }
1647
1648 pub fn addFloat(gz: *GenZir, number: f32, src_node: ast.Node.Index) !Zir.Inst.Ref {
1649 return gz.add(.{
1650 .tag = .float,
1651 .data = .{ .float = .{
1652 .src_node = gz.nodeIndexToRelative(src_node),
1653 .number = number,
1654 } },
1655 });
1656 }
1657
1658 pub fn addUnNode(
1659 gz: *GenZir,
1660 tag: Zir.Inst.Tag,
1661 operand: Zir.Inst.Ref,
1662 /// Absolute node index. This function does the conversion to offset from Decl.
1663 src_node: ast.Node.Index,
1664 ) !Zir.Inst.Ref {
1665 assert(operand != .none);
1666 return gz.add(.{
1667 .tag = tag,
1668 .data = .{ .un_node = .{
1669 .operand = operand,
1670 .src_node = gz.nodeIndexToRelative(src_node),
1671 } },
1672 });
1673 }
1674
1675 pub fn addPlNode(
1676 gz: *GenZir,
1677 tag: Zir.Inst.Tag,
1678 /// Absolute node index. This function does the conversion to offset from Decl.
1679 src_node: ast.Node.Index,
1680 extra: anytype,
1681 ) !Zir.Inst.Ref {
1682 const gpa = gz.astgen.gpa;
1683 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1684 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1685
1686 const payload_index = try gz.astgen.addExtra(extra);
1687 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1688 gz.astgen.instructions.appendAssumeCapacity(.{
1689 .tag = tag,
1690 .data = .{ .pl_node = .{
1691 .src_node = gz.nodeIndexToRelative(src_node),
1692 .payload_index = payload_index,
1693 } },
1694 });
1695 gz.instructions.appendAssumeCapacity(new_index);
1696 return gz.indexToRef(new_index);
1697 }
1698
1699 pub fn addExtendedPayload(
1700 gz: *GenZir,
1701 opcode: Zir.Inst.Extended,
1702 extra: anytype,
1703 ) !Zir.Inst.Ref {
1704 const gpa = gz.astgen.gpa;
1705
1706 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1707 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1708
1709 const payload_index = try gz.astgen.addExtra(extra);
1710 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1711 gz.astgen.instructions.appendAssumeCapacity(.{
1712 .tag = .extended,
1713 .data = .{ .extended = .{
1714 .opcode = opcode,
1715 .small = undefined,
1716 .operand = payload_index,
1717 } },
1718 });
1719 gz.instructions.appendAssumeCapacity(new_index);
1720 return gz.indexToRef(new_index);
1721 }
1722
1723 pub fn addExtendedMultiOp(
1724 gz: *GenZir,
1725 opcode: Zir.Inst.Extended,
1726 node: ast.Node.Index,
1727 operands: []const Zir.Inst.Ref,
1728 ) !Zir.Inst.Ref {
1729 const astgen = gz.astgen;
1730 const gpa = astgen.gpa;
1731
1732 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1733 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1734 try astgen.extra.ensureUnusedCapacity(
1735 gpa,
1736 @typeInfo(Zir.Inst.NodeMultiOp).Struct.fields.len + operands.len,
1737 );
1738
1739 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.NodeMultiOp{
1740 .src_node = gz.nodeIndexToRelative(node),
1741 });
1742 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1743 astgen.instructions.appendAssumeCapacity(.{
1744 .tag = .extended,
1745 .data = .{ .extended = .{
1746 .opcode = opcode,
1747 .small = @intCast(u16, operands.len),
1748 .operand = payload_index,
1749 } },
1750 });
1751 gz.instructions.appendAssumeCapacity(new_index);
1752 astgen.appendRefsAssumeCapacity(operands);
1753 return gz.indexToRef(new_index);
1754 }
1755
1756 pub fn addArrayTypeSentinel(
1757 gz: *GenZir,
1758 len: Zir.Inst.Ref,
1759 sentinel: Zir.Inst.Ref,
1760 elem_type: Zir.Inst.Ref,
1761 ) !Zir.Inst.Ref {
1762 const gpa = gz.astgen.gpa;
1763 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1764 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
1765
1766 const payload_index = try gz.astgen.addExtra(Zir.Inst.ArrayTypeSentinel{
1767 .sentinel = sentinel,
1768 .elem_type = elem_type,
1769 });
1770 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
1771 gz.astgen.instructions.appendAssumeCapacity(.{
1772 .tag = .array_type_sentinel,
1773 .data = .{ .array_type_sentinel = .{
1774 .len = len,
1775 .payload_index = payload_index,
1776 } },
1777 });
1778 gz.instructions.appendAssumeCapacity(new_index);
1779 return gz.indexToRef(new_index);
1780 }
1781
1782 pub fn addUnTok(
1783 gz: *GenZir,
1784 tag: Zir.Inst.Tag,
1785 operand: Zir.Inst.Ref,
1786 /// Absolute token index. This function does the conversion to Decl offset.
1787 abs_tok_index: ast.TokenIndex,
1788 ) !Zir.Inst.Ref {
1789 assert(operand != .none);
1790 return gz.add(.{
1791 .tag = tag,
1792 .data = .{ .un_tok = .{
1793 .operand = operand,
1794 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
1795 } },
1796 });
1797 }
1798
1799 pub fn addStrTok(
1800 gz: *GenZir,
1801 tag: Zir.Inst.Tag,
1802 str_index: u32,
1803 /// Absolute token index. This function does the conversion to Decl offset.
1804 abs_tok_index: ast.TokenIndex,
1805 ) !Zir.Inst.Ref {
1806 return gz.add(.{
1807 .tag = tag,
1808 .data = .{ .str_tok = .{
1809 .start = str_index,
1810 .src_tok = gz.tokenIndexToRelative(abs_tok_index),
1811 } },
1812 });
1813 }
1814
1815 pub fn addBreak(
1816 gz: *GenZir,
1817 tag: Zir.Inst.Tag,
1818 break_block: Zir.Inst.Index,
1819 operand: Zir.Inst.Ref,
1820 ) !Zir.Inst.Index {
1821 return gz.addAsIndex(.{
1822 .tag = tag,
1823 .data = .{ .@"break" = .{
1824 .block_inst = break_block,
1825 .operand = operand,
1826 } },
1827 });
1828 }
1829
1830 pub fn addBin(
1831 gz: *GenZir,
1832 tag: Zir.Inst.Tag,
1833 lhs: Zir.Inst.Ref,
1834 rhs: Zir.Inst.Ref,
1835 ) !Zir.Inst.Ref {
1836 assert(lhs != .none);
1837 assert(rhs != .none);
1838 return gz.add(.{
1839 .tag = tag,
1840 .data = .{ .bin = .{
1841 .lhs = lhs,
1842 .rhs = rhs,
1843 } },
1844 });
1845 }
1846
1847 pub fn addDecl(
1848 gz: *GenZir,
1849 tag: Zir.Inst.Tag,
1850 decl_index: u32,
1851 src_node: ast.Node.Index,
1852 ) !Zir.Inst.Ref {
1853 return gz.add(.{
1854 .tag = tag,
1855 .data = .{ .pl_node = .{
1856 .src_node = gz.nodeIndexToRelative(src_node),
1857 .payload_index = decl_index,
1858 } },
1859 });
1860 }
1861
1862 pub fn addNode(
1863 gz: *GenZir,
1864 tag: Zir.Inst.Tag,
1865 /// Absolute node index. This function does the conversion to offset from Decl.
1866 src_node: ast.Node.Index,
1867 ) !Zir.Inst.Ref {
1868 return gz.add(.{
1869 .tag = tag,
1870 .data = .{ .node = gz.nodeIndexToRelative(src_node) },
1871 });
1872 }
1873
1874 pub fn addNodeExtended(
1875 gz: *GenZir,
1876 opcode: Zir.Inst.Extended,
1877 /// Absolute node index. This function does the conversion to offset from Decl.
1878 src_node: ast.Node.Index,
1879 ) !Zir.Inst.Ref {
1880 return gz.add(.{
1881 .tag = .extended,
1882 .data = .{ .extended = .{
1883 .opcode = opcode,
1884 .small = undefined,
1885 .operand = @bitCast(u32, gz.nodeIndexToRelative(src_node)),
1886 } },
1887 });
1888 }
1889
1890 pub fn addAllocExtended(
1891 gz: *GenZir,
1892 args: struct {
1893 /// Absolute node index. This function does the conversion to offset from Decl.
1894 node: ast.Node.Index,
1895 type_inst: Zir.Inst.Ref,
1896 align_inst: Zir.Inst.Ref,
1897 is_const: bool,
1898 is_comptime: bool,
1899 },
1900 ) !Zir.Inst.Ref {
1901 const astgen = gz.astgen;
1902 const gpa = astgen.gpa;
1903
1904 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1905 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1906 try astgen.extra.ensureUnusedCapacity(
1907 gpa,
1908 @typeInfo(Zir.Inst.AllocExtended).Struct.fields.len +
1909 @as(usize, @boolToInt(args.type_inst != .none)) +
1910 @as(usize, @boolToInt(args.align_inst != .none)),
1911 );
1912 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{
1913 .src_node = gz.nodeIndexToRelative(args.node),
1914 });
1915 if (args.type_inst != .none) {
1916 astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst));
1917 }
1918 if (args.align_inst != .none) {
1919 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
1920 }
1921
1922 const has_type: u4 = @boolToInt(args.type_inst != .none);
1923 const has_align: u4 = @boolToInt(args.align_inst != .none);
1924 const is_const: u4 = @boolToInt(args.is_const);
1925 const is_comptime: u4 = @boolToInt(args.is_comptime);
1926 const small: u16 = has_type | (has_align << 1) | (is_const << 2) | (is_comptime << 3);
1927
1928 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1929 astgen.instructions.appendAssumeCapacity(.{
1930 .tag = .extended,
1931 .data = .{ .extended = .{
1932 .opcode = .alloc,
1933 .small = small,
1934 .operand = payload_index,
1935 } },
1936 });
1937 gz.instructions.appendAssumeCapacity(new_index);
1938 return gz.indexToRef(new_index);
1939 }
1940
1941 pub fn addAsm(
1942 gz: *GenZir,
1943 args: struct {
1944 /// Absolute node index. This function does the conversion to offset from Decl.
1945 node: ast.Node.Index,
1946 asm_source: Zir.Inst.Ref,
1947 output_type_bits: u32,
1948 is_volatile: bool,
1949 outputs: []const Zir.Inst.Asm.Output,
1950 inputs: []const Zir.Inst.Asm.Input,
1951 clobbers: []const u32,
1952 },
1953 ) !Zir.Inst.Ref {
1954 const astgen = gz.astgen;
1955 const gpa = astgen.gpa;
1956
1957 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1958 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1959 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len +
1960 args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len +
1961 args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len +
1962 args.clobbers.len);
1963
1964 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{
1965 .src_node = gz.nodeIndexToRelative(args.node),
1966 .asm_source = args.asm_source,
1967 .output_type_bits = args.output_type_bits,
1968 });
1969 for (args.outputs) |output| {
1970 _ = gz.astgen.addExtraAssumeCapacity(output);
1971 }
1972 for (args.inputs) |input| {
1973 _ = gz.astgen.addExtraAssumeCapacity(input);
1974 }
1975 gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers);
1976
1977 // * 0b00000000_000XXXXX - `outputs_len`.
1978 // * 0b000000XX_XXX00000 - `inputs_len`.
1979 // * 0b0XXXXX00_00000000 - `clobbers_len`.
1980 // * 0bX0000000_00000000 - is volatile
1981 const small: u16 = @intCast(u16, args.outputs.len) |
1982 @intCast(u16, args.inputs.len << 5) |
1983 @intCast(u16, args.clobbers.len << 10) |
1984 (@as(u16, @boolToInt(args.is_volatile)) << 15);
1985
1986 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1987 astgen.instructions.appendAssumeCapacity(.{
1988 .tag = .extended,
1989 .data = .{ .extended = .{
1990 .opcode = .@"asm",
1991 .small = small,
1992 .operand = payload_index,
1993 } },
1994 });
1995 gz.instructions.appendAssumeCapacity(new_index);
1996 return gz.indexToRef(new_index);
1997 }
1998
1999 /// Note that this returns a `Zir.Inst.Index` not a ref.
2000 /// Does *not* append the block instruction to the scope.
2001 /// Leaves the `payload_index` field undefined.
2002 pub fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
2003 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
2004 const gpa = gz.astgen.gpa;
2005 try gz.astgen.instructions.append(gpa, .{
2006 .tag = tag,
2007 .data = .{ .pl_node = .{
2008 .src_node = gz.nodeIndexToRelative(node),
2009 .payload_index = undefined,
2010 } },
2011 });
2012 return new_index;
2013 }
2014
2015 /// Note that this returns a `Zir.Inst.Index` not a ref.
2016 /// Leaves the `payload_index` field undefined.
2017 pub fn addCondBr(gz: *GenZir, tag: Zir.Inst.Tag, node: ast.Node.Index) !Zir.Inst.Index {
2018 const gpa = gz.astgen.gpa;
2019 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
2020 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
2021 try gz.astgen.instructions.append(gpa, .{
2022 .tag = tag,
2023 .data = .{ .pl_node = .{
2024 .src_node = gz.nodeIndexToRelative(node),
2025 .payload_index = undefined,
2026 } },
2027 });
2028 gz.instructions.appendAssumeCapacity(new_index);
2029 return new_index;
2030 }
2031
2032 pub fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {
2033 return gz.indexToRef(try gz.addAsIndex(inst));
2034 }
2035
2036 pub fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {
2037 const gpa = gz.astgen.gpa;
2038 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
2039 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
2040
2041 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
2042 gz.astgen.instructions.appendAssumeCapacity(inst);
2043 gz.instructions.appendAssumeCapacity(new_index);
2044 return new_index;
2045 }
2046 };
2047
2048 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.
2049 /// This structure lives as long as the AST generation of the Block
2050 /// node that contains the variable.
2051 pub const LocalVal = struct {
2052 pub const base_tag: Tag = .local_val;
2053 base: Scope = Scope{ .tag = base_tag },
2054 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
2055 parent: *Scope,
2056 gen_zir: *GenZir,
2057 inst: Zir.Inst.Ref,
2058 /// Source location of the corresponding variable declaration.
2059 token_src: ast.TokenIndex,
2060 /// String table index.
2061 name: u32,
2062 };
2063
2064 /// This could be a `const` or `var` local. It has a pointer instead of a value.
2065 /// This structure lives as long as the AST generation of the Block
2066 /// node that contains the variable.
2067 pub const LocalPtr = struct {
2068 pub const base_tag: Tag = .local_ptr;
2069 base: Scope = Scope{ .tag = base_tag },
2070 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
2071 parent: *Scope,
2072 gen_zir: *GenZir,
2073 ptr: Zir.Inst.Ref,
2074 /// Source location of the corresponding variable declaration.
2075 token_src: ast.TokenIndex,
2076 /// String table index.
2077 name: u32,
2078 };
2079
2080 pub const Defer = struct {
2081 base: Scope,
2082 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
2083 parent: *Scope,
2084 defer_node: ast.Node.Index,
2085 };
2086
2087 pub const DeclRef = struct {1150 pub const DeclRef = struct {
2088 pub const base_tag: Tag = .decl_ref;1151 pub const base_tag: Tag = .decl_ref;
2089 base: Scope = Scope{ .tag = base_tag },1152 base: Scope = Scope{ .tag = base_tag },
...@@ -3142,7 +2205,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node...@@ -3142,7 +2205,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
3142 }2205 }
3143 file.tree_loaded = true;2206 file.tree_loaded = true;
31442207
3145 file.zir = try AstGen.generate(gpa, file);2208 file.zir = try AstGen.generate(gpa, file.tree);
3146 file.zir_loaded = true;2209 file.zir_loaded = true;
3147 file.status = .success_zir;2210 file.status = .success_zir;
3148 log.debug("AstGen fresh success: {s}", .{file.sub_file_path});2211 log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
...@@ -4536,7 +3599,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In...@@ -4536,7 +3599,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In
4536 }3599 }
4537 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);3600 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);
4538 },3601 },
4539 .gen_zir, .local_val, .local_ptr, .defer_normal, .defer_error => unreachable,
4540 .file => unreachable,3602 .file => unreachable,
4541 .namespace => unreachable,3603 .namespace => unreachable,
4542 .decl_ref => {3604 .decl_ref => {
...@@ -4894,3 +3956,95 @@ fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void {...@@ -4894,3 +3956,95 @@ fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void {
4894 },3956 },
4895 }3957 }
4896}3958}
3959
3960pub const SwitchProngSrc = union(enum) {
3961 scalar: u32,
3962 multi: Multi,
3963 range: Multi,
3964
3965 pub const Multi = struct {
3966 prong: u32,
3967 item: u32,
3968 };
3969
3970 pub const RangeExpand = enum { none, first, last };
3971
3972 /// This function is intended to be called only when it is certain that we need
3973 /// the LazySrcLoc in order to emit a compile error.
3974 pub fn resolve(
3975 prong_src: SwitchProngSrc,
3976 decl: *Decl,
3977 switch_node_offset: i32,
3978 range_expand: RangeExpand,
3979 ) LazySrcLoc {
3980 @setCold(true);
3981 const switch_node = decl.relativeToNodeIndex(switch_node_offset);
3982 const tree = decl.namespace.file_scope.tree;
3983 const main_tokens = tree.nodes.items(.main_token);
3984 const node_datas = tree.nodes.items(.data);
3985 const node_tags = tree.nodes.items(.tag);
3986 const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
3987 const case_nodes = tree.extra_data[extra.start..extra.end];
3988
3989 var multi_i: u32 = 0;
3990 var scalar_i: u32 = 0;
3991 for (case_nodes) |case_node| {
3992 const case = switch (node_tags[case_node]) {
3993 .switch_case_one => tree.switchCaseOne(case_node),
3994 .switch_case => tree.switchCase(case_node),
3995 else => unreachable,
3996 };
3997 if (case.ast.values.len == 0)
3998 continue;
3999 if (case.ast.values.len == 1 and
4000 node_tags[case.ast.values[0]] == .identifier and
4001 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
4002 {
4003 continue;
4004 }
4005 const is_multi = case.ast.values.len != 1 or
4006 node_tags[case.ast.values[0]] == .switch_range;
4007
4008 switch (prong_src) {
4009 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc{
4010 .node_offset = decl.nodeIndexToRelative(case.ast.values[0]),
4011 },
4012 .multi => |s| if (is_multi and s.prong == multi_i) {
4013 var item_i: u32 = 0;
4014 for (case.ast.values) |item_node| {
4015 if (node_tags[item_node] == .switch_range) continue;
4016
4017 if (item_i == s.item) return LazySrcLoc{
4018 .node_offset = decl.nodeIndexToRelative(item_node),
4019 };
4020 item_i += 1;
4021 } else unreachable;
4022 },
4023 .range => |s| if (is_multi and s.prong == multi_i) {
4024 var range_i: u32 = 0;
4025 for (case.ast.values) |range| {
4026 if (node_tags[range] != .switch_range) continue;
4027
4028 if (range_i == s.item) switch (range_expand) {
4029 .none => return LazySrcLoc{
4030 .node_offset = decl.nodeIndexToRelative(range),
4031 },
4032 .first => return LazySrcLoc{
4033 .node_offset = decl.nodeIndexToRelative(node_datas[range].lhs),
4034 },
4035 .last => return LazySrcLoc{
4036 .node_offset = decl.nodeIndexToRelative(node_datas[range].rhs),
4037 },
4038 };
4039 range_i += 1;
4040 } else unreachable;
4041 },
4042 }
4043 if (is_multi) {
4044 multi_i += 1;
4045 } else {
4046 scalar_i += 1;
4047 }
4048 } else unreachable;
4049 }
4050};
src/RangeSet.zig+1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const Order = std.math.Order;2const Order = std.math.Order;
3const Value = @import("value.zig").Value;3const Value = @import("value.zig").Value;
4const RangeSet = @This();4const RangeSet = @This();
5const SwitchProngSrc = @import("AstGen.zig").SwitchProngSrc;5const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
66
7ranges: std.ArrayList(Range),7ranges: std.ArrayList(Range),
88
src/Sema.zig+13-14
...@@ -63,7 +63,6 @@ const InnerError = Module.InnerError;...@@ -63,7 +63,6 @@ const InnerError = Module.InnerError;
63const Decl = Module.Decl;63const Decl = Module.Decl;
64const LazySrcLoc = Module.LazySrcLoc;64const LazySrcLoc = Module.LazySrcLoc;
65const RangeSet = @import("RangeSet.zig");65const RangeSet = @import("RangeSet.zig");
66const AstGen = @import("AstGen.zig");
6766
68pub fn analyzeFnBody(67pub fn analyzeFnBody(
69 sema: *Sema,68 sema: *Sema,
...@@ -3361,10 +3360,10 @@ fn analyzeSwitch(...@@ -3361,10 +3360,10 @@ fn analyzeSwitch(
3361 // Validate for duplicate items, missing else prong, and invalid range.3360 // Validate for duplicate items, missing else prong, and invalid range.
3362 switch (operand.ty.zigTypeTag()) {3361 switch (operand.ty.zigTypeTag()) {
3363 .Enum => {3362 .Enum => {
3364 var seen_fields = try gpa.alloc(?AstGen.SwitchProngSrc, operand.ty.enumFieldCount());3363 var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand.ty.enumFieldCount());
3365 defer gpa.free(seen_fields);3364 defer gpa.free(seen_fields);
33663365
3367 mem.set(?AstGen.SwitchProngSrc, seen_fields, null);3366 mem.set(?Module.SwitchProngSrc, seen_fields, null);
33683367
3369 var extra_index: usize = special.end;3368 var extra_index: usize = special.end;
3370 {3369 {
...@@ -3989,8 +3988,8 @@ fn resolveSwitchItemVal(...@@ -3989,8 +3988,8 @@ fn resolveSwitchItemVal(
3989 block: *Scope.Block,3988 block: *Scope.Block,
3990 item_ref: Zir.Inst.Ref,3989 item_ref: Zir.Inst.Ref,
3991 switch_node_offset: i32,3990 switch_node_offset: i32,
3992 switch_prong_src: AstGen.SwitchProngSrc,3991 switch_prong_src: Module.SwitchProngSrc,
3993 range_expand: AstGen.SwitchProngSrc.RangeExpand,3992 range_expand: Module.SwitchProngSrc.RangeExpand,
3994) InnerError!TypedValue {3993) InnerError!TypedValue {
3995 const item = try sema.resolveInst(item_ref);3994 const item = try sema.resolveInst(item_ref);
3996 // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc3995 // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc
...@@ -4014,7 +4013,7 @@ fn validateSwitchRange(...@@ -4014,7 +4013,7 @@ fn validateSwitchRange(
4014 first_ref: Zir.Inst.Ref,4013 first_ref: Zir.Inst.Ref,
4015 last_ref: Zir.Inst.Ref,4014 last_ref: Zir.Inst.Ref,
4016 src_node_offset: i32,4015 src_node_offset: i32,
4017 switch_prong_src: AstGen.SwitchProngSrc,4016 switch_prong_src: Module.SwitchProngSrc,
4018) InnerError!void {4017) InnerError!void {
4019 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;4018 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
4020 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;4019 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
...@@ -4028,7 +4027,7 @@ fn validateSwitchItem(...@@ -4028,7 +4027,7 @@ fn validateSwitchItem(
4028 range_set: *RangeSet,4027 range_set: *RangeSet,
4029 item_ref: Zir.Inst.Ref,4028 item_ref: Zir.Inst.Ref,
4030 src_node_offset: i32,4029 src_node_offset: i32,
4031 switch_prong_src: AstGen.SwitchProngSrc,4030 switch_prong_src: Module.SwitchProngSrc,
4032) InnerError!void {4031) InnerError!void {
4033 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4032 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
4034 const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);4033 const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);
...@@ -4038,10 +4037,10 @@ fn validateSwitchItem(...@@ -4038,10 +4037,10 @@ fn validateSwitchItem(
4038fn validateSwitchItemEnum(4037fn validateSwitchItemEnum(
4039 sema: *Sema,4038 sema: *Sema,
4040 block: *Scope.Block,4039 block: *Scope.Block,
4041 seen_fields: []?AstGen.SwitchProngSrc,4040 seen_fields: []?Module.SwitchProngSrc,
4042 item_ref: Zir.Inst.Ref,4041 item_ref: Zir.Inst.Ref,
4043 src_node_offset: i32,4042 src_node_offset: i32,
4044 switch_prong_src: AstGen.SwitchProngSrc,4043 switch_prong_src: Module.SwitchProngSrc,
4045) InnerError!void {4044) InnerError!void {
4046 const mod = sema.mod;4045 const mod = sema.mod;
4047 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);4046 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
...@@ -4073,8 +4072,8 @@ fn validateSwitchItemEnum(...@@ -4073,8 +4072,8 @@ fn validateSwitchItemEnum(
4073fn validateSwitchDupe(4072fn validateSwitchDupe(
4074 sema: *Sema,4073 sema: *Sema,
4075 block: *Scope.Block,4074 block: *Scope.Block,
4076 maybe_prev_src: ?AstGen.SwitchProngSrc,4075 maybe_prev_src: ?Module.SwitchProngSrc,
4077 switch_prong_src: AstGen.SwitchProngSrc,4076 switch_prong_src: Module.SwitchProngSrc,
4078 src_node_offset: i32,4077 src_node_offset: i32,
4079) InnerError!void {4078) InnerError!void {
4080 const prev_prong_src = maybe_prev_src orelse return;4079 const prev_prong_src = maybe_prev_src orelse return;
...@@ -4108,7 +4107,7 @@ fn validateSwitchItemBool(...@@ -4108,7 +4107,7 @@ fn validateSwitchItemBool(
4108 false_count: *u8,4107 false_count: *u8,
4109 item_ref: Zir.Inst.Ref,4108 item_ref: Zir.Inst.Ref,
4110 src_node_offset: i32,4109 src_node_offset: i32,
4111 switch_prong_src: AstGen.SwitchProngSrc,4110 switch_prong_src: Module.SwitchProngSrc,
4112) InnerError!void {4111) InnerError!void {
4113 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4112 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
4114 if (item_val.toBool()) {4113 if (item_val.toBool()) {
...@@ -4122,7 +4121,7 @@ fn validateSwitchItemBool(...@@ -4122,7 +4121,7 @@ fn validateSwitchItemBool(
4122 }4121 }
4123}4122}
41244123
4125const ValueSrcMap = std.HashMap(Value, AstGen.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);4124const ValueSrcMap = std.HashMap(Value, Module.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);
41264125
4127fn validateSwitchItemSparse(4126fn validateSwitchItemSparse(
4128 sema: *Sema,4127 sema: *Sema,
...@@ -4130,7 +4129,7 @@ fn validateSwitchItemSparse(...@@ -4130,7 +4129,7 @@ fn validateSwitchItemSparse(
4130 seen_values: *ValueSrcMap,4129 seen_values: *ValueSrcMap,
4131 item_ref: Zir.Inst.Ref,4130 item_ref: Zir.Inst.Ref,
4132 src_node_offset: i32,4131 src_node_offset: i32,
4133 switch_prong_src: AstGen.SwitchProngSrc,4132 switch_prong_src: Module.SwitchProngSrc,
4134) InnerError!void {4133) InnerError!void {
4135 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;4134 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
4136 const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;4135 const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;
src/main.zig+1-1
...@@ -3562,7 +3562,7 @@ pub fn cmdAstgen(...@@ -3562,7 +3562,7 @@ pub fn cmdAstgen(
3562 process.exit(1);3562 process.exit(1);
3563 }3563 }
35643564
3565 file.zir = try AstGen.generate(gpa, &file);3565 file.zir = try AstGen.generate(gpa, file.tree);
3566 file.zir_loaded = true;3566 file.zir_loaded = true;
3567 defer file.zir.deinit(gpa);3567 defer file.zir.deinit(gpa);
35683568