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,...@@ -41,6 +41,8 @@ fn_block: ?*GenZir = null,
41/// Maps string table indexes to the first `@import` ZIR instruction41/// Maps string table indexes to the first `@import` ZIR instruction
42/// that uses this string as the operand.42/// that uses this string as the operand.
43imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},43imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},
44/// Used for temporary storage when building payloads.
45scratch: std.ArrayListUnmanaged(u32) = .{},
4446
45const InnerError = error{ OutOfMemory, AnalysisFail };47const InnerError = error{ OutOfMemory, AnalysisFail };
4648
...@@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {...@@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 {
53fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {55fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 {
54 const fields = std.meta.fields(@TypeOf(extra));56 const fields = std.meta.fields(@TypeOf(extra));
55 const result = @intCast(u32, astgen.extra.items.len);57 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;
56 inline for (fields) |field| {66 inline for (fields) |field| {
57 astgen.extra.appendAssumeCapacity(switch (field.field_type) {67 astgen.extra.items[i] = switch (field.field_type) {
58 u32 => @field(extra, field.name),68 u32 => @field(extra, field.name),
59 Zir.Inst.Ref => @enumToInt(@field(extra, field.name)),69 Zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
60 i32 => @bitCast(u32, @field(extra, field.name)),70 i32 => @bitCast(u32, @field(extra, field.name)),
61 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),71 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
62 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),72 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
63 else => @compileError("bad field type"),73 else => @compileError("bad field type"),
64 });74 };
75 i += 1;
65 }76 }
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);
66 return result;82 return result;
67}83}
6884
...@@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {...@@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {
101117
102 var top_scope: Scope.Top = .{};118 var top_scope: Scope.Top = .{};
103119
120 var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
104 var gen_scope: GenZir = .{121 var gen_scope: GenZir = .{
105 .force_comptime = true,122 .force_comptime = true,
106 .in_defer = false,123 .in_defer = false,
...@@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {...@@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir {
109 .decl_node_index = 0,126 .decl_node_index = 0,
110 .decl_line = 0,127 .decl_line = 0,
111 .astgen = &astgen,128 .astgen = &astgen,
129 .instructions = &gz_instructions,
130 .instructions_top = 0,
112 };131 };
113 defer gen_scope.instructions.deinit(gpa);132 defer gz_instructions.deinit(gpa);
114133
115 const container_decl: Ast.full.ContainerDecl = .{134 const container_decl: Ast.full.ContainerDecl = .{
116 .layout_token = null,135 .layout_token = null,
...@@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {...@@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {
184 astgen.string_bytes.deinit(gpa);203 astgen.string_bytes.deinit(gpa);
185 astgen.compile_errors.deinit(gpa);204 astgen.compile_errors.deinit(gpa);
186 astgen.imports.deinit(gpa);205 astgen.imports.deinit(gpa);
206 astgen.scratch.deinit(gpa);
187}207}
188208
189pub const ResultLoc = union(enum) {209pub const ResultLoc = union(enum) {
...@@ -1024,12 +1044,12 @@ fn suspendExpr(...@@ -1024,12 +1044,12 @@ fn suspendExpr(
1024 }1044 }
1025 assert(body_node != 0);1045 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);
1028 try gz.instructions.append(gpa, suspend_inst);1048 try gz.instructions.append(gpa, suspend_inst);
10291049
1030 var suspend_scope = gz.makeSubBlock(scope);1050 var suspend_scope = gz.makeSubBlock(scope);
1031 suspend_scope.suspend_node = node;1051 suspend_scope.suspend_node = node;
1032 defer suspend_scope.instructions.deinit(gpa);1052 defer suspend_scope.unstack();
10331053
1034 const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node);1054 const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node);
1035 if (!gz.refIsNoReturn(body_result)) {1055 if (!gz.refIsNoReturn(body_result)) {
...@@ -1084,7 +1104,6 @@ fn fnProtoExpr(...@@ -1084,7 +1104,6 @@ fn fnProtoExpr(
1084 fn_proto: Ast.full.FnProto,1104 fn_proto: Ast.full.FnProto,
1085) InnerError!Zir.Inst.Ref {1105) InnerError!Zir.Inst.Ref {
1086 const astgen = gz.astgen;1106 const astgen = gz.astgen;
1087 const gpa = astgen.gpa;
1088 const tree = astgen.tree;1107 const tree = astgen.tree;
1089 const token_tags = tree.tokens.items(.tag);1108 const token_tags = tree.tokens.items(.tag);
10901109
...@@ -1130,14 +1149,14 @@ fn fnProtoExpr(...@@ -1130,14 +1149,14 @@ fn fnProtoExpr(
1130 const param_type_node = param.type_expr;1149 const param_type_node = param.type_expr;
1131 assert(param_type_node != 0);1150 assert(param_type_node != 0);
1132 var param_gz = gz.makeSubBlock(scope);1151 var param_gz = gz.makeSubBlock(scope);
1133 defer param_gz.instructions.deinit(gpa);1152 defer param_gz.unstack();
1134 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);1153 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);
1135 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);1154 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
1136 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);1155 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
1137 const main_tokens = tree.nodes.items(.main_token);1156 const main_tokens = tree.nodes.items(.main_token);
1138 const name_token = param.name_token orelse main_tokens[param_type_node];1157 const name_token = param.name_token orelse main_tokens[param_type_node];
1139 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;1158 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);
1141 assert(param_inst_expected == param_inst);1160 assert(param_inst_expected == param_inst);
1142 }1161 }
1143 }1162 }
...@@ -1172,16 +1191,16 @@ fn fnProtoExpr(...@@ -1172,16 +1191,16 @@ fn fnProtoExpr(
1172 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});1191 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1173 }1192 }
1174 var ret_gz = gz.makeSubBlock(scope);1193 var ret_gz = gz.makeSubBlock(scope);
1175 defer ret_gz.instructions.deinit(gpa);1194 defer ret_gz.unstack();
1176 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);1195 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
1177 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);1196 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
11781197
1179 const result = try gz.addFunc(.{1198 const result = try gz.addFunc(.{
1180 .src_node = fn_proto.ast.proto_node,1199 .src_node = fn_proto.ast.proto_node,
1181 .param_block = 0,1200 .param_block = 0,
1182 .ret_ty = ret_gz.instructions.items,1201 .ret_gz = &ret_gz,
1183 .ret_br = ret_br,1202 .ret_br = ret_br,
1184 .body = &[0]Zir.Inst.Index{},1203 .body_gz = null,
1185 .cc = cc,1204 .cc = cc,
1186 .align_inst = align_inst,1205 .align_inst = align_inst,
1187 .lib_name = 0,1206 .lib_name = 0,
...@@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone(...@@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone(
1307 tag: Zir.Inst.Tag,1326 tag: Zir.Inst.Tag,
1308) InnerError!Zir.Inst.Ref {1327) InnerError!Zir.Inst.Ref {
1309 const astgen = gz.astgen;1328 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| {1330 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1315 elem_list[i] = try expr(gz, scope, .none, elem_init);1331 .operands_len = @intCast(u32, elements.len),
1316 }
1317 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
1318 .operands_len = @intCast(u32, elem_list.len),
1319 });1332 });
1320 try astgen.appendRefs(elem_list);1333 var extra_index = try reserveExtra(astgen, elements.len);
1321 return init_inst;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);
1322}1341}
13231342
1324fn arrayInitExprRlTy(1343fn arrayInitExprRlTy(
...@@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy(...@@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy(
1330 tag: Zir.Inst.Tag,1349 tag: Zir.Inst.Tag,
1331) InnerError!Zir.Inst.Ref {1350) InnerError!Zir.Inst.Ref {
1332 const astgen = gz.astgen;1351 const astgen = gz.astgen;
1333 const gpa = astgen.gpa;
13341352
1335 const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);1353 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1336 defer gpa.free(elem_list);1354 .operands_len = @intCast(u32, elements.len),
1355 });
1356 var extra_index = try reserveExtra(astgen, elements.len);
13371357
1338 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };1358 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
13391359 for (elements) |elem_init| {
1340 for (elements) |elem_init, i| {1360 const elem_ref = try expr(gz, scope, elem_rl, elem_init);
1341 elem_list[i] = try expr(gz, scope, elem_rl, elem_init);1361 astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1362 extra_index += 1;
1342 }1363 }
1343 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{1364 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1344 .operands_len = @intCast(u32, elem_list.len),
1345 });
1346 try astgen.appendRefs(elem_list);
1347 return init_inst;
1348}1365}
13491366
1350fn arrayInitExprRlPtr(1367fn arrayInitExprRlPtr(
...@@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr(...@@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr(
1361 }1378 }
13621379
1363 var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr);1380 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
1366 const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);1383 const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements);
1367 return as_scope.finishCoercion(gz, rl, node, result, array_ty);1384 return as_scope.finishCoercion(gz, rl, node, result, array_ty);
...@@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner(...@@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner(
1375 elements: []const Ast.Node.Index,1392 elements: []const Ast.Node.Index,
1376) InnerError!Zir.Inst.Ref {1393) InnerError!Zir.Inst.Ref {
1377 const astgen = gz.astgen;1394 const astgen = gz.astgen;
1378 const gpa = astgen.gpa;
13791395
1380 const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len);1396 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1381 defer gpa.free(elem_ptr_list);1397 .body_len = @intCast(u32, elements.len),
1398 });
1399 var extra_index = try reserveExtra(astgen, elements.len);
13821400
1383 for (elements) |elem_init, i| {1401 for (elements) |elem_init, i| {
1384 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{1402 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
1385 .ptr = result_ptr,1403 .ptr = result_ptr,
1386 .index = @intCast(u32, i),1404 .index = @intCast(u32, i),
1387 });1405 });
1388 elem_ptr_list[i] = refToIndex(elem_ptr).?;1406 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1407 extra_index += 1;
1389 _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);1408 _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);
1390 }1409 }
1391 _ = try gz.addPlNode(.validate_array_init, node, Zir.Inst.Block{1410 _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index);
1392 .body_len = @intCast(u32, elem_ptr_list.len),
1393 });
1394 try astgen.extra.appendSlice(gpa, elem_ptr_list);
1395 return .void_value;1411 return .void_value;
1396}1412}
13971413
...@@ -1505,30 +1521,25 @@ fn structInitExprRlNone(...@@ -1505,30 +1521,25 @@ fn structInitExprRlNone(
1505 tag: Zir.Inst.Tag,1521 tag: Zir.Inst.Tag,
1506) InnerError!Zir.Inst.Ref {1522) InnerError!Zir.Inst.Ref {
1507 const astgen = gz.astgen;1523 const astgen = gz.astgen;
1508 const gpa = astgen.gpa;
1509 const tree = astgen.tree;1524 const tree = astgen.tree;
15101525
1511 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);1526 const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{
1512 defer gpa.free(fields_list);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| {
1515 const name_token = tree.firstToken(field_init) - 2;1533 const name_token = tree.firstToken(field_init) - 2;
1516 const str_index = try astgen.identAsString(name_token);1534 const str_index = try astgen.identAsString(name_token);
15171535 setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
1518 fields_list[i] = .{
1519 .field_name = str_index,1536 .field_name = str_index,
1520 .init = try expr(gz, scope, .none, field_init),1537 .init = try expr(gz, scope, .none, field_init),
1521 };1538 });
1522 }1539 extra_index += field_size;
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);
1530 }1540 }
1531 return init_inst;1541
1542 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1532}1543}
15331544
1534fn structInitExprRlPtr(1545fn structInitExprRlPtr(
...@@ -1545,7 +1556,7 @@ fn structInitExprRlPtr(...@@ -1545,7 +1556,7 @@ fn structInitExprRlPtr(
1545 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1556 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
15461557
1547 var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr);1558 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
1550 const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);1561 const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr);
1551 return as_scope.finishCoercion(gz, rl, node, result, ty_inst);1562 return as_scope.finishCoercion(gz, rl, node, result, ty_inst);
...@@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner(...@@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner(
1559 result_ptr: Zir.Inst.Ref,1570 result_ptr: Zir.Inst.Ref,
1560) InnerError!Zir.Inst.Ref {1571) InnerError!Zir.Inst.Ref {
1561 const astgen = gz.astgen;1572 const astgen = gz.astgen;
1562 const gpa = astgen.gpa;
1563 const tree = astgen.tree;1573 const tree = astgen.tree;
15641574
1565 const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len);1575 const payload_index = try addExtra(astgen, Zir.Inst.Block{
1566 defer gpa.free(field_ptr_list);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| {
1569 const name_token = tree.firstToken(field_init) - 2;1581 const name_token = tree.firstToken(field_init) - 2;
1570 const str_index = try astgen.identAsString(name_token);1582 const str_index = try astgen.identAsString(name_token);
1571 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{1583 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{
1572 .lhs = result_ptr,1584 .lhs = result_ptr,
1573 .field_name_start = str_index,1585 .field_name_start = str_index,
1574 });1586 });
1575 field_ptr_list[i] = refToIndex(field_ptr).?;1587 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1588 extra_index += 1;
1576 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);1589 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
1577 }1590 }
1578 _ = try gz.addPlNode(.validate_struct_init, node, Zir.Inst.Block{1591
1579 .body_len = @intCast(u32, field_ptr_list.len),1592 _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index);
1580 });
1581 try astgen.extra.appendSlice(gpa, field_ptr_list);
1582 return Zir.Inst.Ref.void_value;1593 return Zir.Inst.Ref.void_value;
1583}1594}
15841595
...@@ -1591,34 +1602,29 @@ fn structInitExprRlTy(...@@ -1591,34 +1602,29 @@ fn structInitExprRlTy(
1591 tag: Zir.Inst.Tag,1602 tag: Zir.Inst.Tag,
1592) InnerError!Zir.Inst.Ref {1603) InnerError!Zir.Inst.Ref {
1593 const astgen = gz.astgen;1604 const astgen = gz.astgen;
1594 const gpa = astgen.gpa;
1595 const tree = astgen.tree;1605 const tree = astgen.tree;
15961606
1597 const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len);1607 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1598 defer gpa.free(fields_list);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| {
1601 const name_token = tree.firstToken(field_init) - 2;1614 const name_token = tree.firstToken(field_init) - 2;
1602 const str_index = try astgen.identAsString(name_token);1615 const str_index = try astgen.identAsString(name_token);
1603
1604 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{1616 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1605 .container_type = ty_inst,1617 .container_type = ty_inst,
1606 .name_start = str_index,1618 .name_start = str_index,
1607 });1619 });
1608 fields_list[i] = .{1620 setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{
1609 .field_type = refToIndex(field_ty_inst).?,1621 .field_type = refToIndex(field_ty_inst).?,
1610 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),1622 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
1611 };1623 });
1612 }1624 extra_index += field_size;
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);
1620 }1625 }
1621 return init_inst;1626
1627 return try gz.addPlNodePayloadIndex(tag, node, payload_index);
1622}1628}
16231629
1624/// This calls expr in a comptime scope, and is intended to be called as a helper function.1630/// This calls expr in a comptime scope, and is intended to be called as a helper function.
...@@ -1871,7 +1877,7 @@ fn labeledBlockExpr(...@@ -1871,7 +1877,7 @@ fn labeledBlockExpr(
18711877
1872 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct1878 // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
1873 // so that break statements can reference it.1879 // 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);
1875 try gz.instructions.append(astgen.gpa, block_inst);1881 try gz.instructions.append(astgen.gpa, block_inst);
18761882
1877 var block_scope = gz.makeSubBlock(parent_scope);1883 var block_scope = gz.makeSubBlock(parent_scope);
...@@ -1880,7 +1886,7 @@ fn labeledBlockExpr(...@@ -1880,7 +1886,7 @@ fn labeledBlockExpr(
1880 .block_inst = block_inst,1886 .block_inst = block_inst,
1881 };1887 };
1882 block_scope.setBreakResultLoc(rl);1888 block_scope.setBreakResultLoc(rl);
1883 defer block_scope.instructions.deinit(astgen.gpa);1889 defer block_scope.unstack();
1884 defer block_scope.labeled_breaks.deinit(astgen.gpa);1890 defer block_scope.labeled_breaks.deinit(astgen.gpa);
1885 defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);1891 defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
18861892
...@@ -2485,7 +2491,6 @@ fn varDecl(...@@ -2485,7 +2491,6 @@ fn varDecl(
2485) InnerError!*Scope {2491) InnerError!*Scope {
2486 try emitDbgNode(gz, node);2492 try emitDbgNode(gz, node);
2487 const astgen = gz.astgen;2493 const astgen = gz.astgen;
2488 const gpa = astgen.gpa;
2489 const tree = astgen.tree;2494 const tree = astgen.tree;
2490 const token_tags = tree.tokens.items(.tag);2495 const token_tags = tree.tokens.items(.tag);
2491 const main_tokens = tree.nodes.items(.main_token);2496 const main_tokens = tree.nodes.items(.main_token);
...@@ -2546,7 +2551,9 @@ fn varDecl(...@@ -2546,7 +2551,9 @@ fn varDecl(
2546 // Detect whether the initialization expression actually uses the2551 // Detect whether the initialization expression actually uses the
2547 // result location pointer.2552 // result location pointer.
2548 var init_scope = gz.makeSubBlock(scope);2553 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
2551 var resolve_inferred_alloc: Zir.Inst.Ref = .none;2558 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
2552 var opt_type_inst: Zir.Inst.Ref = .none;2559 var opt_type_inst: Zir.Inst.Ref = .none;
...@@ -2554,6 +2561,7 @@ fn varDecl(...@@ -2554,6 +2561,7 @@ fn varDecl(
2554 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);2561 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);
2555 opt_type_inst = type_inst;2562 opt_type_inst = type_inst;
2556 if (align_inst == .none) {2563 if (align_inst == .none) {
2564 init_scope.instructions_top = gz.instructions.items.len;
2557 init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node);2565 init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node);
2558 } else {2566 } else {
2559 init_scope.rl_ptr = try gz.addAllocExtended(.{2567 init_scope.rl_ptr = try gz.addAllocExtended(.{
...@@ -2563,19 +2571,24 @@ fn varDecl(...@@ -2563,19 +2571,24 @@ fn varDecl(
2563 .is_const = true,2571 .is_const = true,
2564 .is_comptime = false,2572 .is_comptime = false,
2565 });2573 });
2574 init_scope.instructions_top = gz.instructions.items.len;
2566 }2575 }
2567 init_scope.rl_ty_inst = type_inst;2576 init_scope.rl_ty_inst = type_inst;
2568 } else {2577 } else {
2569 const alloc = if (align_inst == .none)2578 const alloc = if (align_inst == .none) alloc: {
2570 try init_scope.addNode(.alloc_inferred, node)2579 init_scope.instructions_top = gz.instructions.items.len;
2571 else2580 break :alloc try init_scope.addNode(.alloc_inferred, node);
2572 try gz.addAllocExtended(.{2581 } else alloc: {
2582 const ref = try gz.addAllocExtended(.{
2573 .node = node,2583 .node = node,
2574 .type_inst = .none,2584 .type_inst = .none,
2575 .align_inst = align_inst,2585 .align_inst = align_inst,
2576 .is_const = true,2586 .is_const = true,
2577 .is_comptime = false,2587 .is_comptime = false,
2578 });2588 });
2589 init_scope.instructions_top = gz.instructions.items.len;
2590 break :alloc ref;
2591 };
2579 resolve_inferred_alloc = alloc;2592 resolve_inferred_alloc = alloc;
2580 init_scope.rl_ptr = alloc;2593 init_scope.rl_ptr = alloc;
2581 }2594 }
...@@ -2585,20 +2598,24 @@ fn varDecl(...@@ -2585,20 +2598,24 @@ fn varDecl(
2585 const zir_tags = astgen.instructions.items(.tag);2598 const zir_tags = astgen.instructions.items(.tag);
2586 const zir_datas = astgen.instructions.items(.data);2599 const zir_datas = astgen.instructions.items(.data);
25872600
2588 const parent_zir = &gz.instructions;
2589 if (align_inst == .none and init_scope.rvalue_rl_count == 1) {2601 if (align_inst == .none and init_scope.rvalue_rl_count == 1) {
2590 // Result location pointer not used. We don't need an alloc for this2602 // Result location pointer not used. We don't need an alloc for this
2591 // const local, and type inference becomes trivial.2603 // const local, and type inference becomes trivial.
2592 // Move the init_scope instructions into the parent scope, eliding2604 // Implicitly move the init_scope instructions into the parent scope,
2593 // the alloc instruction and the store_to_block_ptr instruction.2605 // then elide the alloc instruction and the store_to_block_ptr instruction.
2594 try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len);2606 var src = init_scope.instructions_top;
2595 for (init_scope.instructions.items) |src_inst| {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];
2596 if (indexToRef(src_inst) == init_scope.rl_ptr) continue;2611 if (indexToRef(src_inst) == init_scope.rl_ptr) continue;
2597 if (zir_tags[src_inst] == .store_to_block_ptr) {2612 if (zir_tags[src_inst] == .store_to_block_ptr) {
2598 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;2613 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;
2599 }2614 }
2600 parent_zir.appendAssumeCapacity(src_inst);2615 gz.instructions.items[dst] = src_inst;
2616 dst += 1;
2601 }2617 }
2618 gz.instructions.items.len = dst;
26022619
2603 const sub_scope = try block_arena.create(Scope.LocalVal);2620 const sub_scope = try block_arena.create(Scope.LocalVal);
2604 sub_scope.* = .{2621 sub_scope.* = .{
...@@ -2613,11 +2630,13 @@ fn varDecl(...@@ -2613,11 +2630,13 @@ fn varDecl(
2613 }2630 }
2614 // The initialization expression took advantage of the result location2631 // The initialization expression took advantage of the result location
2615 // of the const local. In this case we will create an alloc and a LocalPtr for it.2632 // 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, swapping2633 // Implicitly move the init_scope instructions into the parent scope, then swap
2617 // store_to_block_ptr for store_to_inferred_ptr.2634 // store_to_block_ptr for store_to_inferred_ptr.
2618 const expected_len = parent_zir.items.len + init_scope.instructions.items.len;2635
2619 try parent_zir.ensureTotalCapacity(gpa, expected_len);2636 var src = init_scope.instructions_top;
2620 for (init_scope.instructions.items) |src_inst| {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];
2621 if (zir_tags[src_inst] == .store_to_block_ptr) {2640 if (zir_tags[src_inst] == .store_to_block_ptr) {
2622 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {2641 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
2623 if (var_decl.ast.type_node != 0) {2642 if (var_decl.ast.type_node != 0) {
...@@ -2627,9 +2646,7 @@ fn varDecl(...@@ -2627,9 +2646,7 @@ fn varDecl(
2627 }2646 }
2628 }2647 }
2629 }2648 }
2630 parent_zir.appendAssumeCapacity(src_inst);
2631 }2649 }
2632 assert(parent_zir.items.len == expected_len);
2633 if (resolve_inferred_alloc != .none) {2650 if (resolve_inferred_alloc != .none) {
2634 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);2651 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
2635 }2652 }
...@@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I...@@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
2994 return rvalue(gz, rl, result, node);3011 return rvalue(gz, rl, result, node);
2995}3012}
29963013
2997const WipDecls = struct {3014const WipMembers = struct {
2998 decl_index: usize = 0,3015 payload: *ArrayListUnmanaged(u32),
2999 cur_bit_bag: u32 = 0,3016 payload_top: usize,
3000 bit_bag: ArrayListUnmanaged(u32) = .{},3017 decls_start: u32,
3001 payload: ArrayListUnmanaged(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;3054 pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {
3004 const fields_per_u32 = 32 / bits_per_field;3055 const index = self.payload_top + self.decl_index / decls_per_u32;
30053056 assert(index < self.decls_start);
3006 fn next(3057 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index];
3007 wip_decls: *WipDecls,3058 self.payload.items[index] = (bit_bag >> bits_per_decl) |
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) |
3019 (@as(u32, @boolToInt(is_pub)) << 28) |3059 (@as(u32, @boolToInt(is_pub)) << 28) |
3020 (@as(u32, @boolToInt(is_export)) << 29) |3060 (@as(u32, @boolToInt(is_export)) << 29) |
3021 (@as(u32, @boolToInt(has_align)) << 30) |3061 (@as(u32, @boolToInt(has_align)) << 30) |
3022 (@as(u32, @boolToInt(has_section_or_addrspace)) << 31);3062 (@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];
3024 }3120 }
30253121
3026 fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void {3122 pub fn deinit(self: *Self) void {
3027 wip_decls.bit_bag.deinit(gpa);3123 self.payload.items.len = self.payload_top;
3028 wip_decls.payload.deinit(gpa);
3029 }3124 }
3030};3125};
30313126
...@@ -3033,12 +3128,11 @@ fn fnDecl(...@@ -3033,12 +3128,11 @@ fn fnDecl(
3033 astgen: *AstGen,3128 astgen: *AstGen,
3034 gz: *GenZir,3129 gz: *GenZir,
3035 scope: *Scope,3130 scope: *Scope,
3036 wip_decls: *WipDecls,3131 wip_members: *WipMembers,
3037 decl_node: Ast.Node.Index,3132 decl_node: Ast.Node.Index,
3038 body_node: Ast.Node.Index,3133 body_node: Ast.Node.Index,
3039 fn_proto: Ast.full.FnProto,3134 fn_proto: Ast.full.FnProto,
3040) InnerError!void {3135) InnerError!void {
3041 const gpa = astgen.gpa;
3042 const tree = astgen.tree;3136 const tree = astgen.tree;
3043 const token_tags = tree.tokens.items(.tag);3137 const token_tags = tree.tokens.items(.tag);
30443138
...@@ -3048,7 +3142,7 @@ fn fnDecl(...@@ -3048,7 +3142,7 @@ fn fnDecl(
30483142
3049 // We insert this at the beginning so that its instruction index marks the3143 // We insert this at the beginning so that its instruction index marks the
3050 // start of the top level declaration.3144 // 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
3053 var decl_gz: GenZir = .{3147 var decl_gz: GenZir = .{
3054 .force_comptime = true,3148 .force_comptime = true,
...@@ -3057,8 +3151,10 @@ fn fnDecl(...@@ -3057,8 +3151,10 @@ fn fnDecl(
3057 .decl_line = gz.calcLine(decl_node),3151 .decl_line = gz.calcLine(decl_node),
3058 .parent = scope,3152 .parent = scope,
3059 .astgen = astgen,3153 .astgen = astgen,
3154 .instructions = gz.instructions,
3155 .instructions_top = gz.instructions.items.len,
3060 };3156 };
3061 defer decl_gz.instructions.deinit(gpa);3157 defer decl_gz.unstack();
30623158
3063 var fn_gz: GenZir = .{3159 var fn_gz: GenZir = .{
3064 .force_comptime = false,3160 .force_comptime = false,
...@@ -3067,8 +3163,10 @@ fn fnDecl(...@@ -3067,8 +3163,10 @@ fn fnDecl(
3067 .decl_line = decl_gz.decl_line,3163 .decl_line = decl_gz.decl_line,
3068 .parent = &decl_gz.base,3164 .parent = &decl_gz.base,
3069 .astgen = astgen,3165 .astgen = astgen,
3166 .instructions = gz.instructions,
3167 .instructions_top = GenZir.unstacked_top,
3070 };3168 };
3071 defer fn_gz.instructions.deinit(gpa);3169 defer fn_gz.unstack();
30723170
3073 // TODO: support noinline3171 // TODO: support noinline
3074 const is_pub = fn_proto.visib_token != null;3172 const is_pub = fn_proto.visib_token != null;
...@@ -3085,7 +3183,7 @@ fn fnDecl(...@@ -3085,7 +3183,7 @@ fn fnDecl(
3085 break :blk token_tags[maybe_inline_token] == .keyword_inline;3183 break :blk token_tags[maybe_inline_token] == .keyword_inline;
3086 };3184 };
3087 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;3185 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
3090 var params_scope = &fn_gz.base;3188 var params_scope = &fn_gz.base;
3091 const is_var_args = is_var_args: {3189 const is_var_args = is_var_args: {
...@@ -3134,7 +3232,7 @@ fn fnDecl(...@@ -3134,7 +3232,7 @@ fn fnDecl(
3134 const param_type_node = param.type_expr;3232 const param_type_node = param.type_expr;
3135 assert(param_type_node != 0);3233 assert(param_type_node != 0);
3136 var param_gz = decl_gz.makeSubBlock(scope);3234 var param_gz = decl_gz.makeSubBlock(scope);
3137 defer param_gz.instructions.deinit(gpa);3235 defer param_gz.unstack();
3138 const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node);3236 const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node);
3139 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);3237 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
3140 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);3238 _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type);
...@@ -3142,7 +3240,7 @@ fn fnDecl(...@@ -3142,7 +3240,7 @@ fn fnDecl(
3142 const main_tokens = tree.nodes.items(.main_token);3240 const main_tokens = tree.nodes.items(.main_token);
3143 const name_token = param.name_token orelse main_tokens[param_type_node];3241 const name_token = param.name_token orelse main_tokens[param_type_node];
3144 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;3242 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);
3146 assert(param_inst_expected == param_inst);3244 assert(param_inst_expected == param_inst);
3147 break :param indexToRef(param_inst);3245 break :param indexToRef(param_inst);
3148 };3246 };
...@@ -3207,7 +3305,7 @@ fn fnDecl(...@@ -3207,7 +3305,7 @@ fn fnDecl(
3207 };3305 };
32083306
3209 var ret_gz = decl_gz.makeSubBlock(params_scope);3307 var ret_gz = decl_gz.makeSubBlock(params_scope);
3210 defer ret_gz.instructions.deinit(gpa);3308 defer ret_gz.unstack();
3211 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);3309 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3212 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);3310 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
32133311
...@@ -3220,10 +3318,10 @@ fn fnDecl(...@@ -3220,10 +3318,10 @@ fn fnDecl(
3220 }3318 }
3221 break :func try decl_gz.addFunc(.{3319 break :func try decl_gz.addFunc(.{
3222 .src_node = decl_node,3320 .src_node = decl_node,
3223 .ret_ty = ret_gz.instructions.items,3321 .ret_gz = &ret_gz,
3224 .ret_br = ret_br,3322 .ret_br = ret_br,
3225 .param_block = block_inst,3323 .param_block = block_inst,
3226 .body = &[0]Zir.Inst.Index{},3324 .body_gz = null,
3227 .cc = cc,3325 .cc = cc,
3228 .align_inst = .none, // passed in the per-decl data3326 .align_inst = .none, // passed in the per-decl data
3229 .lib_name = lib_name,3327 .lib_name = lib_name,
...@@ -3237,6 +3335,9 @@ fn fnDecl(...@@ -3237,6 +3335,9 @@ fn fnDecl(
3237 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});3335 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
3238 }3336 }
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
3240 const prev_fn_block = astgen.fn_block;3341 const prev_fn_block = astgen.fn_block;
3241 astgen.fn_block = &fn_gz;3342 astgen.fn_block = &fn_gz;
3242 defer astgen.fn_block = prev_fn_block;3343 defer astgen.fn_block = prev_fn_block;
...@@ -3250,14 +3351,7 @@ fn fnDecl(...@@ -3250,14 +3351,7 @@ fn fnDecl(
3250 _ = try expr(&fn_gz, params_scope, .none, body_node);3351 _ = try expr(&fn_gz, params_scope, .none, body_node);
3251 try checkUsed(gz, &fn_gz.base, params_scope);3352 try checkUsed(gz, &fn_gz.base, params_scope);
32523353
3253 const need_implicit_ret = blk: {3354 if (!fn_gz.endsWithNoReturn()) {
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) {
3261 // Since we are adding the return instruction here, we must handle the coercion.3355 // Since we are adding the return instruction here, we must handle the coercion.
3262 // We do this by using the `ret_coerce` instruction.3356 // We do this by using the `ret_coerce` instruction.
3263 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));3357 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
...@@ -3268,9 +3362,9 @@ fn fnDecl(...@@ -3268,9 +3362,9 @@ fn fnDecl(
3268 .lbrace_line = lbrace_line,3362 .lbrace_line = lbrace_line,
3269 .lbrace_column = lbrace_column,3363 .lbrace_column = lbrace_column,
3270 .param_block = block_inst,3364 .param_block = block_inst,
3271 .ret_ty = ret_gz.instructions.items,3365 .ret_gz = &ret_gz,
3272 .ret_br = ret_br,3366 .ret_br = ret_br,
3273 .body = fn_gz.instructions.items,3367 .body_gz = &fn_gz,
3274 .cc = cc,3368 .cc = cc,
3275 .align_inst = .none, // passed in the per-decl data3369 .align_inst = .none, // passed in the per-decl data
3276 .lib_name = lib_name,3370 .lib_name = lib_name,
...@@ -3282,29 +3376,27 @@ fn fnDecl(...@@ -3282,29 +3376,27 @@ fn fnDecl(
3282 };3376 };
32833377
3284 // We add this at the end so that its instruction index marks the end range3378 // 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.
3286 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);3380 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
3287 try decl_gz.setBlockBody(block_inst);3381 try decl_gz.setBlockBody(block_inst);
32883382
3289 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
3290 {3383 {
3291 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));3384 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
3292 const casted = @bitCast([4]u32, contents_hash);3385 const casted = @bitCast([4]u32, contents_hash);
3293 wip_decls.payload.appendSliceAssumeCapacity(&casted);3386 wip_members.appendToDeclSlice(&casted);
3294 }3387 }
3295 {3388 {
3296 const line_delta = decl_gz.decl_line - gz.decl_line;3389 const line_delta = decl_gz.decl_line - gz.decl_line;
3297 wip_decls.payload.appendAssumeCapacity(line_delta);3390 wip_members.appendToDecl(line_delta);
3298 }3391 }
3299 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);3392 wip_members.appendToDecl(fn_name_str_index);
3300 wip_decls.payload.appendAssumeCapacity(block_inst);3393 wip_members.appendToDecl(block_inst);
3301 if (align_inst != .none) {3394 if (align_inst != .none) {
3302 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));3395 wip_members.appendToDecl(@enumToInt(align_inst));
3303 }3396 }
3304
3305 if (has_section_or_addrspace) {3397 if (has_section_or_addrspace) {
3306 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));3398 wip_members.appendToDecl(@enumToInt(section_inst));
3307 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));3399 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3308 }3400 }
3309}3401}
33103402
...@@ -3312,18 +3404,17 @@ fn globalVarDecl(...@@ -3312,18 +3404,17 @@ fn globalVarDecl(
3312 astgen: *AstGen,3404 astgen: *AstGen,
3313 gz: *GenZir,3405 gz: *GenZir,
3314 scope: *Scope,3406 scope: *Scope,
3315 wip_decls: *WipDecls,3407 wip_members: *WipMembers,
3316 node: Ast.Node.Index,3408 node: Ast.Node.Index,
3317 var_decl: Ast.full.VarDecl,3409 var_decl: Ast.full.VarDecl,
3318) InnerError!void {3410) InnerError!void {
3319 const gpa = astgen.gpa;
3320 const tree = astgen.tree;3411 const tree = astgen.tree;
3321 const token_tags = tree.tokens.items(.tag);3412 const token_tags = tree.tokens.items(.tag);
33223413
3323 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;3414 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
3324 // We do this at the beginning so that the instruction index marks the range start3415 // We do this at the beginning so that the instruction index marks the range start
3325 // of the top level declaration.3416 // 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
3328 const name_token = var_decl.ast.mut_token + 1;3419 const name_token = var_decl.ast.mut_token + 1;
3329 const name_str_index = try astgen.identAsString(name_token);3420 const name_str_index = try astgen.identAsString(name_token);
...@@ -3336,8 +3427,10 @@ fn globalVarDecl(...@@ -3336,8 +3427,10 @@ fn globalVarDecl(
3336 .force_comptime = true,3427 .force_comptime = true,
3337 .in_defer = false,3428 .in_defer = false,
3338 .anon_name_strategy = .parent,3429 .anon_name_strategy = .parent,
3430 .instructions = gz.instructions,
3431 .instructions_top = gz.instructions.items.len,
3339 };3432 };
3340 defer block_scope.instructions.deinit(gpa);3433 defer block_scope.unstack();
33413434
3342 const is_pub = var_decl.visib_token != null;3435 const is_pub = var_decl.visib_token != null;
3343 const is_export = blk: {3436 const is_export = blk: {
...@@ -3358,7 +3451,7 @@ fn globalVarDecl(...@@ -3358,7 +3451,7 @@ fn globalVarDecl(
3358 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);3451 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
3359 };3452 };
3360 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;3453 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
3363 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {3456 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
3364 if (!is_mutable) {3457 if (!is_mutable) {
...@@ -3436,24 +3529,23 @@ fn globalVarDecl(...@@ -3436,24 +3529,23 @@ fn globalVarDecl(
3436 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);3529 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
3437 try block_scope.setBlockBody(block_inst);3530 try block_scope.setBlockBody(block_inst);
34383531
3439 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
3440 {3532 {
3441 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3533 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3442 const casted = @bitCast([4]u32, contents_hash);3534 const casted = @bitCast([4]u32, contents_hash);
3443 wip_decls.payload.appendSliceAssumeCapacity(&casted);3535 wip_members.appendToDeclSlice(&casted);
3444 }3536 }
3445 {3537 {
3446 const line_delta = block_scope.decl_line - gz.decl_line;3538 const line_delta = block_scope.decl_line - gz.decl_line;
3447 wip_decls.payload.appendAssumeCapacity(line_delta);3539 wip_members.appendToDecl(line_delta);
3448 }3540 }
3449 wip_decls.payload.appendAssumeCapacity(name_str_index);3541 wip_members.appendToDecl(name_str_index);
3450 wip_decls.payload.appendAssumeCapacity(block_inst);3542 wip_members.appendToDecl(block_inst);
3451 if (align_inst != .none) {3543 if (align_inst != .none) {
3452 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));3544 wip_members.appendToDecl(@enumToInt(align_inst));
3453 }3545 }
3454 if (has_section_or_addrspace) {3546 if (has_section_or_addrspace) {
3455 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));3547 wip_members.appendToDecl(@enumToInt(section_inst));
3456 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));3548 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3457 }3549 }
3458}3550}
34593551
...@@ -3461,18 +3553,17 @@ fn comptimeDecl(...@@ -3461,18 +3553,17 @@ fn comptimeDecl(
3461 astgen: *AstGen,3553 astgen: *AstGen,
3462 gz: *GenZir,3554 gz: *GenZir,
3463 scope: *Scope,3555 scope: *Scope,
3464 wip_decls: *WipDecls,3556 wip_members: *WipMembers,
3465 node: Ast.Node.Index,3557 node: Ast.Node.Index,
3466) InnerError!void {3558) InnerError!void {
3467 const gpa = astgen.gpa;
3468 const tree = astgen.tree;3559 const tree = astgen.tree;
3469 const node_datas = tree.nodes.items(.data);3560 const node_datas = tree.nodes.items(.data);
3470 const body_node = node_datas[node].lhs;3561 const body_node = node_datas[node].lhs;
34713562
3472 // Up top so the ZIR instruction index marks the start range of this3563 // Up top so the ZIR instruction index marks the start range of this
3473 // top-level declaration.3564 // top-level declaration.
3474 const block_inst = try gz.addBlock(.block_inline, node);3565 const block_inst = try gz.makeBlockInst(.block_inline, node);
3475 try wip_decls.next(gpa, false, false, false, false);3566 wip_members.nextDecl(false, false, false, false);
34763567
3477 var decl_block: GenZir = .{3568 var decl_block: GenZir = .{
3478 .force_comptime = true,3569 .force_comptime = true,
...@@ -3481,37 +3572,37 @@ fn comptimeDecl(...@@ -3481,37 +3572,37 @@ fn comptimeDecl(
3481 .decl_line = gz.calcLine(node),3572 .decl_line = gz.calcLine(node),
3482 .parent = scope,3573 .parent = scope,
3483 .astgen = astgen,3574 .astgen = astgen,
3575 .instructions = gz.instructions,
3576 .instructions_top = gz.instructions.items.len,
3484 };3577 };
3485 defer decl_block.instructions.deinit(gpa);3578 defer decl_block.unstack();
34863579
3487 const block_result = try expr(&decl_block, &decl_block.base, .none, body_node);3580 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)) {
3489 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);3582 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);
3490 }3583 }
3491 try decl_block.setBlockBody(block_inst);3584 try decl_block.setBlockBody(block_inst);
34923585
3493 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3494 {3586 {
3495 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3587 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3496 const casted = @bitCast([4]u32, contents_hash);3588 const casted = @bitCast([4]u32, contents_hash);
3497 wip_decls.payload.appendSliceAssumeCapacity(&casted);3589 wip_members.appendToDeclSlice(&casted);
3498 }3590 }
3499 {3591 {
3500 const line_delta = decl_block.decl_line - gz.decl_line;3592 const line_delta = decl_block.decl_line - gz.decl_line;
3501 wip_decls.payload.appendAssumeCapacity(line_delta);3593 wip_members.appendToDecl(line_delta);
3502 }3594 }
3503 wip_decls.payload.appendAssumeCapacity(0);3595 wip_members.appendToDecl(0);
3504 wip_decls.payload.appendAssumeCapacity(block_inst);3596 wip_members.appendToDecl(block_inst);
3505}3597}
35063598
3507fn usingnamespaceDecl(3599fn usingnamespaceDecl(
3508 astgen: *AstGen,3600 astgen: *AstGen,
3509 gz: *GenZir,3601 gz: *GenZir,
3510 scope: *Scope,3602 scope: *Scope,
3511 wip_decls: *WipDecls,3603 wip_members: *WipMembers,
3512 node: Ast.Node.Index,3604 node: Ast.Node.Index,
3513) InnerError!void {3605) InnerError!void {
3514 const gpa = astgen.gpa;
3515 const tree = astgen.tree;3606 const tree = astgen.tree;
3516 const node_datas = tree.nodes.items(.data);3607 const node_datas = tree.nodes.items(.data);
35173608
...@@ -3524,8 +3615,8 @@ fn usingnamespaceDecl(...@@ -3524,8 +3615,8 @@ fn usingnamespaceDecl(
3524 };3615 };
3525 // Up top so the ZIR instruction index marks the start range of this3616 // Up top so the ZIR instruction index marks the start range of this
3526 // top-level declaration.3617 // top-level declaration.
3527 const block_inst = try gz.addBlock(.block_inline, node);3618 const block_inst = try gz.makeBlockInst(.block_inline, node);
3528 try wip_decls.next(gpa, is_pub, true, false, false);3619 wip_members.nextDecl(is_pub, true, false, false);
35293620
3530 var decl_block: GenZir = .{3621 var decl_block: GenZir = .{
3531 .force_comptime = true,3622 .force_comptime = true,
...@@ -3534,44 +3625,44 @@ fn usingnamespaceDecl(...@@ -3534,44 +3625,44 @@ fn usingnamespaceDecl(
3534 .decl_line = gz.calcLine(node),3625 .decl_line = gz.calcLine(node),
3535 .parent = scope,3626 .parent = scope,
3536 .astgen = astgen,3627 .astgen = astgen,
3628 .instructions = gz.instructions,
3629 .instructions_top = gz.instructions.items.len,
3537 };3630 };
3538 defer decl_block.instructions.deinit(gpa);3631 defer decl_block.unstack();
35393632
3540 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);3633 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
3541 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);3634 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
3542 try decl_block.setBlockBody(block_inst);3635 try decl_block.setBlockBody(block_inst);
35433636
3544 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3545 {3637 {
3546 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3638 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3547 const casted = @bitCast([4]u32, contents_hash);3639 const casted = @bitCast([4]u32, contents_hash);
3548 wip_decls.payload.appendSliceAssumeCapacity(&casted);3640 wip_members.appendToDeclSlice(&casted);
3549 }3641 }
3550 {3642 {
3551 const line_delta = decl_block.decl_line - gz.decl_line;3643 const line_delta = decl_block.decl_line - gz.decl_line;
3552 wip_decls.payload.appendAssumeCapacity(line_delta);3644 wip_members.appendToDecl(line_delta);
3553 }3645 }
3554 wip_decls.payload.appendAssumeCapacity(0);3646 wip_members.appendToDecl(0);
3555 wip_decls.payload.appendAssumeCapacity(block_inst);3647 wip_members.appendToDecl(block_inst);
3556}3648}
35573649
3558fn testDecl(3650fn testDecl(
3559 astgen: *AstGen,3651 astgen: *AstGen,
3560 gz: *GenZir,3652 gz: *GenZir,
3561 scope: *Scope,3653 scope: *Scope,
3562 wip_decls: *WipDecls,3654 wip_members: *WipMembers,
3563 node: Ast.Node.Index,3655 node: Ast.Node.Index,
3564) InnerError!void {3656) InnerError!void {
3565 const gpa = astgen.gpa;
3566 const tree = astgen.tree;3657 const tree = astgen.tree;
3567 const node_datas = tree.nodes.items(.data);3658 const node_datas = tree.nodes.items(.data);
3568 const body_node = node_datas[node].rhs;3659 const body_node = node_datas[node].rhs;
35693660
3570 // Up top so the ZIR instruction index marks the start range of this3661 // Up top so the ZIR instruction index marks the start range of this
3571 // top-level declaration.3662 // 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
3576 var decl_block: GenZir = .{3667 var decl_block: GenZir = .{
3577 .force_comptime = true,3668 .force_comptime = true,
...@@ -3580,8 +3671,10 @@ fn testDecl(...@@ -3580,8 +3671,10 @@ fn testDecl(
3580 .decl_line = gz.calcLine(node),3671 .decl_line = gz.calcLine(node),
3581 .parent = scope,3672 .parent = scope,
3582 .astgen = astgen,3673 .astgen = astgen,
3674 .instructions = gz.instructions,
3675 .instructions_top = gz.instructions.items.len,
3583 };3676 };
3584 defer decl_block.instructions.deinit(gpa);3677 defer decl_block.unstack();
35853678
3586 const test_name: u32 = blk: {3679 const test_name: u32 = blk: {
3587 const main_tokens = tree.nodes.items(.main_token);3680 const main_tokens = tree.nodes.items(.main_token);
...@@ -3602,8 +3695,10 @@ fn testDecl(...@@ -3602,8 +3695,10 @@ fn testDecl(
3602 .decl_line = decl_block.decl_line,3695 .decl_line = decl_block.decl_line,
3603 .parent = &decl_block.base,3696 .parent = &decl_block.base,
3604 .astgen = astgen,3697 .astgen = astgen,
3698 .instructions = decl_block.instructions,
3699 .instructions_top = decl_block.instructions.items.len,
3605 };3700 };
3606 defer fn_block.instructions.deinit(gpa);3701 defer fn_block.unstack();
36073702
3608 const prev_fn_block = astgen.fn_block;3703 const prev_fn_block = astgen.fn_block;
3609 astgen.fn_block = &fn_block;3704 astgen.fn_block = &fn_block;
...@@ -3616,7 +3711,7 @@ fn testDecl(...@@ -3616,7 +3711,7 @@ fn testDecl(
3616 const lbrace_column = @intCast(u32, astgen.source_column);3711 const lbrace_column = @intCast(u32, astgen.source_column);
36173712
3618 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);3713 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)) {
3620 // Since we are adding the return instruction here, we must handle the coercion.3715 // Since we are adding the return instruction here, we must handle the coercion.
3621 // We do this by using the `ret_coerce` instruction.3716 // We do this by using the `ret_coerce` instruction.
3622 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));3717 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
...@@ -3627,9 +3722,9 @@ fn testDecl(...@@ -3627,9 +3722,9 @@ fn testDecl(
3627 .lbrace_line = lbrace_line,3722 .lbrace_line = lbrace_line,
3628 .lbrace_column = lbrace_column,3723 .lbrace_column = lbrace_column,
3629 .param_block = block_inst,3724 .param_block = block_inst,
3630 .ret_ty = &.{},3725 .ret_gz = null,
3631 .ret_br = 0,3726 .ret_br = 0,
3632 .body = fn_block.instructions.items,3727 .body_gz = &fn_block,
3633 .cc = .none,3728 .cc = .none,
3634 .align_inst = .none,3729 .align_inst = .none,
3635 .lib_name = 0,3730 .lib_name = 0,
...@@ -3642,18 +3737,17 @@ fn testDecl(...@@ -3642,18 +3737,17 @@ fn testDecl(
3642 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);3737 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
3643 try decl_block.setBlockBody(block_inst);3738 try decl_block.setBlockBody(block_inst);
36443739
3645 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3646 {3740 {
3647 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3741 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3648 const casted = @bitCast([4]u32, contents_hash);3742 const casted = @bitCast([4]u32, contents_hash);
3649 wip_decls.payload.appendSliceAssumeCapacity(&casted);3743 wip_members.appendToDeclSlice(&casted);
3650 }3744 }
3651 {3745 {
3652 const line_delta = decl_block.decl_line - gz.decl_line;3746 const line_delta = decl_block.decl_line - gz.decl_line;
3653 wip_decls.payload.appendAssumeCapacity(line_delta);3747 wip_members.appendToDecl(line_delta);
3654 }3748 }
3655 wip_decls.payload.appendAssumeCapacity(test_name);3749 wip_members.appendToDecl(test_name);
3656 wip_decls.payload.appendAssumeCapacity(block_inst);3750 wip_members.appendToDecl(block_inst);
3657}3751}
36583752
3659fn structDeclInner(3753fn structDeclInner(
...@@ -3681,7 +3775,6 @@ fn structDeclInner(...@@ -3681,7 +3775,6 @@ fn structDeclInner(
3681 const gpa = astgen.gpa;3775 const gpa = astgen.gpa;
3682 const tree = astgen.tree;3776 const tree = astgen.tree;
3683 const node_tags = tree.nodes.items(.tag);3777 const node_tags = tree.nodes.items(.tag);
3684 const node_datas = tree.nodes.items(.data);
36853778
3686 var namespace: Scope.Namespace = .{3779 var namespace: Scope.Namespace = .{
3687 .parent = scope,3780 .parent = scope,
...@@ -3701,162 +3794,28 @@ fn structDeclInner(...@@ -3701,162 +3794,28 @@ fn structDeclInner(
3701 .astgen = astgen,3794 .astgen = astgen,
3702 .force_comptime = true,3795 .force_comptime = true,
3703 .in_defer = false,3796 .in_defer = false,
3797 .instructions = gz.instructions,
3798 .instructions_top = gz.instructions.items.len,
3704 };3799 };
3705 defer block_scope.instructions.deinit(gpa);3800 defer block_scope.unstack();
3706
3707 try astgen.scanDecls(&namespace, container_decl.ast.members);
3708
3709 var wip_decls: WipDecls = .{};
3710 defer wip_decls.deinit(gpa);
37113801
3712 // We don't know which members are fields until we iterate, so cannot do3802 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
3713 // an accurate ensureTotalCapacity yet.3803 const field_count = @intCast(u32, container_decl.ast.members.len - decl_count);
3714 var fields_data = ArrayListUnmanaged(u32){};
3715 defer fields_data.deinit(gpa);
37163804
3717 const bits_per_field = 4;3805 const bits_per_field = 4;
3718 const fields_per_u32 = 32 / bits_per_field;3806 const max_field_size = 4;
3719 // We only need this if there are greater than fields_per_u32 fields.3807 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3720 var bit_bag = ArrayListUnmanaged(u32){};3808 defer wip_members.deinit();
3721 defer bit_bag.deinit(gpa);
37223809
3723 var known_has_bits = false;3810 var known_has_bits = false;
3724 var cur_bit_bag: u32 = 0;
3725 var field_index: usize = 0;
3726 for (container_decl.ast.members) |member_node| {3811 for (container_decl.ast.members) |member_node| {
3727 const member = switch (node_tags[member_node]) {3812 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
3728 .container_field_init => tree.containerFieldInit(member_node),3813 .decl => continue,
3729 .container_field_align => tree.containerFieldAlign(member_node),3814 .field => |field| field,
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,
3851 };3815 };
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
3858 const field_name = try astgen.identAsString(member.ast.name_token);3817 const field_name = try astgen.identAsString(member.ast.name_token);
3859 fields_data.appendAssumeCapacity(field_name);3818 wip_members.appendToField(field_name);
38603819
3861 if (member.ast.type_expr == 0) {3820 if (member.ast.type_expr == 0) {
3862 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});3821 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
...@@ -3866,7 +3825,7 @@ fn structDeclInner(...@@ -3866,7 +3825,7 @@ fn structDeclInner(
3866 .none3825 .none
3867 else3826 else
3868 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);3827 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
3871 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);3830 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
38723831
...@@ -3874,79 +3833,47 @@ fn structDeclInner(...@@ -3874,79 +3833,47 @@ fn structDeclInner(
3874 const have_value = member.ast.value_expr != 0;3833 const have_value = member.ast.value_expr != 0;
3875 const is_comptime = member.comptime_token != null;3834 const is_comptime = member.comptime_token != null;
3876 const unused = false;3835 const unused = false;
3877 cur_bit_bag = (cur_bit_bag >> bits_per_field) |3836 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused });
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);
38823837
3883 if (have_align) {3838 if (have_align) {
3884 const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);3839 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));
3886 }3841 }
3887 if (have_value) {3842 if (have_value) {
3888 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };3843 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
38893844
3890 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);3845 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));
3892 } else if (member.comptime_token) |comptime_token| {3847 } else if (member.comptime_token) |comptime_token| {
3893 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});3848 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
3894 }3849 }
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 }
3909 }3850 }
39103851
3911 if (block_scope.instructions.items.len != 0) {3852 if (!block_scope.isEmpty()) {
3912 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);3853 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
3913 }3854 }
39143855
3856 const body = block_scope.instructionsSlice();
3857
3915 try gz.setStruct(decl_inst, .{3858 try gz.setStruct(decl_inst, .{
3916 .src_node = node,3859 .src_node = node,
3917 .layout = layout,3860 .layout = layout,
3918 .body_len = @intCast(u32, block_scope.instructions.items.len),3861 .body_len = @intCast(u32, body.len),
3919 .fields_len = @intCast(u32, field_index),3862 .fields_len = field_count,
3920 .decls_len = @intCast(u32, wip_decls.decl_index),3863 .decls_len = decl_count,
3921 .known_has_bits = known_has_bits,3864 .known_has_bits = known_has_bits,
3922 });3865 });
39233866
3924 // zig fmt: off3867 wip_members.finishBits(bits_per_field);
3925 try astgen.extra.ensureUnusedCapacity(gpa,3868 const decls_slice = wip_members.declsSlice();
3926 bit_bag.items.len +3869 const fields_slice = wip_members.fieldsSlice();
3927 @boolToInt(wip_decls.decl_index != 0) +3870 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
3928 wip_decls.payload.items.len +3871 astgen.extra.appendSliceAssumeCapacity(decls_slice);
3929 block_scope.instructions.items.len +3872 astgen.extra.appendSliceAssumeCapacity(body);
3930 wip_decls.bit_bag.items.len +3873 astgen.extra.appendSliceAssumeCapacity(fields_slice);
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);
39493874
3875 block_scope.unstack();
3876 try gz.addNamespaceCaptures(&namespace);
3950 return indexToRef(decl_inst);3877 return indexToRef(decl_inst);
3951}3878}
39523879
...@@ -3965,7 +3892,6 @@ fn unionDeclInner(...@@ -3965,7 +3892,6 @@ fn unionDeclInner(
3965 const gpa = astgen.gpa;3892 const gpa = astgen.gpa;
3966 const tree = astgen.tree;3893 const tree = astgen.tree;
3967 const node_tags = tree.nodes.items(.tag);3894 const node_tags = tree.nodes.items(.tag);
3968 const node_datas = tree.nodes.items(.data);
39693895
3970 var namespace: Scope.Namespace = .{3896 var namespace: Scope.Namespace = .{
3971 .parent = scope,3897 .parent = scope,
...@@ -3985,192 +3911,54 @@ fn unionDeclInner(...@@ -3985,192 +3911,54 @@ fn unionDeclInner(
3985 .astgen = astgen,3911 .astgen = astgen,
3986 .force_comptime = true,3912 .force_comptime = true,
3987 .in_defer = false,3913 .in_defer = false,
3914 .instructions = gz.instructions,
3915 .instructions_top = gz.instructions.items.len,
3988 };3916 };
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
3993 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)3922 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
3994 try typeExpr(&block_scope, &namespace.base, arg_node)3923 try typeExpr(&block_scope, &namespace.base, arg_node)
3995 else3924 else
3996 .none;3925 .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
4006 const bits_per_field = 4;3927 const bits_per_field = 4;
4007 const fields_per_u32 = 32 / bits_per_field;3928 const max_field_size = 4;
4008 // We only need this if there are greater than fields_per_u32 fields.3929 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
4009 var bit_bag = ArrayListUnmanaged(u32){};3930 defer wip_members.deinit();
4010 defer bit_bag.deinit(gpa);
40113931
4012 var cur_bit_bag: u32 = 0;
4013 var field_index: usize = 0;
4014 for (members) |member_node| {3932 for (members) |member_node| {
4015 const member = switch (node_tags[member_node]) {3933 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
4016 .container_field_init => tree.containerFieldInit(member_node),3934 .decl => continue,
4017 .container_field_align => tree.containerFieldAlign(member_node),3935 .field => |field| field,
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,
4139 };3936 };
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 }
4144 if (member.comptime_token) |comptime_token| {3937 if (member.comptime_token) |comptime_token| {
4145 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});3938 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
4146 }3939 }
4147 try fields_data.ensureUnusedCapacity(gpa, 4);
41483940
4149 const field_name = try astgen.identAsString(member.ast.name_token);3941 const field_name = try astgen.identAsString(member.ast.name_token);
4150 fields_data.appendAssumeCapacity(field_name);3942 wip_members.appendToField(field_name);
41513943
4152 const have_type = member.ast.type_expr != 0;3944 const have_type = member.ast.type_expr != 0;
4153 const have_align = member.ast.align_expr != 0;3945 const have_align = member.ast.align_expr != 0;
4154 const have_value = member.ast.value_expr != 0;3946 const have_value = member.ast.value_expr != 0;
4155 const unused = false;3947 const unused = false;
4156 cur_bit_bag = (cur_bit_bag >> bits_per_field) |3948 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
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);
41613949
4162 if (have_type) {3950 if (have_type) {
4163 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")3951 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
4164 .none3952 .none
4165 else3953 else
4166 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);3954 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
4167 fields_data.appendAssumeCapacity(@enumToInt(field_type));3955 wip_members.appendToField(@enumToInt(field_type));
4168 } else if (arg_inst == .none and !have_auto_enum) {3956 } else if (arg_inst == .none and !have_auto_enum) {
4169 return astgen.failNode(member_node, "union field missing type", .{});3957 return astgen.failNode(member_node, "union field missing type", .{});
4170 }3958 }
4171 if (have_align) {3959 if (have_align) {
4172 const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);3960 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));
4174 }3962 }
4175 if (have_value) {3963 if (have_value) {
4176 if (arg_inst == .none) {3964 if (arg_inst == .none) {
...@@ -4202,65 +3990,39 @@ fn unionDeclInner(...@@ -4202,65 +3990,39 @@ fn unionDeclInner(
4202 );3990 );
4203 }3991 }
4204 const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);3992 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));
4206 }3994 }
4207
4208 field_index += 1;
4209 }3995 }
4210 if (field_index == 0) {3996 if (field_count == 0) {
4211 return astgen.failNode(node, "union declarations must have at least one tag", .{});3997 return astgen.failNode(node, "union declarations must have at least one tag", .{});
4212 }3998 }
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()) {
4227 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);4001 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
4228 }4002 }
42294003
4004 const body = block_scope.instructionsSlice();
4005
4230 try gz.setUnion(decl_inst, .{4006 try gz.setUnion(decl_inst, .{
4231 .src_node = node,4007 .src_node = node,
4232 .layout = layout,4008 .layout = layout,
4233 .tag_type = arg_inst,4009 .tag_type = arg_inst,
4234 .body_len = @intCast(u32, block_scope.instructions.items.len),4010 .body_len = @intCast(u32, body.len),
4235 .fields_len = @intCast(u32, field_index),4011 .fields_len = field_count,
4236 .decls_len = @intCast(u32, wip_decls.decl_index),4012 .decls_len = decl_count,
4237 .auto_enum_tag = have_auto_enum,4013 .auto_enum_tag = have_auto_enum,
4238 });4014 });
42394015
4240 // zig fmt: off4016 wip_members.finishBits(bits_per_field);
4241 try astgen.extra.ensureUnusedCapacity(gpa,4017 const decls_slice = wip_members.declsSlice();
4242 bit_bag.items.len +4018 const fields_slice = wip_members.fieldsSlice();
4243 @boolToInt(wip_decls.decl_index != 0) +4019 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
4244 wip_decls.payload.items.len +4020 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4245 block_scope.instructions.items.len +4021 astgen.extra.appendSliceAssumeCapacity(body);
4246 wip_decls.bit_bag.items.len +4022 astgen.extra.appendSliceAssumeCapacity(fields_slice);
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);
42634023
4024 block_scope.unstack();
4025 try gz.addNamespaceCaptures(&namespace);
4264 return indexToRef(decl_inst);4026 return indexToRef(decl_inst);
4265}4027}
42664028
...@@ -4276,7 +4038,6 @@ fn containerDecl(...@@ -4276,7 +4038,6 @@ fn containerDecl(
4276 const tree = astgen.tree;4038 const tree = astgen.tree;
4277 const token_tags = tree.tokens.items(.tag);4039 const token_tags = tree.tokens.items(.tag);
4278 const node_tags = tree.nodes.items(.tag);4040 const node_tags = tree.nodes.items(.tag);
4279 const node_datas = tree.nodes.items(.data);
42804041
4281 const prev_fn_block = astgen.fn_block;4042 const prev_fn_block = astgen.fn_block;
4282 astgen.fn_block = null;4043 astgen.fn_block = null;
...@@ -4430,172 +4191,39 @@ fn containerDecl(...@@ -4430,172 +4191,39 @@ fn containerDecl(
4430 .astgen = astgen,4191 .astgen = astgen,
4431 .force_comptime = true,4192 .force_comptime = true,
4432 .in_defer = false,4193 .in_defer = false,
4194 .instructions = gz.instructions,
4195 .instructions_top = gz.instructions.items.len,
4433 };4196 };
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
4438 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)4201 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4439 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)4202 try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
4440 else4203 else
4441 .none;4204 .none;
44424205
4443 var wip_decls: WipDecls = .{};4206 const bits_per_field = 1;
4444 defer wip_decls.deinit(gpa);4207 const max_field_size = 2;
44454208 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4446 var fields_data = ArrayListUnmanaged(u32){};4209 defer wip_members.deinit();
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);
44544210
4455 var cur_bit_bag: u32 = 0;
4456 var field_index: usize = 0;
4457 for (container_decl.ast.members) |member_node| {4211 for (container_decl.ast.members) |member_node| {
4458 if (member_node == counts.nonexhaustive_node)4212 if (member_node == counts.nonexhaustive_node)
4459 continue;4213 continue;
4460 const member = switch (node_tags[member_node]) {4214 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
4461 .container_field_init => tree.containerFieldInit(member_node),4215 .decl => continue,
4462 .container_field_align => tree.containerFieldAlign(member_node),4216 .field => |field| field,
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,
4584 };4217 };
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 }
4589 assert(member.comptime_token == null);4218 assert(member.comptime_token == null);
4590 assert(member.ast.type_expr == 0);4219 assert(member.ast.type_expr == 0);
4591 assert(member.ast.align_expr == 0);4220 assert(member.ast.align_expr == 0);
45924221
4593 const field_name = try astgen.identAsString(member.ast.name_token);4222 const field_name = try astgen.identAsString(member.ast.name_token);
4594 fields_data.appendAssumeCapacity(field_name);4223 wip_members.appendToField(field_name);
45954224
4596 const have_value = member.ast.value_expr != 0;4225 const have_value = member.ast.value_expr != 0;
4597 cur_bit_bag = (cur_bit_bag >> 1) |4226 wip_members.nextField(bits_per_field, .{have_value});
4598 (@as(u32, @boolToInt(have_value)) << 31);
45994227
4600 if (have_value) {4228 if (have_value) {
4601 if (arg_inst == .none) {4229 if (arg_inst == .none) {
...@@ -4613,60 +4241,35 @@ fn containerDecl(...@@ -4613,60 +4241,35 @@ fn containerDecl(
4613 );4241 );
4614 }4242 }
4615 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);4243 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));4244 wip_members.appendToField(@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);
4631 }4245 }
4632 }4246 }
46334247
4634 if (block_scope.instructions.items.len != 0) {4248 if (!block_scope.isEmpty()) {
4635 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);4249 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
4636 }4250 }
46374251
4252 const body = block_scope.instructionsSlice();
4253
4638 try gz.setEnum(decl_inst, .{4254 try gz.setEnum(decl_inst, .{
4639 .src_node = node,4255 .src_node = node,
4640 .nonexhaustive = nonexhaustive,4256 .nonexhaustive = nonexhaustive,
4641 .tag_type = arg_inst,4257 .tag_type = arg_inst,
4642 .body_len = @intCast(u32, block_scope.instructions.items.len),4258 .body_len = @intCast(u32, body.len),
4643 .fields_len = @intCast(u32, field_index),4259 .fields_len = @intCast(u32, counts.total_fields),
4644 .decls_len = @intCast(u32, wip_decls.decl_index),4260 .decls_len = @intCast(u32, counts.decls),
4645 });4261 });
46464262
4647 // zig fmt: off4263 wip_members.finishBits(bits_per_field);
4648 try astgen.extra.ensureUnusedCapacity(gpa,4264 const decls_slice = wip_members.declsSlice();
4649 bit_bag.items.len +4265 const fields_slice = wip_members.fieldsSlice();
4650 @boolToInt(wip_decls.decl_index != 0) +4266 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len);
4651 wip_decls.payload.items.len +4267 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4652 block_scope.instructions.items.len +4268 astgen.extra.appendSliceAssumeCapacity(body);
4653 wip_decls.bit_bag.items.len +4269 astgen.extra.appendSliceAssumeCapacity(fields_slice);
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);
46694270
4271 block_scope.unstack();
4272 try gz.addNamespaceCaptures(&namespace);
4670 return rvalue(gz, rl, indexToRef(decl_inst), node);4273 return rvalue(gz, rl, indexToRef(decl_inst), node);
4671 },4274 },
4672 .keyword_opaque => {4275 .keyword_opaque => {
...@@ -4682,166 +4285,155 @@ fn containerDecl(...@@ -4682,166 +4285,155 @@ fn containerDecl(
4682 };4285 };
4683 defer namespace.deinit(gpa);4286 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 = .{};4290 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0);
4688 defer wip_decls.deinit(gpa);4291 defer wip_members.deinit();
46894292
4690 for (container_decl.ast.members) |member_node| {4293 for (container_decl.ast.members) |member_node| {
4691 switch (node_tags[member_node]) {4294 _ = try containerMember(gz, &namespace.base, &wip_members, 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 }
4820 }4295 }
48214296
4822 try gz.setOpaque(decl_inst, .{4297 try gz.setOpaque(decl_inst, .{
4823 .src_node = node,4298 .src_node = node,
4824 .decls_len = @intCast(u32, wip_decls.decl_index),4299 .decls_len = decl_count,
4825 });4300 });
48264301
4827 // zig fmt: off4302 wip_members.finishBits(0);
4828 try astgen.extra.ensureUnusedCapacity(gpa,4303 const decls_slice = wip_members.declsSlice();
4829 wip_decls.bit_bag.items.len +4304 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len);
4830 @boolToInt(wip_decls.decl_index != 0) +4305 astgen.extra.appendSliceAssumeCapacity(decls_slice);
4831 wip_decls.payload.items.len
4832 );
4833 // zig fmt: on
48344306
4835 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.4307 try gz.addNamespaceCaptures(&namespace);
4836 if (wip_decls.decl_index != 0) {4308 return rvalue(gz, rl, indexToRef(decl_inst), node);
4837 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);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,
4838 }4362 }
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 };
4842 },4433 },
4843 else => unreachable,4434 else => unreachable,
4844 }4435 }
4436 return .decl;
4845}4437}
48464438
4847fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {4439fn 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...@@ -4851,20 +4443,18 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
4851 const main_tokens = tree.nodes.items(.main_token);4443 const main_tokens = tree.nodes.items(.main_token);
4852 const token_tags = tree.tokens.items(.tag);4444 const token_tags = tree.tokens.items(.tag);
48534445
4854 var field_names: std.ArrayListUnmanaged(u32) = .{};4446 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len);
4855 defer field_names.deinit(gpa);4447 var fields_len: usize = 0;
4856
4857 {4448 {
4858 const error_token = main_tokens[node];4449 const error_token = main_tokens[node];
4859 var tok_i = error_token + 2;4450 var tok_i = error_token + 2;
4860 var field_i: usize = 0;
4861 while (true) : (tok_i += 1) {4451 while (true) : (tok_i += 1) {
4862 switch (token_tags[tok_i]) {4452 switch (token_tags[tok_i]) {
4863 .doc_comment, .comma => {},4453 .doc_comment, .comma => {},
4864 .identifier => {4454 .identifier => {
4865 const str_index = try astgen.identAsString(tok_i);4455 const str_index = try astgen.identAsString(tok_i);
4866 try field_names.append(gpa, str_index);4456 try astgen.extra.append(gpa, str_index);
4867 field_i += 1;4457 fields_len += 1;
4868 },4458 },
4869 .r_brace => break,4459 .r_brace => break,
4870 else => unreachable,4460 else => unreachable,
...@@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir...@@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir
4872 }4462 }
4873 }4463 }
48744464
4875 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{4465 setExtra(astgen, payload_index, Zir.Inst.ErrorSetDecl{
4876 .fields_len = @intCast(u32, field_names.items.len),4466 .fields_len = @intCast(u32, fields_len),
4877 });4467 });
4878 try astgen.extra.appendSlice(gpa, field_names.items);4468 const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index);
4879 return rvalue(gz, rl, result, node);4469 return rvalue(gz, rl, result, node);
4880}4470}
48814471
...@@ -4896,7 +4486,7 @@ fn tryExpr(...@@ -4896,7 +4486,7 @@ fn tryExpr(
48964486
4897 var block_scope = parent_gz.makeSubBlock(scope);4487 var block_scope = parent_gz.makeSubBlock(scope);
4898 block_scope.setBreakResultLoc(rl);4488 block_scope.setBreakResultLoc(rl);
4899 defer block_scope.instructions.deinit(astgen.gpa);4489 defer block_scope.unstack();
49004490
4901 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {4491 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
4902 .ref => .ref,4492 .ref => .ref,
...@@ -4916,12 +4506,13 @@ fn tryExpr(...@@ -4916,12 +4506,13 @@ fn tryExpr(
4916 const cond = try block_scope.addUnNode(err_ops[0], operand, node);4506 const cond = try block_scope.addUnNode(err_ops[0], operand, node);
4917 const condbr = try block_scope.addCondBr(.condbr, node);4507 const condbr = try block_scope.addCondBr(.condbr, node);
49184508
4919 const block = try parent_gz.addBlock(.block, node);4509 const block = try parent_gz.makeBlockInst(.block, node);
4920 try parent_gz.instructions.append(astgen.gpa, block);
4921 try block_scope.setBlockBody(block);4510 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
4923 var then_scope = parent_gz.makeSubBlock(scope);4514 var then_scope = parent_gz.makeSubBlock(scope);
4924 defer then_scope.instructions.deinit(astgen.gpa);4515 defer then_scope.unstack();
49254516
4926 block_scope.break_count += 1;4517 block_scope.break_count += 1;
4927 // This could be a pointer or value depending on `err_ops[2]`.4518 // This could be a pointer or value depending on `err_ops[2]`.
...@@ -4931,8 +4522,9 @@ fn tryExpr(...@@ -4931,8 +4522,9 @@ fn tryExpr(
4931 else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),4522 else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node),
4932 };4523 };
49334524
4525 // else_scope will be stacked on then_scope as both are stacked on parent_gz
4934 var else_scope = parent_gz.makeSubBlock(scope);4526 var else_scope = parent_gz.makeSubBlock(scope);
4935 defer else_scope.instructions.deinit(astgen.gpa);4527 defer else_scope.unstack();
49364528
4937 const err_code = try else_scope.addUnNode(err_ops[1], operand, node);4529 const err_code = try else_scope.addUnNode(err_ops[1], operand, node);
4938 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });4530 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
...@@ -4972,7 +4564,7 @@ fn orelseCatchExpr(...@@ -4972,7 +4564,7 @@ fn orelseCatchExpr(
49724564
4973 var block_scope = parent_gz.makeSubBlock(scope);4565 var block_scope = parent_gz.makeSubBlock(scope);
4974 block_scope.setBreakResultLoc(rl);4566 block_scope.setBreakResultLoc(rl);
4975 defer block_scope.instructions.deinit(astgen.gpa);4567 defer block_scope.unstack();
49764568
4977 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {4569 const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
4978 .ref => .ref,4570 .ref => .ref,
...@@ -4987,12 +4579,13 @@ fn orelseCatchExpr(...@@ -4987,12 +4579,13 @@ fn orelseCatchExpr(
4987 const cond = try block_scope.addUnNode(cond_op, operand, node);4579 const cond = try block_scope.addUnNode(cond_op, operand, node);
4988 const condbr = try block_scope.addCondBr(.condbr, node);4580 const condbr = try block_scope.addCondBr(.condbr, node);
49894581
4990 const block = try parent_gz.addBlock(.block, node);4582 const block = try parent_gz.makeBlockInst(.block, node);
4991 try parent_gz.instructions.append(astgen.gpa, block);
4992 try block_scope.setBlockBody(block);4583 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
4994 var then_scope = parent_gz.makeSubBlock(scope);4587 var then_scope = parent_gz.makeSubBlock(scope);
4995 defer then_scope.instructions.deinit(astgen.gpa);4588 defer then_scope.unstack();
49964589
4997 // This could be a pointer or value depending on `unwrap_op`.4590 // This could be a pointer or value depending on `unwrap_op`.
4998 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);4591 const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node);
...@@ -5002,7 +4595,7 @@ fn orelseCatchExpr(...@@ -5002,7 +4595,7 @@ fn orelseCatchExpr(
5002 };4595 };
50034596
5004 var else_scope = parent_gz.makeSubBlock(scope);4597 var else_scope = parent_gz.makeSubBlock(scope);
5005 defer else_scope.instructions.deinit(astgen.gpa);4598 defer else_scope.unstack();
50064599
5007 var err_val_scope: Scope.LocalVal = undefined;4600 var err_val_scope: Scope.LocalVal = undefined;
5008 const else_sub_scope = blk: {4601 const else_sub_scope = blk: {
...@@ -5049,6 +4642,7 @@ fn orelseCatchExpr(...@@ -5049,6 +4642,7 @@ fn orelseCatchExpr(
5049 );4642 );
5050}4643}
50514644
4645/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.
5052fn finishThenElseBlock(4646fn finishThenElseBlock(
5053 parent_gz: *GenZir,4647 parent_gz: *GenZir,
5054 rl: ResultLoc,4648 rl: ResultLoc,
...@@ -5067,33 +4661,33 @@ fn finishThenElseBlock(...@@ -5067,33 +4661,33 @@ fn finishThenElseBlock(
5067 // We now have enough information to decide whether the result instruction should4661 // We now have enough information to decide whether the result instruction should
5068 // be communicated via result location pointer or break instructions.4662 // be communicated via result location pointer or break instructions.
5069 const strat = rl.strategy(block_scope);4663 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
5070 switch (strat.tag) {4670 switch (strat.tag) {
5071 .break_void => {4671 .break_void => {
5072 if (!then_scope.endsWithNoReturn()) {4672 const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, .void_value) else 0;
5073 _ = try then_scope.addBreak(break_tag, then_break_block, .void_value);4673 const else_break = if (!else_no_return) try else_scope.makeBreak(break_tag, main_block, .void_value) else 0;
5074 }
5075 if (!else_scope.endsWithNoReturn()) {
5076 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
5077 }
5078 assert(!strat.elide_store_to_block_ptr_instructions);4674 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);
5080 return indexToRef(main_block);4676 return indexToRef(main_block);
5081 },4677 },
5082 .break_operand => {4678 .break_operand => {
5083 if (!then_scope.endsWithNoReturn()) {4679 const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0;
5084 _ = try then_scope.addBreak(break_tag, then_break_block, then_result);4680 const else_break = if (else_result == .none)
5085 }4681 try else_scope.makeBreak(break_tag, main_block, .void_value)
5086 if (else_result != .none) {4682 else if (!else_no_return)
5087 if (!else_scope.endsWithNoReturn()) {4683 try else_scope.makeBreak(break_tag, main_block, else_result)
5088 _ = try else_scope.addBreak(break_tag, main_block, else_result);4684 else
5089 }4685 0;
5090 } else {4686
5091 _ = try else_scope.addBreak(break_tag, main_block, .void_value);
5092 }
5093 if (strat.elide_store_to_block_ptr_instructions) {4687 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);
5095 } else {4689 } else {
5096 try setCondBrPayload(condbr, cond, then_scope, else_scope);4690 try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break);
5097 }4691 }
5098 const block_ref = indexToRef(main_block);4692 const block_ref = indexToRef(main_block);
5099 switch (rl) {4693 switch (rl) {
...@@ -5221,7 +4815,7 @@ fn boolBinOp(...@@ -5221,7 +4815,7 @@ fn boolBinOp(
5221 const bool_br = try gz.addBoolBr(zir_tag, lhs);4815 const bool_br = try gz.addBoolBr(zir_tag, lhs);
52224816
5223 var rhs_scope = gz.makeSubBlock(scope);4817 var rhs_scope = gz.makeSubBlock(scope);
5224 defer rhs_scope.instructions.deinit(gz.astgen.gpa);4818 defer rhs_scope.unstack();
5225 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);4819 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
5226 if (!gz.refIsNoReturn(rhs)) {4820 if (!gz.refIsNoReturn(rhs)) {
5227 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);4821 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
...@@ -5245,7 +4839,7 @@ fn ifExpr(...@@ -5245,7 +4839,7 @@ fn ifExpr(
52454839
5246 var block_scope = parent_gz.makeSubBlock(scope);4840 var block_scope = parent_gz.makeSubBlock(scope);
5247 block_scope.setBreakResultLoc(rl);4841 block_scope.setBreakResultLoc(rl);
5248 defer block_scope.instructions.deinit(astgen.gpa);4842 defer block_scope.unstack();
52494843
5250 const payload_is_ref = if (if_full.payload_token) |payload_token|4844 const payload_is_ref = if (if_full.payload_token) |payload_token|
5251 token_tags[payload_token] == .asterisk4845 token_tags[payload_token] == .asterisk
...@@ -5283,12 +4877,13 @@ fn ifExpr(...@@ -5283,12 +4877,13 @@ fn ifExpr(
52834877
5284 const condbr = try block_scope.addCondBr(.condbr, node);4878 const condbr = try block_scope.addCondBr(.condbr, node);
52854879
5286 const block = try parent_gz.addBlock(.block, node);4880 const block = try parent_gz.makeBlockInst(.block, node);
5287 try parent_gz.instructions.append(astgen.gpa, block);
5288 try block_scope.setBlockBody(block);4881 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
5290 var then_scope = parent_gz.makeSubBlock(scope);4885 var then_scope = parent_gz.makeSubBlock(scope);
5291 defer then_scope.instructions.deinit(astgen.gpa);4886 defer then_scope.unstack();
52924887
5293 var payload_val_scope: Scope.LocalVal = undefined;4888 var payload_val_scope: Scope.LocalVal = undefined;
52944889
...@@ -5354,7 +4949,7 @@ fn ifExpr(...@@ -5354,7 +4949,7 @@ fn ifExpr(
5354 // instructions or not.4949 // instructions or not.
53554950
5356 var else_scope = parent_gz.makeSubBlock(scope);4951 var else_scope = parent_gz.makeSubBlock(scope);
5357 defer else_scope.instructions.deinit(astgen.gpa);4952 defer else_scope.unstack();
53584953
5359 const else_node = if_full.ast.else_expr;4954 const else_node = if_full.ast.else_expr;
5360 const else_info: struct {4955 const else_info: struct {
...@@ -5417,52 +5012,70 @@ fn ifExpr(...@@ -5417,52 +5012,70 @@ fn ifExpr(
5417 );5012 );
5418}5013}
54195014
5015/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
5420fn setCondBrPayload(5016fn setCondBrPayload(
5421 condbr: Zir.Inst.Index,5017 condbr: Zir.Inst.Index,
5422 cond: Zir.Inst.Ref,5018 cond: Zir.Inst.Ref,
5423 then_scope: *GenZir,5019 then_scope: *GenZir,
5020 then_break: Zir.Inst.Index,
5424 else_scope: *GenZir,5021 else_scope: *GenZir,
5022 else_break: Zir.Inst.Index,
5425) !void {5023) !void {
5024 defer then_scope.unstack();
5025 defer else_scope.unstack();
5426 const astgen = then_scope.astgen;5026 const astgen = then_scope.astgen;
54275027 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));
5428 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +5031 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
5431 const zir_datas = astgen.instructions.items(.data);5034 const zir_datas = astgen.instructions.items(.data);
5432 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{5035 zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
5433 .condition = cond,5036 .condition = cond,
5434 .then_body_len = @intCast(u32, then_scope.instructions.items.len),5037 .then_body_len = then_body_len,
5435 .else_body_len = @intCast(u32, else_scope.instructions.items.len),5038 .else_body_len = else_body_len,
5436 });5039 });
5437 astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items);5040 astgen.extra.appendSliceAssumeCapacity(then_body);
5438 astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items);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);
5439}5044}
54405045
5046/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
5441fn setCondBrPayloadElideBlockStorePtr(5047fn setCondBrPayloadElideBlockStorePtr(
5442 condbr: Zir.Inst.Index,5048 condbr: Zir.Inst.Index,
5443 cond: Zir.Inst.Ref,5049 cond: Zir.Inst.Ref,
5444 then_scope: *GenZir,5050 then_scope: *GenZir,
5051 then_break: Zir.Inst.Index,
5445 else_scope: *GenZir,5052 else_scope: *GenZir,
5053 else_break: Zir.Inst.Index,
5446 block_ptr: Zir.Inst.Ref,5054 block_ptr: Zir.Inst.Ref,
5447) !void {5055) !void {
5056 defer then_scope.unstack();
5057 defer else_scope.unstack();
5448 const astgen = then_scope.astgen;5058 const astgen = then_scope.astgen;
54495059 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));
5450 try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len +5063 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
5453 const zir_tags = astgen.instructions.items(.tag);5066 const zir_tags = astgen.instructions.items(.tag);
5454 const zir_datas = astgen.instructions.items(.data);5067 const zir_datas = astgen.instructions.items(.data);
54555068
5456 const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{5069 const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
5457 .condition = cond,5070 .condition = cond,
5458 .then_body_len = @intCast(u32, then_scope.instructions.items.len),5071 .then_body_len = then_body_len,
5459 .else_body_len = @intCast(u32, else_scope.instructions.items.len),5072 .else_body_len = else_body_len,
5460 });5073 });
5461 zir_datas[condbr].pl_node.payload_index = condbr_pl;5074 zir_datas[condbr].pl_node.payload_index = condbr_pl;
5462 const then_body_len_index = condbr_pl + 1;5075 const then_body_len_index = condbr_pl + 1;
5463 const else_body_len_index = condbr_pl + 2;5076 const else_body_len_index = condbr_pl + 2;
54645077
5465 for (then_scope.instructions.items) |src_inst| {5078 for (then_body) |src_inst| {
5466 if (zir_tags[src_inst] == .store_to_block_ptr) {5079 if (zir_tags[src_inst] == .store_to_block_ptr) {
5467 if (zir_datas[src_inst].bin.lhs == block_ptr) {5080 if (zir_datas[src_inst].bin.lhs == block_ptr) {
5468 astgen.extra.items[then_body_len_index] -= 1;5081 astgen.extra.items[then_body_len_index] -= 1;
...@@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr(...@@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr(
5471 }5084 }
5472 astgen.extra.appendAssumeCapacity(src_inst);5085 astgen.extra.appendAssumeCapacity(src_inst);
5473 }5086 }
5474 for (else_scope.instructions.items) |src_inst| {5087 if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break);
5088 for (else_body) |src_inst| {
5475 if (zir_tags[src_inst] == .store_to_block_ptr) {5089 if (zir_tags[src_inst] == .store_to_block_ptr) {
5476 if (zir_datas[src_inst].bin.lhs == block_ptr) {5090 if (zir_datas[src_inst].bin.lhs == block_ptr) {
5477 astgen.extra.items[else_body_len_index] -= 1;5091 astgen.extra.items[else_body_len_index] -= 1;
...@@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr(...@@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr(
5480 }5094 }
5481 astgen.extra.appendAssumeCapacity(src_inst);5095 astgen.extra.appendAssumeCapacity(src_inst);
5482 }5096 }
5097 if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break);
5483}5098}
54845099
5485fn whileExpr(5100fn whileExpr(
...@@ -5499,17 +5114,17 @@ fn whileExpr(...@@ -5499,17 +5114,17 @@ fn whileExpr(
54995114
5500 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;5115 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
5501 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;5116 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);
5503 try parent_gz.instructions.append(astgen.gpa, loop_block);5118 try parent_gz.instructions.append(astgen.gpa, loop_block);
55045119
5505 var loop_scope = parent_gz.makeSubBlock(scope);5120 var loop_scope = parent_gz.makeSubBlock(scope);
5506 loop_scope.setBreakResultLoc(rl);5121 loop_scope.setBreakResultLoc(rl);
5507 defer loop_scope.instructions.deinit(astgen.gpa);5122 defer loop_scope.unstack();
5508 defer loop_scope.labeled_breaks.deinit(astgen.gpa);5123 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
5509 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);5124 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
55105125
5511 var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);5126 var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);
5512 defer continue_scope.instructions.deinit(astgen.gpa);5127 defer continue_scope.unstack();
55135128
5514 const payload_is_ref = if (while_full.payload_token) |payload_token|5129 const payload_is_ref = if (while_full.payload_token) |payload_token|
5515 token_tags[payload_token] == .asterisk5130 token_tags[payload_token] == .asterisk
...@@ -5548,15 +5163,19 @@ fn whileExpr(...@@ -5548,15 +5163,19 @@ fn whileExpr(
5548 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;5163 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
5549 const condbr = try continue_scope.addCondBr(condbr_tag, node);5164 const condbr = try continue_scope.addCondBr(condbr_tag, node);
5550 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;5165 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5551 const cond_block = try loop_scope.addBlock(block_tag, node);5166 const cond_block = try loop_scope.makeBlockInst(block_tag, node);
5552 try loop_scope.instructions.append(astgen.gpa, cond_block);
5553 try continue_scope.setBlockBody(cond_block);5167 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
5555 var then_scope = parent_gz.makeSubBlock(&continue_scope.base);5173 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;
5558 var payload_val_scope: Scope.LocalVal = undefined;5178 var payload_val_scope: Scope.LocalVal = undefined;
5559
5560 const then_sub_scope = s: {5179 const then_sub_scope = s: {
5561 if (while_full.error_token != null) {5180 if (while_full.error_token != null) {
5562 if (while_full.payload_token) |payload_token| {5181 if (while_full.payload_token) |payload_token| {
...@@ -5564,7 +5183,8 @@ fn whileExpr(...@@ -5564,7 +5183,8 @@ fn whileExpr(
5564 .err_union_payload_unsafe_ptr5183 .err_union_payload_unsafe_ptr
5565 else5184 else
5566 .err_union_payload_unsafe;5185 .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);
5568 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;5188 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
5569 const ident_bytes = tree.tokenSlice(ident_token);5189 const ident_bytes = tree.tokenSlice(ident_token);
5570 if (mem.eql(u8, "_", ident_bytes))5190 if (mem.eql(u8, "_", ident_bytes))
...@@ -5576,7 +5196,7 @@ fn whileExpr(...@@ -5576,7 +5196,7 @@ fn whileExpr(
5576 .parent = &then_scope.base,5196 .parent = &then_scope.base,
5577 .gen_zir = &then_scope,5197 .gen_zir = &then_scope,
5578 .name = ident_name,5198 .name = ident_name,
5579 .inst = payload_inst,5199 .inst = indexToRef(payload_inst),
5580 .token_src = payload_token,5200 .token_src = payload_token,
5581 .id_cat = .@"capture",5201 .id_cat = .@"capture",
5582 };5202 };
...@@ -5590,7 +5210,8 @@ fn whileExpr(...@@ -5590,7 +5210,8 @@ fn whileExpr(
5590 .optional_payload_unsafe_ptr5210 .optional_payload_unsafe_ptr
5591 else5211 else
5592 .optional_payload_unsafe;5212 .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);
5594 const ident_name = try astgen.identAsString(ident_token);5215 const ident_name = try astgen.identAsString(ident_token);
5595 const ident_bytes = tree.tokenSlice(ident_token);5216 const ident_bytes = tree.tokenSlice(ident_token);
5596 if (mem.eql(u8, "_", ident_bytes))5217 if (mem.eql(u8, "_", ident_bytes))
...@@ -5600,7 +5221,7 @@ fn whileExpr(...@@ -5600,7 +5221,7 @@ fn whileExpr(
5600 .parent = &then_scope.base,5221 .parent = &then_scope.base,
5601 .gen_zir = &then_scope,5222 .gen_zir = &then_scope,
5602 .name = ident_name,5223 .name = ident_name,
5603 .inst = payload_inst,5224 .inst = indexToRef(payload_inst),
5604 .token_src = ident_token,5225 .token_src = ident_token,
5605 .id_cat = .@"capture",5226 .id_cat = .@"capture",
5606 };5227 };
...@@ -5630,6 +5251,9 @@ fn whileExpr(...@@ -5630,6 +5251,9 @@ fn whileExpr(
5630 });5251 });
5631 }5252 }
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);
5633 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);5257 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
5634 if (!then_scope.endsWithNoReturn()) {5258 if (!then_scope.endsWithNoReturn()) {
5635 loop_scope.break_count += 1;5259 loop_scope.break_count += 1;
...@@ -5637,7 +5261,7 @@ fn whileExpr(...@@ -5637,7 +5261,7 @@ fn whileExpr(
5637 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);5261 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
56385262
5639 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);5263 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
5640 defer else_scope.instructions.deinit(astgen.gpa);5264 defer else_scope.unstack();
56415265
5642 const else_node = while_full.ast.else_expr;5266 const else_node = while_full.ast.else_expr;
5643 const else_info: struct {5267 const else_info: struct {
...@@ -5650,7 +5274,7 @@ fn whileExpr(...@@ -5650,7 +5274,7 @@ fn whileExpr(
5650 .err_union_code_ptr5274 .err_union_code_ptr
5651 else5275 else
5652 .err_union_code;5276 .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);
5654 const ident_name = try astgen.identAsString(error_token);5278 const ident_name = try astgen.identAsString(error_token);
5655 const ident_bytes = tree.tokenSlice(error_token);5279 const ident_bytes = tree.tokenSlice(error_token);
5656 if (mem.eql(u8, ident_bytes, "_"))5280 if (mem.eql(u8, ident_bytes, "_"))
...@@ -5660,7 +5284,7 @@ fn whileExpr(...@@ -5660,7 +5284,7 @@ fn whileExpr(
5660 .parent = &else_scope.base,5284 .parent = &else_scope.base,
5661 .gen_zir = &else_scope,5285 .gen_zir = &else_scope,
5662 .name = ident_name,5286 .name = ident_name,
5663 .inst = payload_inst,5287 .inst = else_payload_inst,
5664 .token_src = error_token,5288 .token_src = error_token,
5665 .id_cat = .@"capture",5289 .id_cat = .@"capture",
5666 };5290 };
...@@ -5742,17 +5366,17 @@ fn forExpr(...@@ -5742,17 +5366,17 @@ fn forExpr(
5742 };5366 };
57435367
5744 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;5368 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);
5746 try parent_gz.instructions.append(astgen.gpa, loop_block);5370 try parent_gz.instructions.append(astgen.gpa, loop_block);
57475371
5748 var loop_scope = parent_gz.makeSubBlock(scope);5372 var loop_scope = parent_gz.makeSubBlock(scope);
5749 loop_scope.setBreakResultLoc(rl);5373 loop_scope.setBreakResultLoc(rl);
5750 defer loop_scope.instructions.deinit(astgen.gpa);5374 defer loop_scope.unstack();
5751 defer loop_scope.labeled_breaks.deinit(astgen.gpa);5375 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
5752 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);5376 defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa);
57535377
5754 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);5378 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
5755 defer cond_scope.instructions.deinit(astgen.gpa);5379 defer cond_scope.unstack();
57565380
5757 // check condition i < array_expr.len5381 // check condition i < array_expr.len
5758 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);5382 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
...@@ -5764,9 +5388,10 @@ fn forExpr(...@@ -5764,9 +5388,10 @@ fn forExpr(
5764 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;5388 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
5765 const condbr = try cond_scope.addCondBr(condbr_tag, node);5389 const condbr = try cond_scope.addCondBr(condbr_tag, node);
5766 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;5390 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
5767 const cond_block = try loop_scope.addBlock(block_tag, node);5391 const cond_block = try loop_scope.makeBlockInst(block_tag, node);
5768 try loop_scope.instructions.append(astgen.gpa, cond_block);
5769 try cond_scope.setBlockBody(cond_block);5392 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
5771 // Increment the index variable.5396 // Increment the index variable.
5772 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);5397 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
...@@ -5789,7 +5414,7 @@ fn forExpr(...@@ -5789,7 +5414,7 @@ fn forExpr(
5789 }5414 }
57905415
5791 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);5416 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
5792 defer then_scope.instructions.deinit(astgen.gpa);5417 defer then_scope.unstack();
57935418
5794 var payload_val_scope: Scope.LocalVal = undefined;5419 var payload_val_scope: Scope.LocalVal = undefined;
5795 var index_scope: Scope.LocalPtr = undefined;5420 var index_scope: Scope.LocalPtr = undefined;
...@@ -5851,7 +5476,7 @@ fn forExpr(...@@ -5851,7 +5476,7 @@ fn forExpr(
5851 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);5476 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
58525477
5853 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);5478 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
5854 defer else_scope.instructions.deinit(astgen.gpa);5479 defer else_scope.unstack();
58555480
5856 const else_node = for_full.ast.else_expr;5481 const else_node = for_full.ast.else_expr;
5857 const else_info: struct {5482 const else_info: struct {
...@@ -6030,27 +5655,29 @@ fn switchExpr(...@@ -6030,27 +5655,29 @@ fn switchExpr(
6030 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);5655 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6031 const item_rl: ResultLoc = .{ .ty = cond_ty_inst };5656 const item_rl: ResultLoc = .{ .ty = cond_ty_inst };
60325657
6033 // These contain the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti.5658 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
6034 // This is the optional else prong body.5659 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
6035 var special_case_payload = ArrayListUnmanaged(u32){};5660 // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes
6036 defer special_case_payload.deinit(gpa);5661 const payloads = &astgen.scratch;
6037 // This is all the scalar cases.5662 const scratch_top = astgen.scratch.items.len;
6038 var scalar_cases_payload = ArrayListUnmanaged(u32){};5663 const case_table_start = scratch_top;
6039 defer scalar_cases_payload.deinit(gpa);5664 const scalar_case_table = case_table_start + @boolToInt(special_prong != .none);
6040 // Same deal, but this is only the `extra` data for the multi cases.5665 const multi_case_table = scalar_case_table + scalar_cases_len;
6041 var multi_cases_payload = ArrayListUnmanaged(u32){};5666 const case_table_end = multi_case_table + multi_cases_len;
6042 defer multi_cases_payload.deinit(gpa);5667 try astgen.scratch.resize(gpa, case_table_end);
5668 defer astgen.scratch.items.len = scratch_top;
60435669
6044 var block_scope = parent_gz.makeSubBlock(scope);5670 var block_scope = parent_gz.makeSubBlock(scope);
5671 // block_scope not used for collecting instructions
5672 block_scope.instructions_top = GenZir.unstacked_top;
6045 block_scope.setBreakResultLoc(rl);5673 block_scope.setBreakResultLoc(rl);
6046 defer block_scope.instructions.deinit(gpa);
60475674
6048 // This gets added to the parent block later, after the item expressions.5675 // 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
6051 // We re-use this same scope for all cases, including the special prong, if any.5678 // We re-use this same scope for all cases, including the special prong, if any.
6052 var case_scope = parent_gz.makeSubBlock(&block_scope.base);5679 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
6055 // In this pass we generate all the item and prong expressions.5682 // In this pass we generate all the item and prong expressions.
6056 var multi_case_index: u32 = 0;5683 var multi_case_index: u32 = 0;
...@@ -6062,21 +5689,12 @@ fn switchExpr(...@@ -6062,21 +5689,12 @@ fn switchExpr(
6062 else => unreachable,5689 else => unreachable,
6063 };5690 };
60645691
6065 // Reset the scope.
6066 case_scope.instructions.shrinkRetainingCapacity(0);
6067
6068 const is_multi_case = case.ast.values.len > 1 or5692 const is_multi_case = case.ast.values.len > 1 or
6069 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);5693 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
60705694
5695 var capture_inst: Zir.Inst.Index = 0;
6071 var capture_val_scope: Scope.LocalVal = undefined;5696 var capture_val_scope: Scope.LocalVal = undefined;
6072 const sub_scope = blk: {5697 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 };
6080 const payload_token = case.payload_token orelse break :blk &case_scope.base;5698 const payload_token = case.payload_token orelse break :blk &case_scope.base;
6081 const ident = if (token_tags[payload_token] == .asterisk)5699 const ident = if (token_tags[payload_token] == .asterisk)
6082 payload_token + 15700 payload_token + 1
...@@ -6089,19 +5707,20 @@ fn switchExpr(...@@ -6089,19 +5707,20 @@ fn switchExpr(
6089 }5707 }
6090 break :blk &case_scope.base;5708 break :blk &case_scope.base;
6091 }5709 }
6092 const capture = if (case_node == special_node) capture: {5710 if (case_node == special_node) {
6093 const capture_tag: Zir.Inst.Tag = if (is_ptr)5711 const capture_tag: Zir.Inst.Tag = if (is_ptr)
6094 .switch_capture_else_ref5712 .switch_capture_else_ref
6095 else5713 else
6096 .switch_capture_else;5714 .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, .{
6098 .tag = capture_tag,5717 .tag = capture_tag,
6099 .data = .{ .switch_capture = .{5718 .data = .{ .switch_capture = .{
6100 .switch_inst = switch_block,5719 .switch_inst = switch_block,
6101 .prong_index = undefined,5720 .prong_index = undefined,
6102 } },5721 } },
6103 });5722 });
6104 } else capture: {5723 } else {
6105 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);5724 const is_multi_case_bits: u2 = @boolToInt(is_multi_case);
6106 const is_ptr_bits: u2 = @boolToInt(is_ptr);5725 const is_ptr_bits: u2 = @boolToInt(is_ptr);
6107 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {5726 const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) {
...@@ -6110,30 +5729,33 @@ fn switchExpr(...@@ -6110,30 +5729,33 @@ fn switchExpr(
6110 0b10 => .switch_capture_multi,5729 0b10 => .switch_capture_multi,
6111 0b11 => .switch_capture_multi_ref,5730 0b11 => .switch_capture_multi_ref,
6112 };5731 };
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, .{
6114 .tag = capture_tag,5735 .tag = capture_tag,
6115 .data = .{ .switch_capture = .{5736 .data = .{ .switch_capture = .{
6116 .switch_inst = switch_block,5737 .switch_inst = switch_block,
6117 .prong_index = capture_index,5738 .prong_index = capture_index,
6118 } },5739 } },
6119 });5740 });
6120 };5741 }
6121 const capture_name = try astgen.identAsString(ident);5742 const capture_name = try astgen.identAsString(ident);
6122 capture_val_scope = .{5743 capture_val_scope = .{
6123 .parent = &case_scope.base,5744 .parent = &case_scope.base,
6124 .gen_zir = &case_scope,5745 .gen_zir = &case_scope,
6125 .name = capture_name,5746 .name = capture_name,
6126 .inst = capture,5747 .inst = indexToRef(capture_inst),
6127 .token_src = payload_token,5748 .token_src = payload_token,
6128 .id_cat = .@"capture",5749 .id_cat = .@"capture",
6129 };5750 };
6130 break :blk &capture_val_scope.base;5751 break :blk &capture_val_scope.base;
6131 };5752 };
61325753
6133 if (is_multi_case) {5754 const header_index = @intCast(u32, payloads.items.len);
6134 // items_len, ranges_len, body_len5755 const body_len_index = if (is_multi_case) blk: {
6135 const header_index = multi_cases_payload.items.len;5756 payloads.items[multi_case_table + multi_case_index] = header_index;
6136 try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3);5757 multi_case_index += 1;
5758 try payloads.resize(gpa, header_index + 3); // items_len, ranges_len, body_len
61375759
6138 // items5760 // items
6139 var items_len: u32 = 0;5761 var items_len: u32 = 0;
...@@ -6142,7 +5764,7 @@ fn switchExpr(...@@ -6142,7 +5764,7 @@ fn switchExpr(
6142 items_len += 1;5764 items_len += 1;
61435765
6144 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);5766 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));
6146 }5768 }
61475769
6148 // ranges5770 // ranges
...@@ -6153,47 +5775,44 @@ fn switchExpr(...@@ -6153,47 +5775,44 @@ fn switchExpr(
61535775
6154 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);5776 const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs);
6155 const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs);5777 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{
6157 @enumToInt(first), @enumToInt(last),5779 @enumToInt(first), @enumToInt(last),
6158 });5780 });
6159 }5781 }
61605782
6161 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);5783 payloads.items[header_index] = items_len;
6162 try checkUsed(parent_gz, &case_scope.base, sub_scope);5784 payloads.items[header_index + 1] = ranges_len;
6163 if (!parent_gz.refIsNoReturn(case_result)) {5785 break :blk header_index + 2;
6164 block_scope.break_count += 1;5786 } else if (case_node == special_node) blk: {
6165 _ = try case_scope.addBreak(.@"break", switch_block, case_result);5787 payloads.items[case_table_start] = header_index;
6166 }5788 try payloads.resize(gpa, header_index + 1); // body_len
61675789 break :blk header_index;
6168 multi_cases_payload.items[header_index + 0] = items_len;5790 } else blk: {
6169 multi_cases_payload.items[header_index + 1] = ranges_len;5791 payloads.items[scalar_case_table + scalar_case_index] = header_index;
6170 multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len);5792 scalar_case_index += 1;
6171 try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items);5793 try payloads.resize(gpa, header_index + 2); // item, body_len
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 {
6184 const item_node = case.ast.values[0];5794 const item_node = case.ast.values[0];
6185 const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node);5795 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);
6186 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);5806 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
6187 try checkUsed(parent_gz, &case_scope.base, sub_scope);5807 try checkUsed(parent_gz, &case_scope.base, sub_scope);
6188 if (!parent_gz.refIsNoReturn(case_result)) {5808 if (!parent_gz.refIsNoReturn(case_result)) {
6189 block_scope.break_count += 1;5809 block_scope.break_count += 1;
6190 _ = try case_scope.addBreak(.@"break", switch_block, case_result);5810 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
6191 }5811 }
6192 try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + // item + body_len5812
6193 case_scope.instructions.items.len);5813 const case_slice = case_scope.instructionsSlice();
6194 scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst));5814 payloads.items[body_len_index] = @intCast(u32, case_slice.len);
6195 scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len));5815 try payloads.appendSlice(gpa, case_slice);
6196 scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items);
6197 }5816 }
6198 }5817 }
6199 // Now that the item expressions are generated we can add this.5818 // Now that the item expressions are generated we can add this.
...@@ -6201,9 +5820,7 @@ fn switchExpr(...@@ -6201,9 +5820,7 @@ fn switchExpr(
62015820
6202 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +5821 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +
6203 @boolToInt(multi_cases_len != 0) +5822 @boolToInt(multi_cases_len != 0) +
6204 special_case_payload.items.len +5823 payloads.items.len - case_table_end);
6205 scalar_cases_payload.items.len +
6206 multi_cases_payload.items.len);
62075824
6208 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{5825 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{
6209 .operand = cond,5826 .operand = cond,
...@@ -6216,105 +5833,59 @@ fn switchExpr(...@@ -6216,105 +5833,59 @@ fn switchExpr(
6216 },5833 },
6217 });5834 });
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
6224 if (multi_cases_len != 0) {5836 if (multi_cases_len != 0) {
6225 astgen.extra.appendAssumeCapacity(multi_cases_len);5837 astgen.extra.appendAssumeCapacity(multi_cases_len);
6226 }5838 }
62275839
6228 const strat = rl.strategy(&block_scope);5840 const zir_datas = astgen.instructions.items(.data);
6229 switch (strat.tag) {5841 const zir_tags = astgen.instructions.items(.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 }
62405842
6241 // There will necessarily be a store_to_block_ptr for5843 zir_datas[switch_block].pl_node.payload_index = payload_index;
6242 // all prongs, except for prongs that ended with a noreturn instruction.
6243 // Elide all the `store_to_block_ptr` instructions.
62445844
6245 // The break instructions need to have their operands coerced if the5845 const strat = rl.strategy(&block_scope);
6246 // switch's result location is a `ty`. In this case we overwrite the5846 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {
6247 // `store_to_block_ptr` instruction with an `as` instruction and repurpose5847 var body_len_index = start_index;
6248 // it as the break operand.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;5862 const body_len = payloads.items[body_len_index];
6251 if (special_prong != .none) special_prong: {5863 end_index += body_len;
6252 const body_len_index = extra_index;5864
6253 const body_len = special_case_payload.items[extra_index];5865 switch (strat.tag) {
6254 extra_index += 1;5866 .break_operand => blk: {
6255 if (body_len < 2) {5867 // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus
6256 extra_index += body_len;5868 // `elide_store_to_block_ptr_instructions` will either be true,
6257 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);5869 // or all prongs are noreturn.
6258 break :special_prong;5870 if (!strat.elide_store_to_block_ptr_instructions)
6259 }5871 break :blk;
6260 extra_index += body_len - 2;5872
6261 const store_inst = special_case_payload.items[extra_index];5873 // There will necessarily be a store_to_block_ptr for
6262 if (zir_tags[store_inst] != .store_to_block_ptr or5874 // all prongs, except for prongs that ended with a noreturn instruction.
6263 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)5875 // Elide all the `store_to_block_ptr` instructions.
6264 {5876
6265 extra_index += 2;5877 // The break instructions need to have their operands coerced if the
6266 astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]);5878 // switch's result location is a `ty`. In this case we overwrite the
6267 break :special_prong;5879 // `store_to_block_ptr` instruction with an `as` instruction and repurpose
6268 }5880 // it as the break operand.
6269 assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr);5881 if (body_len < 2)
6270 if (block_scope.rl_ty_inst != .none) {5882 break :blk;
6271 extra_index += 1;5883 const store_inst = payloads.items[end_index - 2];
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];
6306 if (zir_tags[store_inst] != .store_to_block_ptr or5884 if (zir_tags[store_inst] != .store_to_block_ptr or
6307 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)5885 zir_datas[store_inst].bin.lhs != block_scope.rl_ptr)
6308 {5886 break :blk;
6309 extra_index += 2;5887 const break_inst = payloads.items[end_index - 1];
6310 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);
6311 continue;
6312 }
6313 if (block_scope.rl_ty_inst != .none) {5888 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]);
6318 zir_tags[store_inst] = .as;5889 zir_tags[store_inst] = .as;
6319 zir_datas[store_inst].bin = .{5890 zir_datas[store_inst].bin = .{
6320 .lhs = block_scope.rl_ty_inst,5891 .lhs = block_scope.rl_ty_inst,
...@@ -6322,125 +5893,30 @@ fn switchExpr(...@@ -6322,125 +5893,30 @@ fn switchExpr(
6322 };5893 };
6323 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);5894 zir_datas[break_inst].@"break".operand = indexToRef(store_inst);
6324 } else {5895 } else {
6325 scalar_cases_payload.items[body_len_index] -= 1;5896 payloads.items[body_len_index] -= 1;
6326 astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]);5897 astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index .. end_index - 2]);
6327 extra_index += 1;5898 astgen.extra.appendAssumeCapacity(break_inst);
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]);
6357 continue;5899 continue;
6358 }5900 }
6359 if (block_scope.rl_ty_inst != .none) {5901 },
6360 extra_index += 1;5902 .break_void => {
6361 const break_inst = multi_cases_payload.items[extra_index];5903 assert(!strat.elide_store_to_block_ptr_instructions);
6362 extra_index += 1;5904 const last_inst = payloads.items[end_index - 1];
6363 astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]);5905 if (zir_tags[last_inst] == .@"break" and
6364 zir_tags[store_inst] = .as;5906 zir_datas[last_inst].@"break".block_inst == switch_block)
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)
6436 {5907 {
6437 zir_datas[last].@"break".operand = .void_value;5908 zir_datas[last_inst].@"break".operand = .void_value;
6438 }5909 }
6439 }5910 },
5911 }
64405912
6441 return indexToRef(switch_block);5913 astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index..end_index]);
6442 },
6443 }5914 }
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;
6444}5920}
64455921
6446fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {5922fn 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...@@ -6519,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6519 const condbr = try gz.addCondBr(.condbr, node);5995 const condbr = try gz.addCondBr(.condbr, node);
65205996
6521 var then_scope = gz.makeSubBlock(scope);5997 var then_scope = gz.makeSubBlock(scope);
6522 defer then_scope.instructions.deinit(astgen.gpa);5998 defer then_scope.unstack();
65235999
6524 try genDefers(&then_scope, defer_outer, scope, .normal_only);6000 try genDefers(&then_scope, defer_outer, scope, .normal_only);
6525 try then_scope.addRet(rl, operand, node);6001 try then_scope.addRet(rl, operand, node);
65266002
6527 var else_scope = gz.makeSubBlock(scope);6003 var else_scope = gz.makeSubBlock(scope);
6528 defer else_scope.instructions.deinit(astgen.gpa);6004 defer else_scope.unstack();
65296005
6530 const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{6006 const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{
6531 .both = try else_scope.addUnNode(.err_union_code, result, node),6007 .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...@@ -6533,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6533 try genDefers(&else_scope, defer_outer, scope, which_ones);6009 try genDefers(&else_scope, defer_outer, scope, which_ones);
6534 try else_scope.addRet(rl, operand, node);6010 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
6538 return Zir.Inst.Ref.unreachable_value;6014 return Zir.Inst.Ref.unreachable_value;
6539 },6015 },
...@@ -6559,25 +6035,25 @@ fn identifier(...@@ -6559,25 +6035,25 @@ fn identifier(
6559 if (mem.eql(u8, ident_name_raw, "_")) {6035 if (mem.eql(u8, ident_name_raw, "_")) {
6560 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});6036 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
6561 }6037 }
6562 const ident_name = try astgen.identifierTokenString(ident_token);
65636038
6039 // if not @"" syntax, just use raw token slice
6564 if (ident_name_raw[0] != '@') {6040 if (ident_name_raw[0] != '@') {
6565 if (primitives.get(ident_name)) |zir_const_ref| {6041 if (primitives.get(ident_name_raw)) |zir_const_ref| {
6566 return rvalue(gz, rl, zir_const_ref, ident);6042 return rvalue(gz, rl, zir_const_ref, ident);
6567 }6043 }
65686044
6569 if (ident_name.len >= 2) integer: {6045 if (ident_name_raw.len >= 2) integer: {
6570 const first_c = ident_name[0];6046 const first_c = ident_name_raw[0];
6571 if (first_c == 'i' or first_c == 'u') {6047 if (first_c == 'i' or first_c == 'u') {
6572 const signedness: std.builtin.Signedness = switch (first_c == 'i') {6048 const signedness: std.builtin.Signedness = switch (first_c == 'i') {
6573 true => .signed,6049 true => .signed,
6574 false => .unsigned,6050 false => .unsigned,
6575 };6051 };
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) {
6577 error.Overflow => return astgen.failNode(6053 error.Overflow => return astgen.failNode(
6578 ident,6054 ident,
6579 "primitive integer type '{s}' exceeds maximum bit width of 65535",6055 "primitive integer type '{s}' exceeds maximum bit width of 65535",
6580 .{ident_name},6056 .{ident_name_raw},
6581 ),6057 ),
6582 error.InvalidCharacter => break :integer,6058 error.InvalidCharacter => break :integer,
6583 };6059 };
...@@ -6630,6 +6106,7 @@ fn identifier(...@@ -6630,6 +6106,7 @@ fn identifier(
66306106
6631 // Can't close over a runtime variable6107 // Can't close over a runtime variable
6632 if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) {6108 if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) {
6109 const ident_name = try astgen.identifierTokenString(ident_token);
6633 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{6110 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
6634 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),6111 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
6635 try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}),6112 try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}),
...@@ -6677,6 +6154,7 @@ fn identifier(...@@ -6677,6 +6154,7 @@ fn identifier(
6677 .top => break,6154 .top => break,
6678 };6155 };
6679 if (found_already == null) {6156 if (found_already == null) {
6157 const ident_name = try astgen.identifierTokenString(ident_token);
6680 return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name});6158 return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name});
6681 }6159 }
66826160
...@@ -6712,9 +6190,15 @@ fn tunnelThroughClosure(...@@ -6712,9 +6190,15 @@ fn tunnelThroughClosure(
6712 // already has one for this value.6190 // already has one for this value.
6713 const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?);6191 const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?);
6714 if (!gop.found_existing) {6192 if (!gop.found_existing) {
6715 // Make a new capture for this value6193 // Make a new capture for this value but don't add it to the declaring_gz yet
6716 const capture_ref = try ns.?.declaring_gz.?.addUnTok(.closure_capture, value, token);6194 try gz.astgen.instructions.append(gz.astgen.gpa, .{
6717 gop.value_ptr.* = refToIndex(capture_ref).?;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);
6718 }6202 }
67196203
6720 // Add an instruction to get the value from the closure into6204 // Add an instruction to get the value from the closure into
...@@ -7155,10 +6639,8 @@ fn asRlPtr(...@@ -7155,10 +6639,8 @@ fn asRlPtr(
7155 operand_node: Ast.Node.Index,6639 operand_node: Ast.Node.Index,
7156 dest_type: Zir.Inst.Ref,6640 dest_type: Zir.Inst.Ref,
7157) InnerError!Zir.Inst.Ref {6641) InnerError!Zir.Inst.Ref {
7158 const astgen = parent_gz.astgen;
7159
7160 var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr);6642 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
7163 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);6645 const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node);
7164 return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type);6646 return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type);
...@@ -7196,13 +6678,18 @@ fn typeOf(...@@ -7196,13 +6678,18 @@ fn typeOf(
7196 const result = try gz.addUnNode(.typeof, expr_result, node);6678 const result = try gz.addUnNode(.typeof, expr_result, node);
7197 return rvalue(gz, rl, result, node);6679 return rvalue(gz, rl, result, node);
7198 }6680 }
7199 const arena = gz.astgen.arena;6681
7200 var items = try arena.alloc(Zir.Inst.Ref, params.len);6682 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
7201 for (params) |param, param_i| {6683 .src_node = gz.nodeIndexToRelative(node),
7202 items[param_i] = try reachableExpr(gz, scope, .none, param, 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;
7203 }6690 }
72046691
7205 const result = try gz.addExtendedMultiOp(.typeof_peer, node, items);6692 const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len);
7206 return rvalue(gz, rl, result, node);6693 return rvalue(gz, rl, result, node);
7207}6694}
72086695
...@@ -7259,12 +6746,16 @@ fn builtinCall(...@@ -7259,12 +6746,16 @@ fn builtinCall(
7259 return rvalue(gz, rl, result, node);6746 return rvalue(gz, rl, result, node);
7260 },6747 },
7261 .compile_log => {6748 .compile_log => {
7262 const arg_refs = try astgen.gpa.alloc(Zir.Inst.Ref, params.len);6749 const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
7263 defer astgen.gpa.free(arg_refs);6750 .src_node = gz.nodeIndexToRelative(node),
72646751 });
7265 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);6752 var extra_index = try reserveExtra(gz.astgen, params.len);
72666753 for (params) |param| {
7267 const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs);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);
7268 return rvalue(gz, rl, result, node);6759 return rvalue(gz, rl, result, node);
7269 },6760 },
7270 .field => {6761 .field => {
...@@ -7921,14 +7412,15 @@ fn cImport(...@@ -7921,14 +7412,15 @@ fn cImport(
7921 var block_scope = gz.makeSubBlock(scope);7412 var block_scope = gz.makeSubBlock(scope);
7922 block_scope.force_comptime = true;7413 block_scope.force_comptime = true;
7923 block_scope.c_import = true;7414 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);
7927 const block_result = try expr(&block_scope, &block_scope.base, .none, body_node);7418 const block_result = try expr(&block_scope, &block_scope.base, .none, body_node);
7928 if (!gz.refIsNoReturn(block_result)) {7419 if (!gz.refIsNoReturn(block_result)) {
7929 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);7420 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
7930 }7421 }
7931 try block_scope.setBlockBody(block_inst);7422 try block_scope.setBlockBody(block_inst);
7423 // block_scope unstacked now, can add new instructions to gz
7932 try gz.instructions.append(gpa, block_inst);7424 try gz.instructions.append(gpa, block_inst);
79337425
7934 return indexToRef(block_inst);7426 return indexToRef(block_inst);
...@@ -7974,22 +7466,6 @@ fn callExpr(...@@ -7974,22 +7466,6 @@ fn callExpr(
7974 const astgen = gz.astgen;7466 const astgen = gz.astgen;
79757467
7976 const callee = try calleeExpr(gz, scope, call.ast.fn_expr);7468 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
7993 const modifier: std.builtin.CallOptions.Modifier = blk: {7469 const modifier: std.builtin.CallOptions.Modifier = blk: {
7994 if (gz.force_comptime) {7470 if (gz.force_comptime) {
7995 break :blk .compile_time;7471 break :blk .compile_time;
...@@ -8002,7 +7478,28 @@ fn callExpr(...@@ -8002,7 +7478,28 @@ fn callExpr(
8002 }7478 }
8003 break :blk .auto;7479 break :blk .auto;
8004 };7480 };
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);
8006 return rvalue(gz, rl, call_inst, node); // TODO function call with result location7503 return rvalue(gz, rl, call_inst, node); // TODO function call with result location
8007}7504}
80087505
...@@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool {
8747/// result locations must call this function on their result.8244/// result locations must call this function on their result.
8748/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.8245/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
8749/// If the `ResultLoc` is `ty`, it will coerce the result to the type.8246/// If the `ResultLoc` is `ty`, it will coerce the result to the type.
8247/// Assumes nothing stacked on `gz`.
8750fn rvalue(8248fn rvalue(
8751 gz: *GenZir,8249 gz: *GenZir,
8752 rl: ResultLoc,8250 rl: ResultLoc,
...@@ -9326,7 +8824,7 @@ const Scope = struct {...@@ -9326,7 +8824,7 @@ const Scope = struct {
93268824
9327 /// Map from the raw captured value to the instruction8825 /// Map from the raw captured value to the instruction
9328 /// ref of the capture for decls in this namespace8826 /// 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
9331 pub fn deinit(self: *Namespace, gpa: *Allocator) void {8829 pub fn deinit(self: *Namespace, gpa: *Allocator) void {
9332 self.decls.deinit(gpa);8830 self.decls.deinit(gpa);
...@@ -9359,9 +8857,12 @@ const GenZir = struct {...@@ -9359,9 +8857,12 @@ const GenZir = struct {
9359 parent: *Scope,8857 parent: *Scope,
9360 /// All `GenZir` scopes for the same ZIR share this.8858 /// All `GenZir` scopes for the same ZIR share this.
9361 astgen: *AstGen,8859 astgen: *AstGen,
9362 /// Keeps track of the list of instructions in this scope only. Indexes8860 /// Keeps track of the list of instructions in this scope. Possibly shared.
9363 /// to instructions in `astgen`.8861 /// Indexes to instructions in `astgen`.
9364 instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{},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,
9365 label: ?Label = null,8866 label: ?Label = null,
9366 break_block: Zir.Inst.Index = 0,8867 break_block: Zir.Inst.Index = 0,
9367 continue_block: Zir.Inst.Index = 0,8868 continue_block: Zir.Inst.Index = 0,
...@@ -9397,6 +8898,36 @@ const GenZir = struct {...@@ -9397,6 +8898,36 @@ const GenZir = struct {
9397 /// Keys are the raw instruction index, values are the closure_capture instruction.8898 /// Keys are the raw instruction index, values are the closure_capture instruction.
9398 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},8899 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
9400 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {8931 fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir {
9401 return .{8932 return .{
9402 .force_comptime = gz.force_comptime,8933 .force_comptime = gz.force_comptime,
...@@ -9408,6 +8939,8 @@ const GenZir = struct {...@@ -9408,6 +8939,8 @@ const GenZir = struct {
9408 .astgen = gz.astgen,8939 .astgen = gz.astgen,
9409 .suspend_node = gz.suspend_node,8940 .suspend_node = gz.suspend_node,
9410 .nosuspend_node = gz.nosuspend_node,8941 .nosuspend_node = gz.nosuspend_node,
8942 .instructions = gz.instructions,
8943 .instructions_top = gz.instructions.items.len,
9411 };8944 };
9412 }8945 }
94138946
...@@ -9421,12 +8954,13 @@ const GenZir = struct {...@@ -9421,12 +8954,13 @@ const GenZir = struct {
9421 // result location. If it does, elide the coerce_result_ptr instruction8954 // result location. If it does, elide the coerce_result_ptr instruction
9422 // as well as the store instruction, instead passing the result as an rvalue.8955 // as well as the store instruction, instead passing the result as an rvalue.
9423 var as_scope = parent_gz.makeSubBlock(scope);8956 var as_scope = parent_gz.makeSubBlock(scope);
9424 errdefer as_scope.instructions.deinit(parent_gz.astgen.gpa);8957 errdefer as_scope.unstack();
9425 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);8958 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
94268959
9427 return as_scope;8960 return as_scope;
9428 }8961 }
94298962
8963 /// Assumes `as_scope` is stacked immediately on top of `parent_gz`. Unstacks `as_scope`.
9430 fn finishCoercion(8964 fn finishCoercion(
9431 as_scope: *GenZir,8965 as_scope: *GenZir,
9432 parent_gz: *GenZir,8966 parent_gz: *GenZir,
...@@ -9434,25 +8968,32 @@ const GenZir = struct {...@@ -9434,25 +8968,32 @@ const GenZir = struct {
9434 src_node: Ast.Node.Index,8968 src_node: Ast.Node.Index,
9435 result: Zir.Inst.Ref,8969 result: Zir.Inst.Ref,
9436 dest_type: Zir.Inst.Ref,8970 dest_type: Zir.Inst.Ref,
9437 ) !Zir.Inst.Ref {8971 ) InnerError!Zir.Inst.Ref {
8972 assert(as_scope.instructions == parent_gz.instructions);
9438 const astgen = as_scope.astgen;8973 const astgen = as_scope.astgen;
9439 const parent_zir = &parent_gz.instructions;
9440 if (as_scope.rvalue_rl_count == 1) {8974 if (as_scope.rvalue_rl_count == 1) {
9441 // Busted! This expression didn't actually need a pointer.8975 // Busted! This expression didn't actually need a pointer.
9442 const zir_tags = astgen.instructions.items(.tag);8976 const zir_tags = astgen.instructions.items(.tag);
9443 const zir_datas = astgen.instructions.items(.data);8977 const zir_datas = astgen.instructions.items(.data);
9444 try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len);8978 var src: usize = as_scope.instructions_top;
9445 for (as_scope.instructions.items) |src_inst| {8979 var dst: usize = src;
8980 while (src < as_scope.instructions.items.len) : (src += 1) {
8981 const src_inst = as_scope.instructions.items[src];
9446 if (indexToRef(src_inst) == as_scope.rl_ptr) continue;8982 if (indexToRef(src_inst) == as_scope.rl_ptr) continue;
9447 if (zir_tags[src_inst] == .store_to_block_ptr) {8983 if (zir_tags[src_inst] == .store_to_block_ptr) {
9448 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;8984 if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;
9449 }8985 }
9450 parent_zir.appendAssumeCapacity(src_inst);8986 as_scope.instructions.items[dst] = src_inst;
8987 dst += 1;
9451 }8988 }
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
9452 const casted_result = try parent_gz.addBin(.as, dest_type, result);8992 const casted_result = try parent_gz.addBin(.as, dest_type, result);
9453 return rvalue(parent_gz, rl, casted_result, src_node);8993 return rvalue(parent_gz, rl, casted_result, src_node);
9454 } else {8994 } 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;
9456 return result;8997 return result;
9457 }8998 }
9458 }8999 }
...@@ -9463,9 +9004,10 @@ const GenZir = struct {...@@ -9463,9 +9004,10 @@ const GenZir = struct {
9463 used: bool = false,9004 used: bool = false,
9464 };9005 };
94659006
9007 /// Assumes nothing stacked on `gz`.
9466 fn endsWithNoReturn(gz: GenZir) bool {9008 fn endsWithNoReturn(gz: GenZir) bool {
9009 if (gz.isEmpty()) return false;
9467 const tags = gz.astgen.instructions.items(.tag);9010 const tags = gz.astgen.instructions.items(.tag);
9468 if (gz.instructions.items.len == 0) return false;
9469 const last_inst = gz.instructions.items[gz.instructions.items.len - 1];9011 const last_inst = gz.instructions.items[gz.instructions.items.len - 1];
9470 return tags[last_inst].isNoReturn();9012 return tags[last_inst].isNoReturn();
9471 }9013 }
...@@ -9535,41 +9077,46 @@ const GenZir = struct {...@@ -9535,41 +9077,46 @@ const GenZir = struct {
9535 }9077 }
9536 }9078 }
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 {
9539 const gpa = gz.astgen.gpa;9082 const gpa = gz.astgen.gpa;
9540 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +9083 const body = gz.instructionsSlice();
9541 gz.instructions.items.len);9084 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
9542 const zir_datas = gz.astgen.instructions.items(.data);9085 const zir_datas = gz.astgen.instructions.items(.data);
9543 zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity(9086 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) },
9545 );9088 );
9546 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);9089 gz.astgen.extra.appendSliceAssumeCapacity(body);
9090 gz.unstack();
9547 }9091 }
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 {
9550 const gpa = gz.astgen.gpa;9095 const gpa = gz.astgen.gpa;
9551 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +9096 const body = gz.instructionsSlice();
9552 gz.instructions.items.len);9097 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
9553 const zir_datas = gz.astgen.instructions.items(.data);9098 const zir_datas = gz.astgen.instructions.items(.data);
9554 zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity(9099 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) },
9556 );9101 );
9557 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);9102 gz.astgen.extra.appendSliceAssumeCapacity(body);
9103 gz.unstack();
9558 }9104 }
95599105
9560 /// Same as `setBlockBody` except we don't copy instructions which are9106 /// Same as `setBlockBody` except we don't copy instructions which are
9561 /// `store_to_block_ptr` instructions with lhs set to .none.9107 /// `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 {
9563 const gpa = gz.astgen.gpa;9110 const gpa = gz.astgen.gpa;
9564 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len +9111 const body = gz.instructionsSlice();
9565 gz.instructions.items.len);9112 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len);
9566 const zir_datas = gz.astgen.instructions.items(.data);9113 const zir_datas = gz.astgen.instructions.items(.data);
9567 const zir_tags = gz.astgen.instructions.items(.tag);9114 const zir_tags = gz.astgen.instructions.items(.tag);
9568 const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{9115 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),
9570 });9117 });
9571 zir_datas[inst].pl_node.payload_index = block_pl_index;9118 zir_datas[inst].pl_node.payload_index = block_pl_index;
9572 for (gz.instructions.items) |sub_inst| {9119 for (body) |sub_inst| {
9573 if (zir_tags[sub_inst] == .store_to_block_ptr and9120 if (zir_tags[sub_inst] == .store_to_block_ptr and
9574 zir_datas[sub_inst].bin.lhs == .none)9121 zir_datas[sub_inst].bin.lhs == .none)
9575 {9122 {
...@@ -9579,15 +9126,17 @@ const GenZir = struct {...@@ -9579,15 +9126,17 @@ const GenZir = struct {
9579 }9126 }
9580 gz.astgen.extra.appendAssumeCapacity(sub_inst);9127 gz.astgen.extra.appendAssumeCapacity(sub_inst);
9581 }9128 }
9129 gz.unstack();
9582 }9130 }
95839131
9132 /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`.
9584 fn addFunc(gz: *GenZir, args: struct {9133 fn addFunc(gz: *GenZir, args: struct {
9585 src_node: Ast.Node.Index,9134 src_node: Ast.Node.Index,
9586 lbrace_line: u32 = 0,9135 lbrace_line: u32 = 0,
9587 lbrace_column: u32 = 0,9136 lbrace_column: u32 = 0,
9588 body: []const Zir.Inst.Index,9137 body_gz: ?*GenZir,
9589 param_block: Zir.Inst.Index,9138 param_block: Zir.Inst.Index,
9590 ret_ty: []const Zir.Inst.Index,9139 ret_gz: ?*GenZir,
9591 ret_br: Zir.Inst.Index,9140 ret_br: Zir.Inst.Index,
9592 cc: Zir.Inst.Ref,9141 cc: Zir.Inst.Ref,
9593 align_inst: Zir.Inst.Ref,9142 align_inst: Zir.Inst.Ref,
...@@ -9601,12 +9150,13 @@ const GenZir = struct {...@@ -9601,12 +9150,13 @@ const GenZir = struct {
9601 const astgen = gz.astgen;9150 const astgen = gz.astgen;
9602 const gpa = astgen.gpa;9151 const gpa = astgen.gpa;
96039152
9604 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9605 try astgen.instructions.ensureUnusedCapacity(gpa, 1);9153 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{};
9607 var src_locs_buffer: [3]u32 = undefined;9157 var src_locs_buffer: [3]u32 = undefined;
9608 var src_locs: []u32 = src_locs_buffer[0..0];9158 var src_locs: []u32 = src_locs_buffer[0..0];
9609 if (args.body.len != 0) {9159 if (args.body_gz) |body_gz| {
9610 const tree = astgen.tree;9160 const tree = astgen.tree;
9611 const node_tags = tree.nodes.items(.tag);9161 const node_tags = tree.nodes.items(.tag);
9612 const node_datas = tree.nodes.items(.data);9162 const node_datas = tree.nodes.items(.data);
...@@ -9624,6 +9174,13 @@ const GenZir = struct {...@@ -9624,6 +9174,13 @@ const GenZir = struct {
9624 src_locs_buffer[1] = rbrace_line;9174 src_locs_buffer[1] = rbrace_line;
9625 src_locs_buffer[2] = columns;9175 src_locs_buffer[2] = columns;
9626 src_locs = &src_locs_buffer;9176 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();
9627 }9184 }
96289185
9629 if (args.cc != .none or args.lib_name != 0 or9186 if (args.cc != .none or args.lib_name != 0 or
...@@ -9633,7 +9190,7 @@ const GenZir = struct {...@@ -9633,7 +9190,7 @@ const GenZir = struct {
9633 try astgen.extra.ensureUnusedCapacity(9190 try astgen.extra.ensureUnusedCapacity(
9634 gpa,9191 gpa,
9635 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +9192 @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 +
9637 @boolToInt(args.lib_name != 0) +9194 @boolToInt(args.lib_name != 0) +
9638 @boolToInt(args.align_inst != .none) +9195 @boolToInt(args.align_inst != .none) +
9639 @boolToInt(args.cc != .none),9196 @boolToInt(args.cc != .none),
...@@ -9641,8 +9198,8 @@ const GenZir = struct {...@@ -9641,8 +9198,8 @@ const GenZir = struct {
9641 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{9198 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
9642 .src_node = gz.nodeIndexToRelative(args.src_node),9199 .src_node = gz.nodeIndexToRelative(args.src_node),
9643 .param_block = args.param_block,9200 .param_block = args.param_block,
9644 .ret_body_len = @intCast(u32, args.ret_ty.len),9201 .ret_body_len = @intCast(u32, ret_ty.len),
9645 .body_len = @intCast(u32, args.body.len),9202 .body_len = @intCast(u32, body.len),
9646 });9203 });
9647 if (args.lib_name != 0) {9204 if (args.lib_name != 0) {
9648 astgen.extra.appendAssumeCapacity(args.lib_name);9205 astgen.extra.appendAssumeCapacity(args.lib_name);
...@@ -9653,9 +9210,13 @@ const GenZir = struct {...@@ -9653,9 +9210,13 @@ const GenZir = struct {
9653 if (args.align_inst != .none) {9210 if (args.align_inst != .none) {
9654 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));9211 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
9655 }9212 }
9656 astgen.extra.appendSliceAssumeCapacity(args.ret_ty);9213 astgen.extra.appendSliceAssumeCapacity(ret_ty);
9657 astgen.extra.appendSliceAssumeCapacity(args.body);9214 astgen.extra.appendSliceAssumeCapacity(body);
9658 astgen.extra.appendSliceAssumeCapacity(src_locs);9215 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
9660 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);9221 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
9661 if (args.ret_br != 0) {9222 if (args.ret_br != 0) {
...@@ -9683,17 +9244,21 @@ const GenZir = struct {...@@ -9683,17 +9244,21 @@ const GenZir = struct {
9683 try astgen.extra.ensureUnusedCapacity(9244 try astgen.extra.ensureUnusedCapacity(
9684 gpa,9245 gpa,
9685 @typeInfo(Zir.Inst.Func).Struct.fields.len +9246 @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,
9687 );9248 );
96889249
9689 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{9250 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
9690 .param_block = args.param_block,9251 .param_block = args.param_block,
9691 .ret_body_len = @intCast(u32, args.ret_ty.len),9252 .ret_body_len = @intCast(u32, ret_ty.len),
9692 .body_len = @intCast(u32, args.body.len),9253 .body_len = @intCast(u32, body.len),
9693 });9254 });
9694 astgen.extra.appendSliceAssumeCapacity(args.ret_ty);9255 astgen.extra.appendSliceAssumeCapacity(ret_ty);
9695 astgen.extra.appendSliceAssumeCapacity(args.body);9256 astgen.extra.appendSliceAssumeCapacity(body);
9696 astgen.extra.appendSliceAssumeCapacity(src_locs);9257 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
9698 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;9263 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
9699 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);9264 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
...@@ -9765,44 +9330,6 @@ const GenZir = struct {...@@ -9765,44 +9330,6 @@ const GenZir = struct {
9765 return indexToRef(new_index);9330 return indexToRef(new_index);
9766 }9331 }
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
9806 /// Note that this returns a `Zir.Inst.Index` not a ref.9333 /// Note that this returns a `Zir.Inst.Index` not a ref.
9807 /// Leaves the `payload_index` field undefined.9334 /// Leaves the `payload_index` field undefined.
9808 fn addBoolBr(9335 fn addBoolBr(
...@@ -9878,6 +9405,25 @@ const GenZir = struct {...@@ -9878,6 +9405,25 @@ const GenZir = struct {
9878 });9405 });
9879 }9406 }
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
9881 fn addPlNode(9427 fn addPlNode(
9882 gz: *GenZir,9428 gz: *GenZir,
9883 tag: Zir.Inst.Tag,9429 tag: Zir.Inst.Tag,
...@@ -9902,25 +9448,43 @@ const GenZir = struct {...@@ -9902,25 +9448,43 @@ const GenZir = struct {
9902 return indexToRef(new_index);9448 return indexToRef(new_index);
9903 }9449 }
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`.
9905 fn addParam(9468 fn addParam(
9906 gz: *GenZir,9469 gz: *GenZir,
9470 param_gz: *GenZir,
9907 tag: Zir.Inst.Tag,9471 tag: Zir.Inst.Tag,
9908 /// Absolute token index. This function does the conversion to Decl offset.9472 /// Absolute token index. This function does the conversion to Decl offset.
9909 abs_tok_index: Ast.TokenIndex,9473 abs_tok_index: Ast.TokenIndex,
9910 name: u32,9474 name: u32,
9911 body: []const u32,
9912 ) !Zir.Inst.Index {9475 ) !Zir.Inst.Index {
9913 const gpa = gz.astgen.gpa;9476 const gpa = gz.astgen.gpa;
9914 try gz.instructions.ensureUnusedCapacity(gpa, 1);9477 const param_body = param_gz.instructionsSlice();
9915 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);9478 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
9916 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len +9479 try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len +
9917 body.len);9480 param_body.len);
99189481
9919 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{9482 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{
9920 .name = name,9483 .name = name,
9921 .body_len = @intCast(u32, body.len),9484 .body_len = @intCast(u32, param_body.len),
9922 });9485 });
9923 gz.astgen.extra.appendSliceAssumeCapacity(body);9486 gz.astgen.extra.appendSliceAssumeCapacity(param_body);
9487 param_gz.unstack();
99249488
9925 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);9489 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
9926 gz.astgen.instructions.appendAssumeCapacity(.{9490 gz.astgen.instructions.appendAssumeCapacity(.{
...@@ -9991,6 +9555,30 @@ const GenZir = struct {...@@ -9991,6 +9555,30 @@ const GenZir = struct {
9991 return indexToRef(new_index);9555 return indexToRef(new_index);
9992 }9556 }
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
9994 fn addUnTok(9582 fn addUnTok(
9995 gz: *GenZir,9583 gz: *GenZir,
9996 tag: Zir.Inst.Tag,9584 tag: Zir.Inst.Tag,
...@@ -10039,6 +9627,23 @@ const GenZir = struct {...@@ -10039,6 +9627,23 @@ const GenZir = struct {
10039 });9627 });
10040 }9628 }
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
10042 fn addBin(9647 fn addBin(
10043 gz: *GenZir,9648 gz: *GenZir,
10044 tag: Zir.Inst.Tag,9649 tag: Zir.Inst.Tag,
...@@ -10227,7 +9832,7 @@ const GenZir = struct {...@@ -10227,7 +9832,7 @@ const GenZir = struct {
10227 /// Note that this returns a `Zir.Inst.Index` not a ref.9832 /// Note that this returns a `Zir.Inst.Index` not a ref.
10228 /// Does *not* append the block instruction to the scope.9833 /// Does *not* append the block instruction to the scope.
10229 /// Leaves the `payload_index` field undefined.9834 /// 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 {
10231 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);9836 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
10232 const gpa = gz.astgen.gpa;9837 const gpa = gz.astgen.gpa;
10233 try gz.astgen.instructions.append(gpa, .{9838 try gz.astgen.instructions.append(gpa, .{
...@@ -10464,6 +10069,15 @@ const GenZir = struct {...@@ -10464,6 +10069,15 @@ const GenZir = struct {
10464 else => unreachable,10069 else => unreachable,
10465 }10070 }
10466 }10071 }
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 }
10467};10081};
1046810082
10469/// This can only be for short-lived references; the memory becomes invalidated10083/// 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 {...@@ -10581,12 +10195,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
10581 astgen.source_column = column;10195 astgen.source_column = column;
10582}10196}
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 {
10585 const gpa = astgen.gpa;10199 const gpa = astgen.gpa;
10586 const tree = astgen.tree;10200 const tree = astgen.tree;
10587 const node_tags = tree.nodes.items(.tag);10201 const node_tags = tree.nodes.items(.tag);
10588 const main_tokens = tree.nodes.items(.main_token);10202 const main_tokens = tree.nodes.items(.main_token);
10589 const token_tags = tree.tokens.items(.tag);10203 const token_tags = tree.tokens.items(.tag);
10204 var decl_count: u32 = 0;
10590 for (members) |member_node| {10205 for (members) |member_node| {
10591 const name_token = switch (node_tags[member_node]) {10206 const name_token = switch (node_tags[member_node]) {
10592 .fn_proto_simple,10207 .fn_proto_simple,
...@@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10597 .local_var_decl,10212 .local_var_decl,
10598 .simple_var_decl,10213 .simple_var_decl,
10599 .aligned_var_decl,10214 .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
10602 .fn_decl => blk: {10220 .fn_decl => blk: {
10221 decl_count += 1;
10603 const ident = main_tokens[member_node] + 1;10222 const ident = main_tokens[member_node] + 1;
10604 if (token_tags[ident] != .identifier) {10223 if (token_tags[ident] != .identifier) {
10605 switch (astgen.failNode(member_node, "missing function name", .{})) {10224 switch (astgen.failNode(member_node, "missing function name", .{})) {
...@@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10610 break :blk ident;10229 break :blk ident;
10611 },10230 },
1061210231
10232 .@"comptime", .@"usingnamespace", .test_decl => {
10233 decl_count += 1;
10234 continue;
10235 },
10236
10613 else => continue,10237 else => continue,
10614 };10238 };
1061510239
...@@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
10643 }10267 }
10644 gop.value_ptr.* = member_node;10268 gop.value_ptr.* = member_node;
10645 }10269 }
10270 return decl_count;
10646}10271}