authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-27 02:00:55+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-29 23:38:17+00:00
logf6abf022b790847e6145569241e4e5685abf359c
tree3058edcd61dcbe4d531c7705da8d3e0566967710
parentf0a4bb6bd15b8a605e450af3359fe1622302463a
signaturelock-open Commit is signed but in an unrecognized format.

AstGen: elide block instruction when already in empty body

In the code `if (cond) { ... }`, the "then body" of the `if` is technically a block. However, we don't need to emit a real ZIR `block` corresponding to it, because we are already within a condbr body; we have a separate gz, and appropriate scoping for allocs and debug variables. In this case, and many like it, we can trivially elide the block here, instead emitting the block statements directly into the current `GenZir`. This results in a significant decrease in ZIR bytes for real code.

1 files changed, 81 insertions(+), 29 deletions(-)

lib/std/zig/AstGen.zig+81-29
...@@ -1232,7 +1232,7 @@ fn suspendExpr(...@@ -1232,7 +1232,7 @@ fn suspendExpr(
1232 suspend_scope.suspend_node = node;1232 suspend_scope.suspend_node = node;
1233 defer suspend_scope.unstack();1233 defer suspend_scope.unstack();
12341234
1235 const body_result = try expr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node);1235 const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node);
1236 if (!gz.refIsNoReturn(body_result)) {1236 if (!gz.refIsNoReturn(body_result)) {
1237 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);1237 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);
1238 }1238 }
...@@ -1353,7 +1353,7 @@ fn fnProtoExpr(...@@ -1353,7 +1353,7 @@ fn fnProtoExpr(
1353 assert(param_type_node != 0);1353 assert(param_type_node != 0);
1354 var param_gz = block_scope.makeSubBlock(scope);1354 var param_gz = block_scope.makeSubBlock(scope);
1355 defer param_gz.unstack();1355 defer param_gz.unstack();
1356 const param_type = try expr(&param_gz, scope, coerced_type_ri, param_type_node);1356 const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node);
1357 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);1357 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
1358 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);1358 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
1359 const main_tokens = tree.nodes.items(.main_token);1359 const main_tokens = tree.nodes.items(.main_token);
...@@ -2060,7 +2060,7 @@ fn comptimeExpr(...@@ -2060,7 +2060,7 @@ fn comptimeExpr(
2060 else2060 else
2061 .none,2061 .none,
2062 };2062 };
2063 const block_result = try expr(&block_scope, scope, ty_only_ri, node);2063 const block_result = try fullBodyExpr(&block_scope, scope, ty_only_ri, node);
2064 if (!gz.refIsNoReturn(block_result)) {2064 if (!gz.refIsNoReturn(block_result)) {
2065 _ = try block_scope.addBreak(.@"break", block_inst, block_result);2065 _ = try block_scope.addBreak(.@"break", block_inst, block_result);
2066 }2066 }
...@@ -2291,6 +2291,53 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2291,6 +2291,53 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2291 }2291 }
2292}2292}
22932293
2294/// Similar to `expr`, but intended for use when `gz` corresponds to a body
2295/// which will contain only this node's code. Differs from `expr` in that if the
2296/// root expression is an unlabeled block, does not emit an actual block.
2297/// Instead, the block contents are emitted directly into `gz`.
2298fn fullBodyExpr(
2299 gz: *GenZir,
2300 scope: *Scope,
2301 ri: ResultInfo,
2302 node: Ast.Node.Index,
2303) InnerError!Zir.Inst.Ref {
2304 const tree = gz.astgen.tree;
2305 const node_tags = tree.nodes.items(.tag);
2306 const node_datas = tree.nodes.items(.data);
2307 const main_tokens = tree.nodes.items(.main_token);
2308 const token_tags = tree.tokens.items(.tag);
2309 var stmt_buf: [2]Ast.Node.Index = undefined;
2310 const statements: []const Ast.Node.Index = switch (node_tags[node]) {
2311 else => return expr(gz, scope, ri, node),
2312 .block_two, .block_two_semicolon => if (node_datas[node].lhs == 0) s: {
2313 break :s &.{};
2314 } else if (node_datas[node].rhs == 0) s: {
2315 stmt_buf[0] = node_datas[node].lhs;
2316 break :s stmt_buf[0..1];
2317 } else s: {
2318 stmt_buf[0] = node_datas[node].lhs;
2319 stmt_buf[1] = node_datas[node].rhs;
2320 break :s stmt_buf[0..2];
2321 },
2322 .block, .block_semicolon => tree.extra_data[node_datas[node].lhs..node_datas[node].rhs],
2323 };
2324
2325 const lbrace = main_tokens[node];
2326 if (token_tags[lbrace - 1] == .colon and
2327 token_tags[lbrace - 2] == .identifier)
2328 {
2329 // Labeled blocks are tricky - forwarding result location information properly is non-trivial,
2330 // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This
2331 // case is rare, so just treat it as a normal expression and create a nested block.
2332 return expr(gz, scope, ri, node);
2333 }
2334
2335 var sub_gz = gz.makeSubBlock(scope);
2336 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
2337
2338 return rvalue(gz, ri, .void_value, node);
2339}
2340
2294fn blockExpr(2341fn blockExpr(
2295 gz: *GenZir,2342 gz: *GenZir,
2296 scope: *Scope,2343 scope: *Scope,
...@@ -4102,7 +4149,7 @@ fn fnDecl(...@@ -4102,7 +4149,7 @@ fn fnDecl(
4102 assert(param_type_node != 0);4149 assert(param_type_node != 0);
4103 var param_gz = decl_gz.makeSubBlock(scope);4150 var param_gz = decl_gz.makeSubBlock(scope);
4104 defer param_gz.unstack();4151 defer param_gz.unstack();
4105 const param_type = try expr(&param_gz, params_scope, coerced_type_ri, param_type_node);4152 const param_type = try fullBodyExpr(&param_gz, params_scope, coerced_type_ri, param_type_node);
4106 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);4153 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
4107 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);4154 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
41084155
...@@ -4220,7 +4267,7 @@ fn fnDecl(...@@ -4220,7 +4267,7 @@ fn fnDecl(
4220 var ret_gz = decl_gz.makeSubBlock(params_scope);4267 var ret_gz = decl_gz.makeSubBlock(params_scope);
4221 defer ret_gz.unstack();4268 defer ret_gz.unstack();
4222 const ret_ref: Zir.Inst.Ref = inst: {4269 const ret_ref: Zir.Inst.Ref = inst: {
4223 const inst = try expr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type);4270 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type);
4224 if (ret_gz.instructionsSlice().len == 0) {4271 if (ret_gz.instructionsSlice().len == 0) {
4225 // In this case we will send a len=0 body which can be encoded more efficiently.4272 // In this case we will send a len=0 body which can be encoded more efficiently.
4226 break :inst inst;4273 break :inst inst;
...@@ -4285,7 +4332,7 @@ fn fnDecl(...@@ -4285,7 +4332,7 @@ fn fnDecl(
4285 const lbrace_line = astgen.source_line - decl_gz.decl_line;4332 const lbrace_line = astgen.source_line - decl_gz.decl_line;
4286 const lbrace_column = astgen.source_column;4333 const lbrace_column = astgen.source_column;
42874334
4288 _ = try expr(&fn_gz, params_scope, .{ .rl = .none }, body_node);4335 _ = try fullBodyExpr(&fn_gz, params_scope, .{ .rl = .none }, body_node);
4289 try checkUsed(gz, &fn_gz.base, params_scope);4336 try checkUsed(gz, &fn_gz.base, params_scope);
42904337
4291 if (!fn_gz.endsWithNoReturn()) {4338 if (!fn_gz.endsWithNoReturn()) {
...@@ -4471,19 +4518,19 @@ fn globalVarDecl(...@@ -4471,19 +4518,19 @@ fn globalVarDecl(
44714518
4472 var align_gz = block_scope.makeSubBlock(scope);4519 var align_gz = block_scope.makeSubBlock(scope);
4473 if (var_decl.ast.align_node != 0) {4520 if (var_decl.ast.align_node != 0) {
4474 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);4521 const align_inst = try fullBodyExpr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);
4475 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);4522 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4476 }4523 }
44774524
4478 var linksection_gz = align_gz.makeSubBlock(scope);4525 var linksection_gz = align_gz.makeSubBlock(scope);
4479 if (var_decl.ast.section_node != 0) {4526 if (var_decl.ast.section_node != 0) {
4480 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);4527 const linksection_inst = try fullBodyExpr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);
4481 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);4528 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4482 }4529 }
44834530
4484 var addrspace_gz = linksection_gz.makeSubBlock(scope);4531 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4485 if (var_decl.ast.addrspace_node != 0) {4532 if (var_decl.ast.addrspace_node != 0) {
4486 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node);4533 const addrspace_inst = try fullBodyExpr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node);
4487 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);4534 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4488 }4535 }
44894536
...@@ -4532,7 +4579,7 @@ fn comptimeDecl(...@@ -4532,7 +4579,7 @@ fn comptimeDecl(
4532 };4579 };
4533 defer decl_block.unstack();4580 defer decl_block.unstack();
45344581
4535 const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);4582 const block_result = try fullBodyExpr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);
4536 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {4583 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
4537 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);4584 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);
4538 }4585 }
...@@ -4734,7 +4781,7 @@ fn testDecl(...@@ -4734,7 +4781,7 @@ fn testDecl(
4734 const lbrace_line = astgen.source_line - decl_block.decl_line;4781 const lbrace_line = astgen.source_line - decl_block.decl_line;
4735 const lbrace_column = astgen.source_column;4782 const lbrace_column = astgen.source_column;
47364783
4737 const block_result = try expr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node);4784 const block_result = try fullBodyExpr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node);
4738 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {4785 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
47394786
4740 // As our last action before the return, "pop" the error trace if needed4787 // As our last action before the return, "pop" the error trace if needed
...@@ -5981,7 +6028,7 @@ fn orelseCatchExpr(...@@ -5981,7 +6028,7 @@ fn orelseCatchExpr(
5981 break :blk &err_val_scope.base;6028 break :blk &err_val_scope.base;
5982 };6029 };
59836030
5984 const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs);6031 const else_result = try fullBodyExpr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs);
5985 if (!else_scope.endsWithNoReturn()) {6032 if (!else_scope.endsWithNoReturn()) {
5986 // As our last action before the break, "pop" the error trace if needed6033 // As our last action before the break, "pop" the error trace if needed
5987 if (do_err_trace)6034 if (do_err_trace)
...@@ -6149,7 +6196,7 @@ fn boolBinOp(...@@ -6149,7 +6196,7 @@ fn boolBinOp(
61496196
6150 var rhs_scope = gz.makeSubBlock(scope);6197 var rhs_scope = gz.makeSubBlock(scope);
6151 defer rhs_scope.unstack();6198 defer rhs_scope.unstack();
6152 const rhs = try expr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs);6199 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs);
6153 if (!gz.refIsNoReturn(rhs)) {6200 if (!gz.refIsNoReturn(rhs)) {
6154 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);6201 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
6155 }6202 }
...@@ -6293,7 +6340,7 @@ fn ifExpr(...@@ -6293,7 +6340,7 @@ fn ifExpr(
6293 }6340 }
6294 };6341 };
62956342
6296 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);6343 const then_result = try fullBodyExpr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);
6297 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6344 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6298 if (!then_scope.endsWithNoReturn()) {6345 if (!then_scope.endsWithNoReturn()) {
6299 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node);6346 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node);
...@@ -6335,7 +6382,7 @@ fn ifExpr(...@@ -6335,7 +6382,7 @@ fn ifExpr(
6335 break :s &else_scope.base;6382 break :s &else_scope.base;
6336 }6383 }
6337 };6384 };
6338 const else_result = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node);6385 const else_result = try fullBodyExpr(&else_scope, sub_scope, block_scope.break_result_info, else_node);
6339 if (!else_scope.endsWithNoReturn()) {6386 if (!else_scope.endsWithNoReturn()) {
6340 // As our last action before the break, "pop" the error trace if needed6387 // As our last action before the break, "pop" the error trace if needed
6341 if (do_err_trace)6388 if (do_err_trace)
...@@ -6444,7 +6491,7 @@ fn whileExpr(...@@ -6444,7 +6491,7 @@ fn whileExpr(
6444 } = c: {6491 } = c: {
6445 if (while_full.error_token) |_| {6492 if (while_full.error_token) |_| {
6446 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };6493 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
6447 const err_union = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);6494 const err_union = try fullBodyExpr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
6448 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;6495 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
6449 break :c .{6496 break :c .{
6450 .inst = err_union,6497 .inst = err_union,
...@@ -6452,14 +6499,14 @@ fn whileExpr(...@@ -6452,14 +6499,14 @@ fn whileExpr(
6452 };6499 };
6453 } else if (while_full.payload_token) |_| {6500 } else if (while_full.payload_token) |_| {
6454 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };6501 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
6455 const optional = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);6502 const optional = try fullBodyExpr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
6456 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;6503 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
6457 break :c .{6504 break :c .{
6458 .inst = optional,6505 .inst = optional,
6459 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr),6506 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr),
6460 };6507 };
6461 } else {6508 } else {
6462 const cond = try expr(&cond_scope, &cond_scope.base, coerced_bool_ri, while_full.ast.cond_expr);6509 const cond = try fullBodyExpr(&cond_scope, &cond_scope.base, coerced_bool_ri, while_full.ast.cond_expr);
6463 break :c .{6510 break :c .{
6464 .inst = cond,6511 .inst = cond,
6465 .bool_bit = cond,6512 .bool_bit = cond,
...@@ -6582,7 +6629,11 @@ fn whileExpr(...@@ -6582,7 +6629,11 @@ fn whileExpr(
6582 }6629 }
65836630
6584 continue_scope.instructions_top = continue_scope.instructions.items.len;6631 continue_scope.instructions_top = continue_scope.instructions.items.len;
6585 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node);6632 {
6633 try emitDbgNode(&continue_scope, then_node);
6634 const unused_result = try fullBodyExpr(&continue_scope, &continue_scope.base, .{ .rl = .none }, then_node);
6635 _ = try addEnsureResult(&continue_scope, unused_result, then_node);
6636 }
6586 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6637 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6587 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6638 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6588 if (!continue_scope.endsWithNoReturn()) {6639 if (!continue_scope.endsWithNoReturn()) {
...@@ -6626,7 +6677,7 @@ fn whileExpr(...@@ -6626,7 +6677,7 @@ fn whileExpr(
6626 // control flow apply to outer loops; not this one.6677 // control flow apply to outer loops; not this one.
6627 loop_scope.continue_block = .none;6678 loop_scope.continue_block = .none;
6628 loop_scope.break_block = .none;6679 loop_scope.break_block = .none;
6629 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);6680 const else_result = try fullBodyExpr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
6630 if (is_statement) {6681 if (is_statement) {
6631 _ = try addEnsureResult(&else_scope, else_result, else_node);6682 _ = try addEnsureResult(&else_scope, else_result, else_node);
6632 }6683 }
...@@ -6894,7 +6945,7 @@ fn forExpr(...@@ -6894,7 +6945,7 @@ fn forExpr(
6894 break :blk capture_sub_scope;6945 break :blk capture_sub_scope;
6895 };6946 };
68966947
6897 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node);6948 const then_result = try fullBodyExpr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node);
6898 _ = try addEnsureResult(&then_scope, then_result, then_node);6949 _ = try addEnsureResult(&then_scope, then_result, then_node);
68996950
6900 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6951 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
...@@ -6913,7 +6964,7 @@ fn forExpr(...@@ -6913,7 +6964,7 @@ fn forExpr(
6913 // control flow apply to outer loops; not this one.6964 // control flow apply to outer loops; not this one.
6914 loop_scope.continue_block = .none;6965 loop_scope.continue_block = .none;
6915 loop_scope.break_block = .none;6966 loop_scope.break_block = .none;
6916 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);6967 const else_result = try fullBodyExpr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
6917 if (is_statement) {6968 if (is_statement) {
6918 _ = try addEnsureResult(&else_scope, else_result, else_node);6969 _ = try addEnsureResult(&else_scope, else_result, else_node);
6919 }6970 }
...@@ -7388,7 +7439,7 @@ fn switchExprErrUnion(...@@ -7388,7 +7439,7 @@ fn switchExprErrUnion(
7388 }7439 }
73897440
7390 const target_expr_node = case.ast.target_expr;7441 const target_expr_node = case.ast.target_expr;
7391 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);7442 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
7392 // check capture_scope, not err_scope to avoid false positive unused error capture7443 // check capture_scope, not err_scope to avoid false positive unused error capture
7393 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);7444 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
7394 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;7445 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;
...@@ -7849,7 +7900,7 @@ fn switchExpr(...@@ -7849,7 +7900,7 @@ fn switchExpr(
7849 try case_scope.addDbgVar(.dbg_var_val, dbg_var_tag_name, dbg_var_tag_inst);7900 try case_scope.addDbgVar(.dbg_var_val, dbg_var_tag_name, dbg_var_tag_inst);
7850 }7901 }
7851 const target_expr_node = case.ast.target_expr;7902 const target_expr_node = case.ast.target_expr;
7852 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);7903 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
7853 try checkUsed(parent_gz, &case_scope.base, sub_scope);7904 try checkUsed(parent_gz, &case_scope.base, sub_scope);
7854 if (!parent_gz.refIsNoReturn(case_result)) {7905 if (!parent_gz.refIsNoReturn(case_result)) {
7855 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);7906 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);
...@@ -9752,7 +9803,7 @@ fn cImport(...@@ -9752,7 +9803,7 @@ fn cImport(
9752 defer block_scope.unstack();9803 defer block_scope.unstack();
97539804
9754 const block_inst = try gz.makeBlockInst(.c_import, node);9805 const block_inst = try gz.makeBlockInst(.c_import, node);
9755 const block_result = try expr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node);9806 const block_result = try fullBodyExpr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node);
9756 _ = try gz.addUnNode(.ensure_result_used, block_result, node);9807 _ = try gz.addUnNode(.ensure_result_used, block_result, node);
9757 if (!gz.refIsNoReturn(block_result)) {9808 if (!gz.refIsNoReturn(block_result)) {
9758 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);9809 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
...@@ -9835,7 +9886,7 @@ fn callExpr(...@@ -9835,7 +9886,7 @@ fn callExpr(
9835 defer arg_block.unstack();9886 defer arg_block.unstack();
98369887
9837 // `call_inst` is reused to provide the param type.9888 // `call_inst` is reused to provide the param type.
9838 const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);9889 const arg_ref = try fullBodyExpr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
9839 _ = try arg_block.addBreakWithSrcNode(.break_inline, call_index, arg_ref, param_node);9890 _ = try arg_block.addBreakWithSrcNode(.break_inline, call_index, arg_ref, param_node);
98409891
9841 const body = arg_block.instructionsSlice();9892 const body = arg_block.instructionsSlice();
...@@ -10871,11 +10922,11 @@ fn rvalueInner(...@@ -10871,11 +10922,11 @@ fn rvalueInner(
10871 .ty => |ty_inst| {10922 .ty => |ty_inst| {
10872 // Quickly eliminate some common, unnecessary type coercion.10923 // Quickly eliminate some common, unnecessary type coercion.
10873 const as_ty = @as(u64, @intFromEnum(Zir.Inst.Ref.type_type)) << 32;10924 const as_ty = @as(u64, @intFromEnum(Zir.Inst.Ref.type_type)) << 32;
10874 const as_comptime_int = @as(u64, @intFromEnum(Zir.Inst.Ref.comptime_int_type)) << 32;
10875 const as_bool = @as(u64, @intFromEnum(Zir.Inst.Ref.bool_type)) << 32;10925 const as_bool = @as(u64, @intFromEnum(Zir.Inst.Ref.bool_type)) << 32;
10926 const as_void = @as(u64, @intFromEnum(Zir.Inst.Ref.void_type)) << 32;
10927 const as_comptime_int = @as(u64, @intFromEnum(Zir.Inst.Ref.comptime_int_type)) << 32;
10876 const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32;10928 const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32;
10877 const as_u8 = @as(u64, @intFromEnum(Zir.Inst.Ref.u8_type)) << 32;10929 const as_u8 = @as(u64, @intFromEnum(Zir.Inst.Ref.u8_type)) << 32;
10878 const as_void = @as(u64, @intFromEnum(Zir.Inst.Ref.void_type)) << 32;
10879 switch ((@as(u64, @intFromEnum(ty_inst)) << 32) | @as(u64, @intFromEnum(result))) {10930 switch ((@as(u64, @intFromEnum(ty_inst)) << 32) | @as(u64, @intFromEnum(result))) {
10880 as_ty | @intFromEnum(Zir.Inst.Ref.u1_type),10931 as_ty | @intFromEnum(Zir.Inst.Ref.u1_type),
10881 as_ty | @intFromEnum(Zir.Inst.Ref.u8_type),10932 as_ty | @intFromEnum(Zir.Inst.Ref.u8_type),
...@@ -11694,7 +11745,8 @@ const GenZir = struct {...@@ -11694,7 +11745,8 @@ const GenZir = struct {
11694 /// Whether we're in an expression within a `@TypeOf` operand. In this case, closure of runtime11745 /// Whether we're in an expression within a `@TypeOf` operand. In this case, closure of runtime
11695 /// variables is permitted where it is usually not.11746 /// variables is permitted where it is usually not.
11696 is_typeof: bool = false,11747 is_typeof: bool = false,
11697 /// This is set to true for inline loops; false otherwise.11748 /// This is set to true for a `GenZir` of a `block_inline`, indicating that
11749 /// exits from this block should use `break_inline` rather than `break`.
11698 is_inline: bool = false,11750 is_inline: bool = false,
11699 c_import: bool = false,11751 c_import: bool = false,
11700 /// How decls created in this scope should be named.11752 /// How decls created in this scope should be named.