authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-03 18:30:08-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-03 18:30:08-04:00
loga55dc4a3bcecbd5adc7ee1724c487786f74cbd8e
treea318daa6c5c8734f04bc3e724a3242537e188a01
parent08dc840247536cffb970b9fa3974017db44ed373
parent01842a6eadbe6e01d4afc4fc06394e73c9f24d58
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10079 from mattbork/astgen-temp-allocs

stage2: Reduce temporary allocations in AstGen

1 files changed, 1037 insertions(+), 1412 deletions(-)

src/AstGen.zig+1037-1412
......@@ -41,6 +41,8 @@ fn_block: ?*GenZir = null,
4141/// Maps string table indexes to the first `@import` ZIR instruction
4242/// that uses this string as the operand.
4343imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},
44/// Used for temporary storage when building payloads.
45scratch: std.ArrayListUnmanaged(u32) = .{},
4446
4547const InnerError = error{ OutOfMemory, AnalysisFail };
4648
......@@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
5355fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
5456 const fields = std.meta.fields(@TypeOf(extra));
5557 const result = @intCast(u32, astgen.extra.items.len);
58 astgen.extra.items.len += fields.len;
59 setExtra(astgen, result, extra);
60 return result;
61}
62
63fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
64 const fields = std.meta.fields(@TypeOf(extra));
65 var i = index;
5666 inline for (fields) |field| {
57 astgen.extra.appendAssumeCapacity(switch (field.field_type) {
67 astgen.extra.items[i] = switch (field.field_type) {
5868 u32 => @field(extra, field.name),
5969 Zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
6070 i32 => @bitCast(u32, @field(extra, field.name)),
6171 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
6272 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
6373 else => @compileError("bad field type"),
64 });
74 };
75 i += 1;
6576 }
77}
78
79fn reserveExtra(astgen: *AstGen, size: usize) Allocator.Error!u32 {
80 const result = @intCast(u32, astgen.extra.items.len);
81 try astgen.extra.resize(astgen.gpa, result + size);
6682 return result;
6783}
6884
......@@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {
101117
102118 var top_scope: Scope.Top = .{};
103119
120 var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
104121 var gen_scope: GenZir = .{
105122 .force_comptime = true,
106123 .in_defer = false,
......@@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {
109126 .decl_node_index = 0,
110127 .decl_line = 0,
111128 .astgen = &astgen,
129 .instructions = &gz_instructions,
130 .instructions_top = 0,
112131 };
113 defer gen_scope.instructions.deinit(gpa);
132 defer gz_instructions.deinit(gpa);
114133
115134 const container_decl: Ast.full.ContainerDecl = .{
116135 .layout_token = null,
......@@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {
184203 astgen.string_bytes.deinit(gpa);
185204 astgen.compile_errors.deinit(gpa);
186205 astgen.imports.deinit(gpa);
206 astgen.scratch.deinit(gpa);
187207}
188208
189209pub const ResultLoc = union(enum) {
......@@ -1024,12 +1044,12 @@ fn suspendExpr(
10241044 }
10251045 assert(body_node != 0);
10261046
1027 const suspend_inst = try gz.addBlock(.suspend_block, node);
1047 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);
10281048 try gz.instructions.append(gpa, suspend_inst);
10291049
10301050 var suspend_scope = gz.makeSubBlock(scope);
10311051 suspend_scope.suspend_node = node;
1032 defer suspend_scope.instructions.deinit(gpa);
1052 defer suspend_scope.unstack();
10331053
10341054 const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node);
10351055 if (!gz.refIsNoReturn(body_result)) {
......@@ -1084,7 +1104,6 @@ fn fnProtoExpr(
10841104 fn_proto: Ast.full.FnProto,
10851105) InnerError!Zir.Inst.Ref {
10861106 const astgen = gz.astgen;
1087 const gpa = astgen.gpa;
10881107 const tree = astgen.tree;
10891108 const token_tags = tree.tokens.items(.tag);
10901109
......@@ -1130,14 +1149,14 @@ fn fnProtoExpr(
11301149 const param_type_node = param.type_expr;
11311150 assert(param_type_node != 0);
11321151 var param_gz = gz.makeSubBlock(scope);
1133 defer param_gz.instructions.deinit(gpa);
1152 defer param_gz.unstack();
11341153 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);
11351154 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
11361155 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
11371156 const main_tokens = tree.nodes.items(.main_token);
11381157 const name_token = param.name_token orelse main_tokens[param_type_node];
11391158 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
1140 const param_inst = try gz.addParam(tag, name_token, param_name, param_gz.instructions.items);
1159 const param_inst = try gz.addParam(&param_gz, tag, name_token, param_name);
11411160 assert(param_inst_expected == param_inst);
11421161 }
11431162 }
......@@ -1172,16 +1191,16 @@ fn fnProtoExpr(
11721191 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
11731192 }
11741193 var ret_gz = gz.makeSubBlock(scope);
1175 defer ret_gz.instructions.deinit(gpa);
1194 defer ret_gz.unstack();
11761195 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
11771196 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
11781197
11791198 const result = try gz.addFunc(.{
11801199 .src_node = fn_proto.ast.proto_node,
11811200 .param_block = 0,
1182 .ret_ty = ret_gz.instructions.items,
1201 .ret_gz = &ret_gz,
11831202 .ret_br = ret_br,
1184 .body = &[0]Zir.Inst.Index{},
1203 .body_gz = null,
11851204 .cc = cc,
11861205 .align_inst = align_inst,
11871206 .lib_name = 0,
......@@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone(
13071326 tag: Zir.Inst.Tag,
13081327) InnerError!Zir.Inst.Ref {
13091328 const astgen = gz.astgen;
1310 const gpa = astgen.gpa;
1311 const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
1312 defer gpa.free(elem_list);
13131329
1314 for (elements) |elem_init, i| {
1315 elem_list[i] = try expr(gz, scope, .none, elem_init);
1316 }
1317 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
1318 .operands_len = @intCast(u32, elem_list.len),
1330 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1331 .operands_len = @intCast(u32, elements.len),
13191332 });
1320 try astgen.appendRefs(elem_list);
1321 return init_inst;
1333 var extra_index = try reserveExtra(astgen, elements.len);
1334
1335 for (elements) |elem_init| {
1336 const elem_ref = try expr(gz, scope, .none, elem_init);
1337 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1338 extra_index += 1;
1339 }
1340 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
13221341}
13231342
13241343fn arrayInitExprRlTy(
......@@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy(
13301349 tag: Zir.Inst.Tag,
13311350) InnerError!Zir.Inst.Ref {
13321351 const astgen = gz.astgen;
1333 const gpa = astgen.gpa;
13341352
1335 const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
1336 defer gpa.free(elem_list);
1353 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1354 .operands_len = @intCast(u32, elements.len),
1355 });
1356 var extra_index = try reserveExtra(astgen, elements.len);
13371357
13381358 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
1339
1340 for (elements) |elem_init, i| {
1341 elem_list[i] = try expr(gz, scope, elem_rl, elem_init);
1359 for (elements) |elem_init| {
1360 const elem_ref = try expr(gz, scope, elem_rl, elem_init);
1361 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1362 extra_index += 1;
13421363 }
1343 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
1344 .operands_len = @intCast(u32, elem_list.len),
1345 });
1346 try astgen.appendRefs(elem_list);
1347 return init_inst;
1364 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
13481365}
13491366
13501367fn arrayInitExprRlPtr(
......@@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr(
13611378 }
13621379
13631380 var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr);
1364 defer as_scope.instructions.deinit(gz.astgen.gpa);
1381 defer as_scope.unstack();
13651382
13661383 const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);
13671384 return as_scope.finishCoercion(gz, rl, node, result, array_ty);
......@@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner(
13751392 elements: []const Ast.Node.Index,
13761393) InnerError!Zir.Inst.Ref {
13771394 const astgen = gz.astgen;
1378 const gpa = astgen.gpa;
13791395
1380 const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len);
1381 defer gpa.free(elem_ptr_list);
1396 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1397 .body_len = @intCast(u32, elements.len),
1398 });
1399 var extra_index = try reserveExtra(astgen, elements.len);
13821400
13831401 for (elements) |elem_init, i| {
13841402 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
13851403 .ptr = result_ptr,
13861404 .index = @intCast(u32, i),
13871405 });
1388 elem_ptr_list[i] = refToIndex(elem_ptr).?;
1406 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1407 extra_index += 1;
13891408 _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);
13901409 }
1391 _ = try gz.addPlNode(.validate_array_init, node, Zir.Inst.Block{
1392 .body_len = @intCast(u32, elem_ptr_list.len),
1393 });
1394 try astgen.extra.appendSlice(gpa, elem_ptr_list);
1410 _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index);
13951411 return .void_value;
13961412}
13971413
......@@ -1505,30 +1521,25 @@ fn structInitExprRlNone(
15051521 tag: Zir.Inst.Tag,
15061522) InnerError!Zir.Inst.Ref {
15071523 const astgen = gz.astgen;
1508 const gpa = astgen.gpa;
15091524 const tree = astgen.tree;
15101525
1511 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);
1512 defer gpa.free(fields_list);
1526 const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{
1527 .fields_len = @intCast(u32, struct_init.ast.fields.len),
1528 });
1529 const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len;
1530 var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size);
15131531
1514 for (struct_init.ast.fields) |field_init, i| {
1532 for (struct_init.ast.fields) |field_init| {
15151533 const name_token = tree.firstToken(field_init) - 2;
15161534 const str_index = try astgen.identAsString(name_token);
1517
1518 fields_list[i] = .{
1535 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
15191536 .field_name = str_index,
15201537 .init = try expr(gz, scope, .none, field_init),
1521 };
1522 }
1523 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{
1524 .fields_len = @intCast(u32, fields_list.len),
1525 });
1526 try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len *
1527 @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);
1528 for (fields_list) |field| {
1529 _ = gz.astgen.addExtraAssumeCapacity(field);
1538 });
1539 extra_index += field_size;
15301540 }
1531 return init_inst;
1541
1542 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
15321543}
15331544
15341545fn structInitExprRlPtr(
......@@ -1545,7 +1556,7 @@ fn structInitExprRlPtr(
15451556 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
15461557
15471558 var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr);
1548 defer as_scope.instructions.deinit(gz.astgen.gpa);
1559 defer as_scope.unstack();
15491560
15501561 const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);
15511562 return as_scope.finishCoercion(gz, rl, node, result, ty_inst);
......@@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner(
15591570 result_ptr: Zir.Inst.Ref,
15601571) InnerError!Zir.Inst.Ref {
15611572 const astgen = gz.astgen;
1562 const gpa = astgen.gpa;
15631573 const tree = astgen.tree;
15641574
1565 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);
1566 defer gpa.free(field_ptr_list);
1575 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1576 .body_len = @intCast(u32, struct_init.ast.fields.len),
1577 });
1578 var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len);
15671579
1568 for (struct_init.ast.fields) |field_init, i| {
1580 for (struct_init.ast.fields) |field_init| {
15691581 const name_token = tree.firstToken(field_init) - 2;
15701582 const str_index = try astgen.identAsString(name_token);
15711583 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{
15721584 .lhs = result_ptr,
15731585 .field_name_start = str_index,
15741586 });
1575 field_ptr_list[i] = refToIndex(field_ptr).?;
1587 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1588 extra_index += 1;
15761589 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
15771590 }
1578 _ = try gz.addPlNode(.validate_struct_init, node, Zir.Inst.Block{
1579 .body_len = @intCast(u32, field_ptr_list.len),
1580 });
1581 try astgen.extra.appendSlice(gpa, field_ptr_list);
1591
1592 _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index);
15821593 return Zir.Inst.Ref.void_value;
15831594}
15841595
......@@ -1591,34 +1602,29 @@ fn structInitExprRlTy(
15911602 tag: Zir.Inst.Tag,
15921603) InnerError!Zir.Inst.Ref {
15931604 const astgen = gz.astgen;
1594 const gpa = astgen.gpa;
15951605 const tree = astgen.tree;
15961606
1597 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);
1598 defer gpa.free(fields_list);
1607 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1608 .fields_len = @intCast(u32, struct_init.ast.fields.len),
1609 });
1610 const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len;
1611 var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size);
15991612
1600 for (struct_init.ast.fields) |field_init, i| {
1613 for (struct_init.ast.fields) |field_init| {
16011614 const name_token = tree.firstToken(field_init) - 2;
16021615 const str_index = try astgen.identAsString(name_token);
1603
16041616 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
16051617 .container_type = ty_inst,
16061618 .name_start = str_index,
16071619 });
1608 fields_list[i] = .{
1620 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
16091621 .field_type = refToIndex(field_ty_inst).?,
16101622 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
1611 };
1612 }
1613 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{
1614 .fields_len = @intCast(u32, fields_list.len),
1615 });
1616 try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len *
1617 @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len);
1618 for (fields_list) |field| {
1619 _ = gz.astgen.addExtraAssumeCapacity(field);
1623 });
1624 extra_index += field_size;
16201625 }
1621 return init_inst;
1626
1627 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
16221628}
16231629
16241630/// This calls expr in a comptime scope, and is intended to be called as a helper function.
......@@ -1871,7 +1877,7 @@ fn labeledBlockExpr(
18711877
18721878 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
18731879 // so that break statements can reference it.
1874 const block_inst = try gz.addBlock(zir_tag, block_node);
1880 const block_inst = try gz.makeBlockInst(zir_tag, block_node);
18751881 try gz.instructions.append(astgen.gpa, block_inst);
18761882
18771883 var block_scope = gz.makeSubBlock(parent_scope);
......@@ -1880,7 +1886,7 @@ fn labeledBlockExpr(
18801886 .block_inst = block_inst,
18811887 };
18821888 block_scope.setBreakResultLoc(rl);
1883 defer block_scope.instructions.deinit(astgen.gpa);
1889 defer block_scope.unstack();
18841890 defer block_scope.labeled_breaks.deinit(astgen.gpa);
18851891 defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
18861892
......@@ -2485,7 +2491,6 @@ fn varDecl(
24852491) InnerError!*Scope {
24862492 try emitDbgNode(gz, node);
24872493 const astgen = gz.astgen;
2488 const gpa = astgen.gpa;
24892494 const tree = astgen.tree;
24902495 const token_tags = tree.tokens.items(.tag);
24912496 const main_tokens = tree.nodes.items(.main_token);
......@@ -2546,7 +2551,9 @@ fn varDecl(
25462551 // Detect whether the initialization expression actually uses the
25472552 // result location pointer.
25482553 var init_scope = gz.makeSubBlock(scope);
2549 defer init_scope.instructions.deinit(gpa);
2554 // we may add more instructions to gz before stacking init_scope
2555 init_scope.instructions_top = GenZir.unstacked_top;
2556 defer init_scope.unstack();
25502557
25512558 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
25522559 var opt_type_inst: Zir.Inst.Ref = .none;
......@@ -2554,6 +2561,7 @@ fn varDecl(
25542561 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);
25552562 opt_type_inst = type_inst;
25562563 if (align_inst == .none) {
2564 init_scope.instructions_top = gz.instructions.items.len;
25572565 init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node);
25582566 } else {
25592567 init_scope.rl_ptr = try gz.addAllocExtended(.{
......@@ -2563,19 +2571,24 @@ fn varDecl(
25632571 .is_const = true,
25642572 .is_comptime = false,
25652573 });
2574 init_scope.instructions_top = gz.instructions.items.len;
25662575 }
25672576 init_scope.rl_ty_inst = type_inst;
25682577 } else {
2569 const alloc = if (align_inst == .none)
2570 try init_scope.addNode(.alloc_inferred, node)
2571 else
2572 try gz.addAllocExtended(.{
2578 const alloc = if (align_inst == .none) alloc: {
2579 init_scope.instructions_top = gz.instructions.items.len;
2580 break :alloc try init_scope.addNode(.alloc_inferred, node);
2581 } else alloc: {
2582 const ref = try gz.addAllocExtended(.{
25732583 .node = node,
25742584 .type_inst = .none,
25752585 .align_inst = align_inst,
25762586 .is_const = true,
25772587 .is_comptime = false,
25782588 });
2589 init_scope.instructions_top = gz.instructions.items.len;
2590 break :alloc ref;
2591 };
25792592 resolve_inferred_alloc = alloc;
25802593 init_scope.rl_ptr = alloc;
25812594 }
......@@ -2585,20 +2598,24 @@ fn varDecl(
25852598 const zir_tags = astgen.instructions.items(.tag);
25862599 const zir_datas = astgen.instructions.items(.data);
25872600
2588 const parent_zir = &gz.instructions;
25892601 if (align_inst == .none and init_scope.rvalue_rl_count == 1) {
25902602 // Result location pointer not used. We don't need an alloc for this
25912603 // const local, and type inference becomes trivial.
2592 // Move the init_scope instructions into the parent scope, eliding
2593 // the alloc instruction and the store_to_block_ptr instruction.
2594 try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len);
2595 for (init_scope.instructions.items) |src_inst| {
2604 // Implicitly move the init_scope instructions into the parent scope,
2605 // then elide the alloc instruction and the store_to_block_ptr instruction.
2606 var src = init_scope.instructions_top;
2607 var dst = src;
2608 init_scope.instructions_top = GenZir.unstacked_top;
2609 while (src < gz.instructions.items.len) : (src += 1) {
2610 const src_inst = gz.instructions.items[src];
25962611 if (indexToRef(src_inst) == init_scope.rl_ptr) continue;
25972612 if (zir_tags[src_inst] == .store_to_block_ptr) {
25982613 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;
25992614 }
2600 parent_zir.appendAssumeCapacity(src_inst);
2615 gz.instructions.items[dst] = src_inst;
2616 dst += 1;
26012617 }
2618 gz.instructions.items.len = dst;
26022619
26032620 const sub_scope = try block_arena.create(Scope.LocalVal);
26042621 sub_scope.* = .{
......@@ -2613,11 +2630,13 @@ fn varDecl(
26132630 }
26142631 // The initialization expression took advantage of the result location
26152632 // of the const local. In this case we will create an alloc and a LocalPtr for it.
2616 // Move the init_scope instructions into the parent scope, swapping
2633 // Implicitly move the init_scope instructions into the parent scope, then swap
26172634 // store_to_block_ptr for store_to_inferred_ptr.
2618 const expected_len = parent_zir.items.len + init_scope.instructions.items.len;
2619 try parent_zir.ensureTotalCapacity(gpa, expected_len);
2620 for (init_scope.instructions.items) |src_inst| {
2635
2636 var src = init_scope.instructions_top;
2637 init_scope.instructions_top = GenZir.unstacked_top;
2638 while (src < gz.instructions.items.len) : (src += 1) {
2639 const src_inst = gz.instructions.items[src];
26212640 if (zir_tags[src_inst] == .store_to_block_ptr) {
26222641 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
26232642 if (var_decl.ast.type_node != 0) {
......@@ -2627,9 +2646,7 @@ fn varDecl(
26272646 }
26282647 }
26292648 }
2630 parent_zir.appendAssumeCapacity(src_inst);
26312649 }
2632 assert(parent_zir.items.len == expected_len);
26332650 if (resolve_inferred_alloc != .none) {
26342651 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
26352652 }
......@@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
29943011 return rvalue(gz, rl, result, node);
29953012}
29963013
2997const WipDecls = struct {
2998 decl_index: usize = 0,
2999 cur_bit_bag: u32 = 0,
3000 bit_bag: ArrayListUnmanaged(u32) = .{},
3001 payload: ArrayListUnmanaged(u32) = .{},
3014const WipMembers = struct {
3015 payload: *ArrayListUnmanaged(u32),
3016 payload_top: usize,
3017 decls_start: u32,
3018 decls_end: u32,
3019 field_bits_start: u32,
3020 fields_start: u32,
3021 fields_end: u32,
3022 decl_index: u32 = 0,
3023 field_index: u32 = 0,
3024
3025 const Self = @This();
3026 /// struct, union, enum, and opaque decls all use same 4 bits per decl
3027 const bits_per_decl = 4;
3028 const decls_per_u32 = 32 / bits_per_decl;
3029 /// struct, union, enum, and opaque decls all have maximum size of 10 u32 slots
3030 /// (4 for src_hash + line + name + value + align + link_section + address_space)
3031 const max_decl_size = 10;
3032
3033 pub fn init(gpa: *Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3034 const payload_top = @intCast(u32, payload.items.len);
3035 const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32;
3036 const field_bits_start = decls_start + decl_count * max_decl_size;
3037 const fields_start = field_bits_start + if (bits_per_field > 0) blk: {
3038 const fields_per_u32 = 32 / bits_per_field;
3039 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;
3040 } else 0;
3041 const payload_end = fields_start + field_count * max_field_size;
3042 try payload.resize(gpa, payload_end);
3043 return Self{
3044 .payload = payload,
3045 .payload_top = payload_top,
3046 .decls_start = decls_start,
3047 .field_bits_start = field_bits_start,
3048 .fields_start = fields_start,
3049 .decls_end = decls_start,
3050 .fields_end = fields_start,
3051 };
3052 }
30023053
3003 const bits_per_field = 4;
3004 const fields_per_u32 = 32 / bits_per_field;
3005
3006 fn next(
3007 wip_decls: *WipDecls,
3008 gpa: *Allocator,
3009 is_pub: bool,
3010 is_export: bool,
3011 has_align: bool,
3012 has_section_or_addrspace: bool,
3013 ) Allocator.Error!void {
3014 if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) {
3015 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
3016 wip_decls.cur_bit_bag = 0;
3017 }
3018 wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) |
3054 pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {
3055 const index = self.payload_top + self.decl_index / decls_per_u32;
3056 assert(index < self.decls_start);
3057 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index];
3058 self.payload.items[index] = (bit_bag >> bits_per_decl) |
30193059 (@as(u32, @boolToInt(is_pub)) << 28) |
30203060 (@as(u32, @boolToInt(is_export)) << 29) |
30213061 (@as(u32, @boolToInt(has_align)) << 30) |
30223062 (@as(u32, @boolToInt(has_section_or_addrspace)) << 31);
3023 wip_decls.decl_index += 1;
3063 self.decl_index += 1;
3064 }
3065
3066 pub fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void {
3067 const fields_per_u32 = 32 / bits_per_field;
3068 const index = self.field_bits_start + self.field_index / fields_per_u32;
3069 assert(index < self.fields_start);
3070 var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index];
3071 bit_bag >>= bits_per_field;
3072 comptime var i = 0;
3073 inline while (i < bits_per_field) : (i += 1) {
3074 bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i);
3075 }
3076 self.payload.items[index] = bit_bag;
3077 self.field_index += 1;
3078 }
3079
3080 pub fn appendToDecl(self: *Self, data: u32) void {
3081 assert(self.decls_end < self.field_bits_start);
3082 self.payload.items[self.decls_end] = data;
3083 self.decls_end += 1;
3084 }
3085
3086 pub fn appendToDeclSlice(self: *Self, data: []const u32) void {
3087 assert(self.decls_end + data.len <= self.field_bits_start);
3088 mem.copy(u32, self.payload.items[self.decls_end..], data);
3089 self.decls_end += @intCast(u32, data.len);
3090 }
3091
3092 pub fn appendToField(self: *Self, data: u32) void {
3093 assert(self.fields_end < self.payload.items.len);
3094 self.payload.items[self.fields_end] = data;
3095 self.fields_end += 1;
3096 }
3097
3098 pub fn finishBits(self: *Self, comptime bits_per_field: u32) void {
3099 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);
3100 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {
3101 const index = self.payload_top + self.decl_index / decls_per_u32;
3102 self.payload.items[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);
3103 }
3104 if (bits_per_field > 0) {
3105 const fields_per_u32 = 32 / bits_per_field;
3106 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
3107 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {
3108 const index = self.field_bits_start + self.field_index / fields_per_u32;
3109 self.payload.items[index] >>= @intCast(u5, empty_field_slots * bits_per_field);
3110 }
3111 }
3112 }
3113
3114 pub fn declsSlice(self: *Self) []u32 {
3115 return self.payload.items[self.payload_top..self.decls_end];
3116 }
3117
3118 pub fn fieldsSlice(self: *Self) []u32 {
3119 return self.payload.items[self.field_bits_start..self.fields_end];
30243120 }
30253121
3026 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {
3027 wip_decls.bit_bag.deinit(gpa);
3028 wip_decls.payload.deinit(gpa);
3122 pub fn deinit(self: *Self) void {
3123 self.payload.items.len = self.payload_top;
30293124 }
30303125};
30313126
......@@ -3033,12 +3128,11 @@ fn fnDecl(
30333128 astgen: *AstGen,
30343129 gz: *GenZir,
30353130 scope: *Scope,
3036 wip_decls: *WipDecls,
3131 wip_members: *WipMembers,
30373132 decl_node: Ast.Node.Index,
30383133 body_node: Ast.Node.Index,
30393134 fn_proto: Ast.full.FnProto,
30403135) InnerError!void {
3041 const gpa = astgen.gpa;
30423136 const tree = astgen.tree;
30433137 const token_tags = tree.tokens.items(.tag);
30443138
......@@ -3048,7 +3142,7 @@ fn fnDecl(
30483142
30493143 // We insert this at the beginning so that its instruction index marks the
30503144 // start of the top level declaration.
3051 const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node);
3145 const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node);
30523146
30533147 var decl_gz: GenZir = .{
30543148 .force_comptime = true,
......@@ -3057,8 +3151,10 @@ fn fnDecl(
30573151 .decl_line = gz.calcLine(decl_node),
30583152 .parent = scope,
30593153 .astgen = astgen,
3154 .instructions = gz.instructions,
3155 .instructions_top = gz.instructions.items.len,
30603156 };
3061 defer decl_gz.instructions.deinit(gpa);
3157 defer decl_gz.unstack();
30623158
30633159 var fn_gz: GenZir = .{
30643160 .force_comptime = false,
......@@ -3067,8 +3163,10 @@ fn fnDecl(
30673163 .decl_line = decl_gz.decl_line,
30683164 .parent = &decl_gz.base,
30693165 .astgen = astgen,
3166 .instructions = gz.instructions,
3167 .instructions_top = GenZir.unstacked_top,
30703168 };
3071 defer fn_gz.instructions.deinit(gpa);
3169 defer fn_gz.unstack();
30723170
30733171 // TODO: support noinline
30743172 const is_pub = fn_proto.visib_token != null;
......@@ -3085,7 +3183,7 @@ fn fnDecl(
30853183 break :blk token_tags[maybe_inline_token] == .keyword_inline;
30863184 };
30873185 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;
3088 try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);
3186 wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace);
30893187
30903188 var params_scope = &fn_gz.base;
30913189 const is_var_args = is_var_args: {
......@@ -3134,7 +3232,7 @@ fn fnDecl(
31343232 const param_type_node = param.type_expr;
31353233 assert(param_type_node != 0);
31363234 var param_gz = decl_gz.makeSubBlock(scope);
3137 defer param_gz.instructions.deinit(gpa);
3235 defer param_gz.unstack();
31383236 const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node);
31393237 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
31403238 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
......@@ -3142,7 +3240,7 @@ fn fnDecl(
31423240 const main_tokens = tree.nodes.items(.main_token);
31433241 const name_token = param.name_token orelse main_tokens[param_type_node];
31443242 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
3145 const param_inst = try decl_gz.addParam(tag, name_token, param_name, param_gz.instructions.items);
3243 const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name);
31463244 assert(param_inst_expected == param_inst);
31473245 break :param indexToRef(param_inst);
31483246 };
......@@ -3207,7 +3305,7 @@ fn fnDecl(
32073305 };
32083306
32093307 var ret_gz = decl_gz.makeSubBlock(params_scope);
3210 defer ret_gz.instructions.deinit(gpa);
3308 defer ret_gz.unstack();
32113309 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
32123310 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
32133311
......@@ -3220,10 +3318,10 @@ fn fnDecl(
32203318 }
32213319 break :func try decl_gz.addFunc(.{
32223320 .src_node = decl_node,
3223 .ret_ty = ret_gz.instructions.items,
3321 .ret_gz = &ret_gz,
32243322 .ret_br = ret_br,
32253323 .param_block = block_inst,
3226 .body = &[0]Zir.Inst.Index{},
3324 .body_gz = null,
32273325 .cc = cc,
32283326 .align_inst = .none, // passed in the per-decl data
32293327 .lib_name = lib_name,
......@@ -3237,6 +3335,9 @@ fn fnDecl(
32373335 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
32383336 }
32393337
3338 // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz
3339 fn_gz.instructions_top = ret_gz.instructions.items.len;
3340
32403341 const prev_fn_block = astgen.fn_block;
32413342 astgen.fn_block = &fn_gz;
32423343 defer astgen.fn_block = prev_fn_block;
......@@ -3250,14 +3351,7 @@ fn fnDecl(
32503351 _ = try expr(&fn_gz, params_scope, .none, body_node);
32513352 try checkUsed(gz, &fn_gz.base, params_scope);
32523353
3253 const need_implicit_ret = blk: {
3254 if (fn_gz.instructions.items.len == 0)
3255 break :blk true;
3256 const last = fn_gz.instructions.items[fn_gz.instructions.items.len - 1];
3257 const zir_tags = astgen.instructions.items(.tag);
3258 break :blk !zir_tags[last].isNoReturn();
3259 };
3260 if (need_implicit_ret) {
3354 if (!fn_gz.endsWithNoReturn()) {
32613355 // Since we are adding the return instruction here, we must handle the coercion.
32623356 // We do this by using the `ret_coerce` instruction.
32633357 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
......@@ -3268,9 +3362,9 @@ fn fnDecl(
32683362 .lbrace_line = lbrace_line,
32693363 .lbrace_column = lbrace_column,
32703364 .param_block = block_inst,
3271 .ret_ty = ret_gz.instructions.items,
3365 .ret_gz = &ret_gz,
32723366 .ret_br = ret_br,
3273 .body = fn_gz.instructions.items,
3367 .body_gz = &fn_gz,
32743368 .cc = cc,
32753369 .align_inst = .none, // passed in the per-decl data
32763370 .lib_name = lib_name,
......@@ -3282,29 +3376,27 @@ fn fnDecl(
32823376 };
32833377
32843378 // We add this at the end so that its instruction index marks the end range
3285 // of the top level declaration.
3379 // of the top level declaration. addFunc already unstacked fn_gz and ret_gz.
32863380 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
32873381 try decl_gz.setBlockBody(block_inst);
32883382
3289 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
32903383 {
32913384 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
32923385 const casted = @bitCast([4]u32, contents_hash);
3293 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3386 wip_members.appendToDeclSlice(&casted);
32943387 }
32953388 {
32963389 const line_delta = decl_gz.decl_line - gz.decl_line;
3297 wip_decls.payload.appendAssumeCapacity(line_delta);
3390 wip_members.appendToDecl(line_delta);
32983391 }
3299 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
3300 wip_decls.payload.appendAssumeCapacity(block_inst);
3392 wip_members.appendToDecl(fn_name_str_index);
3393 wip_members.appendToDecl(block_inst);
33013394 if (align_inst != .none) {
3302 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
3395 wip_members.appendToDecl(@enumToInt(align_inst));
33033396 }
3304
33053397 if (has_section_or_addrspace) {
3306 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
3307 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));
3398 wip_members.appendToDecl(@enumToInt(section_inst));
3399 wip_members.appendToDecl(@enumToInt(addrspace_inst));
33083400 }
33093401}
33103402
......@@ -3312,18 +3404,17 @@ fn globalVarDecl(
33123404 astgen: *AstGen,
33133405 gz: *GenZir,
33143406 scope: *Scope,
3315 wip_decls: *WipDecls,
3407 wip_members: *WipMembers,
33163408 node: Ast.Node.Index,
33173409 var_decl: Ast.full.VarDecl,
33183410) InnerError!void {
3319 const gpa = astgen.gpa;
33203411 const tree = astgen.tree;
33213412 const token_tags = tree.tokens.items(.tag);
33223413
33233414 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
33243415 // We do this at the beginning so that the instruction index marks the range start
33253416 // of the top level declaration.
3326 const block_inst = try gz.addBlock(.block_inline, node);
3417 const block_inst = try gz.makeBlockInst(.block_inline, node);
33273418
33283419 const name_token = var_decl.ast.mut_token + 1;
33293420 const name_str_index = try astgen.identAsString(name_token);
......@@ -3336,8 +3427,10 @@ fn globalVarDecl(
33363427 .force_comptime = true,
33373428 .in_defer = false,
33383429 .anon_name_strategy = .parent,
3430 .instructions = gz.instructions,
3431 .instructions_top = gz.instructions.items.len,
33393432 };
3340 defer block_scope.instructions.deinit(gpa);
3433 defer block_scope.unstack();
33413434
33423435 const is_pub = var_decl.visib_token != null;
33433436 const is_export = blk: {
......@@ -3358,7 +3451,7 @@ fn globalVarDecl(
33583451 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
33593452 };
33603453 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
3361 try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, has_section_or_addrspace);
3454 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
33623455
33633456 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
33643457 if (!is_mutable) {
......@@ -3436,24 +3529,23 @@ fn globalVarDecl(
34363529 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
34373530 try block_scope.setBlockBody(block_inst);
34383531
3439 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
34403532 {
34413533 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
34423534 const casted = @bitCast([4]u32, contents_hash);
3443 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3535 wip_members.appendToDeclSlice(&casted);
34443536 }
34453537 {
34463538 const line_delta = block_scope.decl_line - gz.decl_line;
3447 wip_decls.payload.appendAssumeCapacity(line_delta);
3539 wip_members.appendToDecl(line_delta);
34483540 }
3449 wip_decls.payload.appendAssumeCapacity(name_str_index);
3450 wip_decls.payload.appendAssumeCapacity(block_inst);
3541 wip_members.appendToDecl(name_str_index);
3542 wip_members.appendToDecl(block_inst);
34513543 if (align_inst != .none) {
3452 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
3544 wip_members.appendToDecl(@enumToInt(align_inst));
34533545 }
34543546 if (has_section_or_addrspace) {
3455 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
3456 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));
3547 wip_members.appendToDecl(@enumToInt(section_inst));
3548 wip_members.appendToDecl(@enumToInt(addrspace_inst));
34573549 }
34583550}
34593551
......@@ -3461,18 +3553,17 @@ fn comptimeDecl(
34613553 astgen: *AstGen,
34623554 gz: *GenZir,
34633555 scope: *Scope,
3464 wip_decls: *WipDecls,
3556 wip_members: *WipMembers,
34653557 node: Ast.Node.Index,
34663558) InnerError!void {
3467 const gpa = astgen.gpa;
34683559 const tree = astgen.tree;
34693560 const node_datas = tree.nodes.items(.data);
34703561 const body_node = node_datas[node].lhs;
34713562
34723563 // Up top so the ZIR instruction index marks the start range of this
34733564 // top-level declaration.
3474 const block_inst = try gz.addBlock(.block_inline, node);
3475 try wip_decls.next(gpa, false, false, false, false);
3565 const block_inst = try gz.makeBlockInst(.block_inline, node);
3566 wip_members.nextDecl(false, false, false, false);
34763567
34773568 var decl_block: GenZir = .{
34783569 .force_comptime = true,
......@@ -3481,37 +3572,37 @@ fn comptimeDecl(
34813572 .decl_line = gz.calcLine(node),
34823573 .parent = scope,
34833574 .astgen = astgen,
3575 .instructions = gz.instructions,
3576 .instructions_top = gz.instructions.items.len,
34843577 };
3485 defer decl_block.instructions.deinit(gpa);
3578 defer decl_block.unstack();
34863579
34873580 const block_result = try expr(&decl_block, &decl_block.base, .none, body_node);
3488 if (decl_block.instructions.items.len == 0 or !decl_block.refIsNoReturn(block_result)) {
3581 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
34893582 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);
34903583 }
34913584 try decl_block.setBlockBody(block_inst);
34923585
3493 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
34943586 {
34953587 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
34963588 const casted = @bitCast([4]u32, contents_hash);
3497 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3589 wip_members.appendToDeclSlice(&casted);
34983590 }
34993591 {
35003592 const line_delta = decl_block.decl_line - gz.decl_line;
3501 wip_decls.payload.appendAssumeCapacity(line_delta);
3593 wip_members.appendToDecl(line_delta);
35023594 }
3503 wip_decls.payload.appendAssumeCapacity(0);
3504 wip_decls.payload.appendAssumeCapacity(block_inst);
3595 wip_members.appendToDecl(0);
3596 wip_members.appendToDecl(block_inst);
35053597}
35063598
35073599fn usingnamespaceDecl(
35083600 astgen: *AstGen,
35093601 gz: *GenZir,
35103602 scope: *Scope,
3511 wip_decls: *WipDecls,
3603 wip_members: *WipMembers,
35123604 node: Ast.Node.Index,
35133605) InnerError!void {
3514 const gpa = astgen.gpa;
35153606 const tree = astgen.tree;
35163607 const node_datas = tree.nodes.items(.data);
35173608
......@@ -3524,8 +3615,8 @@ fn usingnamespaceDecl(
35243615 };
35253616 // Up top so the ZIR instruction index marks the start range of this
35263617 // top-level declaration.
3527 const block_inst = try gz.addBlock(.block_inline, node);
3528 try wip_decls.next(gpa, is_pub, true, false, false);
3618 const block_inst = try gz.makeBlockInst(.block_inline, node);
3619 wip_members.nextDecl(is_pub, true, false, false);
35293620
35303621 var decl_block: GenZir = .{
35313622 .force_comptime = true,
......@@ -3534,44 +3625,44 @@ fn usingnamespaceDecl(
35343625 .decl_line = gz.calcLine(node),
35353626 .parent = scope,
35363627 .astgen = astgen,
3628 .instructions = gz.instructions,
3629 .instructions_top = gz.instructions.items.len,
35373630 };
3538 defer decl_block.instructions.deinit(gpa);
3631 defer decl_block.unstack();
35393632
35403633 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
35413634 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
35423635 try decl_block.setBlockBody(block_inst);
35433636
3544 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
35453637 {
35463638 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
35473639 const casted = @bitCast([4]u32, contents_hash);
3548 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3640 wip_members.appendToDeclSlice(&casted);
35493641 }
35503642 {
35513643 const line_delta = decl_block.decl_line - gz.decl_line;
3552 wip_decls.payload.appendAssumeCapacity(line_delta);
3644 wip_members.appendToDecl(line_delta);
35533645 }
3554 wip_decls.payload.appendAssumeCapacity(0);
3555 wip_decls.payload.appendAssumeCapacity(block_inst);
3646 wip_members.appendToDecl(0);
3647 wip_members.appendToDecl(block_inst);
35563648}
35573649
35583650fn testDecl(
35593651 astgen: *AstGen,
35603652 gz: *GenZir,
35613653 scope: *Scope,
3562 wip_decls: *WipDecls,
3654 wip_members: *WipMembers,
35633655 node: Ast.Node.Index,
35643656) InnerError!void {
3565 const gpa = astgen.gpa;
35663657 const tree = astgen.tree;
35673658 const node_datas = tree.nodes.items(.data);
35683659 const body_node = node_datas[node].rhs;
35693660
35703661 // Up top so the ZIR instruction index marks the start range of this
35713662 // top-level declaration.
3572 const block_inst = try gz.addBlock(.block_inline, node);
3663 const block_inst = try gz.makeBlockInst(.block_inline, node);
35733664
3574 try wip_decls.next(gpa, false, false, false, false);
3665 wip_members.nextDecl(false, false, false, false);
35753666
35763667 var decl_block: GenZir = .{
35773668 .force_comptime = true,
......@@ -3580,8 +3671,10 @@ fn testDecl(
35803671 .decl_line = gz.calcLine(node),
35813672 .parent = scope,
35823673 .astgen = astgen,
3674 .instructions = gz.instructions,
3675 .instructions_top = gz.instructions.items.len,
35833676 };
3584 defer decl_block.instructions.deinit(gpa);
3677 defer decl_block.unstack();
35853678
35863679 const test_name: u32 = blk: {
35873680 const main_tokens = tree.nodes.items(.main_token);
......@@ -3602,8 +3695,10 @@ fn testDecl(
36023695 .decl_line = decl_block.decl_line,
36033696 .parent = &decl_block.base,
36043697 .astgen = astgen,
3698 .instructions = decl_block.instructions,
3699 .instructions_top = decl_block.instructions.items.len,
36053700 };
3606 defer fn_block.instructions.deinit(gpa);
3701 defer fn_block.unstack();
36073702
36083703 const prev_fn_block = astgen.fn_block;
36093704 astgen.fn_block = &fn_block;
......@@ -3616,7 +3711,7 @@ fn testDecl(
36163711 const lbrace_column = @intCast(u32, astgen.source_column);
36173712
36183713 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
3619 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {
3714 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
36203715 // Since we are adding the return instruction here, we must handle the coercion.
36213716 // We do this by using the `ret_coerce` instruction.
36223717 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
......@@ -3627,9 +3722,9 @@ fn testDecl(
36273722 .lbrace_line = lbrace_line,
36283723 .lbrace_column = lbrace_column,
36293724 .param_block = block_inst,
3630 .ret_ty = &.{},
3725 .ret_gz = null,
36313726 .ret_br = 0,
3632 .body = fn_block.instructions.items,
3727 .body_gz = &fn_block,
36333728 .cc = .none,
36343729 .align_inst = .none,
36353730 .lib_name = 0,
......@@ -3642,18 +3737,17 @@ fn testDecl(
36423737 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
36433738 try decl_block.setBlockBody(block_inst);
36443739
3645 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
36463740 {
36473741 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
36483742 const casted = @bitCast([4]u32, contents_hash);
3649 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3743 wip_members.appendToDeclSlice(&casted);
36503744 }
36513745 {
36523746 const line_delta = decl_block.decl_line - gz.decl_line;
3653 wip_decls.payload.appendAssumeCapacity(line_delta);
3747 wip_members.appendToDecl(line_delta);
36543748 }
3655 wip_decls.payload.appendAssumeCapacity(test_name);
3656 wip_decls.payload.appendAssumeCapacity(block_inst);
3749 wip_members.appendToDecl(test_name);
3750 wip_members.appendToDecl(block_inst);
36573751}
36583752
36593753fn structDeclInner(
......@@ -3681,7 +3775,6 @@ fn structDeclInner(
36813775 const gpa = astgen.gpa;
36823776 const tree = astgen.tree;
36833777 const node_tags = tree.nodes.items(.tag);
3684 const node_datas = tree.nodes.items(.data);
36853778
36863779 var namespace: Scope.Namespace = .{
36873780 .parent = scope,
......@@ -3701,162 +3794,28 @@ fn structDeclInner(
37013794 .astgen = astgen,
37023795 .force_comptime = true,
37033796 .in_defer = false,
3797 .instructions = gz.instructions,
3798 .instructions_top = gz.instructions.items.len,
37043799 };
3705 defer block_scope.instructions.deinit(gpa);
3706
3707 try astgen.scanDecls(&namespace, container_decl.ast.members);
3708
3709 var wip_decls: WipDecls = .{};
3710 defer wip_decls.deinit(gpa);
3800 defer block_scope.unstack();
37113801
3712 // We don't know which members are fields until we iterate, so cannot do
3713 // an accurate ensureTotalCapacity yet.
3714 var fields_data = ArrayListUnmanaged(u32){};
3715 defer fields_data.deinit(gpa);
3802 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
3803 const field_count = @intCast(u32, container_decl.ast.members.len - decl_count);
37163804
37173805 const bits_per_field = 4;
3718 const fields_per_u32 = 32 / bits_per_field;
3719 // We only need this if there are greater than fields_per_u32 fields.
3720 var bit_bag = ArrayListUnmanaged(u32){};
3721 defer bit_bag.deinit(gpa);
3806 const max_field_size = 4;
3807 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3808 defer wip_members.deinit();
37223809
37233810 var known_has_bits = false;
3724 var cur_bit_bag: u32 = 0;
3725 var field_index: usize = 0;
37263811 for (container_decl.ast.members) |member_node| {
3727 const member = switch (node_tags[member_node]) {
3728 .container_field_init => tree.containerFieldInit(member_node),
3729 .container_field_align => tree.containerFieldAlign(member_node),
3730 .container_field => tree.containerField(member_node),
3731
3732 .fn_decl => {
3733 const fn_proto = node_datas[member_node].lhs;
3734 const body = node_datas[member_node].rhs;
3735 switch (node_tags[fn_proto]) {
3736 .fn_proto_simple => {
3737 var params: [1]Ast.Node.Index = undefined;
3738 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
3739 error.OutOfMemory => return error.OutOfMemory,
3740 error.AnalysisFail => {},
3741 };
3742 continue;
3743 },
3744 .fn_proto_multi => {
3745 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
3746 error.OutOfMemory => return error.OutOfMemory,
3747 error.AnalysisFail => {},
3748 };
3749 continue;
3750 },
3751 .fn_proto_one => {
3752 var params: [1]Ast.Node.Index = undefined;
3753 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
3754 error.OutOfMemory => return error.OutOfMemory,
3755 error.AnalysisFail => {},
3756 };
3757 continue;
3758 },
3759 .fn_proto => {
3760 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
3761 error.OutOfMemory => return error.OutOfMemory,
3762 error.AnalysisFail => {},
3763 };
3764 continue;
3765 },
3766 else => unreachable,
3767 }
3768 },
3769 .fn_proto_simple => {
3770 var params: [1]Ast.Node.Index = undefined;
3771 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
3772 error.OutOfMemory => return error.OutOfMemory,
3773 error.AnalysisFail => {},
3774 };
3775 continue;
3776 },
3777 .fn_proto_multi => {
3778 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
3779 error.OutOfMemory => return error.OutOfMemory,
3780 error.AnalysisFail => {},
3781 };
3782 continue;
3783 },
3784 .fn_proto_one => {
3785 var params: [1]Ast.Node.Index = undefined;
3786 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
3787 error.OutOfMemory => return error.OutOfMemory,
3788 error.AnalysisFail => {},
3789 };
3790 continue;
3791 },
3792 .fn_proto => {
3793 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
3794 error.OutOfMemory => return error.OutOfMemory,
3795 error.AnalysisFail => {},
3796 };
3797 continue;
3798 },
3799
3800 .global_var_decl => {
3801 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
3802 error.OutOfMemory => return error.OutOfMemory,
3803 error.AnalysisFail => {},
3804 };
3805 continue;
3806 },
3807 .local_var_decl => {
3808 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
3809 error.OutOfMemory => return error.OutOfMemory,
3810 error.AnalysisFail => {},
3811 };
3812 continue;
3813 },
3814 .simple_var_decl => {
3815 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
3816 error.OutOfMemory => return error.OutOfMemory,
3817 error.AnalysisFail => {},
3818 };
3819 continue;
3820 },
3821 .aligned_var_decl => {
3822 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
3823 error.OutOfMemory => return error.OutOfMemory,
3824 error.AnalysisFail => {},
3825 };
3826 continue;
3827 },
3828
3829 .@"comptime" => {
3830 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3831 error.OutOfMemory => return error.OutOfMemory,
3832 error.AnalysisFail => {},
3833 };
3834 continue;
3835 },
3836 .@"usingnamespace" => {
3837 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3838 error.OutOfMemory => return error.OutOfMemory,
3839 error.AnalysisFail => {},
3840 };
3841 continue;
3842 },
3843 .test_decl => {
3844 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
3845 error.OutOfMemory => return error.OutOfMemory,
3846 error.AnalysisFail => {},
3847 };
3848 continue;
3849 },
3850 else => unreachable,
3812 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
3813 .decl => continue,
3814 .field => |field| field,
38513815 };
3852 if (field_index % fields_per_u32 == 0 and field_index != 0) {
3853 try bit_bag.append(gpa, cur_bit_bag);
3854 cur_bit_bag = 0;
3855 }
3856 try fields_data.ensureUnusedCapacity(gpa, 4);
38573816
38583817 const field_name = try astgen.identAsString(member.ast.name_token);
3859 fields_data.appendAssumeCapacity(field_name);
3818 wip_members.appendToField(field_name);
38603819
38613820 if (member.ast.type_expr == 0) {
38623821 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
......@@ -3866,7 +3825,7 @@ fn structDeclInner(
38663825 .none
38673826 else
38683827 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
3869 fields_data.appendAssumeCapacity(@enumToInt(field_type));
3828 wip_members.appendToField(@enumToInt(field_type));
38703829
38713830 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
38723831
......@@ -3874,79 +3833,47 @@ fn structDeclInner(
38743833 const have_value = member.ast.value_expr != 0;
38753834 const is_comptime = member.comptime_token != null;
38763835 const unused = false;
3877 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
3878 (@as(u32, @boolToInt(have_align)) << 28) |
3879 (@as(u32, @boolToInt(have_value)) << 29) |
3880 (@as(u32, @boolToInt(is_comptime)) << 30) |
3881 (@as(u32, @boolToInt(unused)) << 31);
3836 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });
38823837
38833838 if (have_align) {
38843839 const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);
3885 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3840 wip_members.appendToField(@enumToInt(align_inst));
38863841 }
38873842 if (have_value) {
38883843 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
38893844
38903845 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);
3891 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
3846 wip_members.appendToField(@enumToInt(default_inst));
38923847 } else if (member.comptime_token) |comptime_token| {
38933848 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
38943849 }
3895
3896 field_index += 1;
3897 }
3898 {
3899 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
3900 if (empty_slot_count < fields_per_u32) {
3901 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
3902 }
3903 }
3904 {
3905 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
3906 if (empty_slot_count < WipDecls.fields_per_u32) {
3907 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
3908 }
39093850 }
39103851
3911 if (block_scope.instructions.items.len != 0) {
3852 if (!block_scope.isEmpty()) {
39123853 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
39133854 }
39143855
3856 const body = block_scope.instructionsSlice();
3857
39153858 try gz.setStruct(decl_inst, .{
39163859 .src_node = node,
39173860 .layout = layout,
3918 .body_len = @intCast(u32, block_scope.instructions.items.len),
3919 .fields_len = @intCast(u32, field_index),
3920 .decls_len = @intCast(u32, wip_decls.decl_index),
3861 .body_len = @intCast(u32, body.len),
3862 .fields_len = field_count,
3863 .decls_len = decl_count,
39213864 .known_has_bits = known_has_bits,
39223865 });
39233866
3924 // zig fmt: off
3925 try astgen.extra.ensureUnusedCapacity(gpa,
3926 bit_bag.items.len +
3927 @boolToInt(wip_decls.decl_index != 0) +
3928 wip_decls.payload.items.len +
3929 block_scope.instructions.items.len +
3930 wip_decls.bit_bag.items.len +
3931 @boolToInt(field_index != 0) +
3932 fields_data.items.len
3933 );
3934 // zig fmt: on
3935
3936 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3937 if (wip_decls.decl_index != 0) {
3938 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
3939 }
3940 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
3941
3942 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
3943
3944 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
3945 if (field_index != 0) {
3946 astgen.extra.appendAssumeCapacity(cur_bit_bag);
3947 }
3948 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
3867 wip_members.finishBits(bits_per_field);
3868 const decls_slice = wip_members.declsSlice();
3869 const fields_slice = wip_members.fieldsSlice();
3870 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
3871 astgen.extra.appendSliceAssumeCapacity(decls_slice);
3872 astgen.extra.appendSliceAssumeCapacity(body);
3873 astgen.extra.appendSliceAssumeCapacity(fields_slice);
39493874
3875 block_scope.unstack();
3876 try gz.addNamespaceCaptures(&namespace);
39503877 return indexToRef(decl_inst);
39513878}
39523879
......@@ -3965,7 +3892,6 @@ fn unionDeclInner(
39653892 const gpa = astgen.gpa;
39663893 const tree = astgen.tree;
39673894 const node_tags = tree.nodes.items(.tag);
3968 const node_datas = tree.nodes.items(.data);
39693895
39703896 var namespace: Scope.Namespace = .{
39713897 .parent = scope,
......@@ -3985,192 +3911,54 @@ fn unionDeclInner(
39853911 .astgen = astgen,
39863912 .force_comptime = true,
39873913 .in_defer = false,
3914 .instructions = gz.instructions,
3915 .instructions_top = gz.instructions.items.len,
39883916 };
3989 defer block_scope.instructions.deinit(gpa);
3917 defer block_scope.unstack();
39903918
3991 try astgen.scanDecls(&namespace, members);
3919 const decl_count = try astgen.scanDecls(&namespace, members);
3920 const field_count = @intCast(u32, members.len - decl_count);
39923921
39933922 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
39943923 try typeExpr(&block_scope, &namespace.base, arg_node)
39953924 else
39963925 .none;
39973926
3998 var wip_decls: WipDecls = .{};
3999 defer wip_decls.deinit(gpa);
4000
4001 // We don't know which members are fields until we iterate, so cannot do
4002 // an accurate ensureTotalCapacity yet.
4003 var fields_data = ArrayListUnmanaged(u32){};
4004 defer fields_data.deinit(gpa);
4005
40063927 const bits_per_field = 4;
4007 const fields_per_u32 = 32 / bits_per_field;
4008 // We only need this if there are greater than fields_per_u32 fields.
4009 var bit_bag = ArrayListUnmanaged(u32){};
4010 defer bit_bag.deinit(gpa);
3928 const max_field_size = 4;
3929 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3930 defer wip_members.deinit();
40113931
4012 var cur_bit_bag: u32 = 0;
4013 var field_index: usize = 0;
40143932 for (members) |member_node| {
4015 const member = switch (node_tags[member_node]) {
4016 .container_field_init => tree.containerFieldInit(member_node),
4017 .container_field_align => tree.containerFieldAlign(member_node),
4018 .container_field => tree.containerField(member_node),
4019
4020 .fn_decl => {
4021 const fn_proto = node_datas[member_node].lhs;
4022 const body = node_datas[member_node].rhs;
4023 switch (node_tags[fn_proto]) {
4024 .fn_proto_simple => {
4025 var params: [1]Ast.Node.Index = undefined;
4026 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4027 error.OutOfMemory => return error.OutOfMemory,
4028 error.AnalysisFail => {},
4029 };
4030 continue;
4031 },
4032 .fn_proto_multi => {
4033 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4034 error.OutOfMemory => return error.OutOfMemory,
4035 error.AnalysisFail => {},
4036 };
4037 continue;
4038 },
4039 .fn_proto_one => {
4040 var params: [1]Ast.Node.Index = undefined;
4041 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4042 error.OutOfMemory => return error.OutOfMemory,
4043 error.AnalysisFail => {},
4044 };
4045 continue;
4046 },
4047 .fn_proto => {
4048 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4049 error.OutOfMemory => return error.OutOfMemory,
4050 error.AnalysisFail => {},
4051 };
4052 continue;
4053 },
4054 else => unreachable,
4055 }
4056 },
4057 .fn_proto_simple => {
4058 var params: [1]Ast.Node.Index = undefined;
4059 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4060 error.OutOfMemory => return error.OutOfMemory,
4061 error.AnalysisFail => {},
4062 };
4063 continue;
4064 },
4065 .fn_proto_multi => {
4066 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4067 error.OutOfMemory => return error.OutOfMemory,
4068 error.AnalysisFail => {},
4069 };
4070 continue;
4071 },
4072 .fn_proto_one => {
4073 var params: [1]Ast.Node.Index = undefined;
4074 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4075 error.OutOfMemory => return error.OutOfMemory,
4076 error.AnalysisFail => {},
4077 };
4078 continue;
4079 },
4080 .fn_proto => {
4081 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4082 error.OutOfMemory => return error.OutOfMemory,
4083 error.AnalysisFail => {},
4084 };
4085 continue;
4086 },
4087
4088 .global_var_decl => {
4089 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4090 error.OutOfMemory => return error.OutOfMemory,
4091 error.AnalysisFail => {},
4092 };
4093 continue;
4094 },
4095 .local_var_decl => {
4096 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4097 error.OutOfMemory => return error.OutOfMemory,
4098 error.AnalysisFail => {},
4099 };
4100 continue;
4101 },
4102 .simple_var_decl => {
4103 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4104 error.OutOfMemory => return error.OutOfMemory,
4105 error.AnalysisFail => {},
4106 };
4107 continue;
4108 },
4109 .aligned_var_decl => {
4110 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4111 error.OutOfMemory => return error.OutOfMemory,
4112 error.AnalysisFail => {},
4113 };
4114 continue;
4115 },
4116
4117 .@"comptime" => {
4118 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4119 error.OutOfMemory => return error.OutOfMemory,
4120 error.AnalysisFail => {},
4121 };
4122 continue;
4123 },
4124 .@"usingnamespace" => {
4125 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4126 error.OutOfMemory => return error.OutOfMemory,
4127 error.AnalysisFail => {},
4128 };
4129 continue;
4130 },
4131 .test_decl => {
4132 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4133 error.OutOfMemory => return error.OutOfMemory,
4134 error.AnalysisFail => {},
4135 };
4136 continue;
4137 },
4138 else => unreachable,
3933 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
3934 .decl => continue,
3935 .field => |field| field,
41393936 };
4140 if (field_index % fields_per_u32 == 0 and field_index != 0) {
4141 try bit_bag.append(gpa, cur_bit_bag);
4142 cur_bit_bag = 0;
4143 }
41443937 if (member.comptime_token) |comptime_token| {
41453938 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
41463939 }
4147 try fields_data.ensureUnusedCapacity(gpa, 4);
41483940
41493941 const field_name = try astgen.identAsString(member.ast.name_token);
4150 fields_data.appendAssumeCapacity(field_name);
3942 wip_members.appendToField(field_name);
41513943
41523944 const have_type = member.ast.type_expr != 0;
41533945 const have_align = member.ast.align_expr != 0;
41543946 const have_value = member.ast.value_expr != 0;
41553947 const unused = false;
4156 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
4157 (@as(u32, @boolToInt(have_type)) << 28) |
4158 (@as(u32, @boolToInt(have_align)) << 29) |
4159 (@as(u32, @boolToInt(have_value)) << 30) |
4160 (@as(u32, @boolToInt(unused)) << 31);
3948 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
41613949
41623950 if (have_type) {
41633951 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
41643952 .none
41653953 else
41663954 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
4167 fields_data.appendAssumeCapacity(@enumToInt(field_type));
3955 wip_members.appendToField(@enumToInt(field_type));
41683956 } else if (arg_inst == .none and !have_auto_enum) {
41693957 return astgen.failNode(member_node, "union field missing type", .{});
41703958 }
41713959 if (have_align) {
41723960 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
4173 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3961 wip_members.appendToField(@enumToInt(align_inst));
41743962 }
41753963 if (have_value) {
41763964 if (arg_inst == .none) {
......@@ -4202,65 +3990,39 @@ fn unionDeclInner(
42023990 );
42033991 }
42043992 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
4205 fields_data.appendAssumeCapacity(@enumToInt(tag_value));
3993 wip_members.appendToField(@enumToInt(tag_value));
42063994 }
4207
4208 field_index += 1;
42093995 }
4210 if (field_index == 0) {
3996 if (field_count == 0) {
42113997 return astgen.failNode(node, "union declarations must have at least one tag", .{});
42123998 }
4213 {
4214 const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32);
4215 if (empty_slot_count < fields_per_u32) {
4216 cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field);
4217 }
4218 }
4219 {
4220 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4221 if (empty_slot_count < WipDecls.fields_per_u32) {
4222 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4223 }
4224 }
42253999
4226 if (block_scope.instructions.items.len != 0) {
4000 if (!block_scope.isEmpty()) {
42274001 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
42284002 }
42294003
4004 const body = block_scope.instructionsSlice();
4005
42304006 try gz.setUnion(decl_inst, .{
42314007 .src_node = node,
42324008 .layout = layout,
42334009 .tag_type = arg_inst,
4234 .body_len = @intCast(u32, block_scope.instructions.items.len),
4235 .fields_len = @intCast(u32, field_index),
4236 .decls_len = @intCast(u32, wip_decls.decl_index),
4010 .body_len = @intCast(u32, body.len),
4011 .fields_len = field_count,
4012 .decls_len = decl_count,
42374013 .auto_enum_tag = have_auto_enum,
42384014 });
42394015
4240 // zig fmt: off
4241 try astgen.extra.ensureUnusedCapacity(gpa,
4242 bit_bag.items.len +
4243 @boolToInt(wip_decls.decl_index != 0) +
4244 wip_decls.payload.items.len +
4245 block_scope.instructions.items.len +
4246 wip_decls.bit_bag.items.len +
4247 1 + // cur_bit_bag
4248 fields_data.items.len
4249 );
4250 // zig fmt: on
4251
4252 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4253 if (wip_decls.decl_index != 0) {
4254 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4255 }
4256 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4257
4258 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
4259
4260 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
4261 astgen.extra.appendAssumeCapacity(cur_bit_bag);
4262 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
4016 wip_members.finishBits(bits_per_field);
4017 const decls_slice = wip_members.declsSlice();
4018 const fields_slice = wip_members.fieldsSlice();
4019 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
4020 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4021 astgen.extra.appendSliceAssumeCapacity(body);
4022 astgen.extra.appendSliceAssumeCapacity(fields_slice);
42634023
4024 block_scope.unstack();
4025 try gz.addNamespaceCaptures(&namespace);
42644026 return indexToRef(decl_inst);
42654027}
42664028
......@@ -4276,7 +4038,6 @@ fn containerDecl(
42764038 const tree = astgen.tree;
42774039 const token_tags = tree.tokens.items(.tag);
42784040 const node_tags = tree.nodes.items(.tag);
4279 const node_datas = tree.nodes.items(.data);
42804041
42814042 const prev_fn_block = astgen.fn_block;
42824043 astgen.fn_block = null;
......@@ -4430,172 +4191,39 @@ fn containerDecl(
44304191 .astgen = astgen,
44314192 .force_comptime = true,
44324193 .in_defer = false,
4194 .instructions = gz.instructions,
4195 .instructions_top = gz.instructions.items.len,
44334196 };
4434 defer block_scope.instructions.deinit(gpa);
4197 defer block_scope.unstack();
44354198
4436 try astgen.scanDecls(&namespace, container_decl.ast.members);
4199 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
44374200
44384201 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
44394202 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
44404203 else
44414204 .none;
44424205
4443 var wip_decls: WipDecls = .{};
4444 defer wip_decls.deinit(gpa);
4445
4446 var fields_data = ArrayListUnmanaged(u32){};
4447 defer fields_data.deinit(gpa);
4448
4449 try fields_data.ensureTotalCapacity(gpa, counts.total_fields + counts.values);
4450
4451 // We only need this if there are greater than 32 fields.
4452 var bit_bag = ArrayListUnmanaged(u32){};
4453 defer bit_bag.deinit(gpa);
4206 const bits_per_field = 1;
4207 const max_field_size = 2;
4208 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4209 defer wip_members.deinit();
44544210
4455 var cur_bit_bag: u32 = 0;
4456 var field_index: usize = 0;
44574211 for (container_decl.ast.members) |member_node| {
44584212 if (member_node == counts.nonexhaustive_node)
44594213 continue;
4460 const member = switch (node_tags[member_node]) {
4461 .container_field_init => tree.containerFieldInit(member_node),
4462 .container_field_align => tree.containerFieldAlign(member_node),
4463 .container_field => tree.containerField(member_node),
4464
4465 .fn_decl => {
4466 const fn_proto = node_datas[member_node].lhs;
4467 const body = node_datas[member_node].rhs;
4468 switch (node_tags[fn_proto]) {
4469 .fn_proto_simple => {
4470 var params: [1]Ast.Node.Index = undefined;
4471 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4472 error.OutOfMemory => return error.OutOfMemory,
4473 error.AnalysisFail => {},
4474 };
4475 continue;
4476 },
4477 .fn_proto_multi => {
4478 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4479 error.OutOfMemory => return error.OutOfMemory,
4480 error.AnalysisFail => {},
4481 };
4482 continue;
4483 },
4484 .fn_proto_one => {
4485 var params: [1]Ast.Node.Index = undefined;
4486 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4487 error.OutOfMemory => return error.OutOfMemory,
4488 error.AnalysisFail => {},
4489 };
4490 continue;
4491 },
4492 .fn_proto => {
4493 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4494 error.OutOfMemory => return error.OutOfMemory,
4495 error.AnalysisFail => {},
4496 };
4497 continue;
4498 },
4499 else => unreachable,
4500 }
4501 },
4502 .fn_proto_simple => {
4503 var params: [1]Ast.Node.Index = undefined;
4504 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4505 error.OutOfMemory => return error.OutOfMemory,
4506 error.AnalysisFail => {},
4507 };
4508 continue;
4509 },
4510 .fn_proto_multi => {
4511 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4512 error.OutOfMemory => return error.OutOfMemory,
4513 error.AnalysisFail => {},
4514 };
4515 continue;
4516 },
4517 .fn_proto_one => {
4518 var params: [1]Ast.Node.Index = undefined;
4519 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4520 error.OutOfMemory => return error.OutOfMemory,
4521 error.AnalysisFail => {},
4522 };
4523 continue;
4524 },
4525 .fn_proto => {
4526 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4527 error.OutOfMemory => return error.OutOfMemory,
4528 error.AnalysisFail => {},
4529 };
4530 continue;
4531 },
4532
4533 .global_var_decl => {
4534 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4535 error.OutOfMemory => return error.OutOfMemory,
4536 error.AnalysisFail => {},
4537 };
4538 continue;
4539 },
4540 .local_var_decl => {
4541 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4542 error.OutOfMemory => return error.OutOfMemory,
4543 error.AnalysisFail => {},
4544 };
4545 continue;
4546 },
4547 .simple_var_decl => {
4548 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4549 error.OutOfMemory => return error.OutOfMemory,
4550 error.AnalysisFail => {},
4551 };
4552 continue;
4553 },
4554 .aligned_var_decl => {
4555 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4556 error.OutOfMemory => return error.OutOfMemory,
4557 error.AnalysisFail => {},
4558 };
4559 continue;
4560 },
4561
4562 .@"comptime" => {
4563 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4564 error.OutOfMemory => return error.OutOfMemory,
4565 error.AnalysisFail => {},
4566 };
4567 continue;
4568 },
4569 .@"usingnamespace" => {
4570 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4571 error.OutOfMemory => return error.OutOfMemory,
4572 error.AnalysisFail => {},
4573 };
4574 continue;
4575 },
4576 .test_decl => {
4577 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4578 error.OutOfMemory => return error.OutOfMemory,
4579 error.AnalysisFail => {},
4580 };
4581 continue;
4582 },
4583 else => unreachable,
4214 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
4215 .decl => continue,
4216 .field => |field| field,
45844217 };
4585 if (field_index % 32 == 0 and field_index != 0) {
4586 try bit_bag.append(gpa, cur_bit_bag);
4587 cur_bit_bag = 0;
4588 }
45894218 assert(member.comptime_token == null);
45904219 assert(member.ast.type_expr == 0);
45914220 assert(member.ast.align_expr == 0);
45924221
45934222 const field_name = try astgen.identAsString(member.ast.name_token);
4594 fields_data.appendAssumeCapacity(field_name);
4223 wip_members.appendToField(field_name);
45954224
45964225 const have_value = member.ast.value_expr != 0;
4597 cur_bit_bag = (cur_bit_bag >> 1) |
4598 (@as(u32, @boolToInt(have_value)) << 31);
4226 wip_members.nextField(bits_per_field, .{have_value});
45994227
46004228 if (have_value) {
46014229 if (arg_inst == .none) {
......@@ -4613,60 +4241,35 @@ fn containerDecl(
46134241 );
46144242 }
46154243 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);
4616 fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));
4617 }
4618
4619 field_index += 1;
4620 }
4621 {
4622 const empty_slot_count = 32 - (field_index % 32);
4623 if (empty_slot_count < 32) {
4624 cur_bit_bag >>= @intCast(u5, empty_slot_count);
4625 }
4626 }
4627 {
4628 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4629 if (empty_slot_count < WipDecls.fields_per_u32) {
4630 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4244 wip_members.appendToField(@enumToInt(tag_value_inst));
46314245 }
46324246 }
46334247
4634 if (block_scope.instructions.items.len != 0) {
4248 if (!block_scope.isEmpty()) {
46354249 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
46364250 }
46374251
4252 const body = block_scope.instructionsSlice();
4253
46384254 try gz.setEnum(decl_inst, .{
46394255 .src_node = node,
46404256 .nonexhaustive = nonexhaustive,
46414257 .tag_type = arg_inst,
4642 .body_len = @intCast(u32, block_scope.instructions.items.len),
4643 .fields_len = @intCast(u32, field_index),
4644 .decls_len = @intCast(u32, wip_decls.decl_index),
4258 .body_len = @intCast(u32, body.len),
4259 .fields_len = @intCast(u32, counts.total_fields),
4260 .decls_len = @intCast(u32, counts.decls),
46454261 });
46464262
4647 // zig fmt: off
4648 try astgen.extra.ensureUnusedCapacity(gpa,
4649 bit_bag.items.len +
4650 @boolToInt(wip_decls.decl_index != 0) +
4651 wip_decls.payload.items.len +
4652 block_scope.instructions.items.len +
4653 wip_decls.bit_bag.items.len +
4654 1 + // cur_bit_bag
4655 fields_data.items.len
4656 );
4657 // zig fmt: on
4658
4659 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4660 if (wip_decls.decl_index != 0) {
4661 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4662 }
4663 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4664
4665 astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
4666 astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
4667 astgen.extra.appendAssumeCapacity(cur_bit_bag);
4668 astgen.extra.appendSliceAssumeCapacity(fields_data.items);
4263 wip_members.finishBits(bits_per_field);
4264 const decls_slice = wip_members.declsSlice();
4265 const fields_slice = wip_members.fieldsSlice();
4266 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
4267 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4268 astgen.extra.appendSliceAssumeCapacity(body);
4269 astgen.extra.appendSliceAssumeCapacity(fields_slice);
46694270
4271 block_scope.unstack();
4272 try gz.addNamespaceCaptures(&namespace);
46704273 return rvalue(gz, rl, indexToRef(decl_inst), node);
46714274 },
46724275 .keyword_opaque => {
......@@ -4682,166 +4285,155 @@ fn containerDecl(
46824285 };
46834286 defer namespace.deinit(gpa);
46844287
4685 try astgen.scanDecls(&namespace, container_decl.ast.members);
4288 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
46864289
4687 var wip_decls: WipDecls = .{};
4688 defer wip_decls.deinit(gpa);
4290 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0);
4291 defer wip_members.deinit();
46894292
46904293 for (container_decl.ast.members) |member_node| {
4691 switch (node_tags[member_node]) {
4692 .container_field_init, .container_field_align, .container_field => {},
4693
4694 .fn_decl => {
4695 const fn_proto = node_datas[member_node].lhs;
4696 const body = node_datas[member_node].rhs;
4697 switch (node_tags[fn_proto]) {
4698 .fn_proto_simple => {
4699 var params: [1]Ast.Node.Index = undefined;
4700 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4701 error.OutOfMemory => return error.OutOfMemory,
4702 error.AnalysisFail => {},
4703 };
4704 continue;
4705 },
4706 .fn_proto_multi => {
4707 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4708 error.OutOfMemory => return error.OutOfMemory,
4709 error.AnalysisFail => {},
4710 };
4711 continue;
4712 },
4713 .fn_proto_one => {
4714 var params: [1]Ast.Node.Index = undefined;
4715 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4716 error.OutOfMemory => return error.OutOfMemory,
4717 error.AnalysisFail => {},
4718 };
4719 continue;
4720 },
4721 .fn_proto => {
4722 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4723 error.OutOfMemory => return error.OutOfMemory,
4724 error.AnalysisFail => {},
4725 };
4726 continue;
4727 },
4728 else => unreachable,
4729 }
4730 },
4731 .fn_proto_simple => {
4732 var params: [1]Ast.Node.Index = undefined;
4733 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4734 error.OutOfMemory => return error.OutOfMemory,
4735 error.AnalysisFail => {},
4736 };
4737 continue;
4738 },
4739 .fn_proto_multi => {
4740 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4741 error.OutOfMemory => return error.OutOfMemory,
4742 error.AnalysisFail => {},
4743 };
4744 continue;
4745 },
4746 .fn_proto_one => {
4747 var params: [1]Ast.Node.Index = undefined;
4748 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4749 error.OutOfMemory => return error.OutOfMemory,
4750 error.AnalysisFail => {},
4751 };
4752 continue;
4753 },
4754 .fn_proto => {
4755 astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4756 error.OutOfMemory => return error.OutOfMemory,
4757 error.AnalysisFail => {},
4758 };
4759 continue;
4760 },
4761
4762 .global_var_decl => {
4763 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4764 error.OutOfMemory => return error.OutOfMemory,
4765 error.AnalysisFail => {},
4766 };
4767 continue;
4768 },
4769 .local_var_decl => {
4770 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4771 error.OutOfMemory => return error.OutOfMemory,
4772 error.AnalysisFail => {},
4773 };
4774 continue;
4775 },
4776 .simple_var_decl => {
4777 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4778 error.OutOfMemory => return error.OutOfMemory,
4779 error.AnalysisFail => {},
4780 };
4781 continue;
4782 },
4783 .aligned_var_decl => {
4784 astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4785 error.OutOfMemory => return error.OutOfMemory,
4786 error.AnalysisFail => {},
4787 };
4788 continue;
4789 },
4790
4791 .@"comptime" => {
4792 astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4793 error.OutOfMemory => return error.OutOfMemory,
4794 error.AnalysisFail => {},
4795 };
4796 continue;
4797 },
4798 .@"usingnamespace" => {
4799 astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4800 error.OutOfMemory => return error.OutOfMemory,
4801 error.AnalysisFail => {},
4802 };
4803 continue;
4804 },
4805 .test_decl => {
4806 astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) {
4807 error.OutOfMemory => return error.OutOfMemory,
4808 error.AnalysisFail => {},
4809 };
4810 continue;
4811 },
4812 else => unreachable,
4813 }
4814 }
4815 {
4816 const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
4817 if (empty_slot_count < WipDecls.fields_per_u32) {
4818 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4819 }
4294 _ = try containerMember(gz, &namespace.base, &wip_members, member_node);
48204295 }
48214296
48224297 try gz.setOpaque(decl_inst, .{
48234298 .src_node = node,
4824 .decls_len = @intCast(u32, wip_decls.decl_index),
4299 .decls_len = decl_count,
48254300 });
48264301
4827 // zig fmt: off
4828 try astgen.extra.ensureUnusedCapacity(gpa,
4829 wip_decls.bit_bag.items.len +
4830 @boolToInt(wip_decls.decl_index != 0) +
4831 wip_decls.payload.items.len
4832 );
4833 // zig fmt: on
4302 wip_members.finishBits(0);
4303 const decls_slice = wip_members.declsSlice();
4304 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len);
4305 astgen.extra.appendSliceAssumeCapacity(decls_slice);
48344306
4835 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4836 if (wip_decls.decl_index != 0) {
4837 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
4307 try gz.addNamespaceCaptures(&namespace);
4308 return rvalue(gz, rl, indexToRef(decl_inst), node);
4309 },
4310 else => unreachable,
4311 }
4312}
4313
4314const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField };
4315
4316fn containerMember(
4317 gz: *GenZir,
4318 scope: *Scope,
4319 wip_members: *WipMembers,
4320 member_node: Ast.Node.Index,
4321) InnerError!ContainerMemberResult {
4322 const astgen = gz.astgen;
4323 const tree = astgen.tree;
4324 const node_tags = tree.nodes.items(.tag);
4325 const node_datas = tree.nodes.items(.data);
4326 switch (node_tags[member_node]) {
4327 .container_field_init => return ContainerMemberResult{ .field = tree.containerFieldInit(member_node) },
4328 .container_field_align => return ContainerMemberResult{ .field = tree.containerFieldAlign(member_node) },
4329 .container_field => return ContainerMemberResult{ .field = tree.containerField(member_node) },
4330
4331 .fn_decl => {
4332 const fn_proto = node_datas[member_node].lhs;
4333 const body = node_datas[member_node].rhs;
4334 switch (node_tags[fn_proto]) {
4335 .fn_proto_simple => {
4336 var params: [1]Ast.Node.Index = undefined;
4337 astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) {
4338 error.OutOfMemory => return error.OutOfMemory,
4339 error.AnalysisFail => {},
4340 };
4341 },
4342 .fn_proto_multi => {
4343 astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) {
4344 error.OutOfMemory => return error.OutOfMemory,
4345 error.AnalysisFail => {},
4346 };
4347 },
4348 .fn_proto_one => {
4349 var params: [1]Ast.Node.Index = undefined;
4350 astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) {
4351 error.OutOfMemory => return error.OutOfMemory,
4352 error.AnalysisFail => {},
4353 };
4354 },
4355 .fn_proto => {
4356 astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) {
4357 error.OutOfMemory => return error.OutOfMemory,
4358 error.AnalysisFail => {},
4359 };
4360 },
4361 else => unreachable,
48384362 }
4839 astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items);
4363 },
4364 .fn_proto_simple => {
4365 var params: [1]Ast.Node.Index = undefined;
4366 astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) {
4367 error.OutOfMemory => return error.OutOfMemory,
4368 error.AnalysisFail => {},
4369 };
4370 },
4371 .fn_proto_multi => {
4372 astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) {
4373 error.OutOfMemory => return error.OutOfMemory,
4374 error.AnalysisFail => {},
4375 };
4376 },
4377 .fn_proto_one => {
4378 var params: [1]Ast.Node.Index = undefined;
4379 astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) {
4380 error.OutOfMemory => return error.OutOfMemory,
4381 error.AnalysisFail => {},
4382 };
4383 },
4384 .fn_proto => {
4385 astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) {
4386 error.OutOfMemory => return error.OutOfMemory,
4387 error.AnalysisFail => {},
4388 };
4389 },
48404390
4841 return rvalue(gz, rl, indexToRef(decl_inst), node);
4391 .global_var_decl => {
4392 astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) {
4393 error.OutOfMemory => return error.OutOfMemory,
4394 error.AnalysisFail => {},
4395 };
4396 },
4397 .local_var_decl => {
4398 astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) {
4399 error.OutOfMemory => return error.OutOfMemory,
4400 error.AnalysisFail => {},
4401 };
4402 },
4403 .simple_var_decl => {
4404 astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) {
4405 error.OutOfMemory => return error.OutOfMemory,
4406 error.AnalysisFail => {},
4407 };
4408 },
4409 .aligned_var_decl => {
4410 astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) {
4411 error.OutOfMemory => return error.OutOfMemory,
4412 error.AnalysisFail => {},
4413 };
4414 },
4415
4416 .@"comptime" => {
4417 astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
4418 error.OutOfMemory => return error.OutOfMemory,
4419 error.AnalysisFail => {},
4420 };
4421 },
4422 .@"usingnamespace" => {
4423 astgen.usingnamespaceDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
4424 error.OutOfMemory => return error.OutOfMemory,
4425 error.AnalysisFail => {},
4426 };
4427 },
4428 .test_decl => {
4429 astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
4430 error.OutOfMemory => return error.OutOfMemory,
4431 error.AnalysisFail => {},
4432 };
48424433 },
48434434 else => unreachable,
48444435 }
4436 return .decl;
48454437}
48464438
48474439fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
......@@ -4851,20 +4443,18 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
48514443 const main_tokens = tree.nodes.items(.main_token);
48524444 const token_tags = tree.tokens.items(.tag);
48534445
4854 var field_names: std.ArrayListUnmanaged(u32) = .{};
4855 defer field_names.deinit(gpa);
4856
4446 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len);
4447 var fields_len: usize = 0;
48574448 {
48584449 const error_token = main_tokens[node];
48594450 var tok_i = error_token + 2;
4860 var field_i: usize = 0;
48614451 while (true) : (tok_i += 1) {
48624452 switch (token_tags[tok_i]) {
48634453 .doc_comment, .comma => {},
48644454 .identifier => {
48654455 const str_index = try astgen.identAsString(tok_i);
4866 try field_names.append(gpa, str_index);
4867 field_i += 1;
4456 try astgen.extra.append(gpa, str_index);
4457 fields_len += 1;
48684458 },
48694459 .r_brace => break,
48704460 else => unreachable,
......@@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
48724462 }
48734463 }
48744464
4875 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
4876 .fields_len = @intCast(u32, field_names.items.len),
4465 setExtra(astgen, payload_index, Zir.Inst.ErrorSetDecl{
4466 .fields_len = @intCast(u32, fields_len),
48774467 });
4878 try astgen.extra.appendSlice(gpa, field_names.items);
4468 const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index);
48794469 return rvalue(gz, rl, result, node);
48804470}
48814471
......@@ -4896,7 +4486,7 @@ fn tryExpr(
48964486
48974487 var block_scope = parent_gz.makeSubBlock(scope);
48984488 block_scope.setBreakResultLoc(rl);
4899 defer block_scope.instructions.deinit(astgen.gpa);
4489 defer block_scope.unstack();
49004490
49014491 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
49024492 .ref => .ref,
......@@ -4916,12 +4506,13 @@ fn tryExpr(
49164506 const cond = try block_scope.addUnNode(err_ops[0], operand, node);
49174507 const condbr = try block_scope.addCondBr(.condbr, node);
49184508
4919 const block = try parent_gz.addBlock(.block, node);
4920 try parent_gz.instructions.append(astgen.gpa, block);
4509 const block = try parent_gz.makeBlockInst(.block, node);
49214510 try block_scope.setBlockBody(block);
4511 // block_scope unstacked now, can add new instructions to parent_gz
4512 try parent_gz.instructions.append(astgen.gpa, block);
49224513
49234514 var then_scope = parent_gz.makeSubBlock(scope);
4924 defer then_scope.instructions.deinit(astgen.gpa);
4515 defer then_scope.unstack();
49254516
49264517 block_scope.break_count += 1;
49274518 // This could be a pointer or value depending on `err_ops[2]`.
......@@ -4931,8 +4522,9 @@ fn tryExpr(
49314522 else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),
49324523 };
49334524
4525 // else_scope will be stacked on then_scope as both are stacked on parent_gz
49344526 var else_scope = parent_gz.makeSubBlock(scope);
4935 defer else_scope.instructions.deinit(astgen.gpa);
4527 defer else_scope.unstack();
49364528
49374529 const err_code = try else_scope.addUnNode(err_ops[1], operand, node);
49384530 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
......@@ -4972,7 +4564,7 @@ fn orelseCatchExpr(
49724564
49734565 var block_scope = parent_gz.makeSubBlock(scope);
49744566 block_scope.setBreakResultLoc(rl);
4975 defer block_scope.instructions.deinit(astgen.gpa);
4567 defer block_scope.unstack();
49764568
49774569 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
49784570 .ref => .ref,
......@@ -4987,12 +4579,13 @@ fn orelseCatchExpr(
49874579 const cond = try block_scope.addUnNode(cond_op, operand, node);
49884580 const condbr = try block_scope.addCondBr(.condbr, node);
49894581
4990 const block = try parent_gz.addBlock(.block, node);
4991 try parent_gz.instructions.append(astgen.gpa, block);
4582 const block = try parent_gz.makeBlockInst(.block, node);
49924583 try block_scope.setBlockBody(block);
4584 // block_scope unstacked now, can add new instructions to parent_gz
4585 try parent_gz.instructions.append(astgen.gpa, block);
49934586
49944587 var then_scope = parent_gz.makeSubBlock(scope);
4995 defer then_scope.instructions.deinit(astgen.gpa);
4588 defer then_scope.unstack();
49964589
49974590 // This could be a pointer or value depending on `unwrap_op`.
49984591 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
......@@ -5002,7 +4595,7 @@ fn orelseCatchExpr(
50024595 };
50034596
50044597 var else_scope = parent_gz.makeSubBlock(scope);
5005 defer else_scope.instructions.deinit(astgen.gpa);
4598 defer else_scope.unstack();
50064599
50074600 var err_val_scope: Scope.LocalVal = undefined;
50084601 const else_sub_scope = blk: {
......@@ -5049,6 +4642,7 @@ fn orelseCatchExpr(
50494642 );
50504643}
50514644
4645/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.
50524646fn finishThenElseBlock(
50534647 parent_gz: *GenZir,
50544648 rl: ResultLoc,
......@@ -5067,33 +4661,33 @@ fn finishThenElseBlock(
50674661 // We now have enough information to decide whether the result instruction should
50684662 // be communicated via result location pointer or break instructions.
50694663 const strat = rl.strategy(block_scope);
4664 // else_scope may be stacked on then_scope, so check for no-return on then_scope manually
4665 const tags = parent_gz.astgen.instructions.items(.tag);
4666 const then_slice = then_scope.instructionsSliceUpto(else_scope);
4667 const then_no_return = then_slice.len > 0 and tags[then_slice[then_slice.len - 1]].isNoReturn();
4668 const else_no_return = else_scope.endsWithNoReturn();
4669
50704670 switch (strat.tag) {
50714671 .break_void => {
5072 if (!then_scope.endsWithNoReturn()) {
5073 _ = try then_scope.addBreak(break_tag, then_break_block, .void_value);
5074 }
5075 if (!else_scope.endsWithNoReturn()) {
5076 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
5077 }
4672 const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, .void_value) else 0;
4673 const else_break = if (!else_no_return) try else_scope.makeBreak(break_tag, main_block, .void_value) else 0;
50784674 assert(!strat.elide_store_to_block_ptr_instructions);
5079 try setCondBrPayload(condbr, cond, then_scope, else_scope);
4675 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);
50804676 return indexToRef(main_block);
50814677 },
50824678 .break_operand => {
5083 if (!then_scope.endsWithNoReturn()) {
5084 _ = try then_scope.addBreak(break_tag, then_break_block, then_result);
5085 }
5086 if (else_result != .none) {
5087 if (!else_scope.endsWithNoReturn()) {
5088 _ = try else_scope.addBreak(break_tag, main_block, else_result);
5089 }
5090 } else {
5091 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
5092 }
4679 const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0;
4680 const else_break = if (else_result == .none)
4681 try else_scope.makeBreak(break_tag, main_block, .void_value)
4682 else if (!else_no_return)
4683 try else_scope.makeBreak(break_tag, main_block, else_result)
4684 else
4685 0;
4686
50934687 if (strat.elide_store_to_block_ptr_instructions) {
5094 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_scope.rl_ptr);
4688 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, then_break, else_scope, else_break, block_scope.rl_ptr);
50954689 } else {
5096 try setCondBrPayload(condbr, cond, then_scope, else_scope);
4690 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);
50974691 }
50984692 const block_ref = indexToRef(main_block);
50994693 switch (rl) {
......@@ -5221,7 +4815,7 @@ fn boolBinOp(
52214815 const bool_br = try gz.addBoolBr(zir_tag, lhs);
52224816
52234817 var rhs_scope = gz.makeSubBlock(scope);
5224 defer rhs_scope.instructions.deinit(gz.astgen.gpa);
4818 defer rhs_scope.unstack();
52254819 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
52264820 if (!gz.refIsNoReturn(rhs)) {
52274821 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
......@@ -5245,7 +4839,7 @@ fn ifExpr(
52454839
52464840 var block_scope = parent_gz.makeSubBlock(scope);
52474841 block_scope.setBreakResultLoc(rl);
5248 defer block_scope.instructions.deinit(astgen.gpa);
4842 defer block_scope.unstack();
52494843
52504844 const payload_is_ref = if (if_full.payload_token) |payload_token|
52514845 token_tags[payload_token] == .asterisk
......@@ -5283,12 +4877,13 @@ fn ifExpr(
52834877
52844878 const condbr = try block_scope.addCondBr(.condbr, node);
52854879
5286 const block = try parent_gz.addBlock(.block, node);
5287 try parent_gz.instructions.append(astgen.gpa, block);
4880 const block = try parent_gz.makeBlockInst(.block, node);
52884881 try block_scope.setBlockBody(block);
4882 // block_scope unstacked now, can add new instructions to parent_gz
4883 try parent_gz.instructions.append(astgen.gpa, block);
52894884
52904885 var then_scope = parent_gz.makeSubBlock(scope);
5291 defer then_scope.instructions.deinit(astgen.gpa);
4886 defer then_scope.unstack();
52924887
52934888 var payload_val_scope: Scope.LocalVal = undefined;
52944889
......@@ -5354,7 +4949,7 @@ fn ifExpr(
53544949 // instructions or not.
53554950
53564951 var else_scope = parent_gz.makeSubBlock(scope);
5357 defer else_scope.instructions.deinit(astgen.gpa);
4952 defer else_scope.unstack();
53584953
53594954 const else_node = if_full.ast.else_expr;
53604955 const else_info: struct {
......@@ -5417,52 +5012,70 @@ fn ifExpr(
54175012 );
54185013}
54195014
5015/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
54205016fn setCondBrPayload(
54215017 condbr: Zir.Inst.Index,
54225018 cond: Zir.Inst.Ref,
54235019 then_scope: *GenZir,
5020 then_break: Zir.Inst.Index,
54245021 else_scope: *GenZir,
5022 else_break: Zir.Inst.Index,
54255023) !void {
5024 defer then_scope.unstack();
5025 defer else_scope.unstack();
54265026 const astgen = then_scope.astgen;
5427
5027 const then_body = then_scope.instructionsSliceUpto(else_scope);
5028 const else_body = else_scope.instructionsSlice();
5029 const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0));
5030 const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0));
54285031 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
5429 then_scope.instructions.items.len + else_scope.instructions.items.len);
5032 then_body_len + else_body_len);
54305033
54315034 const zir_datas = astgen.instructions.items(.data);
54325035 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
54335036 .condition = cond,
5434 .then_body_len = @intCast(u32, then_scope.instructions.items.len),
5435 .else_body_len = @intCast(u32, else_scope.instructions.items.len),
5037 .then_body_len = then_body_len,
5038 .else_body_len = else_body_len,
54365039 });
5437 astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items);
5438 astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items);
5040 astgen.extra.appendSliceAssumeCapacity(then_body);
5041 if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break);
5042 astgen.extra.appendSliceAssumeCapacity(else_body);
5043 if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break);
54395044}
54405045
5046/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
54415047fn setCondBrPayloadElideBlockStorePtr(
54425048 condbr: Zir.Inst.Index,
54435049 cond: Zir.Inst.Ref,
54445050 then_scope: *GenZir,
5051 then_break: Zir.Inst.Index,
54455052 else_scope: *GenZir,
5053 else_break: Zir.Inst.Index,
54465054 block_ptr: Zir.Inst.Ref,
54475055) !void {
5056 defer then_scope.unstack();
5057 defer else_scope.unstack();
54485058 const astgen = then_scope.astgen;
5449
5059 const then_body = then_scope.instructionsSliceUpto(else_scope);
5060 const else_body = else_scope.instructionsSlice();
5061 const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0));
5062 const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0));
54505063 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +
5451 then_scope.instructions.items.len + else_scope.instructions.items.len);
5064 then_body_len + else_body_len);
54525065
54535066 const zir_tags = astgen.instructions.items(.tag);
54545067 const zir_datas = astgen.instructions.items(.data);
54555068
54565069 const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
54575070 .condition = cond,
5458 .then_body_len = @intCast(u32, then_scope.instructions.items.len),
5459 .else_body_len = @intCast(u32, else_scope.instructions.items.len),
5071 .then_body_len = then_body_len,
5072 .else_body_len = else_body_len,
54605073 });
54615074 zir_datas[condbr].pl_node.payload_index = condbr_pl;
54625075 const then_body_len_index = condbr_pl + 1;
54635076 const else_body_len_index = condbr_pl + 2;
54645077
5465 for (then_scope.instructions.items) |src_inst| {
5078 for (then_body) |src_inst| {
54665079 if (zir_tags[src_inst] == .store_to_block_ptr) {
54675080 if (zir_datas[src_inst].bin.lhs == block_ptr) {
54685081 astgen.extra.items[then_body_len_index] -= 1;
......@@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr(
54715084 }
54725085 astgen.extra.appendAssumeCapacity(src_inst);
54735086 }
5474 for (else_scope.instructions.items) |src_inst| {
5087 if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break);
5088 for (else_body) |src_inst| {
54755089 if (zir_tags[src_inst] == .store_to_block_ptr) {
54765090 if (zir_datas[src_inst].bin.lhs == block_ptr) {
54775091 astgen.extra.items[else_body_len_index] -= 1;
......@@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr(
54805094 }
54815095 astgen.extra.appendAssumeCapacity(src_inst);
54825096 }
5097 if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break);
54835098}
54845099
54855100fn whileExpr(
......@@ -5499,17 +5114,17 @@ fn whileExpr(
54995114
55005115 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
55015116 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
5502 const loop_block = try parent_gz.addBlock(loop_tag, node);
5117 const loop_block = try parent_gz.makeBlockInst(loop_tag, node);
55035118 try parent_gz.instructions.append(astgen.gpa, loop_block);
55045119
55055120 var loop_scope = parent_gz.makeSubBlock(scope);
55065121 loop_scope.setBreakResultLoc(rl);
5507 defer loop_scope.instructions.deinit(astgen.gpa);
5122 defer loop_scope.unstack();
55085123 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
55095124 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
55105125
55115126 var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);
5512 defer continue_scope.instructions.deinit(astgen.gpa);
5127 defer continue_scope.unstack();
55135128
55145129 const payload_is_ref = if (while_full.payload_token) |payload_token|
55155130 token_tags[payload_token] == .asterisk
......@@ -5548,15 +5163,19 @@ fn whileExpr(
55485163 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
55495164 const condbr = try continue_scope.addCondBr(condbr_tag, node);
55505165 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5551 const cond_block = try loop_scope.addBlock(block_tag, node);
5552 try loop_scope.instructions.append(astgen.gpa, cond_block);
5166 const cond_block = try loop_scope.makeBlockInst(block_tag, node);
55535167 try continue_scope.setBlockBody(cond_block);
5168 // continue_scope unstacked now, can add new instructions to loop_scope
5169 try loop_scope.instructions.append(astgen.gpa, cond_block);
55545170
5171 // make scope now but don't stack on parent_gz until loop_scope
5172 // gets unstacked after cont_expr is emitted and added below
55555173 var then_scope = parent_gz.makeSubBlock(&continue_scope.base);
5556 defer then_scope.instructions.deinit(astgen.gpa);
5174 then_scope.instructions_top = GenZir.unstacked_top;
5175 defer then_scope.unstack();
55575176
5177 var payload_inst: Zir.Inst.Index = 0;
55585178 var payload_val_scope: Scope.LocalVal = undefined;
5559
55605179 const then_sub_scope = s: {
55615180 if (while_full.error_token != null) {
55625181 if (while_full.payload_token) |payload_token| {
......@@ -5564,7 +5183,8 @@ fn whileExpr(
55645183 .err_union_payload_unsafe_ptr
55655184 else
55665185 .err_union_payload_unsafe;
5567 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5186 // will add this instruction to then_scope.instructions below
5187 payload_inst = try then_scope.makeUnNode(tag, cond.inst, node);
55685188 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
55695189 const ident_bytes = tree.tokenSlice(ident_token);
55705190 if (mem.eql(u8, "_", ident_bytes))
......@@ -5576,7 +5196,7 @@ fn whileExpr(
55765196 .parent = &then_scope.base,
55775197 .gen_zir = &then_scope,
55785198 .name = ident_name,
5579 .inst = payload_inst,
5199 .inst = indexToRef(payload_inst),
55805200 .token_src = payload_token,
55815201 .id_cat = .@"capture",
55825202 };
......@@ -5590,7 +5210,8 @@ fn whileExpr(
55905210 .optional_payload_unsafe_ptr
55915211 else
55925212 .optional_payload_unsafe;
5593 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5213 // will add this instruction to then_scope.instructions below
5214 payload_inst = try then_scope.makeUnNode(tag, cond.inst, node);
55945215 const ident_name = try astgen.identAsString(ident_token);
55955216 const ident_bytes = tree.tokenSlice(ident_token);
55965217 if (mem.eql(u8, "_", ident_bytes))
......@@ -5600,7 +5221,7 @@ fn whileExpr(
56005221 .parent = &then_scope.base,
56015222 .gen_zir = &then_scope,
56025223 .name = ident_name,
5603 .inst = payload_inst,
5224 .inst = indexToRef(payload_inst),
56045225 .token_src = ident_token,
56055226 .id_cat = .@"capture",
56065227 };
......@@ -5630,6 +5251,9 @@ fn whileExpr(
56305251 });
56315252 }
56325253
5254 // done adding instructions to loop_scope, can now stack then_scope
5255 then_scope.instructions_top = then_scope.instructions.items.len;
5256 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);
56335257 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
56345258 if (!then_scope.endsWithNoReturn()) {
56355259 loop_scope.break_count += 1;
......@@ -5637,7 +5261,7 @@ fn whileExpr(
56375261 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
56385262
56395263 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
5640 defer else_scope.instructions.deinit(astgen.gpa);
5264 defer else_scope.unstack();
56415265
56425266 const else_node = while_full.ast.else_expr;
56435267 const else_info: struct {
......@@ -5650,7 +5274,7 @@ fn whileExpr(
56505274 .err_union_code_ptr
56515275 else
56525276 .err_union_code;
5653 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
5277 const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
56545278 const ident_name = try astgen.identAsString(error_token);
56555279 const ident_bytes = tree.tokenSlice(error_token);
56565280 if (mem.eql(u8, ident_bytes, "_"))
......@@ -5660,7 +5284,7 @@ fn whileExpr(
56605284 .parent = &else_scope.base,
56615285 .gen_zir = &else_scope,
56625286 .name = ident_name,
5663 .inst = payload_inst,
5287 .inst = else_payload_inst,
56645288 .token_src = error_token,
56655289 .id_cat = .@"capture",
56665290 };
......@@ -5742,17 +5366,17 @@ fn forExpr(
57425366 };
57435367
57445368 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
5745 const loop_block = try parent_gz.addBlock(loop_tag, node);
5369 const loop_block = try parent_gz.makeBlockInst(loop_tag, node);
57465370 try parent_gz.instructions.append(astgen.gpa, loop_block);
57475371
57485372 var loop_scope = parent_gz.makeSubBlock(scope);
57495373 loop_scope.setBreakResultLoc(rl);
5750 defer loop_scope.instructions.deinit(astgen.gpa);
5374 defer loop_scope.unstack();
57515375 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
57525376 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
57535377
57545378 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
5755 defer cond_scope.instructions.deinit(astgen.gpa);
5379 defer cond_scope.unstack();
57565380
57575381 // check condition i < array_expr.len
57585382 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
......@@ -5764,9 +5388,10 @@ fn forExpr(
57645388 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
57655389 const condbr = try cond_scope.addCondBr(condbr_tag, node);
57665390 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5767 const cond_block = try loop_scope.addBlock(block_tag, node);
5768 try loop_scope.instructions.append(astgen.gpa, cond_block);
5391 const cond_block = try loop_scope.makeBlockInst(block_tag, node);
57695392 try cond_scope.setBlockBody(cond_block);
5393 // cond_block unstacked now, can add new instructions to loop_scope
5394 try loop_scope.instructions.append(astgen.gpa, cond_block);
57705395
57715396 // Increment the index variable.
57725397 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
......@@ -5789,7 +5414,7 @@ fn forExpr(
57895414 }
57905415
57915416 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
5792 defer then_scope.instructions.deinit(astgen.gpa);
5417 defer then_scope.unstack();
57935418
57945419 var payload_val_scope: Scope.LocalVal = undefined;
57955420 var index_scope: Scope.LocalPtr = undefined;
......@@ -5851,7 +5476,7 @@ fn forExpr(
58515476 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
58525477
58535478 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
5854 defer else_scope.instructions.deinit(astgen.gpa);
5479 defer else_scope.unstack();
58555480
58565481 const else_node = for_full.ast.else_expr;
58575482 const else_info: struct {
......@@ -6030,27 +5655,29 @@ fn switchExpr(
60305655 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
60315656 const item_rl: ResultLoc = .{ .ty = cond_ty_inst };
60325657
6033 // These contain the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti.
6034 // This is the optional else prong body.
6035 var special_case_payload = ArrayListUnmanaged(u32){};
6036 defer special_case_payload.deinit(gpa);
6037 // This is all the scalar cases.
6038 var scalar_cases_payload = ArrayListUnmanaged(u32){};
6039 defer scalar_cases_payload.deinit(gpa);
6040 // Same deal, but this is only the `extra` data for the multi cases.
6041 var multi_cases_payload = ArrayListUnmanaged(u32){};
6042 defer multi_cases_payload.deinit(gpa);
5658 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
5659 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
5660 // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes
5661 const payloads = &astgen.scratch;
5662 const scratch_top = astgen.scratch.items.len;
5663 const case_table_start = scratch_top;
5664 const scalar_case_table = case_table_start + @boolToInt(special_prong != .none);
5665 const multi_case_table = scalar_case_table + scalar_cases_len;
5666 const case_table_end = multi_case_table + multi_cases_len;
5667 try astgen.scratch.resize(gpa, case_table_end);
5668 defer astgen.scratch.items.len = scratch_top;
60435669
60445670 var block_scope = parent_gz.makeSubBlock(scope);
5671 // block_scope not used for collecting instructions
5672 block_scope.instructions_top = GenZir.unstacked_top;
60455673 block_scope.setBreakResultLoc(rl);
6046 defer block_scope.instructions.deinit(gpa);
60475674
60485675 // This gets added to the parent block later, after the item expressions.
6049 const switch_block = try parent_gz.addBlock(.switch_block, switch_node);
5676 const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node);
60505677
60515678 // We re-use this same scope for all cases, including the special prong, if any.
60525679 var case_scope = parent_gz.makeSubBlock(&block_scope.base);
6053 defer case_scope.instructions.deinit(gpa);
5680 case_scope.instructions_top = GenZir.unstacked_top;
60545681
60555682 // In this pass we generate all the item and prong expressions.
60565683 var multi_case_index: u32 = 0;
......@@ -6062,21 +5689,12 @@ fn switchExpr(
60625689 else => unreachable,
60635690 };
60645691
6065 // Reset the scope.
6066 case_scope.instructions.shrinkRetainingCapacity(0);
6067
60685692 const is_multi_case = case.ast.values.len > 1 or
60695693 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
60705694
5695 var capture_inst: Zir.Inst.Index = 0;
60715696 var capture_val_scope: Scope.LocalVal = undefined;
60725697 const sub_scope = blk: {
6073 const capture_index = if (is_multi_case) ci: {
6074 multi_case_index += 1;
6075 break :ci multi_case_index - 1;
6076 } else ci: {
6077 scalar_case_index += 1;
6078 break :ci scalar_case_index - 1;
6079 };
60805698 const payload_token = case.payload_token orelse break :blk &case_scope.base;
60815699 const ident = if (token_tags[payload_token] == .asterisk)
60825700 payload_token + 1
......@@ -6089,19 +5707,20 @@ fn switchExpr(
60895707 }
60905708 break :blk &case_scope.base;
60915709 }
6092 const capture = if (case_node == special_node) capture: {
5710 if (case_node == special_node) {
60935711 const capture_tag: Zir.Inst.Tag = if (is_ptr)
60945712 .switch_capture_else_ref
60955713 else
60965714 .switch_capture_else;
6097 break :capture try case_scope.add(.{
5715 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
5716 try astgen.instructions.append(gpa, .{
60985717 .tag = capture_tag,
60995718 .data = .{ .switch_capture = .{
61005719 .switch_inst = switch_block,
61015720 .prong_index = undefined,
61025721 } },
61035722 });
6104 } else capture: {
5723 } else {
61055724 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);
61065725 const is_ptr_bits: u2 = @boolToInt(is_ptr);
61075726 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {
......@@ -6110,30 +5729,33 @@ fn switchExpr(
61105729 0b10 => .switch_capture_multi,
61115730 0b11 => .switch_capture_multi_ref,
61125731 };
6113 break :capture try case_scope.add(.{
5732 const capture_index = if (is_multi_case) multi_case_index else scalar_case_index;
5733 capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
5734 try astgen.instructions.append(gpa, .{
61145735 .tag = capture_tag,
61155736 .data = .{ .switch_capture = .{
61165737 .switch_inst = switch_block,
61175738 .prong_index = capture_index,
61185739 } },
61195740 });
6120 };
5741 }
61215742 const capture_name = try astgen.identAsString(ident);
61225743 capture_val_scope = .{
61235744 .parent = &case_scope.base,
61245745 .gen_zir = &case_scope,
61255746 .name = capture_name,
6126 .inst = capture,
5747 .inst = indexToRef(capture_inst),
61275748 .token_src = payload_token,
61285749 .id_cat = .@"capture",
61295750 };
61305751 break :blk &capture_val_scope.base;
61315752 };
61325753
6133 if (is_multi_case) {
6134 // items_len, ranges_len, body_len
6135 const header_index = multi_cases_payload.items.len;
6136 try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3);
5754 const header_index = @intCast(u32, payloads.items.len);
5755 const body_len_index = if (is_multi_case) blk: {
5756 payloads.items[multi_case_table + multi_case_index] = header_index;
5757 multi_case_index += 1;
5758 try payloads.resize(gpa, header_index + 3); // items_len, ranges_len, body_len
61375759
61385760 // items
61395761 var items_len: u32 = 0;
......@@ -6142,7 +5764,7 @@ fn switchExpr(
61425764 items_len += 1;
61435765
61445766 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
6145 try multi_cases_payload.append(gpa, @enumToInt(item_inst));
5767 try payloads.append(gpa, @enumToInt(item_inst));
61465768 }
61475769
61485770 // ranges
......@@ -6153,47 +5775,44 @@ fn switchExpr(
61535775
61545776 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
61555777 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);
6156 try multi_cases_payload.appendSlice(gpa, &[_]u32{
5778 try payloads.appendSlice(gpa, &[_]u32{
61575779 @enumToInt(first), @enumToInt(last),
61585780 });
61595781 }
61605782
6161 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
6162 try checkUsed(parent_gz, &case_scope.base, sub_scope);
6163 if (!parent_gz.refIsNoReturn(case_result)) {
6164 block_scope.break_count += 1;
6165 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
6166 }
6167
6168 multi_cases_payload.items[header_index + 0] = items_len;
6169 multi_cases_payload.items[header_index + 1] = ranges_len;
6170 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);
6171 try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items);
6172 } else if (case_node == special_node) {
6173 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
6174 try checkUsed(parent_gz, &case_scope.base, sub_scope);
6175 if (!parent_gz.refIsNoReturn(case_result)) {
6176 block_scope.break_count += 1;
6177 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
6178 }
6179 try special_case_payload.ensureUnusedCapacity(gpa, 1 + // body_len
6180 case_scope.instructions.items.len);
6181 special_case_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
6182 special_case_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
6183 } else {
5783 payloads.items[header_index] = items_len;
5784 payloads.items[header_index + 1] = ranges_len;
5785 break :blk header_index + 2;
5786 } else if (case_node == special_node) blk: {
5787 payloads.items[case_table_start] = header_index;
5788 try payloads.resize(gpa, header_index + 1); // body_len
5789 break :blk header_index;
5790 } else blk: {
5791 payloads.items[scalar_case_table + scalar_case_index] = header_index;
5792 scalar_case_index += 1;
5793 try payloads.resize(gpa, header_index + 2); // item, body_len
61845794 const item_node = case.ast.values[0];
61855795 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);
5796 payloads.items[header_index] = @enumToInt(item_inst);
5797 break :blk header_index + 1;
5798 };
5799
5800 {
5801 // temporarily stack case_scope on parent_gz
5802 case_scope.instructions_top = parent_gz.instructions.items.len;
5803 defer case_scope.unstack();
5804
5805 if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst);
61865806 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
61875807 try checkUsed(parent_gz, &case_scope.base, sub_scope);
61885808 if (!parent_gz.refIsNoReturn(case_result)) {
61895809 block_scope.break_count += 1;
61905810 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
61915811 }
6192 try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + // item + body_len
6193 case_scope.instructions.items.len);
6194 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));
6195 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));
6196 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
5812
5813 const case_slice = case_scope.instructionsSlice();
5814 payloads.items[body_len_index] = @intCast(u32, case_slice.len);
5815 try payloads.appendSlice(gpa, case_slice);
61975816 }
61985817 }
61995818 // Now that the item expressions are generated we can add this.
......@@ -6201,9 +5820,7 @@ fn switchExpr(
62015820
62025821 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +
62035822 @boolToInt(multi_cases_len != 0) +
6204 special_case_payload.items.len +
6205 scalar_cases_payload.items.len +
6206 multi_cases_payload.items.len);
5823 payloads.items.len - case_table_end);
62075824
62085825 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{
62095826 .operand = cond,
......@@ -6216,105 +5833,59 @@ fn switchExpr(
62165833 },
62175834 });
62185835
6219 const zir_datas = astgen.instructions.items(.data);
6220 const zir_tags = astgen.instructions.items(.tag);
6221
6222 zir_datas[switch_block].pl_node.payload_index = payload_index;
6223
62245836 if (multi_cases_len != 0) {
62255837 astgen.extra.appendAssumeCapacity(multi_cases_len);
62265838 }
62275839
6228 const strat = rl.strategy(&block_scope);
6229 switch (strat.tag) {
6230 .break_operand => {
6231 // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus
6232 // `elide_store_to_block_ptr_instructions` will either be true,
6233 // or all prongs are noreturn.
6234 if (!strat.elide_store_to_block_ptr_instructions) {
6235 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items);
6236 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
6237 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
6238 return indexToRef(switch_block);
6239 }
5840 const zir_datas = astgen.instructions.items(.data);
5841 const zir_tags = astgen.instructions.items(.tag);
62405842
6241 // There will necessarily be a store_to_block_ptr for
6242 // all prongs, except for prongs that ended with a noreturn instruction.
6243 // Elide all the `store_to_block_ptr` instructions.
5843 zir_datas[switch_block].pl_node.payload_index = payload_index;
62445844
6245 // The break instructions need to have their operands coerced if the
6246 // switch's result location is a `ty`. In this case we overwrite the
6247 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
6248 // it as the break operand.
5845 const strat = rl.strategy(&block_scope);
5846 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {
5847 var body_len_index = start_index;
5848 var end_index = start_index;
5849 const table_index = case_table_start + i;
5850 if (table_index < scalar_case_table) {
5851 end_index += 1;
5852 } else if (table_index < multi_case_table) {
5853 body_len_index += 1;
5854 end_index += 2;
5855 } else {
5856 body_len_index += 2;
5857 const items_len = payloads.items[start_index];
5858 const ranges_len = payloads.items[start_index + 1];
5859 end_index += 3 + items_len + 2 * ranges_len;
5860 }
62495861
6250 var extra_index: usize = 0;
6251 if (special_prong != .none) special_prong: {
6252 const body_len_index = extra_index;
6253 const body_len = special_case_payload.items[extra_index];
6254 extra_index += 1;
6255 if (body_len < 2) {
6256 extra_index += body_len;
6257 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6258 break :special_prong;
6259 }
6260 extra_index += body_len - 2;
6261 const store_inst = special_case_payload.items[extra_index];
6262 if (zir_tags[store_inst] != .store_to_block_ptr or
6263 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
6264 {
6265 extra_index += 2;
6266 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6267 break :special_prong;
6268 }
6269 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
6270 if (block_scope.rl_ty_inst != .none) {
6271 extra_index += 1;
6272 const break_inst = special_case_payload.items[extra_index];
6273 extra_index += 1;
6274 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6275 zir_tags[store_inst] = .as;
6276 zir_datas[store_inst].bin = .{
6277 .lhs = block_scope.rl_ty_inst,
6278 .rhs = zir_datas[break_inst].@"break".operand,
6279 };
6280 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);
6281 } else {
6282 special_case_payload.items[body_len_index] -= 1;
6283 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6284 extra_index += 1;
6285 astgen.extra.appendAssumeCapacity(special_case_payload.items[extra_index]);
6286 extra_index += 1;
6287 }
6288 } else {
6289 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);
6290 }
6291 extra_index = 0;
6292 var scalar_i: u32 = 0;
6293 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
6294 const start_index = extra_index;
6295 extra_index += 1;
6296 const body_len_index = extra_index;
6297 const body_len = scalar_cases_payload.items[extra_index];
6298 extra_index += 1;
6299 if (body_len < 2) {
6300 extra_index += body_len;
6301 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
6302 continue;
6303 }
6304 extra_index += body_len - 2;
6305 const store_inst = scalar_cases_payload.items[extra_index];
5862 const body_len = payloads.items[body_len_index];
5863 end_index += body_len;
5864
5865 switch (strat.tag) {
5866 .break_operand => blk: {
5867 // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus
5868 // `elide_store_to_block_ptr_instructions` will either be true,
5869 // or all prongs are noreturn.
5870 if (!strat.elide_store_to_block_ptr_instructions)
5871 break :blk;
5872
5873 // There will necessarily be a store_to_block_ptr for
5874 // all prongs, except for prongs that ended with a noreturn instruction.
5875 // Elide all the `store_to_block_ptr` instructions.
5876
5877 // The break instructions need to have their operands coerced if the
5878 // switch's result location is a `ty`. In this case we overwrite the
5879 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
5880 // it as the break operand.
5881 if (body_len < 2)
5882 break :blk;
5883 const store_inst = payloads.items[end_index - 2];
63065884 if (zir_tags[store_inst] != .store_to_block_ptr or
63075885 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
6308 {
6309 extra_index += 2;
6310 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
6311 continue;
6312 }
5886 break :blk;
5887 const break_inst = payloads.items[end_index - 1];
63135888 if (block_scope.rl_ty_inst != .none) {
6314 extra_index += 1;
6315 const break_inst = scalar_cases_payload.items[extra_index];
6316 extra_index += 1;
6317 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
63185889 zir_tags[store_inst] = .as;
63195890 zir_datas[store_inst].bin = .{
63205891 .lhs = block_scope.rl_ty_inst,
......@@ -6322,125 +5893,30 @@ fn switchExpr(
63225893 };
63235894 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);
63245895 } else {
6325 scalar_cases_payload.items[body_len_index] -= 1;
6326 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
6327 extra_index += 1;
6328 astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]);
6329 extra_index += 1;
6330 }
6331 }
6332 extra_index = 0;
6333 var multi_i: u32 = 0;
6334 while (multi_i < multi_cases_len) : (multi_i += 1) {
6335 const start_index = extra_index;
6336 const items_len = multi_cases_payload.items[extra_index];
6337 extra_index += 1;
6338 const ranges_len = multi_cases_payload.items[extra_index];
6339 extra_index += 1;
6340 const body_len_index = extra_index;
6341 const body_len = multi_cases_payload.items[extra_index];
6342 extra_index += 1;
6343 extra_index += items_len;
6344 extra_index += 2 * ranges_len;
6345 if (body_len < 2) {
6346 extra_index += body_len;
6347 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
6348 continue;
6349 }
6350 extra_index += body_len - 2;
6351 const store_inst = multi_cases_payload.items[extra_index];
6352 if (zir_tags[store_inst] != .store_to_block_ptr or
6353 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
6354 {
6355 extra_index += 2;
6356 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
5896 payloads.items[body_len_index] -= 1;
5897 astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index .. end_index - 2]);
5898 astgen.extra.appendAssumeCapacity(break_inst);
63575899 continue;
63585900 }
6359 if (block_scope.rl_ty_inst != .none) {
6360 extra_index += 1;
6361 const break_inst = multi_cases_payload.items[extra_index];
6362 extra_index += 1;
6363 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
6364 zir_tags[store_inst] = .as;
6365 zir_datas[store_inst].bin = .{
6366 .lhs = block_scope.rl_ty_inst,
6367 .rhs = zir_datas[break_inst].@"break".operand,
6368 };
6369 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);
6370 } else {
6371 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);
6372 multi_cases_payload.items[body_len_index] -= 1;
6373 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);
6374 extra_index += 1;
6375 astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]);
6376 extra_index += 1;
6377 }
6378 }
6379
6380 const block_ref = indexToRef(switch_block);
6381 switch (rl) {
6382 .ref => return block_ref,
6383 else => return rvalue(parent_gz, rl, block_ref, switch_node),
6384 }
6385 },
6386 .break_void => {
6387 assert(!strat.elide_store_to_block_ptr_instructions);
6388 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items);
6389 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items);
6390 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items);
6391 // Modify all the terminating instruction tags to become `break` variants.
6392 var extra_index: usize = payload_index;
6393 extra_index += 2;
6394 extra_index += @boolToInt(multi_cases_len != 0);
6395 if (special_prong != .none) {
6396 const body_len = astgen.extra.items[extra_index];
6397 extra_index += 1;
6398 const body = astgen.extra.items[extra_index..][0..body_len];
6399 extra_index += body_len;
6400 const last = body[body.len - 1];
6401 if (zir_tags[last] == .@"break" and
6402 zir_datas[last].@"break".block_inst == switch_block)
6403 {
6404 zir_datas[last].@"break".operand = .void_value;
6405 }
6406 }
6407 var scalar_i: u32 = 0;
6408 while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
6409 extra_index += 1;
6410 const body_len = astgen.extra.items[extra_index];
6411 extra_index += 1;
6412 const body = astgen.extra.items[extra_index..][0..body_len];
6413 extra_index += body_len;
6414 const last = body[body.len - 1];
6415 if (zir_tags[last] == .@"break" and
6416 zir_datas[last].@"break".block_inst == switch_block)
6417 {
6418 zir_datas[last].@"break".operand = .void_value;
6419 }
6420 }
6421 var multi_i: u32 = 0;
6422 while (multi_i < multi_cases_len) : (multi_i += 1) {
6423 const items_len = astgen.extra.items[extra_index];
6424 extra_index += 1;
6425 const ranges_len = astgen.extra.items[extra_index];
6426 extra_index += 1;
6427 const body_len = astgen.extra.items[extra_index];
6428 extra_index += 1;
6429 extra_index += items_len;
6430 extra_index += 2 * ranges_len;
6431 const body = astgen.extra.items[extra_index..][0..body_len];
6432 extra_index += body_len;
6433 const last = body[body.len - 1];
6434 if (zir_tags[last] == .@"break" and
6435 zir_datas[last].@"break".block_inst == switch_block)
5901 },
5902 .break_void => {
5903 assert(!strat.elide_store_to_block_ptr_instructions);
5904 const last_inst = payloads.items[end_index - 1];
5905 if (zir_tags[last_inst] == .@"break" and
5906 zir_datas[last_inst].@"break".block_inst == switch_block)
64365907 {
6437 zir_datas[last].@"break".operand = .void_value;
5908 zir_datas[last_inst].@"break".operand = .void_value;
64385909 }
6439 }
5910 },
5911 }
64405912
6441 return indexToRef(switch_block);
6442 },
5913 astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index..end_index]);
64435914 }
5915
5916 const block_ref = indexToRef(switch_block);
5917 if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref)
5918 return rvalue(parent_gz, rl, block_ref, switch_node);
5919 return block_ref;
64445920}
64455921
64465922fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
......@@ -6519,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
65195995 const condbr = try gz.addCondBr(.condbr, node);
65205996
65215997 var then_scope = gz.makeSubBlock(scope);
6522 defer then_scope.instructions.deinit(astgen.gpa);
5998 defer then_scope.unstack();
65235999
65246000 try genDefers(&then_scope, defer_outer, scope, .normal_only);
65256001 try then_scope.addRet(rl, operand, node);
65266002
65276003 var else_scope = gz.makeSubBlock(scope);
6528 defer else_scope.instructions.deinit(astgen.gpa);
6004 defer else_scope.unstack();
65296005
65306006 const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{
65316007 .both = try else_scope.addUnNode(.err_union_code, result, node),
......@@ -6533,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
65336009 try genDefers(&else_scope, defer_outer, scope, which_ones);
65346010 try else_scope.addRet(rl, operand, node);
65356011
6536 try setCondBrPayload(condbr, is_non_err, &then_scope, &else_scope);
6012 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
65376013
65386014 return Zir.Inst.Ref.unreachable_value;
65396015 },
......@@ -6559,25 +6035,25 @@ fn identifier(
65596035 if (mem.eql(u8, ident_name_raw, "_")) {
65606036 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
65616037 }
6562 const ident_name = try astgen.identifierTokenString(ident_token);
65636038
6039 // if not @"" syntax, just use raw token slice
65646040 if (ident_name_raw[0] != '@') {
6565 if (primitives.get(ident_name)) |zir_const_ref| {
6041 if (primitives.get(ident_name_raw)) |zir_const_ref| {
65666042 return rvalue(gz, rl, zir_const_ref, ident);
65676043 }
65686044
6569 if (ident_name.len >= 2) integer: {
6570 const first_c = ident_name[0];
6045 if (ident_name_raw.len >= 2) integer: {
6046 const first_c = ident_name_raw[0];
65716047 if (first_c == 'i' or first_c == 'u') {
65726048 const signedness: std.builtin.Signedness = switch (first_c == 'i') {
65736049 true => .signed,
65746050 false => .unsigned,
65756051 };
6576 const bit_count = std.fmt.parseInt(u16, ident_name[1..], 10) catch |err| switch (err) {
6052 const bit_count = std.fmt.parseInt(u16, ident_name_raw[1..], 10) catch |err| switch (err) {
65776053 error.Overflow => return astgen.failNode(
65786054 ident,
65796055 "primitive integer type '{s}' exceeds maximum bit width of 65535",
6580 .{ident_name},
6056 .{ident_name_raw},
65816057 ),
65826058 error.InvalidCharacter => break :integer,
65836059 };
......@@ -6630,6 +6106,7 @@ fn identifier(
66306106
66316107 // Can't close over a runtime variable
66326108 if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) {
6109 const ident_name = try astgen.identifierTokenString(ident_token);
66336110 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
66346111 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
66356112 try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}),
......@@ -6677,6 +6154,7 @@ fn identifier(
66776154 .top => break,
66786155 };
66796156 if (found_already == null) {
6157 const ident_name = try astgen.identifierTokenString(ident_token);
66806158 return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name});
66816159 }
66826160
......@@ -6712,9 +6190,15 @@ fn tunnelThroughClosure(
67126190 // already has one for this value.
67136191 const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?);
67146192 if (!gop.found_existing) {
6715 // Make a new capture for this value
6716 const capture_ref = try ns.?.declaring_gz.?.addUnTok(.closure_capture, value, token);
6717 gop.value_ptr.* = refToIndex(capture_ref).?;
6193 // Make a new capture for this value but don't add it to the declaring_gz yet
6194 try gz.astgen.instructions.append(gz.astgen.gpa, .{
6195 .tag = .closure_capture,
6196 .data = .{ .un_tok = .{
6197 .operand = value,
6198 .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token),
6199 } },
6200 });
6201 gop.value_ptr.* = @intCast(Zir.Inst.Index, gz.astgen.instructions.len - 1);
67186202 }
67196203
67206204 // Add an instruction to get the value from the closure into
......@@ -7155,10 +6639,8 @@ fn asRlPtr(
71556639 operand_node: Ast.Node.Index,
71566640 dest_type: Zir.Inst.Ref,
71576641) InnerError!Zir.Inst.Ref {
7158 const astgen = parent_gz.astgen;
7159
71606642 var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr);
7161 defer as_scope.instructions.deinit(astgen.gpa);
6643 defer as_scope.unstack();
71626644
71636645 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);
71646646 return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type);
......@@ -7196,13 +6678,18 @@ fn typeOf(
71966678 const result = try gz.addUnNode(.typeof, expr_result, node);
71976679 return rvalue(gz, rl, result, node);
71986680 }
7199 const arena = gz.astgen.arena;
7200 var items = try arena.alloc(Zir.Inst.Ref, params.len);
7201 for (params) |param, param_i| {
7202 items[param_i] = try reachableExpr(gz, scope, .none, param, node);
6681
6682 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
6683 .src_node = gz.nodeIndexToRelative(node),
6684 });
6685 var extra_index = try reserveExtra(gz.astgen, params.len);
6686 for (params) |param| {
6687 const param_ref = try reachableExpr(gz, scope, .none, param, node);
6688 gz.astgen.extra.items[extra_index] = @enumToInt(param_ref);
6689 extra_index += 1;
72036690 }
72046691
7205 const result = try gz.addExtendedMultiOp(.typeof_peer, node, items);
6692 const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len);
72066693 return rvalue(gz, rl, result, node);
72076694}
72086695
......@@ -7259,12 +6746,16 @@ fn builtinCall(
72596746 return rvalue(gz, rl, result, node);
72606747 },
72616748 .compile_log => {
7262 const arg_refs = try astgen.gpa.alloc(Zir.Inst.Ref, params.len);
7263 defer astgen.gpa.free(arg_refs);
7264
7265 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);
7266
7267 const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs);
6749 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
6750 .src_node = gz.nodeIndexToRelative(node),
6751 });
6752 var extra_index = try reserveExtra(gz.astgen, params.len);
6753 for (params) |param| {
6754 const param_ref = try expr(gz, scope, .none, param);
6755 astgen.extra.items[extra_index] = @enumToInt(param_ref);
6756 extra_index += 1;
6757 }
6758 const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log,payload_index, params.len);
72686759 return rvalue(gz, rl, result, node);
72696760 },
72706761 .field => {
......@@ -7921,14 +7412,15 @@ fn cImport(
79217412 var block_scope = gz.makeSubBlock(scope);
79227413 block_scope.force_comptime = true;
79237414 block_scope.c_import = true;
7924 defer block_scope.instructions.deinit(gpa);
7415 defer block_scope.unstack();
79257416
7926 const block_inst = try gz.addBlock(.c_import, node);
7417 const block_inst = try gz.makeBlockInst(.c_import, node);
79277418 const block_result = try expr(&block_scope, &block_scope.base, .none, body_node);
79287419 if (!gz.refIsNoReturn(block_result)) {
79297420 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
79307421 }
79317422 try block_scope.setBlockBody(block_inst);
7423 // block_scope unstacked now, can add new instructions to gz
79327424 try gz.instructions.append(gpa, block_inst);
79337425
79347426 return indexToRef(block_inst);
......@@ -7974,22 +7466,6 @@ fn callExpr(
79747466 const astgen = gz.astgen;
79757467
79767468 const callee = try calleeExpr(gz, scope, call.ast.fn_expr);
7977
7978 // A large proportion of calls have 5 or less arguments, due to this preventing allocations
7979 // for calls with few arguments has a sizeable effect on the aggregated runtime of this function
7980 var arg_buffer: [5]Zir.Inst.Ref = undefined;
7981 const args: []Zir.Inst.Ref = if (call.ast.params.len <= arg_buffer.len)
7982 arg_buffer[0..call.ast.params.len]
7983 else
7984 try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len);
7985 defer if (call.ast.params.len > arg_buffer.len) astgen.gpa.free(args);
7986
7987 for (call.ast.params) |param_node, i| {
7988 // Parameters are always temporary values, they have no
7989 // meaningful result location. Sema will coerce them.
7990 args[i] = try expr(gz, scope, .none, param_node);
7991 }
7992
79937469 const modifier: std.builtin.CallOptions.Modifier = blk: {
79947470 if (gz.force_comptime) {
79957471 break :blk .compile_time;
......@@ -8002,7 +7478,28 @@ fn callExpr(
80027478 }
80037479 break :blk .auto;
80047480 };
8005 const call_inst = try gz.addCall(modifier, callee, args, node);
7481
7482 assert(callee != .none);
7483 assert(node != 0);
7484
7485 const payload_index = try addExtra(astgen, Zir.Inst.Call{
7486 .callee = callee,
7487 .flags = .{
7488 .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)),
7489 .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len),
7490 },
7491 });
7492 var extra_index = try reserveExtra(astgen, call.ast.params.len);
7493
7494 for (call.ast.params) |param_node| {
7495 // Parameters are always temporary values, they have no
7496 // meaningful result location. Sema will coerce them.
7497 const arg_ref = try expr(gz, scope, .none, param_node);
7498 astgen.extra.items[extra_index] = @enumToInt(arg_ref);
7499 extra_index += 1;
7500 }
7501
7502 const call_inst = try gz.addPlNodePayloadIndex(.call, node, payload_index);
80067503 return rvalue(gz, rl, call_inst, node); // TODO function call with result location
80077504}
80087505
......@@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
87478244/// result locations must call this function on their result.
87488245/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
87498246/// If the `ResultLoc` is `ty`, it will coerce the result to the type.
8247/// Assumes nothing stacked on `gz`.
87508248fn rvalue(
87518249 gz: *GenZir,
87528250 rl: ResultLoc,
......@@ -9326,7 +8824,7 @@ const Scope = struct {
93268824
93278825 /// Map from the raw captured value to the instruction
93288826 /// ref of the capture for decls in this namespace
9329 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
8827 captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
93308828
93318829 pub fn deinit(self: *Namespace, gpa: *Allocator) void {
93328830 self.decls.deinit(gpa);
......@@ -9359,9 +8857,12 @@ const GenZir = struct {
93598857 parent: *Scope,
93608858 /// All `GenZir` scopes for the same ZIR share this.
93618859 astgen: *AstGen,
9362 /// Keeps track of the list of instructions in this scope only. Indexes
9363 /// to instructions in `astgen`.
9364 instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{},
8860 /// Keeps track of the list of instructions in this scope. Possibly shared.
8861 /// Indexes to instructions in `astgen`.
8862 instructions: *ArrayListUnmanaged(Zir.Inst.Index),
8863 /// A sub-block may share its instructions ArrayList with containing GenZir,
8864 /// if use is strictly nested. This saves prior size of list for unstacking.
8865 instructions_top: usize,
93658866 label: ?Label = null,
93668867 break_block: Zir.Inst.Index = 0,
93678868 continue_block: Zir.Inst.Index = 0,
......@@ -9397,6 +8898,36 @@ const GenZir = struct {
93978898 /// Keys are the raw instruction index, values are the closure_capture instruction.
93988899 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
93998900
8901 const unstacked_top = std.math.maxInt(usize);
8902 /// Call unstack before adding any new instructions to containing GenZir.
8903 fn unstack(self: *GenZir) void {
8904 if (self.instructions_top != unstacked_top) {
8905 self.instructions.items.len = self.instructions_top;
8906 self.instructions_top = unstacked_top;
8907 }
8908 }
8909
8910 fn isEmpty(self: *const GenZir) bool {
8911 return (self.instructions_top == unstacked_top) or
8912 (self.instructions.items.len == self.instructions_top);
8913 }
8914
8915 fn instructionsSlice(self: *const GenZir) []Zir.Inst.Index {
8916 return if (self.instructions_top == unstacked_top)
8917 &[0]Zir.Inst.Index{}
8918 else
8919 self.instructions.items[self.instructions_top..];
8920 }
8921
8922 fn instructionsSliceUpto(self: *const GenZir, stacked_gz: *GenZir) []Zir.Inst.Index {
8923 return if (self.instructions_top == unstacked_top)
8924 &[0]Zir.Inst.Index{}
8925 else if (self.instructions == stacked_gz.instructions and stacked_gz.instructions_top != unstacked_top)
8926 self.instructions.items[self.instructions_top..stacked_gz.instructions_top]
8927 else
8928 self.instructions.items[self.instructions_top..];
8929 }
8930
94008931 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
94018932 return .{
94028933 .force_comptime = gz.force_comptime,
......@@ -9408,6 +8939,8 @@ const GenZir = struct {
94088939 .astgen = gz.astgen,
94098940 .suspend_node = gz.suspend_node,
94108941 .nosuspend_node = gz.nosuspend_node,
8942 .instructions = gz.instructions,
8943 .instructions_top = gz.instructions.items.len,
94118944 };
94128945 }
94138946
......@@ -9421,12 +8954,13 @@ const GenZir = struct {
94218954 // result location. If it does, elide the coerce_result_ptr instruction
94228955 // as well as the store instruction, instead passing the result as an rvalue.
94238956 var as_scope = parent_gz.makeSubBlock(scope);
9424 errdefer as_scope.instructions.deinit(parent_gz.astgen.gpa);
8957 errdefer as_scope.unstack();
94258958 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
94268959
94278960 return as_scope;
94288961 }
94298962
8963 /// Assumes `as_scope` is stacked immediately on top of `parent_gz`. Unstacks `as_scope`.
94308964 fn finishCoercion(
94318965 as_scope: *GenZir,
94328966 parent_gz: *GenZir,
......@@ -9434,25 +8968,32 @@ const GenZir = struct {
94348968 src_node: Ast.Node.Index,
94358969 result: Zir.Inst.Ref,
94368970 dest_type: Zir.Inst.Ref,
9437 ) !Zir.Inst.Ref {
8971 ) InnerError!Zir.Inst.Ref {
8972 assert(as_scope.instructions == parent_gz.instructions);
94388973 const astgen = as_scope.astgen;
9439 const parent_zir = &parent_gz.instructions;
94408974 if (as_scope.rvalue_rl_count == 1) {
94418975 // Busted! This expression didn't actually need a pointer.
94428976 const zir_tags = astgen.instructions.items(.tag);
94438977 const zir_datas = astgen.instructions.items(.data);
9444 try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len);
9445 for (as_scope.instructions.items) |src_inst| {
8978 var src: usize = as_scope.instructions_top;
8979 var dst: usize = src;
8980 while (src < as_scope.instructions.items.len) : (src += 1) {
8981 const src_inst = as_scope.instructions.items[src];
94468982 if (indexToRef(src_inst) == as_scope.rl_ptr) continue;
94478983 if (zir_tags[src_inst] == .store_to_block_ptr) {
94488984 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;
94498985 }
9450 parent_zir.appendAssumeCapacity(src_inst);
8986 as_scope.instructions.items[dst] = src_inst;
8987 dst += 1;
94518988 }
8989 parent_gz.instructions.items.len -= src - dst;
8990 as_scope.instructions_top = GenZir.unstacked_top;
8991 // as_scope now unstacked, can add new instructions to parent_gz
94528992 const casted_result = try parent_gz.addBin(.as, dest_type, result);
94538993 return rvalue(parent_gz, rl, casted_result, src_node);
94548994 } else {
9455 try parent_zir.appendSlice(astgen.gpa, as_scope.instructions.items);
8995 // implicitly move all as_scope instructions to parent_gz
8996 as_scope.instructions_top = GenZir.unstacked_top;
94568997 return result;
94578998 }
94588999 }
......@@ -9463,9 +9004,10 @@ const GenZir = struct {
94639004 used: bool = false,
94649005 };
94659006
9007 /// Assumes nothing stacked on `gz`.
94669008 fn endsWithNoReturn(gz: GenZir) bool {
9009 if (gz.isEmpty()) return false;
94679010 const tags = gz.astgen.instructions.items(.tag);
9468 if (gz.instructions.items.len == 0) return false;
94699011 const last_inst = gz.instructions.items[gz.instructions.items.len - 1];
94709012 return tags[last_inst].isNoReturn();
94719013 }
......@@ -9535,41 +9077,46 @@ const GenZir = struct {
95359077 }
95369078 }
95379079
9538 fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void {
9080 /// Assumes nothing stacked on `gz`. Unstacks `gz`.
9081 fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void {
95399082 const gpa = gz.astgen.gpa;
9540 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
9541 gz.instructions.items.len);
9083 const body = gz.instructionsSlice();
9084 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
95429085 const zir_datas = gz.astgen.instructions.items(.data);
95439086 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(
9544 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
9087 Zir.Inst.Block{ .body_len = @intCast(u32, body.len) },
95459088 );
9546 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
9089 gz.astgen.extra.appendSliceAssumeCapacity(body);
9090 gz.unstack();
95479091 }
95489092
9549 fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void {
9093 /// Assumes nothing stacked on `gz`. Unstacks `gz`.
9094 fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void {
95509095 const gpa = gz.astgen.gpa;
9551 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
9552 gz.instructions.items.len);
9096 const body = gz.instructionsSlice();
9097 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
95539098 const zir_datas = gz.astgen.instructions.items(.data);
95549099 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(
9555 Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) },
9100 Zir.Inst.Block{ .body_len = @intCast(u32, body.len) },
95569101 );
9557 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
9102 gz.astgen.extra.appendSliceAssumeCapacity(body);
9103 gz.unstack();
95589104 }
95599105
95609106 /// Same as `setBlockBody` except we don't copy instructions which are
95619107 /// `store_to_block_ptr` instructions with lhs set to .none.
9562 fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
9108 /// Assumes nothing stacked on `gz`. Unstacks `gz`.
9109 fn setBlockBodyEliding(gz: *GenZir, inst: Zir.Inst.Index) !void {
95639110 const gpa = gz.astgen.gpa;
9564 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +
9565 gz.instructions.items.len);
9111 const body = gz.instructionsSlice();
9112 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
95669113 const zir_datas = gz.astgen.instructions.items(.data);
95679114 const zir_tags = gz.astgen.instructions.items(.tag);
95689115 const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
9569 .body_len = @intCast(u32, gz.instructions.items.len),
9116 .body_len = @intCast(u32, body.len),
95709117 });
95719118 zir_datas[inst].pl_node.payload_index = block_pl_index;
9572 for (gz.instructions.items) |sub_inst| {
9119 for (body) |sub_inst| {
95739120 if (zir_tags[sub_inst] == .store_to_block_ptr and
95749121 zir_datas[sub_inst].bin.lhs == .none)
95759122 {
......@@ -9579,15 +9126,17 @@ const GenZir = struct {
95799126 }
95809127 gz.astgen.extra.appendAssumeCapacity(sub_inst);
95819128 }
9129 gz.unstack();
95829130 }
95839131
9132 /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`.
95849133 fn addFunc(gz: *GenZir, args: struct {
95859134 src_node: Ast.Node.Index,
95869135 lbrace_line: u32 = 0,
95879136 lbrace_column: u32 = 0,
9588 body: []const Zir.Inst.Index,
9137 body_gz: ?*GenZir,
95899138 param_block: Zir.Inst.Index,
9590 ret_ty: []const Zir.Inst.Index,
9139 ret_gz: ?*GenZir,
95919140 ret_br: Zir.Inst.Index,
95929141 cc: Zir.Inst.Ref,
95939142 align_inst: Zir.Inst.Ref,
......@@ -9601,12 +9150,13 @@ const GenZir = struct {
96019150 const astgen = gz.astgen;
96029151 const gpa = astgen.gpa;
96039152
9604 try gz.instructions.ensureUnusedCapacity(gpa, 1);
96059153 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
96069154
9155 var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
9156 var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
96079157 var src_locs_buffer: [3]u32 = undefined;
96089158 var src_locs: []u32 = src_locs_buffer[0..0];
9609 if (args.body.len != 0) {
9159 if (args.body_gz) |body_gz| {
96109160 const tree = astgen.tree;
96119161 const node_tags = tree.nodes.items(.tag);
96129162 const node_datas = tree.nodes.items(.data);
......@@ -9624,6 +9174,13 @@ const GenZir = struct {
96249174 src_locs_buffer[1] = rbrace_line;
96259175 src_locs_buffer[2] = columns;
96269176 src_locs = &src_locs_buffer;
9177
9178 body = body_gz.instructionsSlice();
9179 if (args.ret_gz) |ret_gz|
9180 ret_ty = ret_gz.instructionsSliceUpto(body_gz);
9181 } else {
9182 if (args.ret_gz) |ret_gz|
9183 ret_ty = ret_gz.instructionsSlice();
96279184 }
96289185
96299186 if (args.cc != .none or args.lib_name != 0 or
......@@ -9633,7 +9190,7 @@ const GenZir = struct {
96339190 try astgen.extra.ensureUnusedCapacity(
96349191 gpa,
96359192 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
9636 args.ret_ty.len + args.body.len + src_locs.len +
9193 ret_ty.len + body.len + src_locs.len +
96379194 @boolToInt(args.lib_name != 0) +
96389195 @boolToInt(args.align_inst != .none) +
96399196 @boolToInt(args.cc != .none),
......@@ -9641,8 +9198,8 @@ const GenZir = struct {
96419198 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
96429199 .src_node = gz.nodeIndexToRelative(args.src_node),
96439200 .param_block = args.param_block,
9644 .ret_body_len = @intCast(u32, args.ret_ty.len),
9645 .body_len = @intCast(u32, args.body.len),
9201 .ret_body_len = @intCast(u32, ret_ty.len),
9202 .body_len = @intCast(u32, body.len),
96469203 });
96479204 if (args.lib_name != 0) {
96489205 astgen.extra.appendAssumeCapacity(args.lib_name);
......@@ -9653,9 +9210,13 @@ const GenZir = struct {
96539210 if (args.align_inst != .none) {
96549211 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
96559212 }
9656 astgen.extra.appendSliceAssumeCapacity(args.ret_ty);
9657 astgen.extra.appendSliceAssumeCapacity(args.body);
9213 astgen.extra.appendSliceAssumeCapacity(ret_ty);
9214 astgen.extra.appendSliceAssumeCapacity(body);
96589215 astgen.extra.appendSliceAssumeCapacity(src_locs);
9216 // order is important when unstacking
9217 if (args.body_gz) |body_gz| body_gz.unstack();
9218 if (args.ret_gz) |ret_gz| ret_gz.unstack();
9219 try gz.instructions.ensureUnusedCapacity(gpa, 1);
96599220
96609221 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
96619222 if (args.ret_br != 0) {
......@@ -9683,17 +9244,21 @@ const GenZir = struct {
96839244 try astgen.extra.ensureUnusedCapacity(
96849245 gpa,
96859246 @typeInfo(Zir.Inst.Func).Struct.fields.len +
9686 args.ret_ty.len + args.body.len + src_locs.len,
9247 ret_ty.len + body.len + src_locs.len,
96879248 );
96889249
96899250 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
96909251 .param_block = args.param_block,
9691 .ret_body_len = @intCast(u32, args.ret_ty.len),
9692 .body_len = @intCast(u32, args.body.len),
9252 .ret_body_len = @intCast(u32, ret_ty.len),
9253 .body_len = @intCast(u32, body.len),
96939254 });
9694 astgen.extra.appendSliceAssumeCapacity(args.ret_ty);
9695 astgen.extra.appendSliceAssumeCapacity(args.body);
9255 astgen.extra.appendSliceAssumeCapacity(ret_ty);
9256 astgen.extra.appendSliceAssumeCapacity(body);
96969257 astgen.extra.appendSliceAssumeCapacity(src_locs);
9258 // order is important when unstacking
9259 if (args.body_gz) |body_gz| body_gz.unstack();
9260 if (args.ret_gz) |ret_gz| ret_gz.unstack();
9261 try gz.instructions.ensureUnusedCapacity(gpa, 1);
96979262
96989263 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
96999264 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
......@@ -9765,44 +9330,6 @@ const GenZir = struct {
97659330 return indexToRef(new_index);
97669331 }
97679332
9768 fn addCall(
9769 gz: *GenZir,
9770 modifier: std.builtin.CallOptions.Modifier,
9771 callee: Zir.Inst.Ref,
9772 args: []const Zir.Inst.Ref,
9773 /// Absolute node index. This function does the conversion to offset from Decl.
9774 src_node: Ast.Node.Index,
9775 ) !Zir.Inst.Ref {
9776 assert(callee != .none);
9777 assert(src_node != 0);
9778 const gpa = gz.astgen.gpa;
9779 const Call = Zir.Inst.Call;
9780 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9781 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
9782 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Call).Struct.fields.len +
9783 args.len);
9784
9785 const payload_index = gz.astgen.addExtraAssumeCapacity(Call{
9786 .callee = callee,
9787 .flags = .{
9788 .packed_modifier = @intCast(Call.Flags.PackedModifier, @enumToInt(modifier)),
9789 .args_len = @intCast(Call.Flags.PackedArgsLen, args.len),
9790 },
9791 });
9792 gz.astgen.appendRefsAssumeCapacity(args);
9793
9794 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9795 gz.astgen.instructions.appendAssumeCapacity(.{
9796 .tag = .call,
9797 .data = .{ .pl_node = .{
9798 .src_node = gz.nodeIndexToRelative(src_node),
9799 .payload_index = payload_index,
9800 } },
9801 });
9802 gz.instructions.appendAssumeCapacity(new_index);
9803 return indexToRef(new_index);
9804 }
9805
98069333 /// Note that this returns a `Zir.Inst.Index` not a ref.
98079334 /// Leaves the `payload_index` field undefined.
98089335 fn addBoolBr(
......@@ -9878,6 +9405,25 @@ const GenZir = struct {
98789405 });
98799406 }
98809407
9408 fn makeUnNode(
9409 gz: *GenZir,
9410 tag: Zir.Inst.Tag,
9411 operand: Zir.Inst.Ref,
9412 /// Absolute node index. This function does the conversion to offset from Decl.
9413 src_node: Ast.Node.Index,
9414 ) !Zir.Inst.Index {
9415 assert(operand != .none);
9416 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9417 try gz.astgen.instructions.append(gz.astgen.gpa, .{
9418 .tag = tag,
9419 .data = .{ .un_node = .{
9420 .operand = operand,
9421 .src_node = gz.nodeIndexToRelative(src_node),
9422 } },
9423 });
9424 return new_index;
9425 }
9426
98819427 fn addPlNode(
98829428 gz: *GenZir,
98839429 tag: Zir.Inst.Tag,
......@@ -9902,25 +9448,43 @@ const GenZir = struct {
99029448 return indexToRef(new_index);
99039449 }
99049450
9451 fn addPlNodePayloadIndex(
9452 gz: *GenZir,
9453 tag: Zir.Inst.Tag,
9454 /// Absolute node index. This function does the conversion to offset from Decl.
9455 src_node: Ast.Node.Index,
9456 payload_index: u32,
9457 ) !Zir.Inst.Ref {
9458 return try gz.add(.{
9459 .tag = tag,
9460 .data = .{ .pl_node = .{
9461 .src_node = gz.nodeIndexToRelative(src_node),
9462 .payload_index = payload_index,
9463 } },
9464 });
9465 }
9466
9467 /// Supports `param_gz` stacked on `gz`. Assumes nothing stacked on `param_gz`. Unstacks `param_gz`.
99059468 fn addParam(
99069469 gz: *GenZir,
9470 param_gz: *GenZir,
99079471 tag: Zir.Inst.Tag,
99089472 /// Absolute token index. This function does the conversion to Decl offset.
99099473 abs_tok_index: Ast.TokenIndex,
99109474 name: u32,
9911 body: []const u32,
99129475 ) !Zir.Inst.Index {
99139476 const gpa = gz.astgen.gpa;
9914 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9477 const param_body = param_gz.instructionsSlice();
99159478 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
99169479 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len +
9917 body.len);
9480 param_body.len);
99189481
99199482 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
99209483 .name = name,
9921 .body_len = @intCast(u32, body.len),
9484 .body_len = @intCast(u32, param_body.len),
99229485 });
9923 gz.astgen.extra.appendSliceAssumeCapacity(body);
9486 gz.astgen.extra.appendSliceAssumeCapacity(param_body);
9487 param_gz.unstack();
99249488
99259489 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
99269490 gz.astgen.instructions.appendAssumeCapacity(.{
......@@ -9991,6 +9555,30 @@ const GenZir = struct {
99919555 return indexToRef(new_index);
99929556 }
99939557
9558 fn addExtendedMultiOpPayloadIndex(
9559 gz: *GenZir,
9560 opcode: Zir.Inst.Extended,
9561 payload_index: u32,
9562 trailing_len: usize,
9563 ) !Zir.Inst.Ref {
9564 const astgen = gz.astgen;
9565 const gpa = astgen.gpa;
9566
9567 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9568 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
9569 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
9570 astgen.instructions.appendAssumeCapacity(.{
9571 .tag = .extended,
9572 .data = .{ .extended = .{
9573 .opcode = opcode,
9574 .small = @intCast(u16, trailing_len),
9575 .operand = payload_index,
9576 } },
9577 });
9578 gz.instructions.appendAssumeCapacity(new_index);
9579 return indexToRef(new_index);
9580 }
9581
99949582 fn addUnTok(
99959583 gz: *GenZir,
99969584 tag: Zir.Inst.Tag,
......@@ -10039,6 +9627,23 @@ const GenZir = struct {
100399627 });
100409628 }
100419629
9630 fn makeBreak(
9631 gz: *GenZir,
9632 tag: Zir.Inst.Tag,
9633 break_block: Zir.Inst.Index,
9634 operand: Zir.Inst.Ref,
9635 ) !Zir.Inst.Index {
9636 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9637 try gz.astgen.instructions.append(gz.astgen.gpa, .{
9638 .tag = tag,
9639 .data = .{ .@"break" = .{
9640 .block_inst = break_block,
9641 .operand = operand,
9642 } },
9643 });
9644 return new_index;
9645 }
9646
100429647 fn addBin(
100439648 gz: *GenZir,
100449649 tag: Zir.Inst.Tag,
......@@ -10227,7 +9832,7 @@ const GenZir = struct {
102279832 /// Note that this returns a `Zir.Inst.Index` not a ref.
102289833 /// Does *not* append the block instruction to the scope.
102299834 /// Leaves the `payload_index` field undefined.
10230 fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index {
9835 fn makeBlockInst(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index {
102319836 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
102329837 const gpa = gz.astgen.gpa;
102339838 try gz.astgen.instructions.append(gpa, .{
......@@ -10464,6 +10069,15 @@ const GenZir = struct {
1046410069 else => unreachable,
1046510070 }
1046610071 }
10072
10073 fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void {
10074 if (namespace.captures.count() > 0) {
10075 try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count());
10076 for (namespace.captures.values()) |capture| {
10077 gz.instructions.appendAssumeCapacity(capture);
10078 }
10079 }
10080 }
1046710081};
1046810082
1046910083/// This can only be for short-lived references; the memory becomes invalidated
......@@ -10581,12 +10195,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
1058110195 astgen.source_column = column;
1058210196}
1058310197
10584fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !void {
10198fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !u32 {
1058510199 const gpa = astgen.gpa;
1058610200 const tree = astgen.tree;
1058710201 const node_tags = tree.nodes.items(.tag);
1058810202 const main_tokens = tree.nodes.items(.main_token);
1058910203 const token_tags = tree.tokens.items(.tag);
10204 var decl_count: u32 = 0;
1059010205 for (members) |member_node| {
1059110206 const name_token = switch (node_tags[member_node]) {
1059210207 .fn_proto_simple,
......@@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1059710212 .local_var_decl,
1059810213 .simple_var_decl,
1059910214 .aligned_var_decl,
10600 => main_tokens[member_node] + 1,
10215 => blk: {
10216 decl_count += 1;
10217 break :blk main_tokens[member_node] + 1;
10218 },
1060110219
1060210220 .fn_decl => blk: {
10221 decl_count += 1;
1060310222 const ident = main_tokens[member_node] + 1;
1060410223 if (token_tags[ident] != .identifier) {
1060510224 switch (astgen.failNode(member_node, "missing function name", .{})) {
......@@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1061010229 break :blk ident;
1061110230 },
1061210231
10232 .@"comptime", .@"usingnamespace", .test_decl => {
10233 decl_count += 1;
10234 continue;
10235 },
10236
1061310237 else => continue,
1061410238 };
1061510239
......@@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1064310267 }
1064410268 gop.value_ptr.* = member_node;
1064510269 }
10270 return decl_count;
1064610271}