authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-02 04:52:19+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-02 04:52:19+00:00
log9d500bda2d09fe67c39ee98067c1e53c58adbd5e
treef841a65fdab25a8025835055722d994d3040a9a1
parent64f77f32df7656c3d7613d402b332f071ea15557
parent6a87e42c2ea070a6273317bbb005029d95ceae49
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19117 from mlugg/dbg-var-blocks

Major ZIR size optimizations & small cleanups in Sema

5 files changed, 422 insertions(+), 302 deletions(-)

lib/std/zig/AstGen.zig+114-35
......@@ -1232,7 +1232,7 @@ fn suspendExpr(
12321232 suspend_scope.suspend_node = node;
12331233 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);
12361236 if (!gz.refIsNoReturn(body_result)) {
12371237 _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value);
12381238 }
......@@ -1353,7 +1353,7 @@ fn fnProtoExpr(
13531353 assert(param_type_node != 0);
13541354 var param_gz = block_scope.makeSubBlock(scope);
13551355 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);
13571357 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
13581358 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
13591359 const main_tokens = tree.nodes.items(.main_token);
......@@ -2060,7 +2060,7 @@ fn comptimeExpr(
20602060 else
20612061 .none,
20622062 };
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);
20642064 if (!gz.refIsNoReturn(block_result)) {
20652065 _ = try block_scope.addBreak(.@"break", block_inst, block_result);
20662066 }
......@@ -2291,6 +2291,53 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
22912291 }
22922292}
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
22942341fn blockExpr(
22952342 gz: *GenZir,
22962343 scope: *Scope,
......@@ -2516,7 +2563,9 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
25162563 }
25172564 }
25182565
2519 try genDefers(gz, parent_scope, scope, .normal_only);
2566 if (noreturn_src_node == 0) {
2567 try genDefers(gz, parent_scope, scope, .normal_only);
2568 }
25202569 try checkUsed(gz, parent_scope, scope);
25212570}
25222571
......@@ -4102,7 +4151,7 @@ fn fnDecl(
41024151 assert(param_type_node != 0);
41034152 var param_gz = decl_gz.makeSubBlock(scope);
41044153 defer param_gz.unstack();
4105 const param_type = try expr(&param_gz, params_scope, coerced_type_ri, param_type_node);
4154 const param_type = try fullBodyExpr(&param_gz, params_scope, coerced_type_ri, param_type_node);
41064155 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
41074156 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
41084157
......@@ -4220,7 +4269,7 @@ fn fnDecl(
42204269 var ret_gz = decl_gz.makeSubBlock(params_scope);
42214270 defer ret_gz.unstack();
42224271 const ret_ref: Zir.Inst.Ref = inst: {
4223 const inst = try expr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type);
4272 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type);
42244273 if (ret_gz.instructionsSlice().len == 0) {
42254274 // In this case we will send a len=0 body which can be encoded more efficiently.
42264275 break :inst inst;
......@@ -4285,7 +4334,7 @@ fn fnDecl(
42854334 const lbrace_line = astgen.source_line - decl_gz.decl_line;
42864335 const lbrace_column = astgen.source_column;
42874336
4288 _ = try expr(&fn_gz, params_scope, .{ .rl = .none }, body_node);
4337 _ = try fullBodyExpr(&fn_gz, params_scope, .{ .rl = .none }, body_node);
42894338 try checkUsed(gz, &fn_gz.base, params_scope);
42904339
42914340 if (!fn_gz.endsWithNoReturn()) {
......@@ -4471,19 +4520,19 @@ fn globalVarDecl(
44714520
44724521 var align_gz = block_scope.makeSubBlock(scope);
44734522 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);
4523 const align_inst = try fullBodyExpr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);
44754524 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
44764525 }
44774526
44784527 var linksection_gz = align_gz.makeSubBlock(scope);
44794528 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);
4529 const linksection_inst = try fullBodyExpr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);
44814530 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
44824531 }
44834532
44844533 var addrspace_gz = linksection_gz.makeSubBlock(scope);
44854534 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);
4535 const addrspace_inst = try fullBodyExpr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node);
44874536 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
44884537 }
44894538
......@@ -4532,7 +4581,7 @@ fn comptimeDecl(
45324581 };
45334582 defer decl_block.unstack();
45344583
4535 const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);
4584 const block_result = try fullBodyExpr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);
45364585 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
45374586 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);
45384587 }
......@@ -4734,7 +4783,7 @@ fn testDecl(
47344783 const lbrace_line = astgen.source_line - decl_block.decl_line;
47354784 const lbrace_column = astgen.source_column;
47364785
4737 const block_result = try expr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node);
4786 const block_result = try fullBodyExpr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node);
47384787 if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) {
47394788
47404789 // As our last action before the return, "pop" the error trace if needed
......@@ -5981,7 +6030,7 @@ fn orelseCatchExpr(
59816030 break :blk &err_val_scope.base;
59826031 };
59836032
5984 const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs);
6033 const else_result = try fullBodyExpr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs);
59856034 if (!else_scope.endsWithNoReturn()) {
59866035 // As our last action before the break, "pop" the error trace if needed
59876036 if (do_err_trace)
......@@ -6149,7 +6198,7 @@ fn boolBinOp(
61496198
61506199 var rhs_scope = gz.makeSubBlock(scope);
61516200 defer rhs_scope.unstack();
6152 const rhs = try expr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs);
6201 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs);
61536202 if (!gz.refIsNoReturn(rhs)) {
61546203 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
61556204 }
......@@ -6293,7 +6342,7 @@ fn ifExpr(
62936342 }
62946343 };
62956344
6296 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);
6345 const then_result = try fullBodyExpr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);
62976346 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
62986347 if (!then_scope.endsWithNoReturn()) {
62996348 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node);
......@@ -6335,7 +6384,7 @@ fn ifExpr(
63356384 break :s &else_scope.base;
63366385 }
63376386 };
6338 const else_result = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node);
6387 const else_result = try fullBodyExpr(&else_scope, sub_scope, block_scope.break_result_info, else_node);
63396388 if (!else_scope.endsWithNoReturn()) {
63406389 // As our last action before the break, "pop" the error trace if needed
63416390 if (do_err_trace)
......@@ -6444,7 +6493,7 @@ fn whileExpr(
64446493 } = c: {
64456494 if (while_full.error_token) |_| {
64466495 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);
6496 const err_union = try fullBodyExpr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
64486497 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
64496498 break :c .{
64506499 .inst = err_union,
......@@ -6452,14 +6501,14 @@ fn whileExpr(
64526501 };
64536502 } else if (while_full.payload_token) |_| {
64546503 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);
6504 const optional = try fullBodyExpr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
64566505 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
64576506 break :c .{
64586507 .inst = optional,
64596508 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr),
64606509 };
64616510 } else {
6462 const cond = try expr(&cond_scope, &cond_scope.base, coerced_bool_ri, while_full.ast.cond_expr);
6511 const cond = try fullBodyExpr(&cond_scope, &cond_scope.base, coerced_bool_ri, while_full.ast.cond_expr);
64636512 break :c .{
64646513 .inst = cond,
64656514 .bool_bit = cond,
......@@ -6582,7 +6631,11 @@ fn whileExpr(
65826631 }
65836632
65846633 continue_scope.instructions_top = continue_scope.instructions.items.len;
6585 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node);
6634 {
6635 try emitDbgNode(&continue_scope, then_node);
6636 const unused_result = try fullBodyExpr(&continue_scope, &continue_scope.base, .{ .rl = .none }, then_node);
6637 _ = try addEnsureResult(&continue_scope, unused_result, then_node);
6638 }
65866639 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
65876640 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
65886641 if (!continue_scope.endsWithNoReturn()) {
......@@ -6626,7 +6679,7 @@ fn whileExpr(
66266679 // control flow apply to outer loops; not this one.
66276680 loop_scope.continue_block = .none;
66286681 loop_scope.break_block = .none;
6629 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
6682 const else_result = try fullBodyExpr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
66306683 if (is_statement) {
66316684 _ = try addEnsureResult(&else_scope, else_result, else_node);
66326685 }
......@@ -6894,7 +6947,7 @@ fn forExpr(
68946947 break :blk capture_sub_scope;
68956948 };
68966949
6897 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node);
6950 const then_result = try fullBodyExpr(&then_scope, then_sub_scope, .{ .rl = .none }, then_node);
68986951 _ = try addEnsureResult(&then_scope, then_result, then_node);
68996952
69006953 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
......@@ -6913,7 +6966,7 @@ fn forExpr(
69136966 // control flow apply to outer loops; not this one.
69146967 loop_scope.continue_block = .none;
69156968 loop_scope.break_block = .none;
6916 const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
6969 const else_result = try fullBodyExpr(&else_scope, sub_scope, loop_scope.break_result_info, else_node);
69176970 if (is_statement) {
69186971 _ = try addEnsureResult(&else_scope, else_result, else_node);
69196972 }
......@@ -7388,7 +7441,7 @@ fn switchExprErrUnion(
73887441 }
73897442
73907443 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);
7444 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
73927445 // check capture_scope, not err_scope to avoid false positive unused error capture
73937446 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
73947447 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;
......@@ -7849,7 +7902,7 @@ fn switchExpr(
78497902 try case_scope.addDbgVar(.dbg_var_val, dbg_var_tag_name, dbg_var_tag_inst);
78507903 }
78517904 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);
7905 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
78537906 try checkUsed(parent_gz, &case_scope.base, sub_scope);
78547907 if (!parent_gz.refIsNoReturn(case_result)) {
78557908 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);
......@@ -8405,7 +8458,14 @@ fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node:
84058458 try astgen.errNoteTok(num_token, "use '-0.0' for a floating-point signed zero", .{}),
84068459 },
84078460 ),
8408 1 => .one,
8461 1 => {
8462 // Handle the negation here!
8463 const result: Zir.Inst.Ref = switch (sign) {
8464 .positive => .one,
8465 .negative => .negative_one,
8466 };
8467 return rvalue(gz, ri, result, source_node);
8468 },
84098469 else => try gz.addInt(num),
84108470 },
84118471 .big_int => |base| big: {
......@@ -9752,7 +9812,7 @@ fn cImport(
97529812 defer block_scope.unstack();
97539813
97549814 const block_inst = try gz.makeBlockInst(.c_import, node);
9755 const block_result = try expr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node);
9815 const block_result = try fullBodyExpr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node);
97569816 _ = try gz.addUnNode(.ensure_result_used, block_result, node);
97579817 if (!gz.refIsNoReturn(block_result)) {
97589818 _ = try block_scope.addBreak(.break_inline, block_inst, .void_value);
......@@ -9835,7 +9895,7 @@ fn callExpr(
98359895 defer arg_block.unstack();
98369896
98379897 // `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);
9898 const arg_ref = try fullBodyExpr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
98399899 _ = try arg_block.addBreakWithSrcNode(.break_inline, call_index, arg_ref, param_node);
98409900
98419901 const body = arg_block.instructionsSlice();
......@@ -10871,10 +10931,11 @@ fn rvalueInner(
1087110931 .ty => |ty_inst| {
1087210932 // Quickly eliminate some common, unnecessary type coercion.
1087310933 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;
1087510934 const as_bool = @as(u64, @intFromEnum(Zir.Inst.Ref.bool_type)) << 32;
10876 const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32;
1087710935 const as_void = @as(u64, @intFromEnum(Zir.Inst.Ref.void_type)) << 32;
10936 const as_comptime_int = @as(u64, @intFromEnum(Zir.Inst.Ref.comptime_int_type)) << 32;
10937 const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32;
10938 const as_u8 = @as(u64, @intFromEnum(Zir.Inst.Ref.u8_type)) << 32;
1087810939 switch ((@as(u64, @intFromEnum(ty_inst)) << 32) | @as(u64, @intFromEnum(result))) {
1087910940 as_ty | @intFromEnum(Zir.Inst.Ref.u1_type),
1088010941 as_ty | @intFromEnum(Zir.Inst.Ref.u8_type),
......@@ -10939,13 +11000,30 @@ fn rvalueInner(
1093911000 as_ty | @intFromEnum(Zir.Inst.Ref.empty_struct_type),
1094011001 as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero),
1094111002 as_comptime_int | @intFromEnum(Zir.Inst.Ref.one),
10942 as_bool | @intFromEnum(Zir.Inst.Ref.bool_true),
10943 as_bool | @intFromEnum(Zir.Inst.Ref.bool_false),
11003 as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one),
1094411004 as_usize | @intFromEnum(Zir.Inst.Ref.zero_usize),
1094511005 as_usize | @intFromEnum(Zir.Inst.Ref.one_usize),
11006 as_u8 | @intFromEnum(Zir.Inst.Ref.zero_u8),
11007 as_u8 | @intFromEnum(Zir.Inst.Ref.one_u8),
11008 as_u8 | @intFromEnum(Zir.Inst.Ref.four_u8),
11009 as_bool | @intFromEnum(Zir.Inst.Ref.bool_true),
11010 as_bool | @intFromEnum(Zir.Inst.Ref.bool_false),
1094611011 as_void | @intFromEnum(Zir.Inst.Ref.void_value),
1094711012 => return result, // type of result is already correct
1094811013
11014 as_usize | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_usize,
11015 as_u8 | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_u8,
11016 as_usize | @intFromEnum(Zir.Inst.Ref.one) => return .one_usize,
11017 as_u8 | @intFromEnum(Zir.Inst.Ref.one) => return .one_u8,
11018 as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero,
11019 as_u8 | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero_u8,
11020 as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one,
11021 as_u8 | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one_u8,
11022 as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero,
11023 as_usize | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero_usize,
11024 as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one,
11025 as_usize | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one_usize,
11026
1094911027 // Need an explicit type coercion instruction.
1095011028 else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{
1095111029 .dest_type = ty_inst,
......@@ -11676,7 +11754,8 @@ const GenZir = struct {
1167611754 /// Whether we're in an expression within a `@TypeOf` operand. In this case, closure of runtime
1167711755 /// variables is permitted where it is usually not.
1167811756 is_typeof: bool = false,
11679 /// This is set to true for inline loops; false otherwise.
11757 /// This is set to true for a `GenZir` of a `block_inline`, indicating that
11758 /// exits from this block should use `break_inline` rather than `break`.
1168011759 is_inline: bool = false,
1168111760 c_import: bool = false,
1168211761 /// How decls created in this scope should be named.
......@@ -13471,7 +13550,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
1347113550
1347213551fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
1347313552 if (gz.is_comptime) return;
13474 if (gz.instructions.items.len > 0) {
13553 if (gz.instructions.items.len > gz.instructions_top) {
1347513554 const astgen = gz.astgen;
1347613555 const last = gz.instructions.items[gz.instructions.items.len - 1];
1347713556 if (astgen.instructions.items(.tag)[@intFromEnum(last)] == .dbg_stmt) {
......@@ -13497,7 +13576,7 @@ fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
1349713576/// instructions; fix up Sema so we don't need it!
1349813577fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void {
1349913578 const astgen = gz.astgen;
13500 if (gz.instructions.items.len > 0 and
13579 if (gz.instructions.items.len > gz.instructions_top and
1350113580 @intFromEnum(gz.instructions.items[gz.instructions.items.len - 1]) == astgen.instructions.len - 1)
1350213581 {
1350313582 const last = astgen.instructions.len - 1;
src/Autodoc.zig+39-22
......@@ -5137,7 +5137,7 @@ fn analyzeFancyFunction(
51375137 file,
51385138 scope,
51395139 parent_src,
5140 fn_info.body[0],
5140 fn_info.body,
51415141 call_ctx,
51425142 );
51435143 } else {
......@@ -5303,7 +5303,7 @@ fn analyzeFunction(
53035303 file,
53045304 scope,
53055305 parent_src,
5306 fn_info.body[0],
5306 fn_info.body,
53075307 call_ctx,
53085308 );
53095309 } else {
......@@ -5350,17 +5350,10 @@ fn getGenericReturnType(
53505350 file: *File,
53515351 scope: *Scope,
53525352 parent_src: SrcLocInfo, // function decl line
5353 body_main_block: Zir.Inst.Index,
5353 body: []const Zir.Inst.Index,
53545354 call_ctx: ?*const CallContext,
53555355) !DocData.Expr {
53565356 const tags = file.zir.instructions.items(.tag);
5357 const data = file.zir.instructions.items(.data);
5358
5359 // We expect `body_main_block` to be the first instruction
5360 // inside the function body, and for it to be a block instruction.
5361 const pl_node = data[@intFromEnum(body_main_block)].pl_node;
5362 const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index);
5363 const body = file.zir.bodySlice(extra.end, extra.data.body_len);
53645357 if (body.len >= 4) {
53655358 const maybe_ret_inst = body[body.len - 4];
53665359 switch (tags[@intFromEnum(maybe_ret_inst)]) {
......@@ -5676,6 +5669,42 @@ fn walkRef(
56765669 .expr = .{ .int = .{ .value = 1 } },
56775670 };
56785671 },
5672 .negative_one => {
5673 return DocData.WalkResult{
5674 .typeRef = .{ .type = @intFromEnum(Ref.comptime_int_type) },
5675 .expr = .{ .int = .{ .value = 1, .negated = true } },
5676 };
5677 },
5678 .zero_usize => {
5679 return DocData.WalkResult{
5680 .typeRef = .{ .type = @intFromEnum(Ref.usize_type) },
5681 .expr = .{ .int = .{ .value = 0 } },
5682 };
5683 },
5684 .one_usize => {
5685 return DocData.WalkResult{
5686 .typeRef = .{ .type = @intFromEnum(Ref.usize_type) },
5687 .expr = .{ .int = .{ .value = 1 } },
5688 };
5689 },
5690 .zero_u8 => {
5691 return DocData.WalkResult{
5692 .typeRef = .{ .type = @intFromEnum(Ref.u8_type) },
5693 .expr = .{ .int = .{ .value = 0 } },
5694 };
5695 },
5696 .one_u8 => {
5697 return DocData.WalkResult{
5698 .typeRef = .{ .type = @intFromEnum(Ref.u8_type) },
5699 .expr = .{ .int = .{ .value = 1 } },
5700 };
5701 },
5702 .four_u8 => {
5703 return DocData.WalkResult{
5704 .typeRef = .{ .type = @intFromEnum(Ref.u8_type) },
5705 .expr = .{ .int = .{ .value = 4 } },
5706 };
5707 },
56795708
56805709 .void_value => {
56815710 return DocData.WalkResult{
......@@ -5707,18 +5736,6 @@ fn walkRef(
57075736 .empty_struct => {
57085737 return DocData.WalkResult{ .expr = .{ .@"struct" = &.{} } };
57095738 },
5710 .zero_usize => {
5711 return DocData.WalkResult{
5712 .typeRef = .{ .type = @intFromEnum(Ref.usize_type) },
5713 .expr = .{ .int = .{ .value = 0 } },
5714 };
5715 },
5716 .one_usize => {
5717 return DocData.WalkResult{
5718 .typeRef = .{ .type = @intFromEnum(Ref.usize_type) },
5719 .expr = .{ .int = .{ .value = 1 } },
5720 };
5721 },
57225739 .calling_convention_type => {
57235740 return DocData.WalkResult{
57245741 .typeRef = .{ .type = @intFromEnum(Ref.type_type) },
src/Module.zig+12-10
......@@ -3492,6 +3492,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
34923492 @panic("TODO: update owner Decl");
34933493 }
34943494
3495 const decl_inst = decl.zir_decl_index.unwrap().?;
3496
34953497 const gpa = mod.gpa;
34963498 const zir = decl.getFileScope(mod).zir;
34973499
......@@ -3563,7 +3565,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35633565 try sema.declareDependency(.{ .src_hash = try ip.trackZir(
35643566 sema.gpa,
35653567 decl.getFileScope(mod),
3566 decl.zir_decl_index.unwrap().?,
3568 decl_inst,
35673569 ) });
35683570
35693571 var block_scope: Sema.Block = .{
......@@ -3580,7 +3582,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35803582
35813583 const decl_bodies = decl.zirBodies(mod);
35823584
3583 const result_ref = (try sema.analyzeBodyBreak(&block_scope, decl_bodies.value_body)).?.operand;
3585 const result_ref = try sema.resolveInlineBody(&block_scope, decl_bodies.value_body, decl_inst);
35843586 // We'll do some other bits with the Sema. Clear the type target index just
35853587 // in case they analyze any type.
35863588 sema.builtin_type_target_index = .none;
......@@ -3593,7 +3595,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35933595 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
35943596 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
35953597 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
3596 const decl_tv = try sema.resolveInstValueAllowVariables(&block_scope, init_src, result_ref, .{
3598 const decl_tv = try sema.resolveConstValueAllowVariables(&block_scope, init_src, result_ref, .{
35973599 .needed_comptime_reason = "global variable initializer must be comptime-known",
35983600 });
35993601
......@@ -3709,13 +3711,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
37093711 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
37103712 decl.alignment = blk: {
37113713 const align_body = decl_bodies.align_body orelse break :blk .none;
3712 const align_ref = (try sema.analyzeBodyBreak(&block_scope, align_body)).?.operand;
3713 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
3714 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
3715 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
37143716 };
37153717 decl.@"linksection" = blk: {
37163718 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
3717 const linksection_ref = (try sema.analyzeBodyBreak(&block_scope, linksection_body)).?.operand;
3718 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{
3719 const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
3720 const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
37193721 .needed_comptime_reason = "linksection must be comptime-known",
37203722 });
37213723 if (mem.indexOfScalar(u8, bytes, 0) != null) {
......@@ -3741,8 +3743,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
37413743 .constant => target_util.defaultAddressSpace(target, .global_constant),
37423744 else => unreachable,
37433745 };
3744 const addrspace_ref = (try sema.analyzeBodyBreak(&block_scope, addrspace_body)).?.operand;
3745 break :blk try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3746 const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
3747 break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
37463748 };
37473749 decl.has_tv = true;
37483750 decl.analysis = .complete;
......@@ -4513,7 +4515,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
45134515 sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
45144516 inner_block.error_return_trace_index = error_return_trace_index;
45154517
4516 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
4518 sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
45174519 // TODO make these unreachable instead of @panic
45184520 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
45194521 error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
src/Sema.zig+251-229
......@@ -876,104 +876,100 @@ pub fn deinit(sema: *Sema) void {
876876 sema.* = undefined;
877877}
878878
879/// Returns only the result from the body that is specified.
880/// Only appropriate to call when it is determined at comptime that this body
881/// has no peers.
882fn resolveBody(
883 sema: *Sema,
884 block: *Block,
885 body: []const Zir.Inst.Index,
886 /// This is the instruction that a break instruction within `body` can
887 /// use to return from the body.
888 body_inst: Zir.Inst.Index,
889) CompileError!Air.Inst.Ref {
890 const break_data = (try sema.analyzeBodyBreak(block, body)) orelse
891 return .unreachable_value;
892 // For comptime control flow, we need to detect when `analyzeBody` reports
893 // that we need to break from an outer block. In such case we
894 // use Zig's error mechanism to send control flow up the stack until
895 // we find the corresponding block to this break.
896 if (block.is_comptime and break_data.block_inst != body_inst) {
897 sema.comptime_break_inst = break_data.inst;
898 return error.ComptimeBreak;
899 }
900 return try sema.resolveInst(break_data.operand);
901}
902
879/// Performs semantic analysis of a ZIR body which is behind a runtime condition. If comptime
880/// control flow happens here, Sema will convert it to runtime control flow by introducing post-hoc
881/// blocks where necessary.
903882fn analyzeBodyRuntimeBreak(sema: *Sema, block: *Block, body: []const Zir.Inst.Index) !void {
904 _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
883 sema.analyzeBodyInner(block, body) catch |err| switch (err) {
905884 error.ComptimeBreak => {
906885 const zir_datas = sema.code.instructions.items(.data);
907886 const break_data = zir_datas[@intFromEnum(sema.comptime_break_inst)].@"break";
908887 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
909 try sema.addRuntimeBreak(block, .{
910 .block_inst = extra.block_inst,
911 .operand = break_data.operand,
912 .inst = sema.comptime_break_inst,
913 });
888 try sema.addRuntimeBreak(block, extra.block_inst, break_data.operand);
914889 },
915890 else => |e| return e,
916891 };
917892}
918893
919pub fn analyzeBody(
894/// Semantically analyze a ZIR function body. It is guranteed by AstGen that such a body cannot
895/// trigger comptime control flow to move above the function body.
896pub fn analyzeFnBody(
920897 sema: *Sema,
921898 block: *Block,
922899 body: []const Zir.Inst.Index,
923900) !void {
924 _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
901 sema.analyzeBodyInner(block, body) catch |err| switch (err) {
925902 error.ComptimeBreak => unreachable, // unexpected comptime control flow
926903 else => |e| return e,
927904 };
928905}
929906
930const BreakData = struct {
931 block_inst: Zir.Inst.Index,
932 operand: Zir.Inst.Ref,
933 inst: Zir.Inst.Index,
934};
935
936pub fn analyzeBodyBreak(
907/// Given a ZIR body which can be exited via a `break_inline` instruction, or a non-inline body which
908/// we are evaluating at comptime, semantically analyze the body and return the result from it.
909/// Returns `null` if control flow did not break from this block, but instead terminated with some
910/// other runtime noreturn instruction. Compile-time breaks to blocks further up the stack still
911/// return `error.ComptimeBreak`. If `block.is_comptime`, this function will never return `null`.
912fn analyzeInlineBody(
937913 sema: *Sema,
938914 block: *Block,
939915 body: []const Zir.Inst.Index,
940) CompileError!?BreakData {
941 const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {
942 error.ComptimeBreak => sema.comptime_break_inst,
943 else => |e| return e,
944 };
945 if (block.instructions.items.len != 0 and
946 sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()))
916 /// The index which a break instruction can target to break from this body.
917 break_target: Zir.Inst.Index,
918) CompileError!?Air.Inst.Ref {
919 if (sema.analyzeBodyInner(block, body)) |_| {
947920 return null;
921 } else |err| switch (err) {
922 error.ComptimeBreak => {},
923 else => |e| return e,
924 }
925 const break_inst = sema.comptime_break_inst;
948926 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
949927 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
950 return BreakData{
951 .block_inst = extra.block_inst,
952 .operand = break_data.operand,
953 .inst = break_inst,
954 };
955}
956
957/// ZIR instructions which are always `noreturn` return this. This matches the
958/// return type of `analyzeBody` so that we can tail call them.
959/// Only appropriate to return when the instruction is known to be NoReturn
960/// solely based on the ZIR tag.
961const always_noreturn: CompileError!Zir.Inst.Index = @as(Zir.Inst.Index, undefined);
962
963/// This function is the main loop of `Sema` and it can be used in two different ways:
964/// * The traditional way where there are N breaks out of the block and peer type
965/// resolution is done on the break operands. In this case, the `Zir.Inst.Index`
966/// part of the return value will be `undefined`, and callsites should ignore it,
967/// finding the block result value via the block scope.
968/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_inline`
969/// instruction. In this case, the `Zir.Inst.Index` part of the return value will be
970/// the break instruction. This communicates both which block the break applies to, as
971/// well as the operand. No block scope needs to be created for this strategy.
928 if (extra.block_inst != break_target) {
929 // This control flow goes further up the stack.
930 return error.ComptimeBreak;
931 }
932 return try sema.resolveInst(break_data.operand);
933}
934
935/// Like `analyzeInlineBody`, but if the body does not break with a value, returns
936/// `.unreachable_value` instead of `null`. Notably, use this to evaluate an arbitrary
937/// body at comptime to a single result value.
938pub fn resolveInlineBody(
939 sema: *Sema,
940 block: *Block,
941 body: []const Zir.Inst.Index,
942 /// The index which a break instruction can target to break from this body.
943 break_target: Zir.Inst.Index,
944) CompileError!Air.Inst.Ref {
945 return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
946}
947
948/// This function is the main loop of `Sema`. It analyzes a single body of ZIR instructions.
949///
950/// If this function returns normally, the merges of `block` were populated with all possible
951/// (runtime) results of this block. Peer type resolution should be performed on the result,
952/// and relevant runtime instructions written to perform necessary coercions and breaks. See
953/// `resolveAnalyzedBlock`. This form of return is impossible if `block.is_comptime == true`.
954///
955/// Alternatively, this function may return `error.ComptimeBreak`. This indicates that comptime
956/// control flow is happening, and we are breaking at comptime from a block indicated by the
957/// break instruction in `sema.comptime_break_inst`. This occurs for any `break_inline`, or for a
958/// standard `break` at comptime. This error is pushed up the stack until the target block is
959/// reached, at which point the break operand will be fetched.
960///
961/// It is rare to call this function directly. Usually, you want one of the following wrappers:
962/// * If the body is exited via a `break_inline`, or is being evaluated at comptime,
963/// use `Sema.analyzeInlineBody` or `Sema.resolveInlineBody`.
964/// * If the body is behind a fresh runtime condition, use `Sema.analyzeBodyRuntimeBreak`.
965/// * If the body is an entire function body, use `Sema.analyzeFnBody`.
966/// * If the body is to be generated into an AIR `block`, use `Sema.resolveBlockBody`.
967/// * Otherwise, direct usage of `Sema.analyzeBodyInner` may be necessary.
972968fn analyzeBodyInner(
973969 sema: *Sema,
974970 block: *Block,
975971 body: []const Zir.Inst.Index,
976) CompileError!Zir.Inst.Index {
972) CompileError!void {
977973 // No tracy calls here, to avoid interfering with the tail call mechanism.
978974
979975 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);
......@@ -997,7 +993,7 @@ fn analyzeBodyInner(
997993 // the loop. The only way to break out of the loop is with a `noreturn`
998994 // instruction.
999995 var i: u32 = 0;
1000 const result = while (true) {
996 while (true) {
1001997 crash_info.setBodyIndex(i);
1002998 const inst = body[i];
1003999 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{
......@@ -1214,14 +1210,14 @@ fn analyzeBodyInner(
12141210 // Instructions that we know to *always* be noreturn based solely on their tag.
12151211 // These functions match the return type of analyzeBody so that we can
12161212 // tail call them here.
1217 .compile_error => break sema.zirCompileError(block, inst),
1218 .ret_implicit => break sema.zirRetImplicit(block, inst),
1219 .ret_node => break sema.zirRetNode(block, inst),
1220 .ret_load => break sema.zirRetLoad(block, inst),
1221 .ret_err_value => break sema.zirRetErrValue(block, inst),
1222 .@"unreachable" => break sema.zirUnreachable(block, inst),
1223 .panic => break sema.zirPanic(block, inst),
1224 .trap => break sema.zirTrap(block, inst),
1213 .compile_error => break try sema.zirCompileError(block, inst),
1214 .ret_implicit => break try sema.zirRetImplicit(block, inst),
1215 .ret_node => break try sema.zirRetNode(block, inst),
1216 .ret_load => break try sema.zirRetLoad(block, inst),
1217 .ret_err_value => break try sema.zirRetErrValue(block, inst),
1218 .@"unreachable" => break try sema.zirUnreachable(block, inst),
1219 .panic => break try sema.zirPanic(block, inst),
1220 .trap => break try sema.zirTrap(block, inst),
12251221 // zig fmt: on
12261222
12271223 // This instruction never exists in an analyzed body. It exists only in the declaration
......@@ -1247,7 +1243,7 @@ fn analyzeBodyInner(
12471243 .builtin_extern => try sema.zirBuiltinExtern( block, extended),
12481244 .@"asm" => try sema.zirAsm( block, extended, false),
12491245 .asm_expr => try sema.zirAsm( block, extended, true),
1250 .typeof_peer => try sema.zirTypeofPeer( block, extended),
1246 .typeof_peer => try sema.zirTypeofPeer( block, extended, inst),
12511247 .compile_log => try sema.zirCompileLog( extended),
12521248 .min_multi => try sema.zirMinMaxMulti( block, extended, .min),
12531249 .max_multi => try sema.zirMinMaxMulti( block, extended, .max),
......@@ -1522,18 +1518,16 @@ fn analyzeBodyInner(
15221518 // Special case instructions to handle comptime control flow.
15231519 .@"break" => {
15241520 if (block.is_comptime) {
1525 break inst; // same as break_inline
1521 sema.comptime_break_inst = inst;
1522 return error.ComptimeBreak;
15261523 } else {
1527 break sema.zirBreak(block, inst);
1524 try sema.zirBreak(block, inst);
1525 break;
15281526 }
15291527 },
15301528 .break_inline => {
1531 if (block.is_comptime) {
1532 break inst;
1533 } else {
1534 sema.comptime_break_inst = inst;
1535 return error.ComptimeBreak;
1536 }
1529 sema.comptime_break_inst = inst;
1530 return error.ComptimeBreak;
15371531 },
15381532 .repeat => {
15391533 if (block.is_comptime) {
......@@ -1548,7 +1542,10 @@ fn analyzeBodyInner(
15481542 i = 0;
15491543 continue;
15501544 } else {
1551 break always_noreturn;
1545 // We are definitely called by `zirLoop`, which will treat the
1546 // fact that this body does not terminate `noreturn` as an
1547 // implicit repeat.
1548 break;
15521549 }
15531550 },
15541551 .repeat_inline => {
......@@ -1584,13 +1581,8 @@ fn analyzeBodyInner(
15841581 child_block.instructions = block.instructions;
15851582 defer block.instructions = child_block.instructions;
15861583
1587 const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse
1588 break always_noreturn;
1589 if (inst == break_data.block_inst) {
1590 break :blk try sema.resolveInst(break_data.operand);
1591 } else {
1592 break break_data.inst;
1593 }
1584 const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1585 break :blk result;
15941586 },
15951587 .block, .block_comptime => blk: {
15961588 if (!block.is_comptime) {
......@@ -1615,13 +1607,8 @@ fn analyzeBodyInner(
16151607 child_block.instructions = block.instructions;
16161608 defer block.instructions = child_block.instructions;
16171609
1618 const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse
1619 break always_noreturn;
1620 if (inst == break_data.block_inst) {
1621 break :blk try sema.resolveInst(break_data.operand);
1622 } else {
1623 break break_data.inst;
1624 }
1610 const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1611 break :blk result;
16251612 },
16261613 .block_inline => blk: {
16271614 // Directly analyze the block body without introducing a new block.
......@@ -1634,7 +1621,12 @@ fn analyzeBodyInner(
16341621 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
16351622 const gpa = sema.gpa;
16361623
1637 const opt_break_data, const need_debug_scope = b: {
1624 const BreakResult = struct {
1625 block_inst: Zir.Inst.Index,
1626 operand: Zir.Inst.Ref,
1627 };
1628
1629 const opt_break_data: ?BreakResult, const need_debug_scope = b: {
16381630 // Create a temporary child block so that this inline block is properly
16391631 // labeled for any .restore_err_ret_index instructions
16401632 var child_block = block.makeSubBlock();
......@@ -1660,11 +1652,26 @@ fn analyzeBodyInner(
16601652 child_block.instructions = block.instructions;
16611653 defer block.instructions = child_block.instructions;
16621654
1663 const result = try sema.analyzeBodyBreak(&child_block, inline_body);
1655 const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) |_| r: {
1656 break :r null;
1657 } else |err| switch (err) {
1658 error.ComptimeBreak => brk_res: {
1659 const break_inst = sema.comptime_break_inst;
1660 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
1661 const break_extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
1662 break :brk_res .{
1663 .block_inst = break_extra.block_inst,
1664 .operand = break_data.operand,
1665 };
1666 },
1667 else => |e| return e,
1668 };
1669
16641670 if (need_debug_scope) {
16651671 _ = try sema.ensurePostHoc(block, inst);
16661672 }
1667 break :b .{ result, need_debug_scope };
1673
1674 break :b .{ break_result, need_debug_scope };
16681675 };
16691676
16701677 // A runtime conditional branch that needs a post-hoc block to be
......@@ -1686,13 +1693,13 @@ fn analyzeBodyInner(
16861693 // It may pass through our currently being analyzed block_inline or it
16871694 // may point directly to it. In the latter case, this modifies the
16881695 // block that we looked up in the post_hoc_blocks map above.
1689 try sema.addRuntimeBreak(block, break_data);
1696 try sema.addRuntimeBreak(block, break_data.block_inst, break_data.operand);
16901697 }
16911698
16921699 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]);
16931700 block.instructions.items.len = block_index;
16941701
1695 const block_result = try sema.analyzeBlockBody(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges, need_debug_scope);
1702 const block_result = try sema.resolveAnalyzedBlock(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges, need_debug_scope);
16961703 {
16971704 // Destroy the ad-hoc block entry so that it does not interfere with
16981705 // the next iteration of comptime control flow, if any.
......@@ -1703,15 +1710,19 @@ fn analyzeBodyInner(
17031710 break :blk block_result;
17041711 }
17051712
1706 const break_data = opt_break_data orelse break always_noreturn;
1713 const break_data = opt_break_data orelse break;
17071714 if (inst == break_data.block_inst) {
17081715 break :blk try sema.resolveInst(break_data.operand);
17091716 } else {
1710 break break_data.inst;
1717 // `comptime_break_inst` preserved from `analyzeBodyInner` above.
1718 return error.ComptimeBreak;
17111719 }
17121720 },
17131721 .condbr => blk: {
1714 if (!block.is_comptime) break sema.zirCondbr(block, inst);
1722 if (!block.is_comptime) {
1723 try sema.zirCondbr(block, inst);
1724 break;
1725 }
17151726 // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220
17161727 const inst_data = datas[@intFromEnum(inst)].pl_node;
17171728 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
......@@ -1728,13 +1739,9 @@ fn analyzeBodyInner(
17281739 const inline_body = if (cond.val.toBool()) then_body else else_body;
17291740
17301741 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1731 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1732 break always_noreturn;
1733 if (inst == break_data.block_inst) {
1734 break :blk try sema.resolveInst(break_data.operand);
1735 } else {
1736 break break_data.inst;
1737 }
1742
1743 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1744 break :blk result;
17381745 },
17391746 .condbr_inline => blk: {
17401747 const inst_data = datas[@intFromEnum(inst)].pl_node;
......@@ -1754,13 +1761,9 @@ fn analyzeBodyInner(
17541761 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
17551762 const old_runtime_index = block.runtime_index;
17561763 defer block.runtime_index = old_runtime_index;
1757 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1758 break always_noreturn;
1759 if (inst == break_data.block_inst) {
1760 break :blk try sema.resolveInst(break_data.operand);
1761 } else {
1762 break break_data.inst;
1763 }
1764
1765 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1766 break :blk result;
17641767 },
17651768 .@"try" => blk: {
17661769 if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
......@@ -1785,13 +1788,8 @@ fn analyzeBodyInner(
17851788 if (is_non_err_val.toBool()) {
17861789 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
17871790 }
1788 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1789 break always_noreturn;
1790 if (inst == break_data.block_inst) {
1791 break :blk try sema.resolveInst(break_data.operand);
1792 } else {
1793 break break_data.inst;
1794 }
1791 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1792 break :blk result;
17951793 },
17961794 .try_ptr => blk: {
17971795 if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst);
......@@ -1811,22 +1809,22 @@ fn analyzeBodyInner(
18111809 if (is_non_err_val.toBool()) {
18121810 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
18131811 }
1814 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1815 break always_noreturn;
1816 if (inst == break_data.block_inst) {
1817 break :blk try sema.resolveInst(break_data.operand);
1818 } else {
1819 break break_data.inst;
1820 }
1812 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1813 break :blk result;
18211814 },
18221815 .@"defer" => blk: {
18231816 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";
18241817 const defer_body = sema.code.bodySlice(inst_data.index, inst_data.len);
1825 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
1826 error.ComptimeBreak => sema.comptime_break_inst,
1818 if (sema.analyzeBodyInner(block, defer_body)) |_| {
1819 // The defer terminated noreturn - no more analysis needed.
1820 break;
1821 } else |err| switch (err) {
1822 error.ComptimeBreak => {},
18271823 else => |e| return e,
1828 };
1829 if (break_inst != defer_body[defer_body.len - 1]) break always_noreturn;
1824 }
1825 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) {
1826 return error.ComptimeBreak;
1827 }
18301828 break :blk .void_value;
18311829 },
18321830 .defer_err_code => blk: {
......@@ -1835,11 +1833,16 @@ fn analyzeBodyInner(
18351833 const defer_body = sema.code.bodySlice(extra.index, extra.len);
18361834 const err_code = try sema.resolveInst(inst_data.err_code);
18371835 map.putAssumeCapacity(extra.remapped_err_code, err_code);
1838 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
1839 error.ComptimeBreak => sema.comptime_break_inst,
1836 if (sema.analyzeBodyInner(block, defer_body)) |_| {
1837 // The defer terminated noreturn - no more analysis needed.
1838 break;
1839 } else |err| switch (err) {
1840 error.ComptimeBreak => {},
18401841 else => |e| return e,
1841 };
1842 if (break_inst != defer_body[defer_body.len - 1]) break always_noreturn;
1842 }
1843 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) {
1844 return error.ComptimeBreak;
1845 }
18431846 break :blk .void_value;
18441847 },
18451848 };
......@@ -1847,17 +1850,15 @@ fn analyzeBodyInner(
18471850 // We're going to assume that the body itself is noreturn, so let's ensure that now
18481851 assert(block.instructions.items.len > 0);
18491852 assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()));
1850 break always_noreturn;
1853 break;
18511854 }
18521855 map.putAssumeCapacity(inst, air_inst);
18531856 i += 1;
1854 };
1857 }
18551858
18561859 // We may have overwritten the capture scope due to a `repeat` instruction where
18571860 // the body had a capture; restore it now.
18581861 block.wip_capture_scope = parent_capture_scope;
1859
1860 return result;
18611862}
18621863
18631864pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
......@@ -1894,7 +1895,7 @@ fn resolveConstBool(
18941895 return val.toBool();
18951896}
18961897
1897pub fn resolveConstString(
1898fn resolveConstString(
18981899 sema: *Sema,
18991900 block: *Block,
19001901 src: LazySrcLoc,
......@@ -1902,6 +1903,16 @@ pub fn resolveConstString(
19021903 reason: NeededComptimeReason,
19031904) ![]u8 {
19041905 const air_inst = try sema.resolveInst(zir_ref);
1906 return sema.toConstString(block, src, air_inst, reason);
1907}
1908
1909pub fn toConstString(
1910 sema: *Sema,
1911 block: *Block,
1912 src: LazySrcLoc,
1913 air_inst: Air.Inst.Ref,
1914 reason: NeededComptimeReason,
1915) ![]u8 {
19051916 const wanted_type = Type.slice_const_u8;
19061917 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
19071918 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason);
......@@ -2193,9 +2204,8 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val
21932204 return val;
21942205}
21952206
2196/// Returns a compile error if the value has tag `variable`. See `resolveInstValue` for
2197/// a function that does not.
2198pub fn resolveInstConst(
2207/// Returns a compile error if the value has tag `variable`.
2208fn resolveInstConst(
21992209 sema: *Sema,
22002210 block: *Block,
22012211 src: LazySrcLoc,
......@@ -2211,15 +2221,13 @@ pub fn resolveInstConst(
22112221}
22122222
22132223/// Value Tag may be `undef` or `variable`.
2214/// See `resolveInstConst` for an alternative.
2215pub fn resolveInstValueAllowVariables(
2224pub fn resolveConstValueAllowVariables(
22162225 sema: *Sema,
22172226 block: *Block,
22182227 src: LazySrcLoc,
2219 zir_ref: Zir.Inst.Ref,
2228 air_ref: Air.Inst.Ref,
22202229 reason: NeededComptimeReason,
22212230) CompileError!TypedValue {
2222 const air_ref = try sema.resolveInst(zir_ref);
22232231 const val = try sema.resolveValueAllowVariables(air_ref) orelse {
22242232 return sema.failWithNeededComptime(block, src, reason);
22252233 };
......@@ -2616,7 +2624,7 @@ fn reparentOwnedErrorMsg(
26162624
26172625const align_ty = Type.u29;
26182626
2619fn analyzeAsAlign(
2627pub fn analyzeAsAlign(
26202628 sema: *Sema,
26212629 block: *Block,
26222630 src: LazySrcLoc,
......@@ -2654,7 +2662,7 @@ fn validateAlignAllowZero(
26542662 return Alignment.fromNonzeroByteUnits(alignment);
26552663}
26562664
2657pub fn resolveAlign(
2665fn resolveAlign(
26582666 sema: *Sema,
26592667 block: *Block,
26602668 src: LazySrcLoc,
......@@ -3054,7 +3062,7 @@ fn zirEnumDecl(
30543062 defer enum_block.instructions.deinit(sema.gpa);
30553063
30563064 if (body.len != 0) {
3057 try sema.analyzeBody(&enum_block, body);
3065 _ = try sema.analyzeInlineBody(&enum_block, body, inst);
30583066 }
30593067
30603068 if (tag_type_ref != .none) {
......@@ -5597,7 +5605,7 @@ fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
55975605 return Air.internedToRef((try sema.mod.floatValue(Type.comptime_float, number)).toIntern());
55985606}
55995607
5600fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
5608fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
56015609 const tracy = trace(@src());
56025610 defer tracy.end();
56035611
......@@ -5650,7 +5658,7 @@ fn zirCompileLog(
56505658 return .void_value;
56515659}
56525660
5653fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
5661fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
56545662 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
56555663 const src = inst_data.src();
56565664 const msg_inst = try sema.resolveInst(inst_data.operand);
......@@ -5663,16 +5671,14 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.I
56635671 return sema.fail(block, src, "encountered @panic at comptime", .{});
56645672 }
56655673 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");
5666 return always_noreturn;
56675674}
56685675
5669fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
5676fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
56705677 const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;
56715678 const src = LazySrcLoc.nodeOffset(src_node);
56725679 if (block.is_comptime)
56735680 return sema.fail(block, src, "encountered @trap at comptime", .{});
56745681 _ = try block.addNoOp(.trap);
5675 return always_noreturn;
56765682}
56775683
56785684fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -5726,7 +5732,8 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
57265732 var loop_block = child_block.makeSubBlock();
57275733 defer loop_block.instructions.deinit(gpa);
57285734
5729 try sema.analyzeBody(&loop_block, body);
5735 // Use `analyzeBodyInner` directly to push any comptime control flow up the stack.
5736 try sema.analyzeBodyInner(&loop_block, body);
57305737
57315738 const loop_block_len = loop_block.instructions.items.len;
57325739 if (loop_block_len > 0 and sema.typeOf(loop_block.instructions.items[loop_block_len - 1].toRef()).isNoReturn(mod)) {
......@@ -5742,7 +5749,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
57425749 );
57435750 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));
57445751 }
5745 return sema.analyzeBlockBody(parent_block, src, &child_block, merges, false);
5752 return sema.resolveAnalyzedBlock(parent_block, src, &child_block, merges, false);
57465753}
57475754
57485755fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -5785,8 +5792,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
57855792 };
57865793 defer child_block.instructions.deinit(gpa);
57875794
5788 // Ignore the result, all the relevant operations have written to c_import_buf already.
5789 _ = try sema.analyzeBodyBreak(&child_block, body);
5795 _ = try sema.analyzeInlineBody(&child_block, body, inst);
57905796
57915797 var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|
57925798 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
......@@ -5916,6 +5922,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt
59165922 return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
59175923}
59185924
5925/// Semantically analyze the given ZIR body, emitting any resulting runtime code into the AIR block
5926/// specified by `child_block` if necessary (and emitting this block into `parent_block`).
5927/// TODO: `merges` is known from `child_block`, remove this parameter.
59195928fn resolveBlockBody(
59205929 sema: *Sema,
59215930 parent_block: *Block,
......@@ -5928,12 +5937,12 @@ fn resolveBlockBody(
59285937 merges: *Block.Merges,
59295938) CompileError!Air.Inst.Ref {
59305939 if (child_block.is_comptime) {
5931 return sema.resolveBody(child_block, body, body_inst);
5940 return sema.resolveInlineBody(child_block, body, body_inst);
59325941 } else {
59335942 var need_debug_scope = false;
59345943 child_block.need_debug_scope = &need_debug_scope;
59355944 if (sema.analyzeBodyInner(child_block, body)) |_| {
5936 return sema.analyzeBlockBody(parent_block, src, child_block, merges, need_debug_scope);
5945 return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope);
59375946 } else |err| switch (err) {
59385947 error.ComptimeBreak => {
59395948 // Comptime control flow is happening, however child_block may still contain
......@@ -5970,7 +5979,12 @@ fn resolveBlockBody(
59705979 }
59715980}
59725981
5973fn analyzeBlockBody(
5982/// After a body corresponding to an AIR `block` has been analyzed, this function places them into
5983/// the block pointed at by `merges.block_inst` if necessary, or the block may be elided in favor of
5984/// inlining the instructions directly into the parent block. Either way, it considers all merges of
5985/// this block, and combines them appropriately using peer type resolution, returning the final
5986/// value of the block.
5987fn resolveAnalyzedBlock(
59745988 sema: *Sema,
59755989 parent_block: *Block,
59765990 src: LazySrcLoc,
......@@ -6360,7 +6374,7 @@ fn zirFence(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) Co
63606374 });
63616375}
63626376
6363fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
6377fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void {
63646378 const tracy = trace(@src());
63656379 defer tracy.end();
63666380
......@@ -6386,7 +6400,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
63866400 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop;
63876401 block.runtime_loop = start_block.runtime_loop;
63886402 }
6389 return inst;
6403 return;
63906404 }
63916405 }
63926406 block = block.parent.?;
......@@ -7096,7 +7110,7 @@ const CallArgsInfo = union(enum) {
70967110 // Give the arg its result type
70977111 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(param_ty.toIntern()));
70987112 // Resolve the arg!
7099 const uncoerced_arg = try sema.resolveBody(block, arg_body, zir_call.call_inst);
7113 const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
71007114
71017115 if (sema.typeOf(uncoerced_arg).zigTypeTag(mod) == .NoReturn) {
71027116 // This terminates resolution of arguments. The caller should
......@@ -7539,7 +7553,7 @@ fn analyzeCall(
75397553 // each of the parameters, resolving the return type and providing it to the child
75407554 // `Sema` so that it can be used for the `ret_ptr` instruction.
75417555 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
7542 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip))
7556 try sema.resolveInlineBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip))
75437557 else
75447558 try sema.resolveInst(fn_info.ret_ty_ref);
75457559 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
......@@ -7608,11 +7622,11 @@ fn analyzeCall(
76087622 }
76097623
76107624 const result = result: {
7611 sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
7625 sema.analyzeFnBody(&child_block, fn_info.body) catch |err| switch (err) {
76127626 error.ComptimeReturn => break :result inlining.comptime_result,
76137627 else => |e| return e,
76147628 };
7615 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges, false);
7629 break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, false);
76167630 };
76177631
76187632 if (!is_comptime_call and !block.is_typeof and
......@@ -7791,7 +7805,7 @@ fn analyzeInlineCallArg(
77917805 const param_ty = param_ty: {
77927806 const raw_param_ty = func_ty_info.param_types.get(ip)[arg_i.*];
77937807 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
7794 const param_ty_inst = try ics.callee().resolveBody(param_block, param_body, inst);
7808 const param_ty_inst = try ics.callee().resolveInlineBody(param_block, param_body, inst);
77957809 const param_ty = try ics.callee().analyzeAsType(param_block, param_src, param_ty_inst);
77967810 break :param_ty param_ty.toIntern();
77977811 };
......@@ -8026,7 +8040,7 @@ fn instantiateGenericCall(
80268040 child_sema.generic_call_decl = prev_generic_call_decl;
80278041 }
80288042
8029 const param_ty_inst = try child_sema.resolveBody(&child_block, param_ty_body, param_inst);
8043 const param_ty_inst = try child_sema.resolveInlineBody(&child_block, param_ty_body, param_inst);
80308044 break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst);
80318045 },
80328046 else => unreachable,
......@@ -8118,7 +8132,7 @@ fn instantiateGenericCall(
81188132
81198133 // We've already handled parameters, so don't resolve the whole body. Instead, just
81208134 // do the instructions after the params (i.e. the func itself).
8121 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body[args_info.count()..], fn_info.param_body_inst);
8135 const new_func_inst = try child_sema.resolveInlineBody(&child_block, fn_info.param_body[args_info.count()..], fn_info.param_body_inst);
81228136 const callee_index = (child_sema.resolveConstDefinedValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
81238137
81248138 const callee = mod.funcInfo(callee_index);
......@@ -9176,7 +9190,7 @@ fn resolveGenericBody(
91769190 sema.generic_call_decl = prev_generic_call_decl;
91779191 }
91789192
9179 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
9193 const uncasted = sema.resolveInlineBody(block, body, func_inst) catch |err| break :err err;
91809194 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
91819195 const val = sema.resolveConstDefinedValue(block, src, result, reason) catch |err| break :err err;
91829196 return val;
......@@ -9810,7 +9824,7 @@ fn zirParam(
98109824 sema.generic_call_decl = prev_generic_call_decl;
98119825 }
98129826
9813 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
9827 if (sema.resolveInlineBody(block, body, inst)) |param_ty_inst| {
98149828 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
98159829 break :param_ty param_ty;
98169830 } else |err| break :err err;
......@@ -11494,6 +11508,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
1149411508 sub_block.runtime_loop = null;
1149511509 sub_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(main_operand_src, mod);
1149611510 sub_block.runtime_index.increment();
11511 sub_block.need_debug_scope = null; // this body is emitted regardless
1149711512 defer sub_block.instructions.deinit(gpa);
1149811513
1149911514 try sema.analyzeBodyRuntimeBreak(&sub_block, non_error_case.body);
......@@ -11556,7 +11571,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
1155611571 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
1155711572 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
1155811573
11559 return sema.analyzeBlockBody(block, main_src, &child_block, merges, false);
11574 return sema.resolveAnalyzedBlock(block, main_src, &child_block, merges, false);
1156011575}
1156111576
1156211577fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {
......@@ -12178,7 +12193,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1217812193 false,
1217912194 );
1218012195
12181 return sema.analyzeBlockBody(block, src, &child_block, merges, false);
12196 return sema.resolveAnalyzedBlock(block, src, &child_block, merges, false);
1218212197}
1218312198
1218412199const SpecialProng = struct {
......@@ -12229,6 +12244,7 @@ fn analyzeSwitchRuntimeBlock(
1222912244 case_block.runtime_loop = null;
1223012245 case_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(operand_src, mod);
1223112246 case_block.runtime_index.increment();
12247 case_block.need_debug_scope = null; // this body is emitted regardless
1223212248 defer case_block.instructions.deinit(gpa);
1223312249
1223412250 var extra_index: usize = special.end;
......@@ -18602,7 +18618,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1860218618 };
1860318619 defer child_block.instructions.deinit(sema.gpa);
1860418620
18605 const operand = try sema.resolveBody(&child_block, body, inst);
18621 const operand = try sema.resolveInlineBody(&child_block, body, inst);
1860618622 const operand_ty = sema.typeOf(operand);
1860718623 if (operand_ty.isGenericPoison()) return error.GenericPoison;
1860818624 return Air.internedToRef(operand_ty.toIntern());
......@@ -18657,6 +18673,7 @@ fn zirTypeofPeer(
1865718673 sema: *Sema,
1865818674 block: *Block,
1865918675 extended: Zir.Inst.Extended.InstData,
18676 inst: Zir.Inst.Index,
1866018677) CompileError!Air.Inst.Ref {
1866118678 const tracy = trace(@src());
1866218679 defer tracy.end();
......@@ -18681,7 +18698,7 @@ fn zirTypeofPeer(
1868118698 };
1868218699 defer child_block.instructions.deinit(sema.gpa);
1868318700 // Ignore the result, we only care about the instructions in `args`.
18684 _ = try sema.analyzeBodyBreak(&child_block, body);
18701 _ = try sema.analyzeInlineBody(&child_block, body, inst);
1868518702
1868618703 const args = sema.code.refSlice(extra.end, extended.small);
1868718704
......@@ -18748,7 +18765,7 @@ fn zirBoolBr(
1874818765 // comptime-known left-hand side. No need for a block here; the result
1874918766 // is simply the rhs expression. Here we rely on there only being 1
1875018767 // break instruction (`break_inline`).
18751 const rhs_result = try sema.resolveBody(parent_block, body, inst);
18768 const rhs_result = try sema.resolveInlineBody(parent_block, body, inst);
1875218769 if (sema.typeOf(rhs_result).isNoReturn(mod)) {
1875318770 return rhs_result;
1875418771 }
......@@ -18782,7 +18799,7 @@ fn zirBoolBr(
1878218799 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;
1878318800 _ = try lhs_block.addBr(block_inst, lhs_result);
1878418801
18785 const rhs_result = try sema.resolveBody(rhs_block, body, inst);
18802 const rhs_result = try sema.resolveInlineBody(rhs_block, body, inst);
1878618803 const rhs_noret = sema.typeOf(rhs_result).isNoReturn(mod);
1878718804 const coerced_rhs_result = if (!rhs_noret) rhs: {
1878818805 const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src);
......@@ -18933,7 +18950,7 @@ fn zirCondbr(
1893318950 sema: *Sema,
1893418951 parent_block: *Block,
1893518952 inst: Zir.Inst.Index,
18936) CompileError!Zir.Inst.Index {
18953) CompileError!void {
1893718954 const tracy = trace(@src());
1893818955 defer tracy.end();
1893918956
......@@ -18952,8 +18969,7 @@ fn zirCondbr(
1895218969 const body = if (cond_val.toBool()) then_body else else_body;
1895318970
1895418971 try sema.maybeErrorUnwrapCondbr(parent_block, body, extra.data.condition, cond_src);
18955 // We use `analyzeBodyInner` since we want to propagate any possible
18956 // `error.ComptimeBreak` to the caller.
18972 // We use `analyzeBodyInner` since we want to propagate any comptime control flow to the caller.
1895718973 return sema.analyzeBodyInner(parent_block, body);
1895818974 }
1895918975
......@@ -18965,6 +18981,7 @@ fn zirCondbr(
1896518981 sub_block.runtime_loop = null;
1896618982 sub_block.runtime_cond = mod.declPtr(parent_block.src_decl).toSrcLoc(cond_src, mod);
1896718983 sub_block.runtime_index.increment();
18984 sub_block.need_debug_scope = null; // this body is emitted regardless
1896818985 defer sub_block.instructions.deinit(gpa);
1896918986
1897018987 try sema.analyzeBodyRuntimeBreak(&sub_block, then_body);
......@@ -19002,7 +19019,6 @@ fn zirCondbr(
1900219019 });
1900319020 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
1900419021 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
19005 return always_noreturn;
1900619022}
1900719023
1900819024fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -19027,14 +19043,15 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1902719043 }
1902819044 // We can analyze the body directly in the parent block because we know there are
1902919045 // no breaks from the body possible, and that the body is noreturn.
19030 return sema.resolveBody(parent_block, body, inst);
19046 try sema.analyzeBodyInner(parent_block, body);
19047 return .unreachable_value;
1903119048 }
1903219049
1903319050 var sub_block = parent_block.makeSubBlock();
1903419051 defer sub_block.instructions.deinit(sema.gpa);
1903519052
1903619053 // This body is guaranteed to end with noreturn and has no breaks.
19037 _ = try sema.analyzeBodyInner(&sub_block, body);
19054 try sema.analyzeBodyInner(&sub_block, body);
1903819055
1903919056 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +
1904019057 sub_block.instructions.items.len);
......@@ -19074,14 +19091,15 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1907419091 }
1907519092 // We can analyze the body directly in the parent block because we know there are
1907619093 // no breaks from the body possible, and that the body is noreturn.
19077 return sema.resolveBody(parent_block, body, inst);
19094 try sema.analyzeBodyInner(parent_block, body);
19095 return .unreachable_value;
1907819096 }
1907919097
1908019098 var sub_block = parent_block.makeSubBlock();
1908119099 defer sub_block.instructions.deinit(sema.gpa);
1908219100
1908319101 // This body is guaranteed to end with noreturn and has no breaks.
19084 _ = try sema.analyzeBodyInner(&sub_block, body);
19102 try sema.analyzeBodyInner(&sub_block, body);
1908519103
1908619104 const operand_ty = sema.typeOf(operand);
1908719105 const ptr_info = operand_ty.ptrInfo(mod);
......@@ -19156,13 +19174,13 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
1915619174 return labeled_block;
1915719175}
1915819176
19159// A `break` statement is inside a runtime condition, but trying to
19160// break from an inline loop. In such case we must convert it to
19161// a runtime break.
19162fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {
19163 const labeled_block = try sema.ensurePostHoc(child_block, break_data.block_inst);
19177/// A `break` statement is inside a runtime condition, but trying to
19178/// break from an inline loop. In such case we must convert it to
19179/// a runtime break.
19180fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void {
19181 const labeled_block = try sema.ensurePostHoc(child_block, block_inst);
1916419182
19165 const operand = try sema.resolveInst(break_data.operand);
19183 const operand = try sema.resolveInst(break_operand);
1916619184 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
1916719185
1916819186 try labeled_block.label.merges.results.append(sema.gpa, operand);
......@@ -19176,7 +19194,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !voi
1917619194 }
1917719195}
1917819196
19179fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19197fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1918019198 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
1918119199 const src = inst_data.src();
1918219200
......@@ -19193,14 +19211,13 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1919319211 },
1919419212 else => |e| return e,
1919519213 };
19196 return always_noreturn;
1919719214}
1919819215
1919919216fn zirRetErrValue(
1920019217 sema: *Sema,
1920119218 block: *Block,
1920219219 inst: Zir.Inst.Index,
19203) CompileError!Zir.Inst.Index {
19220) CompileError!void {
1920419221 const mod = sema.mod;
1920519222 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
1920619223 const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
......@@ -19219,7 +19236,7 @@ fn zirRetImplicit(
1921919236 sema: *Sema,
1922019237 block: *Block,
1922119238 inst: Zir.Inst.Index,
19222) CompileError!Zir.Inst.Index {
19239) CompileError!void {
1922319240 const tracy = trace(@src());
1922419241 defer tracy.end();
1922519242
......@@ -19234,7 +19251,7 @@ fn zirRetImplicit(
1923419251 } else {
1923519252 try block.addUnreachable(r_brace_src, false);
1923619253 }
19237 return always_noreturn;
19254 return;
1923819255 }
1923919256
1924019257 const operand = try sema.resolveInst(inst_data.operand);
......@@ -19265,7 +19282,7 @@ fn zirRetImplicit(
1926519282 return sema.analyzeRet(block, operand, r_brace_src, r_brace_src);
1926619283}
1926719284
19268fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19285fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1926919286 const tracy = trace(@src());
1927019287 defer tracy.end();
1927119288
......@@ -19276,7 +19293,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1927619293 return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node });
1927719294}
1927819295
19279fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19296fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1928019297 const tracy = trace(@src());
1928119298 defer tracy.end();
1928219299
......@@ -19295,7 +19312,6 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1929519312 }
1929619313
1929719314 _ = try block.addUnOp(.ret_load, ret_ptr);
19298 return always_noreturn;
1929919315}
1930019316
1930119317fn retWithErrTracing(
......@@ -19305,12 +19321,12 @@ fn retWithErrTracing(
1930519321 is_non_err: Air.Inst.Ref,
1930619322 ret_tag: Air.Inst.Tag,
1930719323 operand: Air.Inst.Ref,
19308) CompileError!Zir.Inst.Index {
19324) CompileError!void {
1930919325 const mod = sema.mod;
1931019326 const need_check = switch (is_non_err) {
1931119327 .bool_true => {
1931219328 _ = try block.addUnOp(ret_tag, operand);
19313 return always_noreturn;
19329 return;
1931419330 },
1931519331 .bool_false => false,
1931619332 else => true,
......@@ -19326,7 +19342,7 @@ fn retWithErrTracing(
1932619342 if (!need_check) {
1932719343 try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");
1932819344 _ = try block.addUnOp(ret_tag, operand);
19329 return always_noreturn;
19345 return;
1933019346 }
1933119347
1933219348 var then_block = block.makeSubBlock();
......@@ -19353,8 +19369,6 @@ fn retWithErrTracing(
1935319369 .operand = is_non_err,
1935419370 .payload = cond_br_payload,
1935519371 } } });
19356
19357 return always_noreturn;
1935819372}
1935919373
1936019374fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
......@@ -19481,7 +19495,7 @@ fn analyzeRet(
1948119495 uncasted_operand: Air.Inst.Ref,
1948219496 src: LazySrcLoc,
1948319497 operand_src: LazySrcLoc,
19484) CompileError!Zir.Inst.Index {
19498) CompileError!void {
1948519499 // Special case for returning an error to an inferred error set; we need to
1948619500 // add the error tag to the inferred error set of the in-scope function, so
1948719501 // that the coercion below works correctly.
......@@ -19513,7 +19527,7 @@ fn analyzeRet(
1951319527 try inlining.merges.results.append(sema.gpa, operand);
1951419528 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
1951519529 try inlining.merges.src_locs.append(sema.gpa, operand_src);
19516 return always_noreturn;
19530 return;
1951719531 } else if (block.is_comptime) {
1951819532 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
1951919533 } else if (sema.func_is_naked) {
......@@ -19538,8 +19552,6 @@ fn analyzeRet(
1953819552 }
1953919553
1954019554 _ = try block.addUnOp(air_tag, operand);
19541
19542 return always_noreturn;
1954319555}
1954419556
1954519557fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
......@@ -19616,7 +19628,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1961619628 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
1961719629 const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
1961819630 extra_i += 1;
19619 break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer);
19631 break :blk try sema.resolveAddressSpace(block, addrspace_src, ref, .pointer);
1962019632 } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic;
1962119633
1962219634 const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: {
......@@ -35737,7 +35749,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
3573735749 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
3573835750 } else {
3573935751 const body = zir.bodySlice(extra_index, backing_int_body_len);
35740 const ty_ref = try sema.resolveBody(&block, body, zir_index);
35752 const ty_ref = try sema.resolveInlineBody(&block, body, zir_index);
3574135753 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
3574235754 }
3574335755 };
......@@ -36618,7 +36630,7 @@ fn semaStructFields(
3661836630 assert(zir_field.type_body_len != 0);
3661936631 const body = zir.bodySlice(extra_index, zir_field.type_body_len);
3662036632 extra_index += body.len;
36621 const ty_ref = try sema.resolveBody(&block_scope, body, zir_index);
36633 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
3662236634 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
3662336635 error.NeededSourceLocation => {
3662436636 const ty_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36704,7 +36716,7 @@ fn semaStructFields(
3670436716 if (zir_field.align_body_len > 0) {
3670536717 const body = zir.bodySlice(extra_index, zir_field.align_body_len);
3670636718 extra_index += body.len;
36707 const align_ref = try sema.resolveBody(&block_scope, body, zir_index);
36719 const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
3670836720 const field_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
3670936721 error.NeededSourceLocation => {
3671036722 const align_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36854,7 +36866,7 @@ fn semaStructFieldInits(
3685436866 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index});
3685536867 sema.inst_map.putAssumeCapacity(zir_index, type_ref);
3685636868
36857 const init = try sema.resolveBody(&block_scope, body, zir_index);
36869 const init = try sema.resolveInlineBody(&block_scope, body, zir_index);
3685836870 const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) {
3685936871 error.NeededSourceLocation => {
3686036872 const init_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36971,7 +36983,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3697136983 defer assert(block_scope.instructions.items.len == 0);
3697236984
3697336985 if (body.len != 0) {
36974 try sema.analyzeBody(&block_scope, body);
36986 _ = try sema.analyzeInlineBody(&block_scope, body, zir_index);
3697536987 }
3697636988
3697736989 for (comptime_mutable_decls.items) |ct_decl_index| {
......@@ -37914,15 +37926,25 @@ pub const AddressSpaceContext = enum {
3791437926 pointer,
3791537927};
3791637928
37917pub fn analyzeAddressSpace(
37929fn resolveAddressSpace(
3791837930 sema: *Sema,
3791937931 block: *Block,
3792037932 src: LazySrcLoc,
3792137933 zir_ref: Zir.Inst.Ref,
3792237934 ctx: AddressSpaceContext,
3792337935) !std.builtin.AddressSpace {
37924 const mod = sema.mod;
3792537936 const air_ref = try sema.resolveInst(zir_ref);
37937 return sema.analyzeAsAddressSpace(block, src, air_ref, ctx);
37938}
37939
37940pub fn analyzeAsAddressSpace(
37941 sema: *Sema,
37942 block: *Block,
37943 src: LazySrcLoc,
37944 air_ref: Air.Inst.Ref,
37945 ctx: AddressSpaceContext,
37946) !std.builtin.AddressSpace {
37947 const mod = sema.mod;
3792637948 const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src);
3792737949 const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{
3792837950 .needed_comptime_reason = "address space must be comptime-known",
src/codegen/llvm.zig+6-6
......@@ -5903,10 +5903,10 @@ pub const FuncGen = struct {
59035903 _ = try self.wip.brCond(cond, then_block, else_block);
59045904
59055905 self.wip.cursor = .{ .block = then_block };
5906 try self.genBody(then_body);
5906 try self.genBodyDebugScope(then_body);
59075907
59085908 self.wip.cursor = .{ .block = else_block };
5909 try self.genBody(else_body);
5909 try self.genBodyDebugScope(else_body);
59105910
59115911 // No need to reset the insert cursor since this instruction is noreturn.
59125912 return .none;
......@@ -5987,7 +5987,7 @@ pub const FuncGen = struct {
59875987 _ = try fg.wip.brCond(is_err, return_block, continue_block);
59885988
59895989 fg.wip.cursor = .{ .block = return_block };
5990 try fg.genBody(body);
5990 try fg.genBodyDebugScope(body);
59915991
59925992 fg.wip.cursor = .{ .block = continue_block };
59935993 }
......@@ -6060,13 +6060,13 @@ pub const FuncGen = struct {
60606060 }
60616061
60626062 self.wip.cursor = .{ .block = case_block };
6063 try self.genBody(case_body);
6063 try self.genBodyDebugScope(case_body);
60646064 }
60656065
60666066 self.wip.cursor = .{ .block = else_block };
60676067 const else_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra_index..][0..switch_br.data.else_body_len]);
60686068 if (else_body.len != 0) {
6069 try self.genBody(else_body);
6069 try self.genBodyDebugScope(else_body);
60706070 } else {
60716071 _ = try self.wip.@"unreachable"();
60726072 }
......@@ -6085,7 +6085,7 @@ pub const FuncGen = struct {
60856085 _ = try self.wip.br(loop_block);
60866086
60876087 self.wip.cursor = .{ .block = loop_block };
6088 try self.genBody(body);
6088 try self.genBodyDebugScope(body);
60896089
60906090 // TODO instead of this logic, change AIR to have the property that
60916091 // every block is guaranteed to end with a noreturn instruction.