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 @@
11 * implement lazy struct field resolution; don't resolve struct fields until
22 they are needed.
3 * decouple AstGen from Module, Compilation
43 * AstGen threadlocal
54 * extern "foo" for vars and for functions
65 * 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;
1313const ArrayListUnmanaged = std.ArrayListUnmanaged;
1414
1515const Zir = @import("Zir.zig");
16const Module = @import("Module.zig");
1716const 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;
2317const BuiltinFn = @import("BuiltinFn.zig");
2418
2519gpa: *Allocator,
26file: *Scope.File,
20tree: *const ast.Tree,
2721instructions: std.MultiArrayList(Zir.Inst) = .{},
2822extra: ArrayListUnmanaged(u32) = .{},
2923string_bytes: ArrayListUnmanaged(u8) = .{},
......@@ -37,13 +31,15 @@ fn_block: ?*GenZir = null,
3731/// String table indexes, keeps track of all `@import` operands.
3832imports: 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 {
4137 const fields = std.meta.fields(@TypeOf(extra));
4238 try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len);
4339 return addExtraAssumeCapacity(astgen, extra);
4440}
4541
46pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
42fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
4743 const fields = std.meta.fields(@TypeOf(extra));
4844 const result = @intCast(u32, astgen.extra.items.len);
4945 inline for (fields) |field| {
......@@ -57,24 +53,24 @@ pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
5753 return result;
5854}
5955
60pub fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void {
56fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void {
6157 const coerced = @bitCast([]const u32, refs);
6258 return astgen.extra.appendSlice(astgen.gpa, coerced);
6359}
6460
65pub fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void {
61fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void {
6662 const coerced = @bitCast([]const u32, refs);
6763 astgen.extra.appendSliceAssumeCapacity(coerced);
6864}
6965
70pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
66pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
7167 var arena = std.heap.ArenaAllocator.init(gpa);
7268 defer arena.deinit();
7369
7470 var astgen: AstGen = .{
7571 .gpa = gpa,
7672 .arena = &arena.allocator,
77 .file = file,
73 .tree = &tree,
7874 };
7975 defer astgen.deinit(gpa);
8076
......@@ -83,16 +79,16 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
8379
8480 // We expect at least as many ZIR instructions and extra data items
8581 // as AST nodes.
86 try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len);
82 try astgen.instructions.ensureTotalCapacity(gpa, tree.nodes.len);
8783
8884 // First few indexes of extra are reserved and set at the end.
8985 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);
9187 astgen.extra.items.len += reserved_count;
9288
9389 var gen_scope: GenZir = .{
9490 .force_comptime = true,
95 .parent = &file.base,
91 .parent = null,
9692 .decl_node_index = 0,
9793 .decl_line = 0,
9894 .astgen = &astgen,
......@@ -104,7 +100,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
104100 .ast = .{
105101 .main_token = undefined,
106102 .enum_token = null,
107 .members = file.tree.rootDecls(),
103 .members = tree.rootDecls(),
108104 .arg = 0,
109105 },
110106 };
......@@ -250,7 +246,7 @@ pub const ResultLoc = union(enum) {
250246pub const align_rl: ResultLoc = .{ .ty = .u16_type };
251247pub 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 {
254250 const prev_force_comptime = gz.force_comptime;
255251 gz.force_comptime = true;
256252 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
260256
261257fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
262258 const astgen = gz.astgen;
263 const tree = &astgen.file.tree;
259 const tree = astgen.tree;
264260 const node_tags = tree.nodes.items(.tag);
265261 const main_tokens = tree.nodes.items(.main_token);
266262 switch (node_tags[node]) {
......@@ -453,9 +449,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Ins
453449/// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
454450/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
455451/// 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 {
457453 const astgen = gz.astgen;
458 const tree = &astgen.file.tree;
454 const tree = astgen.tree;
459455 const main_tokens = tree.nodes.items(.main_token);
460456 const token_tags = tree.tokens.items(.tag);
461457 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
888884 }
889885}
890886
891pub fn nosuspendExpr(
887fn nosuspendExpr(
892888 gz: *GenZir,
893889 scope: *Scope,
894890 rl: ResultLoc,
......@@ -896,7 +892,7 @@ pub fn nosuspendExpr(
896892) InnerError!Zir.Inst.Ref {
897893 const astgen = gz.astgen;
898894 const gpa = astgen.gpa;
899 const tree = &astgen.file.tree;
895 const tree = astgen.tree;
900896 const node_datas = tree.nodes.items(.data);
901897 const body_node = node_datas[node].lhs;
902898 assert(body_node != 0);
......@@ -911,7 +907,7 @@ pub fn nosuspendExpr(
911907 return rvalue(gz, scope, rl, result, node);
912908}
913909
914pub fn suspendExpr(
910fn suspendExpr(
915911 gz: *GenZir,
916912 scope: *Scope,
917913 rl: ResultLoc,
......@@ -919,7 +915,7 @@ pub fn suspendExpr(
919915) InnerError!Zir.Inst.Ref {
920916 const astgen = gz.astgen;
921917 const gpa = astgen.gpa;
922 const tree = &astgen.file.tree;
918 const tree = astgen.tree;
923919 const node_datas = tree.nodes.items(.data);
924920 const body_node = node_datas[node].lhs;
925921
......@@ -951,14 +947,14 @@ pub fn suspendExpr(
951947 return gz.indexToRef(suspend_inst);
952948}
953949
954pub fn awaitExpr(
950fn awaitExpr(
955951 gz: *GenZir,
956952 scope: *Scope,
957953 rl: ResultLoc,
958954 node: ast.Node.Index,
959955) InnerError!Zir.Inst.Ref {
960956 const astgen = gz.astgen;
961 const tree = &astgen.file.tree;
957 const tree = astgen.tree;
962958 const node_datas = tree.nodes.items(.data);
963959 const rhs_node = node_datas[node].lhs;
964960
......@@ -973,14 +969,14 @@ pub fn awaitExpr(
973969 return rvalue(gz, scope, rl, result, node);
974970}
975971
976pub fn resumeExpr(
972fn resumeExpr(
977973 gz: *GenZir,
978974 scope: *Scope,
979975 rl: ResultLoc,
980976 node: ast.Node.Index,
981977) InnerError!Zir.Inst.Ref {
982978 const astgen = gz.astgen;
983 const tree = &astgen.file.tree;
979 const tree = astgen.tree;
984980 const node_datas = tree.nodes.items(.data);
985981 const rhs_node = node_datas[node].lhs;
986982 const operand = try expr(gz, scope, .none, rhs_node);
......@@ -988,7 +984,7 @@ pub fn resumeExpr(
988984 return rvalue(gz, scope, rl, result, node);
989985}
990986
991pub fn fnProtoExpr(
987fn fnProtoExpr(
992988 gz: *GenZir,
993989 scope: *Scope,
994990 rl: ResultLoc,
......@@ -996,7 +992,7 @@ pub fn fnProtoExpr(
996992) InnerError!Zir.Inst.Ref {
997993 const astgen = gz.astgen;
998994 const gpa = astgen.gpa;
999 const tree = &astgen.file.tree;
995 const tree = astgen.tree;
1000996 const token_tags = tree.tokens.items(.tag);
1001997
1002998 const is_extern = blk: {
......@@ -1093,7 +1089,7 @@ pub fn fnProtoExpr(
10931089 return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node);
10941090}
10951091
1096pub fn arrayInitExpr(
1092fn arrayInitExpr(
10971093 gz: *GenZir,
10981094 scope: *Scope,
10991095 rl: ResultLoc,
......@@ -1101,7 +1097,7 @@ pub fn arrayInitExpr(
11011097 array_init: ast.full.ArrayInit,
11021098) InnerError!Zir.Inst.Ref {
11031099 const astgen = gz.astgen;
1104 const tree = &astgen.file.tree;
1100 const tree = astgen.tree;
11051101 const gpa = astgen.gpa;
11061102 const node_tags = tree.nodes.items(.tag);
11071103 const main_tokens = tree.nodes.items(.main_token);
......@@ -1192,7 +1188,7 @@ pub fn arrayInitExpr(
11921188 }
11931189}
11941190
1195pub fn arrayInitExprRlNone(
1191fn arrayInitExprRlNone(
11961192 gz: *GenZir,
11971193 scope: *Scope,
11981194 rl: ResultLoc,
......@@ -1215,7 +1211,7 @@ pub fn arrayInitExprRlNone(
12151211 return init_inst;
12161212}
12171213
1218pub fn arrayInitExprRlTy(
1214fn arrayInitExprRlTy(
12191215 gz: *GenZir,
12201216 scope: *Scope,
12211217 rl: ResultLoc,
......@@ -1243,7 +1239,7 @@ pub fn arrayInitExprRlTy(
12431239 return init_inst;
12441240}
12451241
1246pub fn arrayInitExprRlPtr(
1242fn arrayInitExprRlPtr(
12471243 gz: *GenZir,
12481244 scope: *Scope,
12491245 rl: ResultLoc,
......@@ -1273,7 +1269,7 @@ pub fn arrayInitExprRlPtr(
12731269 return .void_value;
12741270}
12751271
1276pub fn structInitExpr(
1272fn structInitExpr(
12771273 gz: *GenZir,
12781274 scope: *Scope,
12791275 rl: ResultLoc,
......@@ -1281,7 +1277,7 @@ pub fn structInitExpr(
12811277 struct_init: ast.full.StructInit,
12821278) InnerError!Zir.Inst.Ref {
12831279 const astgen = gz.astgen;
1284 const tree = &astgen.file.tree;
1280 const tree = astgen.tree;
12851281 const gpa = astgen.gpa;
12861282
12871283 if (struct_init.ast.fields.len == 0) {
......@@ -1351,7 +1347,7 @@ pub fn structInitExpr(
13511347 }
13521348}
13531349
1354pub fn structInitExprRlNone(
1350fn structInitExprRlNone(
13551351 gz: *GenZir,
13561352 scope: *Scope,
13571353 rl: ResultLoc,
......@@ -1361,7 +1357,7 @@ pub fn structInitExprRlNone(
13611357) InnerError!Zir.Inst.Ref {
13621358 const astgen = gz.astgen;
13631359 const gpa = astgen.gpa;
1364 const tree = &astgen.file.tree;
1360 const tree = astgen.tree;
13651361
13661362 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);
13671363 defer gpa.free(fields_list);
......@@ -1386,7 +1382,7 @@ pub fn structInitExprRlNone(
13861382 return init_inst;
13871383}
13881384
1389pub fn structInitExprRlPtr(
1385fn structInitExprRlPtr(
13901386 gz: *GenZir,
13911387 scope: *Scope,
13921388 rl: ResultLoc,
......@@ -1396,7 +1392,7 @@ pub fn structInitExprRlPtr(
13961392) InnerError!Zir.Inst.Ref {
13971393 const astgen = gz.astgen;
13981394 const gpa = astgen.gpa;
1399 const tree = &astgen.file.tree;
1395 const tree = astgen.tree;
14001396
14011397 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);
14021398 defer gpa.free(field_ptr_list);
......@@ -1418,7 +1414,7 @@ pub fn structInitExprRlPtr(
14181414 return .void_value;
14191415}
14201416
1421pub fn structInitExprRlTy(
1417fn structInitExprRlTy(
14221418 gz: *GenZir,
14231419 scope: *Scope,
14241420 rl: ResultLoc,
......@@ -1429,7 +1425,7 @@ pub fn structInitExprRlTy(
14291425) InnerError!Zir.Inst.Ref {
14301426 const astgen = gz.astgen;
14311427 const gpa = astgen.gpa;
1432 const tree = &astgen.file.tree;
1428 const tree = astgen.tree;
14331429
14341430 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);
14351431 defer gpa.free(fields_list);
......@@ -1486,7 +1482,7 @@ fn comptimeExprAst(
14861482 if (gz.force_comptime) {
14871483 return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{});
14881484 }
1489 const tree = &astgen.file.tree;
1485 const tree = astgen.tree;
14901486 const node_datas = tree.nodes.items(.data);
14911487 const body_node = node_datas[node].lhs;
14921488 gz.force_comptime = true;
......@@ -1497,7 +1493,7 @@ fn comptimeExprAst(
14971493
14981494fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
14991495 const astgen = parent_gz.astgen;
1500 const tree = &astgen.file.tree;
1496 const tree = astgen.tree;
15011497 const node_datas = tree.nodes.items(.data);
15021498 const break_label = node_datas[node].lhs;
15031499 const rhs = node_datas[node].rhs;
......@@ -1520,7 +1516,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
15201516 } else if (block_gz.break_block != 0) {
15211517 break :blk block_gz.break_block;
15221518 }
1523 scope = block_gz.parent;
1519 scope = block_gz.parent orelse break;
15241520 continue;
15251521 };
15261522
......@@ -1558,19 +1554,19 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
15581554 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
15591555 },
15601556 .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 },
15671557 }
15681558 }
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 }
15691565}
15701566
15711567fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
15721568 const astgen = parent_gz.astgen;
1573 const tree = &astgen.file.tree;
1569 const tree = astgen.tree;
15741570 const node_datas = tree.nodes.items(.data);
15751571 const break_label = node_datas[node].lhs;
15761572
......@@ -1582,7 +1578,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
15821578 const gen_zir = scope.cast(GenZir).?;
15831579 const continue_block = gen_zir.continue_block;
15841580 if (continue_block == 0) {
1585 scope = gen_zir.parent;
1581 scope = gen_zir.parent orelse break;
15861582 continue;
15871583 }
15881584 if (break_label != 0) blk: {
......@@ -1593,7 +1589,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
15931589 }
15941590 }
15951591 // found continue but either it has a different label, or no label
1596 scope = gen_zir.parent;
1592 scope = gen_zir.parent orelse break;
15971593 continue;
15981594 }
15991595
......@@ -1610,17 +1606,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
16101606 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
16111607 },
16121608 .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 },
16191609 }
16201610 }
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 }
16211617}
16221618
1623pub fn blockExpr(
1619fn blockExpr(
16241620 gz: *GenZir,
16251621 scope: *Scope,
16261622 rl: ResultLoc,
......@@ -1631,7 +1627,7 @@ pub fn blockExpr(
16311627 defer tracy.end();
16321628
16331629 const astgen = gz.astgen;
1634 const tree = &astgen.file.tree;
1630 const tree = astgen.tree;
16351631 const main_tokens = tree.nodes.items(.main_token);
16361632 const token_tags = tree.tokens.items(.tag);
16371633
......@@ -1655,7 +1651,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
16551651 const gen_zir = scope.cast(GenZir).?;
16561652 if (gen_zir.label) |prev_label| {
16571653 if (try astgen.tokenIdentEql(label, prev_label.token)) {
1658 const tree = &astgen.file.tree;
1654 const tree = astgen.tree;
16591655 const main_tokens = tree.nodes.items(.main_token);
16601656
16611657 const label_name = try astgen.identifierTokenString(label);
......@@ -1670,12 +1666,11 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke
16701666 });
16711667 }
16721668 }
1673 scope = gen_zir.parent;
1669 scope = gen_zir.parent orelse return;
16741670 },
16751671 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
16761672 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
16771673 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
1678 else => return,
16791674 }
16801675 }
16811676}
......@@ -1694,7 +1689,7 @@ fn labeledBlockExpr(
16941689 assert(zir_tag == .block);
16951690
16961691 const astgen = gz.astgen;
1697 const tree = &astgen.file.tree;
1692 const tree = astgen.tree;
16981693 const main_tokens = tree.nodes.items(.main_token);
16991694 const token_tags = tree.tokens.items(.tag);
17001695
......@@ -1768,7 +1763,7 @@ fn blockExprStmts(
17681763 statements: []const ast.Node.Index,
17691764) !void {
17701765 const astgen = gz.astgen;
1771 const tree = &astgen.file.tree;
1766 const tree = astgen.tree;
17721767 const main_tokens = tree.nodes.items(.main_token);
17731768 const node_tags = tree.nodes.items(.tag);
17741769
......@@ -2108,13 +2103,13 @@ fn genDefers(
21082103 err_code: Zir.Inst.Ref,
21092104) InnerError!void {
21102105 const astgen = gz.astgen;
2111 const tree = &astgen.file.tree;
2106 const tree = astgen.tree;
21122107 const node_datas = tree.nodes.items(.data);
21132108
21142109 var scope = inner_scope;
21152110 while (scope != outer_scope) {
21162111 switch (scope.tag) {
2117 .gen_zir => scope = scope.cast(GenZir).?.parent,
2112 .gen_zir => scope = scope.cast(GenZir).?.parent.?,
21182113 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
21192114 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
21202115 .defer_normal => {
......@@ -2130,7 +2125,6 @@ fn genDefers(
21302125 const expr_node = node_datas[defer_scope.defer_node].rhs;
21312126 try unusedResultExpr(gz, defer_scope.parent, expr_node);
21322127 },
2133 else => unreachable,
21342128 }
21352129 }
21362130}
......@@ -2161,7 +2155,7 @@ fn varDecl(
21612155 try emitDbgNode(gz, node);
21622156 const astgen = gz.astgen;
21632157 const gpa = astgen.gpa;
2164 const tree = &astgen.file.tree;
2158 const tree = astgen.tree;
21652159 const token_tags = tree.tokens.items(.tag);
21662160
21672161 const name_token = var_decl.ast.mut_token + 1;
......@@ -2201,10 +2195,8 @@ fn varDecl(
22012195 }
22022196 s = local_ptr.parent;
22032197 },
2204 .gen_zir => s = s.cast(GenZir).?.parent,
2198 .gen_zir => s = s.cast(GenZir).?.parent orelse break,
22052199 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
2206 .file => break,
2207 else => unreachable,
22082200 };
22092201 }
22102202
......@@ -2402,7 +2394,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
24022394 if (gz.force_comptime) return;
24032395
24042396 const astgen = gz.astgen;
2405 const tree = &astgen.file.tree;
2397 const tree = astgen.tree;
24062398 const node_tags = tree.nodes.items(.tag);
24072399 const token_starts = tree.tokens.items(.start);
24082400 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
......@@ -2420,7 +2412,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
24202412fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
24212413 try emitDbgNode(gz, infix_node);
24222414 const astgen = gz.astgen;
2423 const tree = &astgen.file.tree;
2415 const tree = astgen.tree;
24242416 const node_datas = tree.nodes.items(.data);
24252417 const main_tokens = tree.nodes.items(.main_token);
24262418 const node_tags = tree.nodes.items(.tag);
......@@ -2447,7 +2439,7 @@ fn assignOp(
24472439) InnerError!void {
24482440 try emitDbgNode(gz, infix_node);
24492441 const astgen = gz.astgen;
2450 const tree = &astgen.file.tree;
2442 const tree = astgen.tree;
24512443 const node_datas = tree.nodes.items(.data);
24522444
24532445 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
......@@ -2470,7 +2462,7 @@ fn assignShift(
24702462) InnerError!void {
24712463 try emitDbgNode(gz, infix_node);
24722464 const astgen = gz.astgen;
2473 const tree = &astgen.file.tree;
2465 const tree = astgen.tree;
24742466 const node_datas = tree.nodes.items(.data);
24752467
24762468 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
......@@ -2487,7 +2479,7 @@ fn assignShift(
24872479
24882480fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
24892481 const astgen = gz.astgen;
2490 const tree = &astgen.file.tree;
2482 const tree = astgen.tree;
24912483 const node_datas = tree.nodes.items(.data);
24922484
24932485 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
24972489
24982490fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
24992491 const astgen = gz.astgen;
2500 const tree = &astgen.file.tree;
2492 const tree = astgen.tree;
25012493 const node_datas = tree.nodes.items(.data);
25022494
25032495 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
......@@ -2513,7 +2505,7 @@ fn negation(
25132505 tag: Zir.Inst.Tag,
25142506) InnerError!Zir.Inst.Ref {
25152507 const astgen = gz.astgen;
2516 const tree = &astgen.file.tree;
2508 const tree = astgen.tree;
25172509 const node_datas = tree.nodes.items(.data);
25182510
25192511 const operand = try expr(gz, scope, .none, node_datas[node].lhs);
......@@ -2529,7 +2521,7 @@ fn ptrType(
25292521 ptr_info: ast.full.PtrType,
25302522) InnerError!Zir.Inst.Ref {
25312523 const astgen = gz.astgen;
2532 const tree = &astgen.file.tree;
2524 const tree = astgen.tree;
25332525
25342526 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
25352527
......@@ -2612,7 +2604,7 @@ fn ptrType(
26122604
26132605fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
26142606 const astgen = gz.astgen;
2615 const tree = &astgen.file.tree;
2607 const tree = astgen.tree;
26162608 const node_datas = tree.nodes.items(.data);
26172609 const node_tags = tree.nodes.items(.tag);
26182610 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
26322624
26332625fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
26342626 const astgen = gz.astgen;
2635 const tree = &astgen.file.tree;
2627 const tree = astgen.tree;
26362628 const node_datas = tree.nodes.items(.data);
26372629 const node_tags = tree.nodes.items(.tag);
26382630 const main_tokens = tree.nodes.items(.main_token);
......@@ -2696,7 +2688,7 @@ fn fnDecl(
26962688 fn_proto: ast.full.FnProto,
26972689) InnerError!void {
26982690 const gpa = astgen.gpa;
2699 const tree = &astgen.file.tree;
2691 const tree = astgen.tree;
27002692 const token_tags = tree.tokens.items(.tag);
27012693
27022694 // We insert this at the beginning so that its instruction index marks the
......@@ -2937,7 +2929,7 @@ fn globalVarDecl(
29372929 var_decl: ast.full.VarDecl,
29382930) InnerError!void {
29392931 const gpa = astgen.gpa;
2940 const tree = &astgen.file.tree;
2932 const tree = astgen.tree;
29412933 const token_tags = tree.tokens.items(.tag);
29422934
29432935 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
......@@ -3076,7 +3068,7 @@ fn comptimeDecl(
30763068 node: ast.Node.Index,
30773069) InnerError!void {
30783070 const gpa = astgen.gpa;
3079 const tree = &astgen.file.tree;
3071 const tree = astgen.tree;
30803072 const node_datas = tree.nodes.items(.data);
30813073 const body_node = node_datas[node].lhs;
30823074
......@@ -3122,7 +3114,7 @@ fn usingnamespaceDecl(
31223114 node: ast.Node.Index,
31233115) InnerError!void {
31243116 const gpa = astgen.gpa;
3125 const tree = &astgen.file.tree;
3117 const tree = astgen.tree;
31263118 const node_datas = tree.nodes.items(.data);
31273119
31283120 const type_expr = node_datas[node].lhs;
......@@ -3172,7 +3164,7 @@ fn testDecl(
31723164 node: ast.Node.Index,
31733165) InnerError!void {
31743166 const gpa = astgen.gpa;
3175 const tree = &astgen.file.tree;
3167 const tree = astgen.tree;
31763168 const node_datas = tree.nodes.items(.data);
31773169 const body_node = node_datas[node].rhs;
31783170
......@@ -3271,7 +3263,7 @@ fn structDeclInner(
32713263
32723264 const astgen = gz.astgen;
32733265 const gpa = astgen.gpa;
3274 const tree = &astgen.file.tree;
3266 const tree = astgen.tree;
32753267 const node_tags = tree.nodes.items(.tag);
32763268 const node_datas = tree.nodes.items(.data);
32773269
......@@ -3483,7 +3475,7 @@ fn unionDeclInner(
34833475) InnerError!Zir.Inst.Ref {
34843476 const astgen = gz.astgen;
34853477 const gpa = astgen.gpa;
3486 const tree = &astgen.file.tree;
3478 const tree = astgen.tree;
34873479 const node_tags = tree.nodes.items(.tag);
34883480 const node_datas = tree.nodes.items(.data);
34893481
......@@ -3705,7 +3697,7 @@ fn containerDecl(
37053697) InnerError!Zir.Inst.Ref {
37063698 const astgen = gz.astgen;
37073699 const gpa = astgen.gpa;
3708 const tree = &astgen.file.tree;
3700 const tree = astgen.tree;
37093701 const token_tags = tree.tokens.items(.tag);
37103702 const node_tags = tree.nodes.items(.tag);
37113703 const node_datas = tree.nodes.items(.data);
......@@ -4149,7 +4141,7 @@ fn errorSetDecl(
41494141) InnerError!Zir.Inst.Ref {
41504142 const astgen = gz.astgen;
41514143 const gpa = astgen.gpa;
4152 const tree = &astgen.file.tree;
4144 const tree = astgen.tree;
41534145 const main_tokens = tree.nodes.items(.main_token);
41544146 const token_tags = tree.tokens.items(.tag);
41554147
......@@ -4189,7 +4181,7 @@ fn tryExpr(
41894181 operand_node: ast.Node.Index,
41904182) InnerError!Zir.Inst.Ref {
41914183 const astgen = parent_gz.astgen;
4192 const tree = &astgen.file.tree;
4184 const tree = astgen.tree;
41934185
41944186 const fn_block = astgen.fn_block orelse {
41954187 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
......@@ -4272,7 +4264,7 @@ fn orelseCatchExpr(
42724264 payload_token: ?ast.TokenIndex,
42734265) InnerError!Zir.Inst.Ref {
42744266 const astgen = parent_gz.astgen;
4275 const tree = &astgen.file.tree;
4267 const tree = astgen.tree;
42764268
42774269 var block_scope = parent_gz.makeSubBlock(scope);
42784270 block_scope.setBreakResultLoc(rl);
......@@ -4421,14 +4413,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: ast.TokenIndex, token2: ast.TokenIndex
44214413 return mem.eql(u8, ident_name_1, ident_name_2);
44224414}
44234415
4424pub fn fieldAccess(
4416fn fieldAccess(
44254417 gz: *GenZir,
44264418 scope: *Scope,
44274419 rl: ResultLoc,
44284420 node: ast.Node.Index,
44294421) InnerError!Zir.Inst.Ref {
44304422 const astgen = gz.astgen;
4431 const tree = &astgen.file.tree;
4423 const tree = astgen.tree;
44324424 const main_tokens = tree.nodes.items(.main_token);
44334425 const node_datas = tree.nodes.items(.data);
44344426
......@@ -4455,7 +4447,7 @@ fn arrayAccess(
44554447 node: ast.Node.Index,
44564448) InnerError!Zir.Inst.Ref {
44574449 const astgen = gz.astgen;
4458 const tree = &astgen.file.tree;
4450 const tree = astgen.tree;
44594451 const main_tokens = tree.nodes.items(.main_token);
44604452 const node_datas = tree.nodes.items(.data);
44614453 switch (rl) {
......@@ -4480,7 +4472,7 @@ fn simpleBinOp(
44804472 op_inst_tag: Zir.Inst.Tag,
44814473) InnerError!Zir.Inst.Ref {
44824474 const astgen = gz.astgen;
4483 const tree = &astgen.file.tree;
4475 const tree = astgen.tree;
44844476 const node_datas = tree.nodes.items(.data);
44854477
44864478 const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{
......@@ -4512,7 +4504,7 @@ fn boolBinOp(
45124504 zir_tag: Zir.Inst.Tag,
45134505) InnerError!Zir.Inst.Ref {
45144506 const astgen = gz.astgen;
4515 const tree = &astgen.file.tree;
4507 const tree = astgen.tree;
45164508 const node_datas = tree.nodes.items(.data);
45174509
45184510 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
......@@ -4538,7 +4530,7 @@ fn ifExpr(
45384530 if_full: ast.full.If,
45394531) InnerError!Zir.Inst.Ref {
45404532 const astgen = parent_gz.astgen;
4541 const tree = &astgen.file.tree;
4533 const tree = astgen.tree;
45424534 const token_tags = tree.tokens.items(.tag);
45434535
45444536 var block_scope = parent_gz.makeSubBlock(scope);
......@@ -4765,7 +4757,7 @@ fn whileExpr(
47654757 while_full: ast.full.While,
47664758) InnerError!Zir.Inst.Ref {
47674759 const astgen = parent_gz.astgen;
4768 const tree = &astgen.file.tree;
4760 const tree = astgen.tree;
47694761 const token_tags = tree.tokens.items(.tag);
47704762
47714763 if (while_full.label_token) |label_token| {
......@@ -4967,7 +4959,7 @@ fn forExpr(
49674959 }
49684960 // Set up variables and constants.
49694961 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
4970 const tree = &astgen.file.tree;
4962 const tree = astgen.tree;
49714963 const token_tags = tree.tokens.items(.tag);
49724964
49734965 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);
......@@ -5123,111 +5115,6 @@ fn forExpr(
51235115 );
51245116}
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
52315118fn switchExpr(
52325119 parent_gz: *GenZir,
52335120 scope: *Scope,
......@@ -5236,7 +5123,7 @@ fn switchExpr(
52365123) InnerError!Zir.Inst.Ref {
52375124 const astgen = parent_gz.astgen;
52385125 const gpa = astgen.gpa;
5239 const tree = &astgen.file.tree;
5126 const tree = astgen.tree;
52405127 const node_datas = tree.nodes.items(.data);
52415128 const node_tags = tree.nodes.items(.tag);
52425129 const main_tokens = tree.nodes.items(.main_token);
......@@ -5348,9 +5235,7 @@ fn switchExpr(
53485235 continue;
53495236 }
53505237
5351 if (case.ast.values.len == 1 and
5352 getRangeNode(node_tags, node_datas, case.ast.values[0]) == null)
5353 {
5238 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
53545239 scalar_cases_len += 1;
53555240 } else {
53565241 multi_cases_len += 1;
......@@ -5472,7 +5357,7 @@ fn switchExpr(
54725357 case_scope.instructions.shrinkRetainingCapacity(0);
54735358
54745359 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
54775362 const sub_scope = blk: {
54785363 const payload_token = case.payload_token orelse break :blk &case_scope.base;
......@@ -5528,7 +5413,7 @@ fn switchExpr(
55285413 // items
55295414 var items_len: u32 = 0;
55305415 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;
55325417 items_len += 1;
55335418
55345419 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
......@@ -5537,8 +5422,8 @@ fn switchExpr(
55375422
55385423 // ranges
55395424 var ranges_len: u32 = 0;
5540 for (case.ast.values) |item_node| {
5541 const range = getRangeNode(node_tags, node_datas, item_node) orelse continue;
5425 for (case.ast.values) |range| {
5426 if (node_tags[range] != .switch_range) continue;
55425427 ranges_len += 1;
55435428
55445429 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
......@@ -5824,7 +5709,7 @@ fn switchExpr(
58245709
58255710fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
58265711 const astgen = gz.astgen;
5827 const tree = &astgen.file.tree;
5712 const tree = astgen.tree;
58285713 const node_datas = tree.nodes.items(.data);
58295714 const main_tokens = tree.nodes.items(.main_token);
58305715
......@@ -5857,7 +5742,7 @@ fn identifier(
58575742 defer tracy.end();
58585743
58595744 const astgen = gz.astgen;
5860 const tree = &astgen.file.tree;
5745 const tree = astgen.tree;
58615746 const main_tokens = tree.nodes.items(.main_token);
58625747
58635748 const ident_token = main_tokens[ident];
......@@ -5922,8 +5807,8 @@ fn identifier(
59225807 }
59235808 s = local_ptr.parent;
59245809 },
5925 .gen_zir => s = s.cast(GenZir).?.parent,
5926 else => break,
5810 .gen_zir => s = s.cast(GenZir).?.parent orelse break,
5811 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
59275812 };
59285813 }
59295814
......@@ -5946,7 +5831,7 @@ fn stringLiteral(
59465831 node: ast.Node.Index,
59475832) InnerError!Zir.Inst.Ref {
59485833 const astgen = gz.astgen;
5949 const tree = astgen.file.tree;
5834 const tree = astgen.tree;
59505835 const main_tokens = tree.nodes.items(.main_token);
59515836 const str_lit_token = main_tokens[node];
59525837 const str = try astgen.strLitAsString(str_lit_token);
......@@ -5967,7 +5852,7 @@ fn multilineStringLiteral(
59675852 node: ast.Node.Index,
59685853) InnerError!Zir.Inst.Ref {
59695854 const astgen = gz.astgen;
5970 const tree = &astgen.file.tree;
5855 const tree = astgen.tree;
59715856 const node_datas = tree.nodes.items(.data);
59725857 const main_tokens = tree.nodes.items(.main_token);
59735858
......@@ -6006,7 +5891,7 @@ fn multilineStringLiteral(
60065891
60075892fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref {
60085893 const astgen = gz.astgen;
6009 const tree = &astgen.file.tree;
5894 const tree = astgen.tree;
60105895 const main_tokens = tree.nodes.items(.main_token);
60115896 const main_token = main_tokens[node];
60125897 const slice = tree.tokenSlice(main_token);
......@@ -6035,7 +5920,7 @@ fn integerLiteral(
60355920 node: ast.Node.Index,
60365921) InnerError!Zir.Inst.Ref {
60375922 const astgen = gz.astgen;
6038 const tree = &astgen.file.tree;
5923 const tree = astgen.tree;
60395924 const main_tokens = tree.nodes.items(.main_token);
60405925 const int_token = main_tokens[node];
60415926 const prefixed_bytes = tree.tokenSlice(int_token);
......@@ -6087,7 +5972,7 @@ fn floatLiteral(
60875972) InnerError!Zir.Inst.Ref {
60885973 const astgen = gz.astgen;
60895974 const arena = astgen.arena;
6090 const tree = &astgen.file.tree;
5975 const tree = astgen.tree;
60915976 const main_tokens = tree.nodes.items(.main_token);
60925977
60935978 const main_token = main_tokens[node];
......@@ -6130,7 +6015,7 @@ fn asmExpr(
61306015) InnerError!Zir.Inst.Ref {
61316016 const astgen = gz.astgen;
61326017 const arena = astgen.arena;
6133 const tree = &astgen.file.tree;
6018 const tree = astgen.tree;
61346019 const main_tokens = tree.nodes.items(.main_token);
61356020 const node_datas = tree.nodes.items(.data);
61366021 const token_tags = tree.tokens.items(.tag);
......@@ -6426,7 +6311,7 @@ fn builtinCall(
64266311 params: []const ast.Node.Index,
64276312) InnerError!Zir.Inst.Ref {
64286313 const astgen = gz.astgen;
6429 const tree = &astgen.file.tree;
6314 const tree = astgen.tree;
64306315 const main_tokens = tree.nodes.items(.main_token);
64316316
64326317 const builtin_token = main_tokens[node];
......@@ -7406,7 +7291,7 @@ fn rvalue(
74067291 },
74077292 .ref => {
74087293 // We need a pointer but we have a value.
7409 const tree = &gz.astgen.file.tree;
7294 const tree = gz.astgen.tree;
74107295 const src_token = tree.firstToken(src_node);
74117296 return gz.addUnTok(.ref, result, src_token);
74127297 },
......@@ -7498,8 +7383,8 @@ fn rvalue(
74987383/// and allocates the result within `astgen.arena`.
74997384/// Otherwise, returns a reference to the source code bytes directly.
75007385/// See also `appendIdentStr` and `parseStrLit`.
7501pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
7502 const tree = &astgen.file.tree;
7386fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 {
7387 const tree = astgen.tree;
75037388 const token_tags = tree.tokens.items(.tag);
75047389 assert(token_tags[token] == .identifier);
75057390 const ident_name = tree.tokenSlice(token);
......@@ -7516,12 +7401,12 @@ pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError!
75167401/// Given an identifier token, obtain the string for it (possibly parsing as a string
75177402/// literal if it is @"" syntax), and append the string to `buf`.
75187403/// See also `identifierTokenString` and `parseStrLit`.
7519pub fn appendIdentStr(
7404fn appendIdentStr(
75207405 astgen: *AstGen,
75217406 token: ast.TokenIndex,
75227407 buf: *ArrayListUnmanaged(u8),
75237408) InnerError!void {
7524 const tree = &astgen.file.tree;
7409 const tree = astgen.tree;
75257410 const token_tags = tree.tokens.items(.tag);
75267411 assert(token_tags[token] == .identifier);
75277412 const ident_name = tree.tokenSlice(token);
......@@ -7533,14 +7418,14 @@ pub fn appendIdentStr(
75337418}
75347419
75357420/// Appends the result to `buf`.
7536pub fn parseStrLit(
7421fn parseStrLit(
75377422 astgen: *AstGen,
75387423 token: ast.TokenIndex,
75397424 buf: *ArrayListUnmanaged(u8),
75407425 bytes: []const u8,
75417426 offset: u32,
75427427) InnerError!void {
7543 const tree = &astgen.file.tree;
7428 const tree = astgen.tree;
75447429 const raw_string = bytes[offset..];
75457430 var buf_managed = buf.toManaged(astgen.gpa);
75467431 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);
......@@ -7598,7 +7483,7 @@ pub fn parseStrLit(
75987483 }
75997484}
76007485
7601pub fn failNode(
7486fn failNode(
76027487 astgen: *AstGen,
76037488 node: ast.Node.Index,
76047489 comptime format: []const u8,
......@@ -7607,7 +7492,7 @@ pub fn failNode(
76077492 return astgen.failNodeNotes(node, format, args, &[0]u32{});
76087493}
76097494
7610pub fn failNodeNotes(
7495fn failNodeNotes(
76117496 astgen: *AstGen,
76127497 node: ast.Node.Index,
76137498 comptime format: []const u8,
......@@ -7639,7 +7524,7 @@ pub fn failNodeNotes(
76397524 return error.AnalysisFail;
76407525}
76417526
7642pub fn failTok(
7527fn failTok(
76437528 astgen: *AstGen,
76447529 token: ast.TokenIndex,
76457530 comptime format: []const u8,
......@@ -7648,7 +7533,7 @@ pub fn failTok(
76487533 return astgen.failTokNotes(token, format, args, &[0]u32{});
76497534}
76507535
7651pub fn failTokNotes(
7536fn failTokNotes(
76527537 astgen: *AstGen,
76537538 token: ast.TokenIndex,
76547539 comptime format: []const u8,
......@@ -7680,9 +7565,8 @@ pub fn failTokNotes(
76807565 return error.AnalysisFail;
76817566}
76827567
7683/// Same as `fail`, except given an absolute byte offset, and the function sets up the `LazySrcLoc`
7684/// for pointing at it relatively by subtracting from the containing `Decl`.
7685pub fn failOff(
7568/// Same as `fail`, except given an absolute byte offset.
7569fn failOff(
76867570 astgen: *AstGen,
76877571 token: ast.TokenIndex,
76887572 byte_offset: u32,
......@@ -7707,7 +7591,7 @@ pub fn failOff(
77077591 return error.AnalysisFail;
77087592}
77097593
7710pub fn errNoteTok(
7594fn errNoteTok(
77117595 astgen: *AstGen,
77127596 token: ast.TokenIndex,
77137597 comptime format: []const u8,
......@@ -7730,7 +7614,7 @@ pub fn errNoteTok(
77307614 });
77317615}
77327616
7733pub fn errNoteNode(
7617fn errNoteNode(
77347618 astgen: *AstGen,
77357619 node: ast.Node.Index,
77367620 comptime format: []const u8,
......@@ -7780,7 +7664,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
77807664 const gpa = astgen.gpa;
77817665 const string_bytes = &astgen.string_bytes;
77827666 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);
77847668 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
77857669 const key = string_bytes.items[str_index..];
77867670 const gop = try astgen.string_table.getOrPut(gpa, key);
......@@ -7811,9 +7695,934 @@ fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
78117695 const gpa = astgen.gpa;
78127696 const string_bytes = &astgen.string_bytes;
78137697 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);
78157699 try string_bytes.append(gpa, 0); // Indicates this is a test.
78167700 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
78177701 try string_bytes.append(gpa, 0);
78187702 return str_index;
78197703}
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 {
628628 pub const NameHash = [16]u8;
629629
630630 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 }
637631 if (base.tag != T.base_tag)
638632 return null;
639633
......@@ -643,11 +637,6 @@ pub const Scope = struct {
643637 pub fn ownerDecl(scope: *Scope) ?*Decl {
644638 return switch (scope.tag) {
645639 .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,
651640 .file => null,
652641 .namespace => null,
653642 .decl_ref => scope.cast(DeclRef).?.decl,
......@@ -657,11 +646,6 @@ pub const Scope = struct {
657646 pub fn srcDecl(scope: *Scope) ?*Decl {
658647 return switch (scope.tag) {
659648 .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,
665649 .file => null,
666650 .namespace => null,
667651 .decl_ref => scope.cast(DeclRef).?.decl,
......@@ -672,11 +656,6 @@ pub const Scope = struct {
672656 pub fn namespace(scope: *Scope) *Namespace {
673657 switch (scope.tag) {
674658 .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,
680659 .file => return scope.cast(File).?.namespace,
681660 .namespace => return scope.cast(Namespace).?,
682661 .decl_ref => return scope.cast(DeclRef).?.decl.namespace,
......@@ -690,11 +669,6 @@ pub const Scope = struct {
690669 .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path,
691670 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
692671 .block => unreachable,
693 .gen_zir => unreachable,
694 .local_val => unreachable,
695 .local_ptr => unreachable,
696 .defer_normal => unreachable,
697 .defer_error => unreachable,
698672 .decl_ref => unreachable,
699673 }
700674 }
......@@ -706,11 +680,6 @@ pub const Scope = struct {
706680 cur = switch (cur.tag) {
707681 .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope,
708682 .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,
714683 .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope,
715684 .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope,
716685 };
......@@ -723,15 +692,10 @@ pub const Scope = struct {
723692 /// Namespace owned by structs, enums, unions, and opaques for decls.
724693 namespace,
725694 block,
726 gen_zir,
727 local_val,
728 local_ptr,
729695 /// Used for simple error reporting. Only contains a reference to a
730696 /// `Decl` for use with `srcDecl` and `ownerDecl`.
731697 /// Has no parents or children.
732698 decl_ref,
733 defer_normal,
734 defer_error,
735699 };
736700
737701 /// The container that structs, enums, unions, and opaques have.
......@@ -1183,907 +1147,6 @@ pub const Scope = struct {
11831147 }
11841148 };
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
20871150 pub const DeclRef = struct {
20881151 pub const base_tag: Tag = .decl_ref;
20891152 base: Scope = Scope{ .tag = base_tag },
......@@ -3142,7 +2205,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
31422205 }
31432206 file.tree_loaded = true;
31442207
3145 file.zir = try AstGen.generate(gpa, file);
2208 file.zir = try AstGen.generate(gpa, file.tree);
31462209 file.zir_loaded = true;
31472210 file.status = .success_zir;
31482211 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
45363599 }
45373600 mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg);
45383601 },
4539 .gen_zir, .local_val, .local_ptr, .defer_normal, .defer_error => unreachable,
45403602 .file => unreachable,
45413603 .namespace => unreachable,
45423604 .decl_ref => {
......@@ -4894,3 +3956,95 @@ fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void {
48943956 },
48953957 }
48963958}
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");
22const Order = std.math.Order;
33const Value = @import("value.zig").Value;
44const RangeSet = @This();
5const SwitchProngSrc = @import("AstGen.zig").SwitchProngSrc;
5const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
66
77ranges: std.ArrayList(Range),
88
src/Sema.zig+13-14
......@@ -63,7 +63,6 @@ const InnerError = Module.InnerError;
6363const Decl = Module.Decl;
6464const LazySrcLoc = Module.LazySrcLoc;
6565const RangeSet = @import("RangeSet.zig");
66const AstGen = @import("AstGen.zig");
6766
6867pub fn analyzeFnBody(
6968 sema: *Sema,
......@@ -3361,10 +3360,10 @@ fn analyzeSwitch(
33613360 // Validate for duplicate items, missing else prong, and invalid range.
33623361 switch (operand.ty.zigTypeTag()) {
33633362 .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());
33653364 defer gpa.free(seen_fields);
33663365
3367 mem.set(?AstGen.SwitchProngSrc, seen_fields, null);
3366 mem.set(?Module.SwitchProngSrc, seen_fields, null);
33683367
33693368 var extra_index: usize = special.end;
33703369 {
......@@ -3989,8 +3988,8 @@ fn resolveSwitchItemVal(
39893988 block: *Scope.Block,
39903989 item_ref: Zir.Inst.Ref,
39913990 switch_node_offset: i32,
3992 switch_prong_src: AstGen.SwitchProngSrc,
3993 range_expand: AstGen.SwitchProngSrc.RangeExpand,
3991 switch_prong_src: Module.SwitchProngSrc,
3992 range_expand: Module.SwitchProngSrc.RangeExpand,
39943993) InnerError!TypedValue {
39953994 const item = try sema.resolveInst(item_ref);
39963995 // We have to avoid the other helper functions here because we cannot construct a LazySrcLoc
......@@ -4014,7 +4013,7 @@ fn validateSwitchRange(
40144013 first_ref: Zir.Inst.Ref,
40154014 last_ref: Zir.Inst.Ref,
40164015 src_node_offset: i32,
4017 switch_prong_src: AstGen.SwitchProngSrc,
4016 switch_prong_src: Module.SwitchProngSrc,
40184017) InnerError!void {
40194018 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
40204019 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
......@@ -4028,7 +4027,7 @@ fn validateSwitchItem(
40284027 range_set: *RangeSet,
40294028 item_ref: Zir.Inst.Ref,
40304029 src_node_offset: i32,
4031 switch_prong_src: AstGen.SwitchProngSrc,
4030 switch_prong_src: Module.SwitchProngSrc,
40324031) InnerError!void {
40334032 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
40344033 const maybe_prev_src = try range_set.add(item_val, item_val, switch_prong_src);
......@@ -4038,10 +4037,10 @@ fn validateSwitchItem(
40384037fn validateSwitchItemEnum(
40394038 sema: *Sema,
40404039 block: *Scope.Block,
4041 seen_fields: []?AstGen.SwitchProngSrc,
4040 seen_fields: []?Module.SwitchProngSrc,
40424041 item_ref: Zir.Inst.Ref,
40434042 src_node_offset: i32,
4044 switch_prong_src: AstGen.SwitchProngSrc,
4043 switch_prong_src: Module.SwitchProngSrc,
40454044) InnerError!void {
40464045 const mod = sema.mod;
40474046 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
......@@ -4073,8 +4072,8 @@ fn validateSwitchItemEnum(
40734072fn validateSwitchDupe(
40744073 sema: *Sema,
40754074 block: *Scope.Block,
4076 maybe_prev_src: ?AstGen.SwitchProngSrc,
4077 switch_prong_src: AstGen.SwitchProngSrc,
4075 maybe_prev_src: ?Module.SwitchProngSrc,
4076 switch_prong_src: Module.SwitchProngSrc,
40784077 src_node_offset: i32,
40794078) InnerError!void {
40804079 const prev_prong_src = maybe_prev_src orelse return;
......@@ -4108,7 +4107,7 @@ fn validateSwitchItemBool(
41084107 false_count: *u8,
41094108 item_ref: Zir.Inst.Ref,
41104109 src_node_offset: i32,
4111 switch_prong_src: AstGen.SwitchProngSrc,
4110 switch_prong_src: Module.SwitchProngSrc,
41124111) InnerError!void {
41134112 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
41144113 if (item_val.toBool()) {
......@@ -4122,7 +4121,7 @@ fn validateSwitchItemBool(
41224121 }
41234122}
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
41274126fn validateSwitchItemSparse(
41284127 sema: *Sema,
......@@ -4130,7 +4129,7 @@ fn validateSwitchItemSparse(
41304129 seen_values: *ValueSrcMap,
41314130 item_ref: Zir.Inst.Ref,
41324131 src_node_offset: i32,
4133 switch_prong_src: AstGen.SwitchProngSrc,
4132 switch_prong_src: Module.SwitchProngSrc,
41344133) InnerError!void {
41354134 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
41364135 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(
35623562 process.exit(1);
35633563 }
35643564
3565 file.zir = try AstGen.generate(gpa, &file);
3565 file.zir = try AstGen.generate(gpa, file.tree);
35663566 file.zir_loaded = true;
35673567 defer file.zir.deinit(gpa);
35683568