authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-27 20:32:31+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-29 23:38:18+00:00
logf51d9ab892caeb63c40fcd2c1da4ade70038119c
tree3d08789436e8f6c4fd748e63d04f4bb58768668b
parent07d8740882616b18a3dd81629b1ad0b698376399
signaturelock-open Commit is signed but in an unrecognized format.

Sema: simplify and clarify analyzeBodyInner and wrapper functions

The signature and variants of Sema's main loop have evolved over time to what was a quite confusing state of affairs. This commit makes minor changes to how `analyzeBodyInner` works, and restructures/renames the wrapper functions, adding doc comments to clarify their purposes. The most notable change is that `analyzeBodyInner` now returns `CompileError!void`; inline breaks are now all communicated via `error.ComptimeBreak`.

2 files changed, 259 insertions(+), 237 deletions(-)

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+247-227
......@@ -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;
......@@ -11556,7 +11570,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
1155611570 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
1155711571 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
1155811572
11559 return sema.analyzeBlockBody(block, main_src, &child_block, merges, false);
11573 return sema.resolveAnalyzedBlock(block, main_src, &child_block, merges, false);
1156011574}
1156111575
1156211576fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {
......@@ -12178,7 +12192,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1217812192 false,
1217912193 );
1218012194
12181 return sema.analyzeBlockBody(block, src, &child_block, merges, false);
12195 return sema.resolveAnalyzedBlock(block, src, &child_block, merges, false);
1218212196}
1218312197
1218412198const SpecialProng = struct {
......@@ -18602,7 +18616,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1860218616 };
1860318617 defer child_block.instructions.deinit(sema.gpa);
1860418618
18605 const operand = try sema.resolveBody(&child_block, body, inst);
18619 const operand = try sema.resolveInlineBody(&child_block, body, inst);
1860618620 const operand_ty = sema.typeOf(operand);
1860718621 if (operand_ty.isGenericPoison()) return error.GenericPoison;
1860818622 return Air.internedToRef(operand_ty.toIntern());
......@@ -18657,6 +18671,7 @@ fn zirTypeofPeer(
1865718671 sema: *Sema,
1865818672 block: *Block,
1865918673 extended: Zir.Inst.Extended.InstData,
18674 inst: Zir.Inst.Index,
1866018675) CompileError!Air.Inst.Ref {
1866118676 const tracy = trace(@src());
1866218677 defer tracy.end();
......@@ -18681,7 +18696,7 @@ fn zirTypeofPeer(
1868118696 };
1868218697 defer child_block.instructions.deinit(sema.gpa);
1868318698 // Ignore the result, we only care about the instructions in `args`.
18684 _ = try sema.analyzeBodyBreak(&child_block, body);
18699 _ = try sema.analyzeInlineBody(&child_block, body, inst);
1868518700
1868618701 const args = sema.code.refSlice(extra.end, extended.small);
1868718702
......@@ -18748,7 +18763,7 @@ fn zirBoolBr(
1874818763 // comptime-known left-hand side. No need for a block here; the result
1874918764 // is simply the rhs expression. Here we rely on there only being 1
1875018765 // break instruction (`break_inline`).
18751 const rhs_result = try sema.resolveBody(parent_block, body, inst);
18766 const rhs_result = try sema.resolveInlineBody(parent_block, body, inst);
1875218767 if (sema.typeOf(rhs_result).isNoReturn(mod)) {
1875318768 return rhs_result;
1875418769 }
......@@ -18782,7 +18797,7 @@ fn zirBoolBr(
1878218797 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;
1878318798 _ = try lhs_block.addBr(block_inst, lhs_result);
1878418799
18785 const rhs_result = try sema.resolveBody(rhs_block, body, inst);
18800 const rhs_result = try sema.resolveInlineBody(rhs_block, body, inst);
1878618801 const rhs_noret = sema.typeOf(rhs_result).isNoReturn(mod);
1878718802 const coerced_rhs_result = if (!rhs_noret) rhs: {
1878818803 const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src);
......@@ -18933,7 +18948,7 @@ fn zirCondbr(
1893318948 sema: *Sema,
1893418949 parent_block: *Block,
1893518950 inst: Zir.Inst.Index,
18936) CompileError!Zir.Inst.Index {
18951) CompileError!void {
1893718952 const tracy = trace(@src());
1893818953 defer tracy.end();
1893918954
......@@ -19002,7 +19017,6 @@ fn zirCondbr(
1900219017 });
1900319018 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
1900419019 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
19005 return always_noreturn;
1900619020}
1900719021
1900819022fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -19027,14 +19041,15 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1902719041 }
1902819042 // We can analyze the body directly in the parent block because we know there are
1902919043 // no breaks from the body possible, and that the body is noreturn.
19030 return sema.resolveBody(parent_block, body, inst);
19044 try sema.analyzeBodyInner(parent_block, body);
19045 return .unreachable_value;
1903119046 }
1903219047
1903319048 var sub_block = parent_block.makeSubBlock();
1903419049 defer sub_block.instructions.deinit(sema.gpa);
1903519050
1903619051 // This body is guaranteed to end with noreturn and has no breaks.
19037 _ = try sema.analyzeBodyInner(&sub_block, body);
19052 try sema.analyzeBodyInner(&sub_block, body);
1903819053
1903919054 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +
1904019055 sub_block.instructions.items.len);
......@@ -19074,14 +19089,15 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1907419089 }
1907519090 // We can analyze the body directly in the parent block because we know there are
1907619091 // no breaks from the body possible, and that the body is noreturn.
19077 return sema.resolveBody(parent_block, body, inst);
19092 try sema.analyzeBodyInner(parent_block, body);
19093 return .unreachable_value;
1907819094 }
1907919095
1908019096 var sub_block = parent_block.makeSubBlock();
1908119097 defer sub_block.instructions.deinit(sema.gpa);
1908219098
1908319099 // This body is guaranteed to end with noreturn and has no breaks.
19084 _ = try sema.analyzeBodyInner(&sub_block, body);
19100 try sema.analyzeBodyInner(&sub_block, body);
1908519101
1908619102 const operand_ty = sema.typeOf(operand);
1908719103 const ptr_info = operand_ty.ptrInfo(mod);
......@@ -19156,13 +19172,13 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
1915619172 return labeled_block;
1915719173}
1915819174
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);
19175/// A `break` statement is inside a runtime condition, but trying to
19176/// break from an inline loop. In such case we must convert it to
19177/// a runtime break.
19178fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void {
19179 const labeled_block = try sema.ensurePostHoc(child_block, block_inst);
1916419180
19165 const operand = try sema.resolveInst(break_data.operand);
19181 const operand = try sema.resolveInst(break_operand);
1916619182 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
1916719183
1916819184 try labeled_block.label.merges.results.append(sema.gpa, operand);
......@@ -19176,7 +19192,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !voi
1917619192 }
1917719193}
1917819194
19179fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19195fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1918019196 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
1918119197 const src = inst_data.src();
1918219198
......@@ -19193,14 +19209,13 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1919319209 },
1919419210 else => |e| return e,
1919519211 };
19196 return always_noreturn;
1919719212}
1919819213
1919919214fn zirRetErrValue(
1920019215 sema: *Sema,
1920119216 block: *Block,
1920219217 inst: Zir.Inst.Index,
19203) CompileError!Zir.Inst.Index {
19218) CompileError!void {
1920419219 const mod = sema.mod;
1920519220 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
1920619221 const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
......@@ -19219,7 +19234,7 @@ fn zirRetImplicit(
1921919234 sema: *Sema,
1922019235 block: *Block,
1922119236 inst: Zir.Inst.Index,
19222) CompileError!Zir.Inst.Index {
19237) CompileError!void {
1922319238 const tracy = trace(@src());
1922419239 defer tracy.end();
1922519240
......@@ -19234,7 +19249,7 @@ fn zirRetImplicit(
1923419249 } else {
1923519250 try block.addUnreachable(r_brace_src, false);
1923619251 }
19237 return always_noreturn;
19252 return;
1923819253 }
1923919254
1924019255 const operand = try sema.resolveInst(inst_data.operand);
......@@ -19265,7 +19280,7 @@ fn zirRetImplicit(
1926519280 return sema.analyzeRet(block, operand, r_brace_src, r_brace_src);
1926619281}
1926719282
19268fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19283fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1926919284 const tracy = trace(@src());
1927019285 defer tracy.end();
1927119286
......@@ -19276,7 +19291,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1927619291 return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node });
1927719292}
1927819293
19279fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
19294fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1928019295 const tracy = trace(@src());
1928119296 defer tracy.end();
1928219297
......@@ -19295,7 +19310,6 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1929519310 }
1929619311
1929719312 _ = try block.addUnOp(.ret_load, ret_ptr);
19298 return always_noreturn;
1929919313}
1930019314
1930119315fn retWithErrTracing(
......@@ -19305,12 +19319,12 @@ fn retWithErrTracing(
1930519319 is_non_err: Air.Inst.Ref,
1930619320 ret_tag: Air.Inst.Tag,
1930719321 operand: Air.Inst.Ref,
19308) CompileError!Zir.Inst.Index {
19322) CompileError!void {
1930919323 const mod = sema.mod;
1931019324 const need_check = switch (is_non_err) {
1931119325 .bool_true => {
1931219326 _ = try block.addUnOp(ret_tag, operand);
19313 return always_noreturn;
19327 return;
1931419328 },
1931519329 .bool_false => false,
1931619330 else => true,
......@@ -19326,7 +19340,7 @@ fn retWithErrTracing(
1932619340 if (!need_check) {
1932719341 try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");
1932819342 _ = try block.addUnOp(ret_tag, operand);
19329 return always_noreturn;
19343 return;
1933019344 }
1933119345
1933219346 var then_block = block.makeSubBlock();
......@@ -19353,8 +19367,6 @@ fn retWithErrTracing(
1935319367 .operand = is_non_err,
1935419368 .payload = cond_br_payload,
1935519369 } } });
19356
19357 return always_noreturn;
1935819370}
1935919371
1936019372fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
......@@ -19481,7 +19493,7 @@ fn analyzeRet(
1948119493 uncasted_operand: Air.Inst.Ref,
1948219494 src: LazySrcLoc,
1948319495 operand_src: LazySrcLoc,
19484) CompileError!Zir.Inst.Index {
19496) CompileError!void {
1948519497 // Special case for returning an error to an inferred error set; we need to
1948619498 // add the error tag to the inferred error set of the in-scope function, so
1948719499 // that the coercion below works correctly.
......@@ -19513,7 +19525,7 @@ fn analyzeRet(
1951319525 try inlining.merges.results.append(sema.gpa, operand);
1951419526 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
1951519527 try inlining.merges.src_locs.append(sema.gpa, operand_src);
19516 return always_noreturn;
19528 return;
1951719529 } else if (block.is_comptime) {
1951819530 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
1951919531 } else if (sema.func_is_naked) {
......@@ -19538,8 +19550,6 @@ fn analyzeRet(
1953819550 }
1953919551
1954019552 _ = try block.addUnOp(air_tag, operand);
19541
19542 return always_noreturn;
1954319553}
1954419554
1954519555fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
......@@ -19616,7 +19626,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1961619626 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
1961719627 const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
1961819628 extra_i += 1;
19619 break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer);
19629 break :blk try sema.resolveAddressSpace(block, addrspace_src, ref, .pointer);
1962019630 } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic;
1962119631
1962219632 const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: {
......@@ -35737,7 +35747,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
3573735747 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
3573835748 } else {
3573935749 const body = zir.bodySlice(extra_index, backing_int_body_len);
35740 const ty_ref = try sema.resolveBody(&block, body, zir_index);
35750 const ty_ref = try sema.resolveInlineBody(&block, body, zir_index);
3574135751 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
3574235752 }
3574335753 };
......@@ -36618,7 +36628,7 @@ fn semaStructFields(
3661836628 assert(zir_field.type_body_len != 0);
3661936629 const body = zir.bodySlice(extra_index, zir_field.type_body_len);
3662036630 extra_index += body.len;
36621 const ty_ref = try sema.resolveBody(&block_scope, body, zir_index);
36631 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
3662236632 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
3662336633 error.NeededSourceLocation => {
3662436634 const ty_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36704,7 +36714,7 @@ fn semaStructFields(
3670436714 if (zir_field.align_body_len > 0) {
3670536715 const body = zir.bodySlice(extra_index, zir_field.align_body_len);
3670636716 extra_index += body.len;
36707 const align_ref = try sema.resolveBody(&block_scope, body, zir_index);
36717 const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
3670836718 const field_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
3670936719 error.NeededSourceLocation => {
3671036720 const align_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36854,7 +36864,7 @@ fn semaStructFieldInits(
3685436864 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index});
3685536865 sema.inst_map.putAssumeCapacity(zir_index, type_ref);
3685636866
36857 const init = try sema.resolveBody(&block_scope, body, zir_index);
36867 const init = try sema.resolveInlineBody(&block_scope, body, zir_index);
3685836868 const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) {
3685936869 error.NeededSourceLocation => {
3686036870 const init_src = mod.fieldSrcLoc(decl_index, .{
......@@ -36971,7 +36981,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3697136981 defer assert(block_scope.instructions.items.len == 0);
3697236982
3697336983 if (body.len != 0) {
36974 try sema.analyzeBody(&block_scope, body);
36984 _ = try sema.analyzeInlineBody(&block_scope, body, zir_index);
3697536985 }
3697636986
3697736987 for (comptime_mutable_decls.items) |ct_decl_index| {
......@@ -37914,15 +37924,25 @@ pub const AddressSpaceContext = enum {
3791437924 pointer,
3791537925};
3791637926
37917pub fn analyzeAddressSpace(
37927fn resolveAddressSpace(
3791837928 sema: *Sema,
3791937929 block: *Block,
3792037930 src: LazySrcLoc,
3792137931 zir_ref: Zir.Inst.Ref,
3792237932 ctx: AddressSpaceContext,
3792337933) !std.builtin.AddressSpace {
37924 const mod = sema.mod;
3792537934 const air_ref = try sema.resolveInst(zir_ref);
37935 return sema.analyzeAsAddressSpace(block, src, air_ref, ctx);
37936}
37937
37938pub fn analyzeAsAddressSpace(
37939 sema: *Sema,
37940 block: *Block,
37941 src: LazySrcLoc,
37942 air_ref: Air.Inst.Ref,
37943 ctx: AddressSpaceContext,
37944) !std.builtin.AddressSpace {
37945 const mod = sema.mod;
3792637946 const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src);
3792737947 const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{
3792837948 .needed_comptime_reason = "address space must be comptime-known",