| ... | ... | @@ -13,17 +13,11 @@ const assert = std.debug.assert; |
| 13 | 13 | const ArrayListUnmanaged = std.ArrayListUnmanaged; |
| 14 | 14 | |
| 15 | 15 | const Zir = @import("Zir.zig"); |
| 16 | | const Module = @import("Module.zig"); |
| 17 | 16 | const trace = @import("tracy.zig").trace; |
| 18 | | const Scope = Module.Scope; |
| 19 | | const GenZir = Scope.GenZir; |
| 20 | | const InnerError = Module.InnerError; |
| 21 | | const Decl = Module.Decl; |
| 22 | | const LazySrcLoc = Module.LazySrcLoc; |
| 23 | 17 | const BuiltinFn = @import("BuiltinFn.zig"); |
| 24 | 18 | |
| 25 | 19 | gpa: *Allocator, |
| 26 | | file: *Scope.File, |
| 20 | tree: *const ast.Tree, |
| 27 | 21 | instructions: std.MultiArrayList(Zir.Inst) = .{}, |
| 28 | 22 | extra: ArrayListUnmanaged(u32) = .{}, |
| 29 | 23 | string_bytes: ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -37,13 +31,15 @@ fn_block: ?*GenZir = null, |
| 37 | 31 | /// String table indexes, keeps track of all `@import` operands. |
| 38 | 32 | imports: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 39 | 33 | |
| 40 | | pub fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { |
| 34 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 35 | |
| 36 | fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { |
| 41 | 37 | const fields = std.meta.fields(@TypeOf(extra)); |
| 42 | 38 | try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + fields.len); |
| 43 | 39 | return addExtraAssumeCapacity(astgen, extra); |
| 44 | 40 | } |
| 45 | 41 | |
| 46 | | pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 42 | fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 47 | 43 | const fields = std.meta.fields(@TypeOf(extra)); |
| 48 | 44 | const result = @intCast(u32, astgen.extra.items.len); |
| 49 | 45 | inline for (fields) |field| { |
| ... | ... | @@ -57,24 +53,24 @@ pub fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 57 | 53 | return result; |
| 58 | 54 | } |
| 59 | 55 | |
| 60 | | pub fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void { |
| 56 | fn appendRefs(astgen: *AstGen, refs: []const Zir.Inst.Ref) !void { |
| 61 | 57 | const coerced = @bitCast([]const u32, refs); |
| 62 | 58 | return astgen.extra.appendSlice(astgen.gpa, coerced); |
| 63 | 59 | } |
| 64 | 60 | |
| 65 | | pub fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void { |
| 61 | fn appendRefsAssumeCapacity(astgen: *AstGen, refs: []const Zir.Inst.Ref) void { |
| 66 | 62 | const coerced = @bitCast([]const u32, refs); |
| 67 | 63 | astgen.extra.appendSliceAssumeCapacity(coerced); |
| 68 | 64 | } |
| 69 | 65 | |
| 70 | | pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { |
| 66 | pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir { |
| 71 | 67 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 72 | 68 | defer arena.deinit(); |
| 73 | 69 | |
| 74 | 70 | var astgen: AstGen = .{ |
| 75 | 71 | .gpa = gpa, |
| 76 | 72 | .arena = &arena.allocator, |
| 77 | | .file = file, |
| 73 | .tree = &tree, |
| 78 | 74 | }; |
| 79 | 75 | defer astgen.deinit(gpa); |
| 80 | 76 | |
| ... | ... | @@ -83,16 +79,16 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { |
| 83 | 79 | |
| 84 | 80 | // We expect at least as many ZIR instructions and extra data items |
| 85 | 81 | // as AST nodes. |
| 86 | | try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len); |
| 82 | try astgen.instructions.ensureTotalCapacity(gpa, tree.nodes.len); |
| 87 | 83 | |
| 88 | 84 | // First few indexes of extra are reserved and set at the end. |
| 89 | 85 | const reserved_count = @typeInfo(Zir.ExtraIndex).Enum.fields.len; |
| 90 | | try astgen.extra.ensureTotalCapacity(gpa, file.tree.nodes.len + reserved_count); |
| 86 | try astgen.extra.ensureTotalCapacity(gpa, tree.nodes.len + reserved_count); |
| 91 | 87 | astgen.extra.items.len += reserved_count; |
| 92 | 88 | |
| 93 | 89 | var gen_scope: GenZir = .{ |
| 94 | 90 | .force_comptime = true, |
| 95 | | .parent = &file.base, |
| 91 | .parent = null, |
| 96 | 92 | .decl_node_index = 0, |
| 97 | 93 | .decl_line = 0, |
| 98 | 94 | .astgen = &astgen, |
| ... | ... | @@ -104,7 +100,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { |
| 104 | 100 | .ast = .{ |
| 105 | 101 | .main_token = undefined, |
| 106 | 102 | .enum_token = null, |
| 107 | | .members = file.tree.rootDecls(), |
| 103 | .members = tree.rootDecls(), |
| 108 | 104 | .arg = 0, |
| 109 | 105 | }, |
| 110 | 106 | }; |
| ... | ... | @@ -250,7 +246,7 @@ pub const ResultLoc = union(enum) { |
| 250 | 246 | pub const align_rl: ResultLoc = .{ .ty = .u16_type }; |
| 251 | 247 | pub const bool_rl: ResultLoc = .{ .ty = .bool_type }; |
| 252 | 248 | |
| 253 | | pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 249 | fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 254 | 250 | const prev_force_comptime = gz.force_comptime; |
| 255 | 251 | gz.force_comptime = true; |
| 256 | 252 | const e = expr(gz, scope, .{ .ty = .type_type }, type_node); |
| ... | ... | @@ -260,7 +256,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro |
| 260 | 256 | |
| 261 | 257 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 262 | 258 | const astgen = gz.astgen; |
| 263 | | const tree = &astgen.file.tree; |
| 259 | const tree = astgen.tree; |
| 264 | 260 | const node_tags = tree.nodes.items(.tag); |
| 265 | 261 | const main_tokens = tree.nodes.items(.main_token); |
| 266 | 262 | switch (node_tags[node]) { |
| ... | ... | @@ -453,9 +449,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Ins |
| 453 | 449 | /// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the |
| 454 | 450 | /// result instruction can be used to inspect whether it is isNoReturn() but that is it, |
| 455 | 451 | /// it must otherwise not be used. |
| 456 | | pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 452 | fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 457 | 453 | const astgen = gz.astgen; |
| 458 | | const tree = &astgen.file.tree; |
| 454 | const tree = astgen.tree; |
| 459 | 455 | const main_tokens = tree.nodes.items(.main_token); |
| 460 | 456 | const token_tags = tree.tokens.items(.tag); |
| 461 | 457 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -888,7 +884,7 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn |
| 888 | 884 | } |
| 889 | 885 | } |
| 890 | 886 | |
| 891 | | pub fn nosuspendExpr( |
| 887 | fn nosuspendExpr( |
| 892 | 888 | gz: *GenZir, |
| 893 | 889 | scope: *Scope, |
| 894 | 890 | rl: ResultLoc, |
| ... | ... | @@ -896,7 +892,7 @@ pub fn nosuspendExpr( |
| 896 | 892 | ) InnerError!Zir.Inst.Ref { |
| 897 | 893 | const astgen = gz.astgen; |
| 898 | 894 | const gpa = astgen.gpa; |
| 899 | | const tree = &astgen.file.tree; |
| 895 | const tree = astgen.tree; |
| 900 | 896 | const node_datas = tree.nodes.items(.data); |
| 901 | 897 | const body_node = node_datas[node].lhs; |
| 902 | 898 | assert(body_node != 0); |
| ... | ... | @@ -911,7 +907,7 @@ pub fn nosuspendExpr( |
| 911 | 907 | return rvalue(gz, scope, rl, result, node); |
| 912 | 908 | } |
| 913 | 909 | |
| 914 | | pub fn suspendExpr( |
| 910 | fn suspendExpr( |
| 915 | 911 | gz: *GenZir, |
| 916 | 912 | scope: *Scope, |
| 917 | 913 | rl: ResultLoc, |
| ... | ... | @@ -919,7 +915,7 @@ pub fn suspendExpr( |
| 919 | 915 | ) InnerError!Zir.Inst.Ref { |
| 920 | 916 | const astgen = gz.astgen; |
| 921 | 917 | const gpa = astgen.gpa; |
| 922 | | const tree = &astgen.file.tree; |
| 918 | const tree = astgen.tree; |
| 923 | 919 | const node_datas = tree.nodes.items(.data); |
| 924 | 920 | const body_node = node_datas[node].lhs; |
| 925 | 921 | |
| ... | ... | @@ -951,14 +947,14 @@ pub fn suspendExpr( |
| 951 | 947 | return gz.indexToRef(suspend_inst); |
| 952 | 948 | } |
| 953 | 949 | |
| 954 | | pub fn awaitExpr( |
| 950 | fn awaitExpr( |
| 955 | 951 | gz: *GenZir, |
| 956 | 952 | scope: *Scope, |
| 957 | 953 | rl: ResultLoc, |
| 958 | 954 | node: ast.Node.Index, |
| 959 | 955 | ) InnerError!Zir.Inst.Ref { |
| 960 | 956 | const astgen = gz.astgen; |
| 961 | | const tree = &astgen.file.tree; |
| 957 | const tree = astgen.tree; |
| 962 | 958 | const node_datas = tree.nodes.items(.data); |
| 963 | 959 | const rhs_node = node_datas[node].lhs; |
| 964 | 960 | |
| ... | ... | @@ -973,14 +969,14 @@ pub fn awaitExpr( |
| 973 | 969 | return rvalue(gz, scope, rl, result, node); |
| 974 | 970 | } |
| 975 | 971 | |
| 976 | | pub fn resumeExpr( |
| 972 | fn resumeExpr( |
| 977 | 973 | gz: *GenZir, |
| 978 | 974 | scope: *Scope, |
| 979 | 975 | rl: ResultLoc, |
| 980 | 976 | node: ast.Node.Index, |
| 981 | 977 | ) InnerError!Zir.Inst.Ref { |
| 982 | 978 | const astgen = gz.astgen; |
| 983 | | const tree = &astgen.file.tree; |
| 979 | const tree = astgen.tree; |
| 984 | 980 | const node_datas = tree.nodes.items(.data); |
| 985 | 981 | const rhs_node = node_datas[node].lhs; |
| 986 | 982 | const operand = try expr(gz, scope, .none, rhs_node); |
| ... | ... | @@ -988,7 +984,7 @@ pub fn resumeExpr( |
| 988 | 984 | return rvalue(gz, scope, rl, result, node); |
| 989 | 985 | } |
| 990 | 986 | |
| 991 | | pub fn fnProtoExpr( |
| 987 | fn fnProtoExpr( |
| 992 | 988 | gz: *GenZir, |
| 993 | 989 | scope: *Scope, |
| 994 | 990 | rl: ResultLoc, |
| ... | ... | @@ -996,7 +992,7 @@ pub fn fnProtoExpr( |
| 996 | 992 | ) InnerError!Zir.Inst.Ref { |
| 997 | 993 | const astgen = gz.astgen; |
| 998 | 994 | const gpa = astgen.gpa; |
| 999 | | const tree = &astgen.file.tree; |
| 995 | const tree = astgen.tree; |
| 1000 | 996 | const token_tags = tree.tokens.items(.tag); |
| 1001 | 997 | |
| 1002 | 998 | const is_extern = blk: { |
| ... | ... | @@ -1093,7 +1089,7 @@ pub fn fnProtoExpr( |
| 1093 | 1089 | return rvalue(gz, scope, rl, result, fn_proto.ast.proto_node); |
| 1094 | 1090 | } |
| 1095 | 1091 | |
| 1096 | | pub fn arrayInitExpr( |
| 1092 | fn arrayInitExpr( |
| 1097 | 1093 | gz: *GenZir, |
| 1098 | 1094 | scope: *Scope, |
| 1099 | 1095 | rl: ResultLoc, |
| ... | ... | @@ -1101,7 +1097,7 @@ pub fn arrayInitExpr( |
| 1101 | 1097 | array_init: ast.full.ArrayInit, |
| 1102 | 1098 | ) InnerError!Zir.Inst.Ref { |
| 1103 | 1099 | const astgen = gz.astgen; |
| 1104 | | const tree = &astgen.file.tree; |
| 1100 | const tree = astgen.tree; |
| 1105 | 1101 | const gpa = astgen.gpa; |
| 1106 | 1102 | const node_tags = tree.nodes.items(.tag); |
| 1107 | 1103 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -1192,7 +1188,7 @@ pub fn arrayInitExpr( |
| 1192 | 1188 | } |
| 1193 | 1189 | } |
| 1194 | 1190 | |
| 1195 | | pub fn arrayInitExprRlNone( |
| 1191 | fn arrayInitExprRlNone( |
| 1196 | 1192 | gz: *GenZir, |
| 1197 | 1193 | scope: *Scope, |
| 1198 | 1194 | rl: ResultLoc, |
| ... | ... | @@ -1215,7 +1211,7 @@ pub fn arrayInitExprRlNone( |
| 1215 | 1211 | return init_inst; |
| 1216 | 1212 | } |
| 1217 | 1213 | |
| 1218 | | pub fn arrayInitExprRlTy( |
| 1214 | fn arrayInitExprRlTy( |
| 1219 | 1215 | gz: *GenZir, |
| 1220 | 1216 | scope: *Scope, |
| 1221 | 1217 | rl: ResultLoc, |
| ... | ... | @@ -1243,7 +1239,7 @@ pub fn arrayInitExprRlTy( |
| 1243 | 1239 | return init_inst; |
| 1244 | 1240 | } |
| 1245 | 1241 | |
| 1246 | | pub fn arrayInitExprRlPtr( |
| 1242 | fn arrayInitExprRlPtr( |
| 1247 | 1243 | gz: *GenZir, |
| 1248 | 1244 | scope: *Scope, |
| 1249 | 1245 | rl: ResultLoc, |
| ... | ... | @@ -1273,7 +1269,7 @@ pub fn arrayInitExprRlPtr( |
| 1273 | 1269 | return .void_value; |
| 1274 | 1270 | } |
| 1275 | 1271 | |
| 1276 | | pub fn structInitExpr( |
| 1272 | fn structInitExpr( |
| 1277 | 1273 | gz: *GenZir, |
| 1278 | 1274 | scope: *Scope, |
| 1279 | 1275 | rl: ResultLoc, |
| ... | ... | @@ -1281,7 +1277,7 @@ pub fn structInitExpr( |
| 1281 | 1277 | struct_init: ast.full.StructInit, |
| 1282 | 1278 | ) InnerError!Zir.Inst.Ref { |
| 1283 | 1279 | const astgen = gz.astgen; |
| 1284 | | const tree = &astgen.file.tree; |
| 1280 | const tree = astgen.tree; |
| 1285 | 1281 | const gpa = astgen.gpa; |
| 1286 | 1282 | |
| 1287 | 1283 | if (struct_init.ast.fields.len == 0) { |
| ... | ... | @@ -1351,7 +1347,7 @@ pub fn structInitExpr( |
| 1351 | 1347 | } |
| 1352 | 1348 | } |
| 1353 | 1349 | |
| 1354 | | pub fn structInitExprRlNone( |
| 1350 | fn structInitExprRlNone( |
| 1355 | 1351 | gz: *GenZir, |
| 1356 | 1352 | scope: *Scope, |
| 1357 | 1353 | rl: ResultLoc, |
| ... | ... | @@ -1361,7 +1357,7 @@ pub fn structInitExprRlNone( |
| 1361 | 1357 | ) InnerError!Zir.Inst.Ref { |
| 1362 | 1358 | const astgen = gz.astgen; |
| 1363 | 1359 | const gpa = astgen.gpa; |
| 1364 | | const tree = &astgen.file.tree; |
| 1360 | const tree = astgen.tree; |
| 1365 | 1361 | |
| 1366 | 1362 | const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); |
| 1367 | 1363 | defer gpa.free(fields_list); |
| ... | ... | @@ -1386,7 +1382,7 @@ pub fn structInitExprRlNone( |
| 1386 | 1382 | return init_inst; |
| 1387 | 1383 | } |
| 1388 | 1384 | |
| 1389 | | pub fn structInitExprRlPtr( |
| 1385 | fn structInitExprRlPtr( |
| 1390 | 1386 | gz: *GenZir, |
| 1391 | 1387 | scope: *Scope, |
| 1392 | 1388 | rl: ResultLoc, |
| ... | ... | @@ -1396,7 +1392,7 @@ pub fn structInitExprRlPtr( |
| 1396 | 1392 | ) InnerError!Zir.Inst.Ref { |
| 1397 | 1393 | const astgen = gz.astgen; |
| 1398 | 1394 | const gpa = astgen.gpa; |
| 1399 | | const tree = &astgen.file.tree; |
| 1395 | const tree = astgen.tree; |
| 1400 | 1396 | |
| 1401 | 1397 | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); |
| 1402 | 1398 | defer gpa.free(field_ptr_list); |
| ... | ... | @@ -1418,7 +1414,7 @@ pub fn structInitExprRlPtr( |
| 1418 | 1414 | return .void_value; |
| 1419 | 1415 | } |
| 1420 | 1416 | |
| 1421 | | pub fn structInitExprRlTy( |
| 1417 | fn structInitExprRlTy( |
| 1422 | 1418 | gz: *GenZir, |
| 1423 | 1419 | scope: *Scope, |
| 1424 | 1420 | rl: ResultLoc, |
| ... | ... | @@ -1429,7 +1425,7 @@ pub fn structInitExprRlTy( |
| 1429 | 1425 | ) InnerError!Zir.Inst.Ref { |
| 1430 | 1426 | const astgen = gz.astgen; |
| 1431 | 1427 | const gpa = astgen.gpa; |
| 1432 | | const tree = &astgen.file.tree; |
| 1428 | const tree = astgen.tree; |
| 1433 | 1429 | |
| 1434 | 1430 | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); |
| 1435 | 1431 | defer gpa.free(fields_list); |
| ... | ... | @@ -1486,7 +1482,7 @@ fn comptimeExprAst( |
| 1486 | 1482 | if (gz.force_comptime) { |
| 1487 | 1483 | return astgen.failNode(node, "redundant comptime keyword in already comptime scope", .{}); |
| 1488 | 1484 | } |
| 1489 | | const tree = &astgen.file.tree; |
| 1485 | const tree = astgen.tree; |
| 1490 | 1486 | const node_datas = tree.nodes.items(.data); |
| 1491 | 1487 | const body_node = node_datas[node].lhs; |
| 1492 | 1488 | gz.force_comptime = true; |
| ... | ... | @@ -1497,7 +1493,7 @@ fn comptimeExprAst( |
| 1497 | 1493 | |
| 1498 | 1494 | fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 1499 | 1495 | const astgen = parent_gz.astgen; |
| 1500 | | const tree = &astgen.file.tree; |
| 1496 | const tree = astgen.tree; |
| 1501 | 1497 | const node_datas = tree.nodes.items(.data); |
| 1502 | 1498 | const break_label = node_datas[node].lhs; |
| 1503 | 1499 | const rhs = node_datas[node].rhs; |
| ... | ... | @@ -1520,7 +1516,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn |
| 1520 | 1516 | } else if (block_gz.break_block != 0) { |
| 1521 | 1517 | break :blk block_gz.break_block; |
| 1522 | 1518 | } |
| 1523 | | scope = block_gz.parent; |
| 1519 | scope = block_gz.parent orelse break; |
| 1524 | 1520 | continue; |
| 1525 | 1521 | }; |
| 1526 | 1522 | |
| ... | ... | @@ -1558,19 +1554,19 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn |
| 1558 | 1554 | try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); |
| 1559 | 1555 | }, |
| 1560 | 1556 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1561 | | else => if (break_label != 0) { |
| 1562 | | const label_name = try astgen.identifierTokenString(break_label); |
| 1563 | | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 1564 | | } else { |
| 1565 | | return astgen.failNode(node, "break expression outside loop", .{}); |
| 1566 | | }, |
| 1567 | 1557 | } |
| 1568 | 1558 | } |
| 1559 | if (break_label != 0) { |
| 1560 | const label_name = try astgen.identifierTokenString(break_label); |
| 1561 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 1562 | } else { |
| 1563 | return astgen.failNode(node, "break expression outside loop", .{}); |
| 1564 | } |
| 1569 | 1565 | } |
| 1570 | 1566 | |
| 1571 | 1567 | fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 1572 | 1568 | const astgen = parent_gz.astgen; |
| 1573 | | const tree = &astgen.file.tree; |
| 1569 | const tree = astgen.tree; |
| 1574 | 1570 | const node_datas = tree.nodes.items(.data); |
| 1575 | 1571 | const break_label = node_datas[node].lhs; |
| 1576 | 1572 | |
| ... | ... | @@ -1582,7 +1578,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) |
| 1582 | 1578 | const gen_zir = scope.cast(GenZir).?; |
| 1583 | 1579 | const continue_block = gen_zir.continue_block; |
| 1584 | 1580 | if (continue_block == 0) { |
| 1585 | | scope = gen_zir.parent; |
| 1581 | scope = gen_zir.parent orelse break; |
| 1586 | 1582 | continue; |
| 1587 | 1583 | } |
| 1588 | 1584 | if (break_label != 0) blk: { |
| ... | ... | @@ -1593,7 +1589,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) |
| 1593 | 1589 | } |
| 1594 | 1590 | } |
| 1595 | 1591 | // found continue but either it has a different label, or no label |
| 1596 | | scope = gen_zir.parent; |
| 1592 | scope = gen_zir.parent orelse break; |
| 1597 | 1593 | continue; |
| 1598 | 1594 | } |
| 1599 | 1595 | |
| ... | ... | @@ -1610,17 +1606,17 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) |
| 1610 | 1606 | try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); |
| 1611 | 1607 | }, |
| 1612 | 1608 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1613 | | else => if (break_label != 0) { |
| 1614 | | const label_name = try astgen.identifierTokenString(break_label); |
| 1615 | | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 1616 | | } else { |
| 1617 | | return astgen.failNode(node, "continue expression outside loop", .{}); |
| 1618 | | }, |
| 1619 | 1609 | } |
| 1620 | 1610 | } |
| 1611 | if (break_label != 0) { |
| 1612 | const label_name = try astgen.identifierTokenString(break_label); |
| 1613 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 1614 | } else { |
| 1615 | return astgen.failNode(node, "continue expression outside loop", .{}); |
| 1616 | } |
| 1621 | 1617 | } |
| 1622 | 1618 | |
| 1623 | | pub fn blockExpr( |
| 1619 | fn blockExpr( |
| 1624 | 1620 | gz: *GenZir, |
| 1625 | 1621 | scope: *Scope, |
| 1626 | 1622 | rl: ResultLoc, |
| ... | ... | @@ -1631,7 +1627,7 @@ pub fn blockExpr( |
| 1631 | 1627 | defer tracy.end(); |
| 1632 | 1628 | |
| 1633 | 1629 | const astgen = gz.astgen; |
| 1634 | | const tree = &astgen.file.tree; |
| 1630 | const tree = astgen.tree; |
| 1635 | 1631 | const main_tokens = tree.nodes.items(.main_token); |
| 1636 | 1632 | const token_tags = tree.tokens.items(.tag); |
| 1637 | 1633 | |
| ... | ... | @@ -1655,7 +1651,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke |
| 1655 | 1651 | const gen_zir = scope.cast(GenZir).?; |
| 1656 | 1652 | if (gen_zir.label) |prev_label| { |
| 1657 | 1653 | if (try astgen.tokenIdentEql(label, prev_label.token)) { |
| 1658 | | const tree = &astgen.file.tree; |
| 1654 | const tree = astgen.tree; |
| 1659 | 1655 | const main_tokens = tree.nodes.items(.main_token); |
| 1660 | 1656 | |
| 1661 | 1657 | const label_name = try astgen.identifierTokenString(label); |
| ... | ... | @@ -1670,12 +1666,11 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: ast.Toke |
| 1670 | 1666 | }); |
| 1671 | 1667 | } |
| 1672 | 1668 | } |
| 1673 | | scope = gen_zir.parent; |
| 1669 | scope = gen_zir.parent orelse return; |
| 1674 | 1670 | }, |
| 1675 | 1671 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 1676 | 1672 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 1677 | 1673 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 1678 | | else => return, |
| 1679 | 1674 | } |
| 1680 | 1675 | } |
| 1681 | 1676 | } |
| ... | ... | @@ -1694,7 +1689,7 @@ fn labeledBlockExpr( |
| 1694 | 1689 | assert(zir_tag == .block); |
| 1695 | 1690 | |
| 1696 | 1691 | const astgen = gz.astgen; |
| 1697 | | const tree = &astgen.file.tree; |
| 1692 | const tree = astgen.tree; |
| 1698 | 1693 | const main_tokens = tree.nodes.items(.main_token); |
| 1699 | 1694 | const token_tags = tree.tokens.items(.tag); |
| 1700 | 1695 | |
| ... | ... | @@ -1768,7 +1763,7 @@ fn blockExprStmts( |
| 1768 | 1763 | statements: []const ast.Node.Index, |
| 1769 | 1764 | ) !void { |
| 1770 | 1765 | const astgen = gz.astgen; |
| 1771 | | const tree = &astgen.file.tree; |
| 1766 | const tree = astgen.tree; |
| 1772 | 1767 | const main_tokens = tree.nodes.items(.main_token); |
| 1773 | 1768 | const node_tags = tree.nodes.items(.tag); |
| 1774 | 1769 | |
| ... | ... | @@ -2108,13 +2103,13 @@ fn genDefers( |
| 2108 | 2103 | err_code: Zir.Inst.Ref, |
| 2109 | 2104 | ) InnerError!void { |
| 2110 | 2105 | const astgen = gz.astgen; |
| 2111 | | const tree = &astgen.file.tree; |
| 2106 | const tree = astgen.tree; |
| 2112 | 2107 | const node_datas = tree.nodes.items(.data); |
| 2113 | 2108 | |
| 2114 | 2109 | var scope = inner_scope; |
| 2115 | 2110 | while (scope != outer_scope) { |
| 2116 | 2111 | switch (scope.tag) { |
| 2117 | | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 2112 | .gen_zir => scope = scope.cast(GenZir).?.parent.?, |
| 2118 | 2113 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2119 | 2114 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2120 | 2115 | .defer_normal => { |
| ... | ... | @@ -2130,7 +2125,6 @@ fn genDefers( |
| 2130 | 2125 | const expr_node = node_datas[defer_scope.defer_node].rhs; |
| 2131 | 2126 | try unusedResultExpr(gz, defer_scope.parent, expr_node); |
| 2132 | 2127 | }, |
| 2133 | | else => unreachable, |
| 2134 | 2128 | } |
| 2135 | 2129 | } |
| 2136 | 2130 | } |
| ... | ... | @@ -2161,7 +2155,7 @@ fn varDecl( |
| 2161 | 2155 | try emitDbgNode(gz, node); |
| 2162 | 2156 | const astgen = gz.astgen; |
| 2163 | 2157 | const gpa = astgen.gpa; |
| 2164 | | const tree = &astgen.file.tree; |
| 2158 | const tree = astgen.tree; |
| 2165 | 2159 | const token_tags = tree.tokens.items(.tag); |
| 2166 | 2160 | |
| 2167 | 2161 | const name_token = var_decl.ast.mut_token + 1; |
| ... | ... | @@ -2201,10 +2195,8 @@ fn varDecl( |
| 2201 | 2195 | } |
| 2202 | 2196 | s = local_ptr.parent; |
| 2203 | 2197 | }, |
| 2204 | | .gen_zir => s = s.cast(GenZir).?.parent, |
| 2198 | .gen_zir => s = s.cast(GenZir).?.parent orelse break, |
| 2205 | 2199 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 2206 | | .file => break, |
| 2207 | | else => unreachable, |
| 2208 | 2200 | }; |
| 2209 | 2201 | } |
| 2210 | 2202 | |
| ... | ... | @@ -2402,7 +2394,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void { |
| 2402 | 2394 | if (gz.force_comptime) return; |
| 2403 | 2395 | |
| 2404 | 2396 | const astgen = gz.astgen; |
| 2405 | | const tree = &astgen.file.tree; |
| 2397 | const tree = astgen.tree; |
| 2406 | 2398 | const node_tags = tree.nodes.items(.tag); |
| 2407 | 2399 | const token_starts = tree.tokens.items(.start); |
| 2408 | 2400 | const decl_start = token_starts[tree.firstToken(gz.decl_node_index)]; |
| ... | ... | @@ -2420,7 +2412,7 @@ fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void { |
| 2420 | 2412 | fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void { |
| 2421 | 2413 | try emitDbgNode(gz, infix_node); |
| 2422 | 2414 | const astgen = gz.astgen; |
| 2423 | | const tree = &astgen.file.tree; |
| 2415 | const tree = astgen.tree; |
| 2424 | 2416 | const node_datas = tree.nodes.items(.data); |
| 2425 | 2417 | const main_tokens = tree.nodes.items(.main_token); |
| 2426 | 2418 | const node_tags = tree.nodes.items(.tag); |
| ... | ... | @@ -2447,7 +2439,7 @@ fn assignOp( |
| 2447 | 2439 | ) InnerError!void { |
| 2448 | 2440 | try emitDbgNode(gz, infix_node); |
| 2449 | 2441 | const astgen = gz.astgen; |
| 2450 | | const tree = &astgen.file.tree; |
| 2442 | const tree = astgen.tree; |
| 2451 | 2443 | const node_datas = tree.nodes.items(.data); |
| 2452 | 2444 | |
| 2453 | 2445 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| ... | ... | @@ -2470,7 +2462,7 @@ fn assignShift( |
| 2470 | 2462 | ) InnerError!void { |
| 2471 | 2463 | try emitDbgNode(gz, infix_node); |
| 2472 | 2464 | const astgen = gz.astgen; |
| 2473 | | const tree = &astgen.file.tree; |
| 2465 | const tree = astgen.tree; |
| 2474 | 2466 | const node_datas = tree.nodes.items(.data); |
| 2475 | 2467 | |
| 2476 | 2468 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| ... | ... | @@ -2487,7 +2479,7 @@ fn assignShift( |
| 2487 | 2479 | |
| 2488 | 2480 | fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2489 | 2481 | const astgen = gz.astgen; |
| 2490 | | const tree = &astgen.file.tree; |
| 2482 | const tree = astgen.tree; |
| 2491 | 2483 | const node_datas = tree.nodes.items(.data); |
| 2492 | 2484 | |
| 2493 | 2485 | const operand = try expr(gz, scope, bool_rl, node_datas[node].lhs); |
| ... | ... | @@ -2497,7 +2489,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne |
| 2497 | 2489 | |
| 2498 | 2490 | fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2499 | 2491 | const astgen = gz.astgen; |
| 2500 | | const tree = &astgen.file.tree; |
| 2492 | const tree = astgen.tree; |
| 2501 | 2493 | const node_datas = tree.nodes.items(.data); |
| 2502 | 2494 | |
| 2503 | 2495 | const operand = try expr(gz, scope, .none, node_datas[node].lhs); |
| ... | ... | @@ -2513,7 +2505,7 @@ fn negation( |
| 2513 | 2505 | tag: Zir.Inst.Tag, |
| 2514 | 2506 | ) InnerError!Zir.Inst.Ref { |
| 2515 | 2507 | const astgen = gz.astgen; |
| 2516 | | const tree = &astgen.file.tree; |
| 2508 | const tree = astgen.tree; |
| 2517 | 2509 | const node_datas = tree.nodes.items(.data); |
| 2518 | 2510 | |
| 2519 | 2511 | const operand = try expr(gz, scope, .none, node_datas[node].lhs); |
| ... | ... | @@ -2529,7 +2521,7 @@ fn ptrType( |
| 2529 | 2521 | ptr_info: ast.full.PtrType, |
| 2530 | 2522 | ) InnerError!Zir.Inst.Ref { |
| 2531 | 2523 | const astgen = gz.astgen; |
| 2532 | | const tree = &astgen.file.tree; |
| 2524 | const tree = astgen.tree; |
| 2533 | 2525 | |
| 2534 | 2526 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); |
| 2535 | 2527 | |
| ... | ... | @@ -2612,7 +2604,7 @@ fn ptrType( |
| 2612 | 2604 | |
| 2613 | 2605 | fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref { |
| 2614 | 2606 | const astgen = gz.astgen; |
| 2615 | | const tree = &astgen.file.tree; |
| 2607 | const tree = astgen.tree; |
| 2616 | 2608 | const node_datas = tree.nodes.items(.data); |
| 2617 | 2609 | const node_tags = tree.nodes.items(.tag); |
| 2618 | 2610 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2632,7 +2624,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z |
| 2632 | 2624 | |
| 2633 | 2625 | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref { |
| 2634 | 2626 | const astgen = gz.astgen; |
| 2635 | | const tree = &astgen.file.tree; |
| 2627 | const tree = astgen.tree; |
| 2636 | 2628 | const node_datas = tree.nodes.items(.data); |
| 2637 | 2629 | const node_tags = tree.nodes.items(.tag); |
| 2638 | 2630 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2696,7 +2688,7 @@ fn fnDecl( |
| 2696 | 2688 | fn_proto: ast.full.FnProto, |
| 2697 | 2689 | ) InnerError!void { |
| 2698 | 2690 | const gpa = astgen.gpa; |
| 2699 | | const tree = &astgen.file.tree; |
| 2691 | const tree = astgen.tree; |
| 2700 | 2692 | const token_tags = tree.tokens.items(.tag); |
| 2701 | 2693 | |
| 2702 | 2694 | // We insert this at the beginning so that its instruction index marks the |
| ... | ... | @@ -2937,7 +2929,7 @@ fn globalVarDecl( |
| 2937 | 2929 | var_decl: ast.full.VarDecl, |
| 2938 | 2930 | ) InnerError!void { |
| 2939 | 2931 | const gpa = astgen.gpa; |
| 2940 | | const tree = &astgen.file.tree; |
| 2932 | const tree = astgen.tree; |
| 2941 | 2933 | const token_tags = tree.tokens.items(.tag); |
| 2942 | 2934 | |
| 2943 | 2935 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| ... | ... | @@ -3076,7 +3068,7 @@ fn comptimeDecl( |
| 3076 | 3068 | node: ast.Node.Index, |
| 3077 | 3069 | ) InnerError!void { |
| 3078 | 3070 | const gpa = astgen.gpa; |
| 3079 | | const tree = &astgen.file.tree; |
| 3071 | const tree = astgen.tree; |
| 3080 | 3072 | const node_datas = tree.nodes.items(.data); |
| 3081 | 3073 | const body_node = node_datas[node].lhs; |
| 3082 | 3074 | |
| ... | ... | @@ -3122,7 +3114,7 @@ fn usingnamespaceDecl( |
| 3122 | 3114 | node: ast.Node.Index, |
| 3123 | 3115 | ) InnerError!void { |
| 3124 | 3116 | const gpa = astgen.gpa; |
| 3125 | | const tree = &astgen.file.tree; |
| 3117 | const tree = astgen.tree; |
| 3126 | 3118 | const node_datas = tree.nodes.items(.data); |
| 3127 | 3119 | |
| 3128 | 3120 | const type_expr = node_datas[node].lhs; |
| ... | ... | @@ -3172,7 +3164,7 @@ fn testDecl( |
| 3172 | 3164 | node: ast.Node.Index, |
| 3173 | 3165 | ) InnerError!void { |
| 3174 | 3166 | const gpa = astgen.gpa; |
| 3175 | | const tree = &astgen.file.tree; |
| 3167 | const tree = astgen.tree; |
| 3176 | 3168 | const node_datas = tree.nodes.items(.data); |
| 3177 | 3169 | const body_node = node_datas[node].rhs; |
| 3178 | 3170 | |
| ... | ... | @@ -3271,7 +3263,7 @@ fn structDeclInner( |
| 3271 | 3263 | |
| 3272 | 3264 | const astgen = gz.astgen; |
| 3273 | 3265 | const gpa = astgen.gpa; |
| 3274 | | const tree = &astgen.file.tree; |
| 3266 | const tree = astgen.tree; |
| 3275 | 3267 | const node_tags = tree.nodes.items(.tag); |
| 3276 | 3268 | const node_datas = tree.nodes.items(.data); |
| 3277 | 3269 | |
| ... | ... | @@ -3483,7 +3475,7 @@ fn unionDeclInner( |
| 3483 | 3475 | ) InnerError!Zir.Inst.Ref { |
| 3484 | 3476 | const astgen = gz.astgen; |
| 3485 | 3477 | const gpa = astgen.gpa; |
| 3486 | | const tree = &astgen.file.tree; |
| 3478 | const tree = astgen.tree; |
| 3487 | 3479 | const node_tags = tree.nodes.items(.tag); |
| 3488 | 3480 | const node_datas = tree.nodes.items(.data); |
| 3489 | 3481 | |
| ... | ... | @@ -3705,7 +3697,7 @@ fn containerDecl( |
| 3705 | 3697 | ) InnerError!Zir.Inst.Ref { |
| 3706 | 3698 | const astgen = gz.astgen; |
| 3707 | 3699 | const gpa = astgen.gpa; |
| 3708 | | const tree = &astgen.file.tree; |
| 3700 | const tree = astgen.tree; |
| 3709 | 3701 | const token_tags = tree.tokens.items(.tag); |
| 3710 | 3702 | const node_tags = tree.nodes.items(.tag); |
| 3711 | 3703 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -4149,7 +4141,7 @@ fn errorSetDecl( |
| 4149 | 4141 | ) InnerError!Zir.Inst.Ref { |
| 4150 | 4142 | const astgen = gz.astgen; |
| 4151 | 4143 | const gpa = astgen.gpa; |
| 4152 | | const tree = &astgen.file.tree; |
| 4144 | const tree = astgen.tree; |
| 4153 | 4145 | const main_tokens = tree.nodes.items(.main_token); |
| 4154 | 4146 | const token_tags = tree.tokens.items(.tag); |
| 4155 | 4147 | |
| ... | ... | @@ -4189,7 +4181,7 @@ fn tryExpr( |
| 4189 | 4181 | operand_node: ast.Node.Index, |
| 4190 | 4182 | ) InnerError!Zir.Inst.Ref { |
| 4191 | 4183 | const astgen = parent_gz.astgen; |
| 4192 | | const tree = &astgen.file.tree; |
| 4184 | const tree = astgen.tree; |
| 4193 | 4185 | |
| 4194 | 4186 | const fn_block = astgen.fn_block orelse { |
| 4195 | 4187 | return astgen.failNode(node, "invalid 'try' outside function scope", .{}); |
| ... | ... | @@ -4272,7 +4264,7 @@ fn orelseCatchExpr( |
| 4272 | 4264 | payload_token: ?ast.TokenIndex, |
| 4273 | 4265 | ) InnerError!Zir.Inst.Ref { |
| 4274 | 4266 | const astgen = parent_gz.astgen; |
| 4275 | | const tree = &astgen.file.tree; |
| 4267 | const tree = astgen.tree; |
| 4276 | 4268 | |
| 4277 | 4269 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4278 | 4270 | block_scope.setBreakResultLoc(rl); |
| ... | ... | @@ -4421,14 +4413,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: ast.TokenIndex, token2: ast.TokenIndex |
| 4421 | 4413 | return mem.eql(u8, ident_name_1, ident_name_2); |
| 4422 | 4414 | } |
| 4423 | 4415 | |
| 4424 | | pub fn fieldAccess( |
| 4416 | fn fieldAccess( |
| 4425 | 4417 | gz: *GenZir, |
| 4426 | 4418 | scope: *Scope, |
| 4427 | 4419 | rl: ResultLoc, |
| 4428 | 4420 | node: ast.Node.Index, |
| 4429 | 4421 | ) InnerError!Zir.Inst.Ref { |
| 4430 | 4422 | const astgen = gz.astgen; |
| 4431 | | const tree = &astgen.file.tree; |
| 4423 | const tree = astgen.tree; |
| 4432 | 4424 | const main_tokens = tree.nodes.items(.main_token); |
| 4433 | 4425 | const node_datas = tree.nodes.items(.data); |
| 4434 | 4426 | |
| ... | ... | @@ -4455,7 +4447,7 @@ fn arrayAccess( |
| 4455 | 4447 | node: ast.Node.Index, |
| 4456 | 4448 | ) InnerError!Zir.Inst.Ref { |
| 4457 | 4449 | const astgen = gz.astgen; |
| 4458 | | const tree = &astgen.file.tree; |
| 4450 | const tree = astgen.tree; |
| 4459 | 4451 | const main_tokens = tree.nodes.items(.main_token); |
| 4460 | 4452 | const node_datas = tree.nodes.items(.data); |
| 4461 | 4453 | switch (rl) { |
| ... | ... | @@ -4480,7 +4472,7 @@ fn simpleBinOp( |
| 4480 | 4472 | op_inst_tag: Zir.Inst.Tag, |
| 4481 | 4473 | ) InnerError!Zir.Inst.Ref { |
| 4482 | 4474 | const astgen = gz.astgen; |
| 4483 | | const tree = &astgen.file.tree; |
| 4475 | const tree = astgen.tree; |
| 4484 | 4476 | const node_datas = tree.nodes.items(.data); |
| 4485 | 4477 | |
| 4486 | 4478 | const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ |
| ... | ... | @@ -4512,7 +4504,7 @@ fn boolBinOp( |
| 4512 | 4504 | zir_tag: Zir.Inst.Tag, |
| 4513 | 4505 | ) InnerError!Zir.Inst.Ref { |
| 4514 | 4506 | const astgen = gz.astgen; |
| 4515 | | const tree = &astgen.file.tree; |
| 4507 | const tree = astgen.tree; |
| 4516 | 4508 | const node_datas = tree.nodes.items(.data); |
| 4517 | 4509 | |
| 4518 | 4510 | const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs); |
| ... | ... | @@ -4538,7 +4530,7 @@ fn ifExpr( |
| 4538 | 4530 | if_full: ast.full.If, |
| 4539 | 4531 | ) InnerError!Zir.Inst.Ref { |
| 4540 | 4532 | const astgen = parent_gz.astgen; |
| 4541 | | const tree = &astgen.file.tree; |
| 4533 | const tree = astgen.tree; |
| 4542 | 4534 | const token_tags = tree.tokens.items(.tag); |
| 4543 | 4535 | |
| 4544 | 4536 | var block_scope = parent_gz.makeSubBlock(scope); |
| ... | ... | @@ -4765,7 +4757,7 @@ fn whileExpr( |
| 4765 | 4757 | while_full: ast.full.While, |
| 4766 | 4758 | ) InnerError!Zir.Inst.Ref { |
| 4767 | 4759 | const astgen = parent_gz.astgen; |
| 4768 | | const tree = &astgen.file.tree; |
| 4760 | const tree = astgen.tree; |
| 4769 | 4761 | const token_tags = tree.tokens.items(.tag); |
| 4770 | 4762 | |
| 4771 | 4763 | if (while_full.label_token) |label_token| { |
| ... | ... | @@ -4967,7 +4959,7 @@ fn forExpr( |
| 4967 | 4959 | } |
| 4968 | 4960 | // Set up variables and constants. |
| 4969 | 4961 | const is_inline = parent_gz.force_comptime or for_full.inline_token != null; |
| 4970 | | const tree = &astgen.file.tree; |
| 4962 | const tree = astgen.tree; |
| 4971 | 4963 | const token_tags = tree.tokens.items(.tag); |
| 4972 | 4964 | |
| 4973 | 4965 | const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr); |
| ... | ... | @@ -5123,111 +5115,6 @@ fn forExpr( |
| 5123 | 5115 | ); |
| 5124 | 5116 | } |
| 5125 | 5117 | |
| 5126 | | fn 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 | | |
| 5138 | | pub 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 | | |
| 5231 | 5118 | fn switchExpr( |
| 5232 | 5119 | parent_gz: *GenZir, |
| 5233 | 5120 | scope: *Scope, |
| ... | ... | @@ -5236,7 +5123,7 @@ fn switchExpr( |
| 5236 | 5123 | ) InnerError!Zir.Inst.Ref { |
| 5237 | 5124 | const astgen = parent_gz.astgen; |
| 5238 | 5125 | const gpa = astgen.gpa; |
| 5239 | | const tree = &astgen.file.tree; |
| 5126 | const tree = astgen.tree; |
| 5240 | 5127 | const node_datas = tree.nodes.items(.data); |
| 5241 | 5128 | const node_tags = tree.nodes.items(.tag); |
| 5242 | 5129 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -5348,9 +5235,7 @@ fn switchExpr( |
| 5348 | 5235 | continue; |
| 5349 | 5236 | } |
| 5350 | 5237 | |
| 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) { |
| 5354 | 5239 | scalar_cases_len += 1; |
| 5355 | 5240 | } else { |
| 5356 | 5241 | multi_cases_len += 1; |
| ... | ... | @@ -5472,7 +5357,7 @@ fn switchExpr( |
| 5472 | 5357 | case_scope.instructions.shrinkRetainingCapacity(0); |
| 5473 | 5358 | |
| 5474 | 5359 | 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; |
| 5476 | 5361 | |
| 5477 | 5362 | const sub_scope = blk: { |
| 5478 | 5363 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| ... | ... | @@ -5528,7 +5413,7 @@ fn switchExpr( |
| 5528 | 5413 | // items |
| 5529 | 5414 | var items_len: u32 = 0; |
| 5530 | 5415 | for (case.ast.values) |item_node| { |
| 5531 | | if (getRangeNode(node_tags, node_datas, item_node) != null) continue; |
| 5416 | if (node_tags[item_node] == .switch_range) continue; |
| 5532 | 5417 | items_len += 1; |
| 5533 | 5418 | |
| 5534 | 5419 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| ... | ... | @@ -5537,8 +5422,8 @@ fn switchExpr( |
| 5537 | 5422 | |
| 5538 | 5423 | // ranges |
| 5539 | 5424 | 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; |
| 5542 | 5427 | ranges_len += 1; |
| 5543 | 5428 | |
| 5544 | 5429 | const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); |
| ... | ... | @@ -5824,7 +5709,7 @@ fn switchExpr( |
| 5824 | 5709 | |
| 5825 | 5710 | fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 5826 | 5711 | const astgen = gz.astgen; |
| 5827 | | const tree = &astgen.file.tree; |
| 5712 | const tree = astgen.tree; |
| 5828 | 5713 | const node_datas = tree.nodes.items(.data); |
| 5829 | 5714 | const main_tokens = tree.nodes.items(.main_token); |
| 5830 | 5715 | |
| ... | ... | @@ -5857,7 +5742,7 @@ fn identifier( |
| 5857 | 5742 | defer tracy.end(); |
| 5858 | 5743 | |
| 5859 | 5744 | const astgen = gz.astgen; |
| 5860 | | const tree = &astgen.file.tree; |
| 5745 | const tree = astgen.tree; |
| 5861 | 5746 | const main_tokens = tree.nodes.items(.main_token); |
| 5862 | 5747 | |
| 5863 | 5748 | const ident_token = main_tokens[ident]; |
| ... | ... | @@ -5922,8 +5807,8 @@ fn identifier( |
| 5922 | 5807 | } |
| 5923 | 5808 | s = local_ptr.parent; |
| 5924 | 5809 | }, |
| 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, |
| 5927 | 5812 | }; |
| 5928 | 5813 | } |
| 5929 | 5814 | |
| ... | ... | @@ -5946,7 +5831,7 @@ fn stringLiteral( |
| 5946 | 5831 | node: ast.Node.Index, |
| 5947 | 5832 | ) InnerError!Zir.Inst.Ref { |
| 5948 | 5833 | const astgen = gz.astgen; |
| 5949 | | const tree = astgen.file.tree; |
| 5834 | const tree = astgen.tree; |
| 5950 | 5835 | const main_tokens = tree.nodes.items(.main_token); |
| 5951 | 5836 | const str_lit_token = main_tokens[node]; |
| 5952 | 5837 | const str = try astgen.strLitAsString(str_lit_token); |
| ... | ... | @@ -5967,7 +5852,7 @@ fn multilineStringLiteral( |
| 5967 | 5852 | node: ast.Node.Index, |
| 5968 | 5853 | ) InnerError!Zir.Inst.Ref { |
| 5969 | 5854 | const astgen = gz.astgen; |
| 5970 | | const tree = &astgen.file.tree; |
| 5855 | const tree = astgen.tree; |
| 5971 | 5856 | const node_datas = tree.nodes.items(.data); |
| 5972 | 5857 | const main_tokens = tree.nodes.items(.main_token); |
| 5973 | 5858 | |
| ... | ... | @@ -6006,7 +5891,7 @@ fn multilineStringLiteral( |
| 6006 | 5891 | |
| 6007 | 5892 | fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Zir.Inst.Ref { |
| 6008 | 5893 | const astgen = gz.astgen; |
| 6009 | | const tree = &astgen.file.tree; |
| 5894 | const tree = astgen.tree; |
| 6010 | 5895 | const main_tokens = tree.nodes.items(.main_token); |
| 6011 | 5896 | const main_token = main_tokens[node]; |
| 6012 | 5897 | const slice = tree.tokenSlice(main_token); |
| ... | ... | @@ -6035,7 +5920,7 @@ fn integerLiteral( |
| 6035 | 5920 | node: ast.Node.Index, |
| 6036 | 5921 | ) InnerError!Zir.Inst.Ref { |
| 6037 | 5922 | const astgen = gz.astgen; |
| 6038 | | const tree = &astgen.file.tree; |
| 5923 | const tree = astgen.tree; |
| 6039 | 5924 | const main_tokens = tree.nodes.items(.main_token); |
| 6040 | 5925 | const int_token = main_tokens[node]; |
| 6041 | 5926 | const prefixed_bytes = tree.tokenSlice(int_token); |
| ... | ... | @@ -6087,7 +5972,7 @@ fn floatLiteral( |
| 6087 | 5972 | ) InnerError!Zir.Inst.Ref { |
| 6088 | 5973 | const astgen = gz.astgen; |
| 6089 | 5974 | const arena = astgen.arena; |
| 6090 | | const tree = &astgen.file.tree; |
| 5975 | const tree = astgen.tree; |
| 6091 | 5976 | const main_tokens = tree.nodes.items(.main_token); |
| 6092 | 5977 | |
| 6093 | 5978 | const main_token = main_tokens[node]; |
| ... | ... | @@ -6130,7 +6015,7 @@ fn asmExpr( |
| 6130 | 6015 | ) InnerError!Zir.Inst.Ref { |
| 6131 | 6016 | const astgen = gz.astgen; |
| 6132 | 6017 | const arena = astgen.arena; |
| 6133 | | const tree = &astgen.file.tree; |
| 6018 | const tree = astgen.tree; |
| 6134 | 6019 | const main_tokens = tree.nodes.items(.main_token); |
| 6135 | 6020 | const node_datas = tree.nodes.items(.data); |
| 6136 | 6021 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -6426,7 +6311,7 @@ fn builtinCall( |
| 6426 | 6311 | params: []const ast.Node.Index, |
| 6427 | 6312 | ) InnerError!Zir.Inst.Ref { |
| 6428 | 6313 | const astgen = gz.astgen; |
| 6429 | | const tree = &astgen.file.tree; |
| 6314 | const tree = astgen.tree; |
| 6430 | 6315 | const main_tokens = tree.nodes.items(.main_token); |
| 6431 | 6316 | |
| 6432 | 6317 | const builtin_token = main_tokens[node]; |
| ... | ... | @@ -7406,7 +7291,7 @@ fn rvalue( |
| 7406 | 7291 | }, |
| 7407 | 7292 | .ref => { |
| 7408 | 7293 | // We need a pointer but we have a value. |
| 7409 | | const tree = &gz.astgen.file.tree; |
| 7294 | const tree = gz.astgen.tree; |
| 7410 | 7295 | const src_token = tree.firstToken(src_node); |
| 7411 | 7296 | return gz.addUnTok(.ref, result, src_token); |
| 7412 | 7297 | }, |
| ... | ... | @@ -7498,8 +7383,8 @@ fn rvalue( |
| 7498 | 7383 | /// and allocates the result within `astgen.arena`. |
| 7499 | 7384 | /// Otherwise, returns a reference to the source code bytes directly. |
| 7500 | 7385 | /// See also `appendIdentStr` and `parseStrLit`. |
| 7501 | | pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 { |
| 7502 | | const tree = &astgen.file.tree; |
| 7386 | fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError![]const u8 { |
| 7387 | const tree = astgen.tree; |
| 7503 | 7388 | const token_tags = tree.tokens.items(.tag); |
| 7504 | 7389 | assert(token_tags[token] == .identifier); |
| 7505 | 7390 | const ident_name = tree.tokenSlice(token); |
| ... | ... | @@ -7516,12 +7401,12 @@ pub fn identifierTokenString(astgen: *AstGen, token: ast.TokenIndex) InnerError! |
| 7516 | 7401 | /// Given an identifier token, obtain the string for it (possibly parsing as a string |
| 7517 | 7402 | /// literal if it is @"" syntax), and append the string to `buf`. |
| 7518 | 7403 | /// See also `identifierTokenString` and `parseStrLit`. |
| 7519 | | pub fn appendIdentStr( |
| 7404 | fn appendIdentStr( |
| 7520 | 7405 | astgen: *AstGen, |
| 7521 | 7406 | token: ast.TokenIndex, |
| 7522 | 7407 | buf: *ArrayListUnmanaged(u8), |
| 7523 | 7408 | ) InnerError!void { |
| 7524 | | const tree = &astgen.file.tree; |
| 7409 | const tree = astgen.tree; |
| 7525 | 7410 | const token_tags = tree.tokens.items(.tag); |
| 7526 | 7411 | assert(token_tags[token] == .identifier); |
| 7527 | 7412 | const ident_name = tree.tokenSlice(token); |
| ... | ... | @@ -7533,14 +7418,14 @@ pub fn appendIdentStr( |
| 7533 | 7418 | } |
| 7534 | 7419 | |
| 7535 | 7420 | /// Appends the result to `buf`. |
| 7536 | | pub fn parseStrLit( |
| 7421 | fn parseStrLit( |
| 7537 | 7422 | astgen: *AstGen, |
| 7538 | 7423 | token: ast.TokenIndex, |
| 7539 | 7424 | buf: *ArrayListUnmanaged(u8), |
| 7540 | 7425 | bytes: []const u8, |
| 7541 | 7426 | offset: u32, |
| 7542 | 7427 | ) InnerError!void { |
| 7543 | | const tree = &astgen.file.tree; |
| 7428 | const tree = astgen.tree; |
| 7544 | 7429 | const raw_string = bytes[offset..]; |
| 7545 | 7430 | var buf_managed = buf.toManaged(astgen.gpa); |
| 7546 | 7431 | const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string); |
| ... | ... | @@ -7598,7 +7483,7 @@ pub fn parseStrLit( |
| 7598 | 7483 | } |
| 7599 | 7484 | } |
| 7600 | 7485 | |
| 7601 | | pub fn failNode( |
| 7486 | fn failNode( |
| 7602 | 7487 | astgen: *AstGen, |
| 7603 | 7488 | node: ast.Node.Index, |
| 7604 | 7489 | comptime format: []const u8, |
| ... | ... | @@ -7607,7 +7492,7 @@ pub fn failNode( |
| 7607 | 7492 | return astgen.failNodeNotes(node, format, args, &[0]u32{}); |
| 7608 | 7493 | } |
| 7609 | 7494 | |
| 7610 | | pub fn failNodeNotes( |
| 7495 | fn failNodeNotes( |
| 7611 | 7496 | astgen: *AstGen, |
| 7612 | 7497 | node: ast.Node.Index, |
| 7613 | 7498 | comptime format: []const u8, |
| ... | ... | @@ -7639,7 +7524,7 @@ pub fn failNodeNotes( |
| 7639 | 7524 | return error.AnalysisFail; |
| 7640 | 7525 | } |
| 7641 | 7526 | |
| 7642 | | pub fn failTok( |
| 7527 | fn failTok( |
| 7643 | 7528 | astgen: *AstGen, |
| 7644 | 7529 | token: ast.TokenIndex, |
| 7645 | 7530 | comptime format: []const u8, |
| ... | ... | @@ -7648,7 +7533,7 @@ pub fn failTok( |
| 7648 | 7533 | return astgen.failTokNotes(token, format, args, &[0]u32{}); |
| 7649 | 7534 | } |
| 7650 | 7535 | |
| 7651 | | pub fn failTokNotes( |
| 7536 | fn failTokNotes( |
| 7652 | 7537 | astgen: *AstGen, |
| 7653 | 7538 | token: ast.TokenIndex, |
| 7654 | 7539 | comptime format: []const u8, |
| ... | ... | @@ -7680,9 +7565,8 @@ pub fn failTokNotes( |
| 7680 | 7565 | return error.AnalysisFail; |
| 7681 | 7566 | } |
| 7682 | 7567 | |
| 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`. |
| 7685 | | pub fn failOff( |
| 7568 | /// Same as `fail`, except given an absolute byte offset. |
| 7569 | fn failOff( |
| 7686 | 7570 | astgen: *AstGen, |
| 7687 | 7571 | token: ast.TokenIndex, |
| 7688 | 7572 | byte_offset: u32, |
| ... | ... | @@ -7707,7 +7591,7 @@ pub fn failOff( |
| 7707 | 7591 | return error.AnalysisFail; |
| 7708 | 7592 | } |
| 7709 | 7593 | |
| 7710 | | pub fn errNoteTok( |
| 7594 | fn errNoteTok( |
| 7711 | 7595 | astgen: *AstGen, |
| 7712 | 7596 | token: ast.TokenIndex, |
| 7713 | 7597 | comptime format: []const u8, |
| ... | ... | @@ -7730,7 +7614,7 @@ pub fn errNoteTok( |
| 7730 | 7614 | }); |
| 7731 | 7615 | } |
| 7732 | 7616 | |
| 7733 | | pub fn errNoteNode( |
| 7617 | fn errNoteNode( |
| 7734 | 7618 | astgen: *AstGen, |
| 7735 | 7619 | node: ast.Node.Index, |
| 7736 | 7620 | comptime format: []const u8, |
| ... | ... | @@ -7780,7 +7664,7 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice { |
| 7780 | 7664 | const gpa = astgen.gpa; |
| 7781 | 7665 | const string_bytes = &astgen.string_bytes; |
| 7782 | 7666 | const str_index = @intCast(u32, string_bytes.items.len); |
| 7783 | | const token_bytes = astgen.file.tree.tokenSlice(str_lit_token); |
| 7667 | const token_bytes = astgen.tree.tokenSlice(str_lit_token); |
| 7784 | 7668 | try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0); |
| 7785 | 7669 | const key = string_bytes.items[str_index..]; |
| 7786 | 7670 | const gop = try astgen.string_table.getOrPut(gpa, key); |
| ... | ... | @@ -7811,9 +7695,934 @@ fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 { |
| 7811 | 7695 | const gpa = astgen.gpa; |
| 7812 | 7696 | const string_bytes = &astgen.string_bytes; |
| 7813 | 7697 | const str_index = @intCast(u32, string_bytes.items.len); |
| 7814 | | const token_bytes = astgen.file.tree.tokenSlice(str_lit_token); |
| 7698 | const token_bytes = astgen.tree.tokenSlice(str_lit_token); |
| 7815 | 7699 | try string_bytes.append(gpa, 0); // Indicates this is a test. |
| 7816 | 7700 | try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0); |
| 7817 | 7701 | try string_bytes.append(gpa, 0); |
| 7818 | 7702 | return str_index; |
| 7819 | 7703 | } |
| 7704 | |
| 7705 | const 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`. |
| 7771 | const 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 | }; |