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 {...@@ -3492,6 +3492,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3492 @panic("TODO: update owner Decl");3492 @panic("TODO: update owner Decl");
3493 }3493 }
34943494
3495 const decl_inst = decl.zir_decl_index.unwrap().?;
3496
3495 const gpa = mod.gpa;3497 const gpa = mod.gpa;
3496 const zir = decl.getFileScope(mod).zir;3498 const zir = decl.getFileScope(mod).zir;
34973499
...@@ -3563,7 +3565,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3563,7 +3565,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3563 try sema.declareDependency(.{ .src_hash = try ip.trackZir(3565 try sema.declareDependency(.{ .src_hash = try ip.trackZir(
3564 sema.gpa,3566 sema.gpa,
3565 decl.getFileScope(mod),3567 decl.getFileScope(mod),
3566 decl.zir_decl_index.unwrap().?,3568 decl_inst,
3567 ) });3569 ) });
35683570
3569 var block_scope: Sema.Block = .{3571 var block_scope: Sema.Block = .{
...@@ -3580,7 +3582,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3580,7 +3582,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35803582
3581 const decl_bodies = decl.zirBodies(mod);3583 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);
3584 // We'll do some other bits with the Sema. Clear the type target index just3586 // We'll do some other bits with the Sema. Clear the type target index just
3585 // in case they analyze any type.3587 // in case they analyze any type.
3586 sema.builtin_type_target_index = .none;3588 sema.builtin_type_target_index = .none;
...@@ -3593,7 +3595,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3593,7 +3595,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3593 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };3595 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
3594 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };3596 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
3595 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };3597 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, .{
3597 .needed_comptime_reason = "global variable initializer must be comptime-known",3599 .needed_comptime_reason = "global variable initializer must be comptime-known",
3598 });3600 });
35993601
...@@ -3709,13 +3711,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3709,13 +3711,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3709 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));3711 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3710 decl.alignment = blk: {3712 decl.alignment = blk: {
3711 const align_body = decl_bodies.align_body orelse break :blk .none;3713 const align_body = decl_bodies.align_body orelse break :blk .none;
3712 const align_ref = (try sema.analyzeBodyBreak(&block_scope, align_body)).?.operand;3714 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
3713 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);3715 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
3714 };3716 };
3715 decl.@"linksection" = blk: {3717 decl.@"linksection" = blk: {
3716 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;3718 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
3717 const linksection_ref = (try sema.analyzeBodyBreak(&block_scope, linksection_body)).?.operand;3719 const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
3718 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{3720 const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
3719 .needed_comptime_reason = "linksection must be comptime-known",3721 .needed_comptime_reason = "linksection must be comptime-known",
3720 });3722 });
3721 if (mem.indexOfScalar(u8, bytes, 0) != null) {3723 if (mem.indexOfScalar(u8, bytes, 0) != null) {
...@@ -3741,8 +3743,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3741,8 +3743,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3741 .constant => target_util.defaultAddressSpace(target, .global_constant),3743 .constant => target_util.defaultAddressSpace(target, .global_constant),
3742 else => unreachable,3744 else => unreachable,
3743 };3745 };
3744 const addrspace_ref = (try sema.analyzeBodyBreak(&block_scope, addrspace_body)).?.operand;3746 const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
3745 break :blk try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);3747 break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3746 };3748 };
3747 decl.has_tv = true;3749 decl.has_tv = true;
3748 decl.analysis = .complete;3750 decl.analysis = .complete;
...@@ -4513,7 +4515,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -4513,7 +4515,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
4513 sema.error_return_trace_index_on_fn_entry = error_return_trace_index;4515 sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
4514 inner_block.error_return_trace_index = error_return_trace_index;4516 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) {
4517 // TODO make these unreachable instead of @panic4519 // TODO make these unreachable instead of @panic
4518 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),4520 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
4519 error.GenericPoison => @panic("zig compiler bug: GenericPoison"),4521 error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
src/Sema.zig+247-227
...@@ -876,104 +876,100 @@ pub fn deinit(sema: *Sema) void {...@@ -876,104 +876,100 @@ pub fn deinit(sema: *Sema) void {
876 sema.* = undefined;876 sema.* = undefined;
877}877}
878878
879/// Returns only the result from the body that is specified.879/// Performs semantic analysis of a ZIR body which is behind a runtime condition. If comptime
880/// Only appropriate to call when it is determined at comptime that this body880/// control flow happens here, Sema will convert it to runtime control flow by introducing post-hoc
881/// has no peers.881/// blocks where necessary.
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
903fn analyzeBodyRuntimeBreak(sema: *Sema, block: *Block, body: []const Zir.Inst.Index) !void {882fn 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) {
905 error.ComptimeBreak => {884 error.ComptimeBreak => {
906 const zir_datas = sema.code.instructions.items(.data);885 const zir_datas = sema.code.instructions.items(.data);
907 const break_data = zir_datas[@intFromEnum(sema.comptime_break_inst)].@"break";886 const break_data = zir_datas[@intFromEnum(sema.comptime_break_inst)].@"break";
908 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;887 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
909 try sema.addRuntimeBreak(block, .{888 try sema.addRuntimeBreak(block, extra.block_inst, break_data.operand);
910 .block_inst = extra.block_inst,
911 .operand = break_data.operand,
912 .inst = sema.comptime_break_inst,
913 });
914 },889 },
915 else => |e| return e,890 else => |e| return e,
916 };891 };
917}892}
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(
920 sema: *Sema,897 sema: *Sema,
921 block: *Block,898 block: *Block,
922 body: []const Zir.Inst.Index,899 body: []const Zir.Inst.Index,
923) !void {900) !void {
924 _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) {901 sema.analyzeBodyInner(block, body) catch |err| switch (err) {
925 error.ComptimeBreak => unreachable, // unexpected comptime control flow902 error.ComptimeBreak => unreachable, // unexpected comptime control flow
926 else => |e| return e,903 else => |e| return e,
927 };904 };
928}905}
929906
930const BreakData = struct {907/// Given a ZIR body which can be exited via a `break_inline` instruction, or a non-inline body which
931 block_inst: Zir.Inst.Index,908/// we are evaluating at comptime, semantically analyze the body and return the result from it.
932 operand: Zir.Inst.Ref,909/// Returns `null` if control flow did not break from this block, but instead terminated with some
933 inst: Zir.Inst.Index,910/// other runtime noreturn instruction. Compile-time breaks to blocks further up the stack still
934};911/// return `error.ComptimeBreak`. If `block.is_comptime`, this function will never return `null`.
935912fn analyzeInlineBody(
936pub fn analyzeBodyBreak(
937 sema: *Sema,913 sema: *Sema,
938 block: *Block,914 block: *Block,
939 body: []const Zir.Inst.Index,915 body: []const Zir.Inst.Index,
940) CompileError!?BreakData {916 /// The index which a break instruction can target to break from this body.
941 const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) {917 break_target: Zir.Inst.Index,
942 error.ComptimeBreak => sema.comptime_break_inst,918) CompileError!?Air.Inst.Ref {
943 else => |e| return e,919 if (sema.analyzeBodyInner(block, body)) |_| {
944 };
945 if (block.instructions.items.len != 0 and
946 sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()))
947 return null;920 return null;
921 } else |err| switch (err) {
922 error.ComptimeBreak => {},
923 else => |e| return e,
924 }
925 const break_inst = sema.comptime_break_inst;
948 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";926 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
949 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;927 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
950 return BreakData{928 if (extra.block_inst != break_target) {
951 .block_inst = extra.block_inst,929 // This control flow goes further up the stack.
952 .operand = break_data.operand,930 return error.ComptimeBreak;
953 .inst = break_inst,931 }
954 };932 return try sema.resolveInst(break_data.operand);
955}933}
956934
957/// ZIR instructions which are always `noreturn` return this. This matches the935/// Like `analyzeInlineBody`, but if the body does not break with a value, returns
958/// return type of `analyzeBody` so that we can tail call them.936/// `.unreachable_value` instead of `null`. Notably, use this to evaluate an arbitrary
959/// Only appropriate to return when the instruction is known to be NoReturn937/// body at comptime to a single result value.
960/// solely based on the ZIR tag.938pub fn resolveInlineBody(
961const always_noreturn: CompileError!Zir.Inst.Index = @as(Zir.Inst.Index, undefined);939 sema: *Sema,
962940 block: *Block,
963/// This function is the main loop of `Sema` and it can be used in two different ways:941 body: []const Zir.Inst.Index,
964/// * The traditional way where there are N breaks out of the block and peer type942 /// The index which a break instruction can target to break from this body.
965/// resolution is done on the break operands. In this case, the `Zir.Inst.Index`943 break_target: Zir.Inst.Index,
966/// part of the return value will be `undefined`, and callsites should ignore it,944) CompileError!Air.Inst.Ref {
967/// finding the block result value via the block scope.945 return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value;
968/// * The "flat" way. There is only 1 break out of the block, and it is with a `break_inline`946}
969/// instruction. In this case, the `Zir.Inst.Index` part of the return value will be947
970/// the break instruction. This communicates both which block the break applies to, as948/// This function is the main loop of `Sema`. It analyzes a single body of ZIR instructions.
971/// well as the operand. No block scope needs to be created for this strategy.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.
972fn analyzeBodyInner(968fn analyzeBodyInner(
973 sema: *Sema,969 sema: *Sema,
974 block: *Block,970 block: *Block,
975 body: []const Zir.Inst.Index,971 body: []const Zir.Inst.Index,
976) CompileError!Zir.Inst.Index {972) CompileError!void {
977 // No tracy calls here, to avoid interfering with the tail call mechanism.973 // No tracy calls here, to avoid interfering with the tail call mechanism.
978974
979 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);975 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);
...@@ -997,7 +993,7 @@ fn analyzeBodyInner(...@@ -997,7 +993,7 @@ fn analyzeBodyInner(
997 // the loop. The only way to break out of the loop is with a `noreturn`993 // the loop. The only way to break out of the loop is with a `noreturn`
998 // instruction.994 // instruction.
999 var i: u32 = 0;995 var i: u32 = 0;
1000 const result = while (true) {996 while (true) {
1001 crash_info.setBodyIndex(i);997 crash_info.setBodyIndex(i);
1002 const inst = body[i];998 const inst = body[i];
1003 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{999 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{
...@@ -1214,14 +1210,14 @@ fn analyzeBodyInner(...@@ -1214,14 +1210,14 @@ fn analyzeBodyInner(
1214 // Instructions that we know to *always* be noreturn based solely on their tag.1210 // Instructions that we know to *always* be noreturn based solely on their tag.
1215 // These functions match the return type of analyzeBody so that we can1211 // These functions match the return type of analyzeBody so that we can
1216 // tail call them here.1212 // tail call them here.
1217 .compile_error => break sema.zirCompileError(block, inst),1213 .compile_error => break try sema.zirCompileError(block, inst),
1218 .ret_implicit => break sema.zirRetImplicit(block, inst),1214 .ret_implicit => break try sema.zirRetImplicit(block, inst),
1219 .ret_node => break sema.zirRetNode(block, inst),1215 .ret_node => break try sema.zirRetNode(block, inst),
1220 .ret_load => break sema.zirRetLoad(block, inst),1216 .ret_load => break try sema.zirRetLoad(block, inst),
1221 .ret_err_value => break sema.zirRetErrValue(block, inst),1217 .ret_err_value => break try sema.zirRetErrValue(block, inst),
1222 .@"unreachable" => break sema.zirUnreachable(block, inst),1218 .@"unreachable" => break try sema.zirUnreachable(block, inst),
1223 .panic => break sema.zirPanic(block, inst),1219 .panic => break try sema.zirPanic(block, inst),
1224 .trap => break sema.zirTrap(block, inst),1220 .trap => break try sema.zirTrap(block, inst),
1225 // zig fmt: on1221 // zig fmt: on
12261222
1227 // This instruction never exists in an analyzed body. It exists only in the declaration1223 // This instruction never exists in an analyzed body. It exists only in the declaration
...@@ -1247,7 +1243,7 @@ fn analyzeBodyInner(...@@ -1247,7 +1243,7 @@ fn analyzeBodyInner(
1247 .builtin_extern => try sema.zirBuiltinExtern( block, extended),1243 .builtin_extern => try sema.zirBuiltinExtern( block, extended),
1248 .@"asm" => try sema.zirAsm( block, extended, false),1244 .@"asm" => try sema.zirAsm( block, extended, false),
1249 .asm_expr => try sema.zirAsm( block, extended, true),1245 .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),
1251 .compile_log => try sema.zirCompileLog( extended),1247 .compile_log => try sema.zirCompileLog( extended),
1252 .min_multi => try sema.zirMinMaxMulti( block, extended, .min),1248 .min_multi => try sema.zirMinMaxMulti( block, extended, .min),
1253 .max_multi => try sema.zirMinMaxMulti( block, extended, .max),1249 .max_multi => try sema.zirMinMaxMulti( block, extended, .max),
...@@ -1522,18 +1518,16 @@ fn analyzeBodyInner(...@@ -1522,18 +1518,16 @@ fn analyzeBodyInner(
1522 // Special case instructions to handle comptime control flow.1518 // Special case instructions to handle comptime control flow.
1523 .@"break" => {1519 .@"break" => {
1524 if (block.is_comptime) {1520 if (block.is_comptime) {
1525 break inst; // same as break_inline1521 sema.comptime_break_inst = inst;
1522 return error.ComptimeBreak;
1526 } else {1523 } else {
1527 break sema.zirBreak(block, inst);1524 try sema.zirBreak(block, inst);
1525 break;
1528 }1526 }
1529 },1527 },
1530 .break_inline => {1528 .break_inline => {
1531 if (block.is_comptime) {1529 sema.comptime_break_inst = inst;
1532 break inst;1530 return error.ComptimeBreak;
1533 } else {
1534 sema.comptime_break_inst = inst;
1535 return error.ComptimeBreak;
1536 }
1537 },1531 },
1538 .repeat => {1532 .repeat => {
1539 if (block.is_comptime) {1533 if (block.is_comptime) {
...@@ -1548,7 +1542,10 @@ fn analyzeBodyInner(...@@ -1548,7 +1542,10 @@ fn analyzeBodyInner(
1548 i = 0;1542 i = 0;
1549 continue;1543 continue;
1550 } else {1544 } 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;
1552 }1549 }
1553 },1550 },
1554 .repeat_inline => {1551 .repeat_inline => {
...@@ -1584,13 +1581,8 @@ fn analyzeBodyInner(...@@ -1584,13 +1581,8 @@ fn analyzeBodyInner(
1584 child_block.instructions = block.instructions;1581 child_block.instructions = block.instructions;
1585 defer block.instructions = child_block.instructions;1582 defer block.instructions = child_block.instructions;
15861583
1587 const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse1584 const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1588 break always_noreturn;1585 break :blk result;
1589 if (inst == break_data.block_inst) {
1590 break :blk try sema.resolveInst(break_data.operand);
1591 } else {
1592 break break_data.inst;
1593 }
1594 },1586 },
1595 .block, .block_comptime => blk: {1587 .block, .block_comptime => blk: {
1596 if (!block.is_comptime) {1588 if (!block.is_comptime) {
...@@ -1615,13 +1607,8 @@ fn analyzeBodyInner(...@@ -1615,13 +1607,8 @@ fn analyzeBodyInner(
1615 child_block.instructions = block.instructions;1607 child_block.instructions = block.instructions;
1616 defer block.instructions = child_block.instructions;1608 defer block.instructions = child_block.instructions;
16171609
1618 const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse1610 const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
1619 break always_noreturn;1611 break :blk result;
1620 if (inst == break_data.block_inst) {
1621 break :blk try sema.resolveInst(break_data.operand);
1622 } else {
1623 break break_data.inst;
1624 }
1625 },1612 },
1626 .block_inline => blk: {1613 .block_inline => blk: {
1627 // Directly analyze the block body without introducing a new block.1614 // Directly analyze the block body without introducing a new block.
...@@ -1634,7 +1621,12 @@ fn analyzeBodyInner(...@@ -1634,7 +1621,12 @@ fn analyzeBodyInner(
1634 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);1621 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
1635 const gpa = sema.gpa;1622 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: {
1638 // Create a temporary child block so that this inline block is properly1630 // Create a temporary child block so that this inline block is properly
1639 // labeled for any .restore_err_ret_index instructions1631 // labeled for any .restore_err_ret_index instructions
1640 var child_block = block.makeSubBlock();1632 var child_block = block.makeSubBlock();
...@@ -1660,11 +1652,26 @@ fn analyzeBodyInner(...@@ -1660,11 +1652,26 @@ fn analyzeBodyInner(
1660 child_block.instructions = block.instructions;1652 child_block.instructions = block.instructions;
1661 defer block.instructions = child_block.instructions;1653 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
1664 if (need_debug_scope) {1670 if (need_debug_scope) {
1665 _ = try sema.ensurePostHoc(block, inst);1671 _ = try sema.ensurePostHoc(block, inst);
1666 }1672 }
1667 break :b .{ result, need_debug_scope };1673
1674 break :b .{ break_result, need_debug_scope };
1668 };1675 };
16691676
1670 // A runtime conditional branch that needs a post-hoc block to be1677 // A runtime conditional branch that needs a post-hoc block to be
...@@ -1686,13 +1693,13 @@ fn analyzeBodyInner(...@@ -1686,13 +1693,13 @@ fn analyzeBodyInner(
1686 // It may pass through our currently being analyzed block_inline or it1693 // It may pass through our currently being analyzed block_inline or it
1687 // may point directly to it. In the latter case, this modifies the1694 // may point directly to it. In the latter case, this modifies the
1688 // block that we looked up in the post_hoc_blocks map above.1695 // 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);
1690 }1697 }
16911698
1692 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]);1699 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]);
1693 block.instructions.items.len = block_index;1700 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);
1696 {1703 {
1697 // Destroy the ad-hoc block entry so that it does not interfere with1704 // Destroy the ad-hoc block entry so that it does not interfere with
1698 // the next iteration of comptime control flow, if any.1705 // the next iteration of comptime control flow, if any.
...@@ -1703,15 +1710,19 @@ fn analyzeBodyInner(...@@ -1703,15 +1710,19 @@ fn analyzeBodyInner(
1703 break :blk block_result;1710 break :blk block_result;
1704 }1711 }
17051712
1706 const break_data = opt_break_data orelse break always_noreturn;1713 const break_data = opt_break_data orelse break;
1707 if (inst == break_data.block_inst) {1714 if (inst == break_data.block_inst) {
1708 break :blk try sema.resolveInst(break_data.operand);1715 break :blk try sema.resolveInst(break_data.operand);
1709 } else {1716 } else {
1710 break break_data.inst;1717 // `comptime_break_inst` preserved from `analyzeBodyInner` above.
1718 return error.ComptimeBreak;
1711 }1719 }
1712 },1720 },
1713 .condbr => blk: {1721 .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 }
1715 // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/82201726 // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220
1716 const inst_data = datas[@intFromEnum(inst)].pl_node;1727 const inst_data = datas[@intFromEnum(inst)].pl_node;
1717 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };1728 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
...@@ -1728,13 +1739,9 @@ fn analyzeBodyInner(...@@ -1728,13 +1739,9 @@ fn analyzeBodyInner(
1728 const inline_body = if (cond.val.toBool()) then_body else else_body;1739 const inline_body = if (cond.val.toBool()) then_body else else_body;
17291740
1730 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1741 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1731 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1742
1732 break always_noreturn;1743 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1733 if (inst == break_data.block_inst) {1744 break :blk result;
1734 break :blk try sema.resolveInst(break_data.operand);
1735 } else {
1736 break break_data.inst;
1737 }
1738 },1745 },
1739 .condbr_inline => blk: {1746 .condbr_inline => blk: {
1740 const inst_data = datas[@intFromEnum(inst)].pl_node;1747 const inst_data = datas[@intFromEnum(inst)].pl_node;
...@@ -1754,13 +1761,9 @@ fn analyzeBodyInner(...@@ -1754,13 +1761,9 @@ fn analyzeBodyInner(
1754 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);1761 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
1755 const old_runtime_index = block.runtime_index;1762 const old_runtime_index = block.runtime_index;
1756 defer block.runtime_index = old_runtime_index;1763 defer block.runtime_index = old_runtime_index;
1757 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1764
1758 break always_noreturn;1765 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1759 if (inst == break_data.block_inst) {1766 break :blk result;
1760 break :blk try sema.resolveInst(break_data.operand);
1761 } else {
1762 break break_data.inst;
1763 }
1764 },1767 },
1765 .@"try" => blk: {1768 .@"try" => blk: {
1766 if (!block.is_comptime) break :blk try sema.zirTry(block, inst);1769 if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
...@@ -1785,13 +1788,8 @@ fn analyzeBodyInner(...@@ -1785,13 +1788,8 @@ fn analyzeBodyInner(
1785 if (is_non_err_val.toBool()) {1788 if (is_non_err_val.toBool()) {
1786 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);1789 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
1787 }1790 }
1788 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1791 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1789 break always_noreturn;1792 break :blk result;
1790 if (inst == break_data.block_inst) {
1791 break :blk try sema.resolveInst(break_data.operand);
1792 } else {
1793 break break_data.inst;
1794 }
1795 },1793 },
1796 .try_ptr => blk: {1794 .try_ptr => blk: {
1797 if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst);1795 if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst);
...@@ -1811,22 +1809,22 @@ fn analyzeBodyInner(...@@ -1811,22 +1809,22 @@ fn analyzeBodyInner(
1811 if (is_non_err_val.toBool()) {1809 if (is_non_err_val.toBool()) {
1812 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);1810 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
1813 }1811 }
1814 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1812 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
1815 break always_noreturn;1813 break :blk result;
1816 if (inst == break_data.block_inst) {
1817 break :blk try sema.resolveInst(break_data.operand);
1818 } else {
1819 break break_data.inst;
1820 }
1821 },1814 },
1822 .@"defer" => blk: {1815 .@"defer" => blk: {
1823 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";1816 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";
1824 const defer_body = sema.code.bodySlice(inst_data.index, inst_data.len);1817 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) {1818 if (sema.analyzeBodyInner(block, defer_body)) |_| {
1826 error.ComptimeBreak => sema.comptime_break_inst,1819 // The defer terminated noreturn - no more analysis needed.
1820 break;
1821 } else |err| switch (err) {
1822 error.ComptimeBreak => {},
1827 else => |e| return e,1823 else => |e| return e,
1828 };1824 }
1829 if (break_inst != defer_body[defer_body.len - 1]) break always_noreturn;1825 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) {
1826 return error.ComptimeBreak;
1827 }
1830 break :blk .void_value;1828 break :blk .void_value;
1831 },1829 },
1832 .defer_err_code => blk: {1830 .defer_err_code => blk: {
...@@ -1835,11 +1833,16 @@ fn analyzeBodyInner(...@@ -1835,11 +1833,16 @@ fn analyzeBodyInner(
1835 const defer_body = sema.code.bodySlice(extra.index, extra.len);1833 const defer_body = sema.code.bodySlice(extra.index, extra.len);
1836 const err_code = try sema.resolveInst(inst_data.err_code);1834 const err_code = try sema.resolveInst(inst_data.err_code);
1837 map.putAssumeCapacity(extra.remapped_err_code, err_code);1835 map.putAssumeCapacity(extra.remapped_err_code, err_code);
1838 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {1836 if (sema.analyzeBodyInner(block, defer_body)) |_| {
1839 error.ComptimeBreak => sema.comptime_break_inst,1837 // The defer terminated noreturn - no more analysis needed.
1838 break;
1839 } else |err| switch (err) {
1840 error.ComptimeBreak => {},
1840 else => |e| return e,1841 else => |e| return e,
1841 };1842 }
1842 if (break_inst != defer_body[defer_body.len - 1]) break always_noreturn;1843 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) {
1844 return error.ComptimeBreak;
1845 }
1843 break :blk .void_value;1846 break :blk .void_value;
1844 },1847 },
1845 };1848 };
...@@ -1847,17 +1850,15 @@ fn analyzeBodyInner(...@@ -1847,17 +1850,15 @@ fn analyzeBodyInner(
1847 // We're going to assume that the body itself is noreturn, so let's ensure that now1850 // We're going to assume that the body itself is noreturn, so let's ensure that now
1848 assert(block.instructions.items.len > 0);1851 assert(block.instructions.items.len > 0);
1849 assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()));1852 assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()));
1850 break always_noreturn;1853 break;
1851 }1854 }
1852 map.putAssumeCapacity(inst, air_inst);1855 map.putAssumeCapacity(inst, air_inst);
1853 i += 1;1856 i += 1;
1854 };1857 }
18551858
1856 // We may have overwritten the capture scope due to a `repeat` instruction where1859 // We may have overwritten the capture scope due to a `repeat` instruction where
1857 // the body had a capture; restore it now.1860 // the body had a capture; restore it now.
1858 block.wip_capture_scope = parent_capture_scope;1861 block.wip_capture_scope = parent_capture_scope;
1859
1860 return result;
1861}1862}
18621863
1863pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {1864pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
...@@ -1894,7 +1895,7 @@ fn resolveConstBool(...@@ -1894,7 +1895,7 @@ fn resolveConstBool(
1894 return val.toBool();1895 return val.toBool();
1895}1896}
18961897
1897pub fn resolveConstString(1898fn resolveConstString(
1898 sema: *Sema,1899 sema: *Sema,
1899 block: *Block,1900 block: *Block,
1900 src: LazySrcLoc,1901 src: LazySrcLoc,
...@@ -1902,6 +1903,16 @@ pub fn resolveConstString(...@@ -1902,6 +1903,16 @@ pub fn resolveConstString(
1902 reason: NeededComptimeReason,1903 reason: NeededComptimeReason,
1903) ![]u8 {1904) ![]u8 {
1904 const air_inst = try sema.resolveInst(zir_ref);1905 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 {
1905 const wanted_type = Type.slice_const_u8;1916 const wanted_type = Type.slice_const_u8;
1906 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);1917 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1907 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason);1918 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason);
...@@ -2193,9 +2204,8 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val...@@ -2193,9 +2204,8 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val
2193 return val;2204 return val;
2194}2205}
21952206
2196/// Returns a compile error if the value has tag `variable`. See `resolveInstValue` for2207/// Returns a compile error if the value has tag `variable`.
2197/// a function that does not.2208fn resolveInstConst(
2198pub fn resolveInstConst(
2199 sema: *Sema,2209 sema: *Sema,
2200 block: *Block,2210 block: *Block,
2201 src: LazySrcLoc,2211 src: LazySrcLoc,
...@@ -2211,15 +2221,13 @@ pub fn resolveInstConst(...@@ -2211,15 +2221,13 @@ pub fn resolveInstConst(
2211}2221}
22122222
2213/// Value Tag may be `undef` or `variable`.2223/// Value Tag may be `undef` or `variable`.
2214/// See `resolveInstConst` for an alternative.2224pub fn resolveConstValueAllowVariables(
2215pub fn resolveInstValueAllowVariables(
2216 sema: *Sema,2225 sema: *Sema,
2217 block: *Block,2226 block: *Block,
2218 src: LazySrcLoc,2227 src: LazySrcLoc,
2219 zir_ref: Zir.Inst.Ref,2228 air_ref: Air.Inst.Ref,
2220 reason: NeededComptimeReason,2229 reason: NeededComptimeReason,
2221) CompileError!TypedValue {2230) CompileError!TypedValue {
2222 const air_ref = try sema.resolveInst(zir_ref);
2223 const val = try sema.resolveValueAllowVariables(air_ref) orelse {2231 const val = try sema.resolveValueAllowVariables(air_ref) orelse {
2224 return sema.failWithNeededComptime(block, src, reason);2232 return sema.failWithNeededComptime(block, src, reason);
2225 };2233 };
...@@ -2616,7 +2624,7 @@ fn reparentOwnedErrorMsg(...@@ -2616,7 +2624,7 @@ fn reparentOwnedErrorMsg(
26162624
2617const align_ty = Type.u29;2625const align_ty = Type.u29;
26182626
2619fn analyzeAsAlign(2627pub fn analyzeAsAlign(
2620 sema: *Sema,2628 sema: *Sema,
2621 block: *Block,2629 block: *Block,
2622 src: LazySrcLoc,2630 src: LazySrcLoc,
...@@ -2654,7 +2662,7 @@ fn validateAlignAllowZero(...@@ -2654,7 +2662,7 @@ fn validateAlignAllowZero(
2654 return Alignment.fromNonzeroByteUnits(alignment);2662 return Alignment.fromNonzeroByteUnits(alignment);
2655}2663}
26562664
2657pub fn resolveAlign(2665fn resolveAlign(
2658 sema: *Sema,2666 sema: *Sema,
2659 block: *Block,2667 block: *Block,
2660 src: LazySrcLoc,2668 src: LazySrcLoc,
...@@ -3054,7 +3062,7 @@ fn zirEnumDecl(...@@ -3054,7 +3062,7 @@ fn zirEnumDecl(
3054 defer enum_block.instructions.deinit(sema.gpa);3062 defer enum_block.instructions.deinit(sema.gpa);
30553063
3056 if (body.len != 0) {3064 if (body.len != 0) {
3057 try sema.analyzeBody(&enum_block, body);3065 _ = try sema.analyzeInlineBody(&enum_block, body, inst);
3058 }3066 }
30593067
3060 if (tag_type_ref != .none) {3068 if (tag_type_ref != .none) {
...@@ -5597,7 +5605,7 @@ fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -5597,7 +5605,7 @@ fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
5597 return Air.internedToRef((try sema.mod.floatValue(Type.comptime_float, number)).toIntern());5605 return Air.internedToRef((try sema.mod.floatValue(Type.comptime_float, number)).toIntern());
5598}5606}
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 {
5601 const tracy = trace(@src());5609 const tracy = trace(@src());
5602 defer tracy.end();5610 defer tracy.end();
56035611
...@@ -5650,7 +5658,7 @@ fn zirCompileLog(...@@ -5650,7 +5658,7 @@ fn zirCompileLog(
5650 return .void_value;5658 return .void_value;
5651}5659}
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 {
5654 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;5662 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
5655 const src = inst_data.src();5663 const src = inst_data.src();
5656 const msg_inst = try sema.resolveInst(inst_data.operand);5664 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...@@ -5663,16 +5671,14 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.I
5663 return sema.fail(block, src, "encountered @panic at comptime", .{});5671 return sema.fail(block, src, "encountered @panic at comptime", .{});
5664 }5672 }
5665 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");5673 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");
5666 return always_noreturn;
5667}5674}
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 {
5670 const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;5677 const src_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].node;
5671 const src = LazySrcLoc.nodeOffset(src_node);5678 const src = LazySrcLoc.nodeOffset(src_node);
5672 if (block.is_comptime)5679 if (block.is_comptime)
5673 return sema.fail(block, src, "encountered @trap at comptime", .{});5680 return sema.fail(block, src, "encountered @trap at comptime", .{});
5674 _ = try block.addNoOp(.trap);5681 _ = try block.addNoOp(.trap);
5675 return always_noreturn;
5676}5682}
56775683
5678fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5684fn 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...@@ -5726,7 +5732,8 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5726 var loop_block = child_block.makeSubBlock();5732 var loop_block = child_block.makeSubBlock();
5727 defer loop_block.instructions.deinit(gpa);5733 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
5731 const loop_block_len = loop_block.instructions.items.len;5738 const loop_block_len = loop_block.instructions.items.len;
5732 if (loop_block_len > 0 and sema.typeOf(loop_block.instructions.items[loop_block_len - 1].toRef()).isNoReturn(mod)) {5739 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...@@ -5742,7 +5749,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5742 );5749 );
5743 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));5750 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));
5744 }5751 }
5745 return sema.analyzeBlockBody(parent_block, src, &child_block, merges, false);5752 return sema.resolveAnalyzedBlock(parent_block, src, &child_block, merges, false);
5746}5753}
57475754
5748fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5755fn 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...@@ -5785,8 +5792,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5785 };5792 };
5786 defer child_block.instructions.deinit(gpa);5793 defer child_block.instructions.deinit(gpa);
57875794
5788 // Ignore the result, all the relevant operations have written to c_import_buf already.5795 _ = try sema.analyzeInlineBody(&child_block, body, inst);
5789 _ = try sema.analyzeBodyBreak(&child_block, body);
57905796
5791 var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|5797 var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|
5792 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});5798 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...@@ -5916,6 +5922,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt
5916 return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);5922 return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges);
5917}5923}
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.
5919fn resolveBlockBody(5928fn resolveBlockBody(
5920 sema: *Sema,5929 sema: *Sema,
5921 parent_block: *Block,5930 parent_block: *Block,
...@@ -5928,12 +5937,12 @@ fn resolveBlockBody(...@@ -5928,12 +5937,12 @@ fn resolveBlockBody(
5928 merges: *Block.Merges,5937 merges: *Block.Merges,
5929) CompileError!Air.Inst.Ref {5938) CompileError!Air.Inst.Ref {
5930 if (child_block.is_comptime) {5939 if (child_block.is_comptime) {
5931 return sema.resolveBody(child_block, body, body_inst);5940 return sema.resolveInlineBody(child_block, body, body_inst);
5932 } else {5941 } else {
5933 var need_debug_scope = false;5942 var need_debug_scope = false;
5934 child_block.need_debug_scope = &need_debug_scope;5943 child_block.need_debug_scope = &need_debug_scope;
5935 if (sema.analyzeBodyInner(child_block, body)) |_| {5944 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);
5937 } else |err| switch (err) {5946 } else |err| switch (err) {
5938 error.ComptimeBreak => {5947 error.ComptimeBreak => {
5939 // Comptime control flow is happening, however child_block may still contain5948 // Comptime control flow is happening, however child_block may still contain
...@@ -5970,7 +5979,12 @@ fn resolveBlockBody(...@@ -5970,7 +5979,12 @@ fn resolveBlockBody(
5970 }5979 }
5971}5980}
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(
5974 sema: *Sema,5988 sema: *Sema,
5975 parent_block: *Block,5989 parent_block: *Block,
5976 src: LazySrcLoc,5990 src: LazySrcLoc,
...@@ -6360,7 +6374,7 @@ fn zirFence(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) Co...@@ -6360,7 +6374,7 @@ fn zirFence(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) Co
6360 });6374 });
6361}6375}
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 {
6364 const tracy = trace(@src());6378 const tracy = trace(@src());
6365 defer tracy.end();6379 defer tracy.end();
63666380
...@@ -6386,7 +6400,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6386,7 +6400,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
6386 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop;6400 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop;
6387 block.runtime_loop = start_block.runtime_loop;6401 block.runtime_loop = start_block.runtime_loop;
6388 }6402 }
6389 return inst;6403 return;
6390 }6404 }
6391 }6405 }
6392 block = block.parent.?;6406 block = block.parent.?;
...@@ -7096,7 +7110,7 @@ const CallArgsInfo = union(enum) {...@@ -7096,7 +7110,7 @@ const CallArgsInfo = union(enum) {
7096 // Give the arg its result type7110 // Give the arg its result type
7097 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(param_ty.toIntern()));7111 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(param_ty.toIntern()));
7098 // Resolve the arg!7112 // 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
7101 if (sema.typeOf(uncoerced_arg).zigTypeTag(mod) == .NoReturn) {7115 if (sema.typeOf(uncoerced_arg).zigTypeTag(mod) == .NoReturn) {
7102 // This terminates resolution of arguments. The caller should7116 // This terminates resolution of arguments. The caller should
...@@ -7539,7 +7553,7 @@ fn analyzeCall(...@@ -7539,7 +7553,7 @@ fn analyzeCall(
7539 // each of the parameters, resolving the return type and providing it to the child7553 // each of the parameters, resolving the return type and providing it to the child
7540 // `Sema` so that it can be used for the `ret_ptr` instruction.7554 // `Sema` so that it can be used for the `ret_ptr` instruction.
7541 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)7555 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))
7543 else7557 else
7544 try sema.resolveInst(fn_info.ret_ty_ref);7558 try sema.resolveInst(fn_info.ret_ty_ref);
7545 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };7559 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
...@@ -7608,11 +7622,11 @@ fn analyzeCall(...@@ -7608,11 +7622,11 @@ fn analyzeCall(
7608 }7622 }
76097623
7610 const result = result: {7624 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) {
7612 error.ComptimeReturn => break :result inlining.comptime_result,7626 error.ComptimeReturn => break :result inlining.comptime_result,
7613 else => |e| return e,7627 else => |e| return e,
7614 };7628 };
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);
7616 };7630 };
76177631
7618 if (!is_comptime_call and !block.is_typeof and7632 if (!is_comptime_call and !block.is_typeof and
...@@ -7791,7 +7805,7 @@ fn analyzeInlineCallArg(...@@ -7791,7 +7805,7 @@ fn analyzeInlineCallArg(
7791 const param_ty = param_ty: {7805 const param_ty = param_ty: {
7792 const raw_param_ty = func_ty_info.param_types.get(ip)[arg_i.*];7806 const raw_param_ty = func_ty_info.param_types.get(ip)[arg_i.*];
7793 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;7807 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);
7795 const param_ty = try ics.callee().analyzeAsType(param_block, param_src, param_ty_inst);7809 const param_ty = try ics.callee().analyzeAsType(param_block, param_src, param_ty_inst);
7796 break :param_ty param_ty.toIntern();7810 break :param_ty param_ty.toIntern();
7797 };7811 };
...@@ -8026,7 +8040,7 @@ fn instantiateGenericCall(...@@ -8026,7 +8040,7 @@ fn instantiateGenericCall(
8026 child_sema.generic_call_decl = prev_generic_call_decl;8040 child_sema.generic_call_decl = prev_generic_call_decl;
8027 }8041 }
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);
8030 break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst);8044 break :param_ty try child_sema.analyzeAsType(&child_block, param_data.src(), param_ty_inst);
8031 },8045 },
8032 else => unreachable,8046 else => unreachable,
...@@ -8118,7 +8132,7 @@ fn instantiateGenericCall(...@@ -8118,7 +8132,7 @@ fn instantiateGenericCall(
81188132
8119 // We've already handled parameters, so don't resolve the whole body. Instead, just8133 // We've already handled parameters, so don't resolve the whole body. Instead, just
8120 // do the instructions after the params (i.e. the func itself).8134 // 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);
8122 const callee_index = (child_sema.resolveConstDefinedValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();8136 const callee_index = (child_sema.resolveConstDefinedValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
81238137
8124 const callee = mod.funcInfo(callee_index);8138 const callee = mod.funcInfo(callee_index);
...@@ -9176,7 +9190,7 @@ fn resolveGenericBody(...@@ -9176,7 +9190,7 @@ fn resolveGenericBody(
9176 sema.generic_call_decl = prev_generic_call_decl;9190 sema.generic_call_decl = prev_generic_call_decl;
9177 }9191 }
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;
9180 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;9194 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
9181 const val = sema.resolveConstDefinedValue(block, src, result, reason) catch |err| break :err err;9195 const val = sema.resolveConstDefinedValue(block, src, result, reason) catch |err| break :err err;
9182 return val;9196 return val;
...@@ -9810,7 +9824,7 @@ fn zirParam(...@@ -9810,7 +9824,7 @@ fn zirParam(
9810 sema.generic_call_decl = prev_generic_call_decl;9824 sema.generic_call_decl = prev_generic_call_decl;
9811 }9825 }
98129826
9813 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {9827 if (sema.resolveInlineBody(block, body, inst)) |param_ty_inst| {
9814 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {9828 if (sema.analyzeAsType(block, src, param_ty_inst)) |param_ty| {
9815 break :param_ty param_ty;9829 break :param_ty param_ty;
9816 } else |err| break :err err;9830 } else |err| break :err err;
...@@ -11556,7 +11570,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11556,7 +11570,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11556 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));11570 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
11557 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));11571 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);
11560}11574}
1156111575
11562fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {11576fn 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...@@ -12178,7 +12192,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12178 false,12192 false,
12179 );12193 );
1218012194
12181 return sema.analyzeBlockBody(block, src, &child_block, merges, false);12195 return sema.resolveAnalyzedBlock(block, src, &child_block, merges, false);
12182}12196}
1218312197
12184const SpecialProng = struct {12198const SpecialProng = struct {
...@@ -18602,7 +18616,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -18602,7 +18616,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
18602 };18616 };
18603 defer child_block.instructions.deinit(sema.gpa);18617 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);
18606 const operand_ty = sema.typeOf(operand);18620 const operand_ty = sema.typeOf(operand);
18607 if (operand_ty.isGenericPoison()) return error.GenericPoison;18621 if (operand_ty.isGenericPoison()) return error.GenericPoison;
18608 return Air.internedToRef(operand_ty.toIntern());18622 return Air.internedToRef(operand_ty.toIntern());
...@@ -18657,6 +18671,7 @@ fn zirTypeofPeer(...@@ -18657,6 +18671,7 @@ fn zirTypeofPeer(
18657 sema: *Sema,18671 sema: *Sema,
18658 block: *Block,18672 block: *Block,
18659 extended: Zir.Inst.Extended.InstData,18673 extended: Zir.Inst.Extended.InstData,
18674 inst: Zir.Inst.Index,
18660) CompileError!Air.Inst.Ref {18675) CompileError!Air.Inst.Ref {
18661 const tracy = trace(@src());18676 const tracy = trace(@src());
18662 defer tracy.end();18677 defer tracy.end();
...@@ -18681,7 +18696,7 @@ fn zirTypeofPeer(...@@ -18681,7 +18696,7 @@ fn zirTypeofPeer(
18681 };18696 };
18682 defer child_block.instructions.deinit(sema.gpa);18697 defer child_block.instructions.deinit(sema.gpa);
18683 // Ignore the result, we only care about the instructions in `args`.18698 // 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
18686 const args = sema.code.refSlice(extra.end, extended.small);18701 const args = sema.code.refSlice(extra.end, extended.small);
1868718702
...@@ -18748,7 +18763,7 @@ fn zirBoolBr(...@@ -18748,7 +18763,7 @@ fn zirBoolBr(
18748 // comptime-known left-hand side. No need for a block here; the result18763 // comptime-known left-hand side. No need for a block here; the result
18749 // is simply the rhs expression. Here we rely on there only being 118764 // is simply the rhs expression. Here we rely on there only being 1
18750 // break instruction (`break_inline`).18765 // 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);
18752 if (sema.typeOf(rhs_result).isNoReturn(mod)) {18767 if (sema.typeOf(rhs_result).isNoReturn(mod)) {
18753 return rhs_result;18768 return rhs_result;
18754 }18769 }
...@@ -18782,7 +18797,7 @@ fn zirBoolBr(...@@ -18782,7 +18797,7 @@ fn zirBoolBr(
18782 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;18797 const lhs_result: Air.Inst.Ref = if (is_bool_or) .bool_true else .bool_false;
18783 _ = try lhs_block.addBr(block_inst, lhs_result);18798 _ = 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);
18786 const rhs_noret = sema.typeOf(rhs_result).isNoReturn(mod);18801 const rhs_noret = sema.typeOf(rhs_result).isNoReturn(mod);
18787 const coerced_rhs_result = if (!rhs_noret) rhs: {18802 const coerced_rhs_result = if (!rhs_noret) rhs: {
18788 const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src);18803 const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src);
...@@ -18933,7 +18948,7 @@ fn zirCondbr(...@@ -18933,7 +18948,7 @@ fn zirCondbr(
18933 sema: *Sema,18948 sema: *Sema,
18934 parent_block: *Block,18949 parent_block: *Block,
18935 inst: Zir.Inst.Index,18950 inst: Zir.Inst.Index,
18936) CompileError!Zir.Inst.Index {18951) CompileError!void {
18937 const tracy = trace(@src());18952 const tracy = trace(@src());
18938 defer tracy.end();18953 defer tracy.end();
1893918954
...@@ -19002,7 +19017,6 @@ fn zirCondbr(...@@ -19002,7 +19017,6 @@ fn zirCondbr(
19002 });19017 });
19003 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));19018 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
19004 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));19019 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
19005 return always_noreturn;
19006}19020}
1900719021
19008fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19022fn 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!...@@ -19027,14 +19041,15 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
19027 }19041 }
19028 // We can analyze the body directly in the parent block because we know there are19042 // We can analyze the body directly in the parent block because we know there are
19029 // no breaks from the body possible, and that the body is noreturn.19043 // 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;
19031 }19046 }
1903219047
19033 var sub_block = parent_block.makeSubBlock();19048 var sub_block = parent_block.makeSubBlock();
19034 defer sub_block.instructions.deinit(sema.gpa);19049 defer sub_block.instructions.deinit(sema.gpa);
1903519050
19036 // This body is guaranteed to end with noreturn and has no breaks.19051 // 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
19039 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +19054 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Try).Struct.fields.len +
19040 sub_block.instructions.items.len);19055 sub_block.instructions.items.len);
...@@ -19074,14 +19089,15 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -19074,14 +19089,15 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
19074 }19089 }
19075 // We can analyze the body directly in the parent block because we know there are19090 // We can analyze the body directly in the parent block because we know there are
19076 // no breaks from the body possible, and that the body is noreturn.19091 // 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;
19078 }19094 }
1907919095
19080 var sub_block = parent_block.makeSubBlock();19096 var sub_block = parent_block.makeSubBlock();
19081 defer sub_block.instructions.deinit(sema.gpa);19097 defer sub_block.instructions.deinit(sema.gpa);
1908219098
19083 // This body is guaranteed to end with noreturn and has no breaks.19099 // 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
19086 const operand_ty = sema.typeOf(operand);19102 const operand_ty = sema.typeOf(operand);
19087 const ptr_info = operand_ty.ptrInfo(mod);19103 const ptr_info = operand_ty.ptrInfo(mod);
...@@ -19156,13 +19172,13 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label...@@ -19156,13 +19172,13 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
19156 return labeled_block;19172 return labeled_block;
19157}19173}
1915819174
19159// A `break` statement is inside a runtime condition, but trying to19175/// A `break` statement is inside a runtime condition, but trying to
19160// break from an inline loop. In such case we must convert it to19176/// break from an inline loop. In such case we must convert it to
19161// a runtime break.19177/// a runtime break.
19162fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {19178fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void {
19163 const labeled_block = try sema.ensurePostHoc(child_block, break_data.block_inst);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);
19166 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);19182 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
1916719183
19168 try labeled_block.label.merges.results.append(sema.gpa, operand);19184 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...@@ -19176,7 +19192,7 @@ fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !voi
19176 }19192 }
19177}19193}
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 {
19180 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";19196 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
19181 const src = inst_data.src();19197 const src = inst_data.src();
1918219198
...@@ -19193,14 +19209,13 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -19193,14 +19209,13 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
19193 },19209 },
19194 else => |e| return e,19210 else => |e| return e,
19195 };19211 };
19196 return always_noreturn;
19197}19212}
1919819213
19199fn zirRetErrValue(19214fn zirRetErrValue(
19200 sema: *Sema,19215 sema: *Sema,
19201 block: *Block,19216 block: *Block,
19202 inst: Zir.Inst.Index,19217 inst: Zir.Inst.Index,
19203) CompileError!Zir.Inst.Index {19218) CompileError!void {
19204 const mod = sema.mod;19219 const mod = sema.mod;
19205 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;19220 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
19206 const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));19221 const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
...@@ -19219,7 +19234,7 @@ fn zirRetImplicit(...@@ -19219,7 +19234,7 @@ fn zirRetImplicit(
19219 sema: *Sema,19234 sema: *Sema,
19220 block: *Block,19235 block: *Block,
19221 inst: Zir.Inst.Index,19236 inst: Zir.Inst.Index,
19222) CompileError!Zir.Inst.Index {19237) CompileError!void {
19223 const tracy = trace(@src());19238 const tracy = trace(@src());
19224 defer tracy.end();19239 defer tracy.end();
1922519240
...@@ -19234,7 +19249,7 @@ fn zirRetImplicit(...@@ -19234,7 +19249,7 @@ fn zirRetImplicit(
19234 } else {19249 } else {
19235 try block.addUnreachable(r_brace_src, false);19250 try block.addUnreachable(r_brace_src, false);
19236 }19251 }
19237 return always_noreturn;19252 return;
19238 }19253 }
1923919254
19240 const operand = try sema.resolveInst(inst_data.operand);19255 const operand = try sema.resolveInst(inst_data.operand);
...@@ -19265,7 +19280,7 @@ fn zirRetImplicit(...@@ -19265,7 +19280,7 @@ fn zirRetImplicit(
19265 return sema.analyzeRet(block, operand, r_brace_src, r_brace_src);19280 return sema.analyzeRet(block, operand, r_brace_src, r_brace_src);
19266}19281}
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 {
19269 const tracy = trace(@src());19284 const tracy = trace(@src());
19270 defer tracy.end();19285 defer tracy.end();
1927119286
...@@ -19276,7 +19291,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir...@@ -19276,7 +19291,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
19276 return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node });19291 return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node });
19277}19292}
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 {
19280 const tracy = trace(@src());19295 const tracy = trace(@src());
19281 defer tracy.end();19296 defer tracy.end();
1928219297
...@@ -19295,7 +19310,6 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir...@@ -19295,7 +19310,6 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
19295 }19310 }
1929619311
19297 _ = try block.addUnOp(.ret_load, ret_ptr);19312 _ = try block.addUnOp(.ret_load, ret_ptr);
19298 return always_noreturn;
19299}19313}
1930019314
19301fn retWithErrTracing(19315fn retWithErrTracing(
...@@ -19305,12 +19319,12 @@ fn retWithErrTracing(...@@ -19305,12 +19319,12 @@ fn retWithErrTracing(
19305 is_non_err: Air.Inst.Ref,19319 is_non_err: Air.Inst.Ref,
19306 ret_tag: Air.Inst.Tag,19320 ret_tag: Air.Inst.Tag,
19307 operand: Air.Inst.Ref,19321 operand: Air.Inst.Ref,
19308) CompileError!Zir.Inst.Index {19322) CompileError!void {
19309 const mod = sema.mod;19323 const mod = sema.mod;
19310 const need_check = switch (is_non_err) {19324 const need_check = switch (is_non_err) {
19311 .bool_true => {19325 .bool_true => {
19312 _ = try block.addUnOp(ret_tag, operand);19326 _ = try block.addUnOp(ret_tag, operand);
19313 return always_noreturn;19327 return;
19314 },19328 },
19315 .bool_false => false,19329 .bool_false => false,
19316 else => true,19330 else => true,
...@@ -19326,7 +19340,7 @@ fn retWithErrTracing(...@@ -19326,7 +19340,7 @@ fn retWithErrTracing(
19326 if (!need_check) {19340 if (!need_check) {
19327 try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");19341 try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");
19328 _ = try block.addUnOp(ret_tag, operand);19342 _ = try block.addUnOp(ret_tag, operand);
19329 return always_noreturn;19343 return;
19330 }19344 }
1933119345
19332 var then_block = block.makeSubBlock();19346 var then_block = block.makeSubBlock();
...@@ -19353,8 +19367,6 @@ fn retWithErrTracing(...@@ -19353,8 +19367,6 @@ fn retWithErrTracing(
19353 .operand = is_non_err,19367 .operand = is_non_err,
19354 .payload = cond_br_payload,19368 .payload = cond_br_payload,
19355 } } });19369 } } });
19356
19357 return always_noreturn;
19358}19370}
1935919371
19360fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {19372fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
...@@ -19481,7 +19493,7 @@ fn analyzeRet(...@@ -19481,7 +19493,7 @@ fn analyzeRet(
19481 uncasted_operand: Air.Inst.Ref,19493 uncasted_operand: Air.Inst.Ref,
19482 src: LazySrcLoc,19494 src: LazySrcLoc,
19483 operand_src: LazySrcLoc,19495 operand_src: LazySrcLoc,
19484) CompileError!Zir.Inst.Index {19496) CompileError!void {
19485 // Special case for returning an error to an inferred error set; we need to19497 // Special case for returning an error to an inferred error set; we need to
19486 // add the error tag to the inferred error set of the in-scope function, so19498 // add the error tag to the inferred error set of the in-scope function, so
19487 // that the coercion below works correctly.19499 // that the coercion below works correctly.
...@@ -19513,7 +19525,7 @@ fn analyzeRet(...@@ -19513,7 +19525,7 @@ fn analyzeRet(
19513 try inlining.merges.results.append(sema.gpa, operand);19525 try inlining.merges.results.append(sema.gpa, operand);
19514 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);19526 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
19515 try inlining.merges.src_locs.append(sema.gpa, operand_src);19527 try inlining.merges.src_locs.append(sema.gpa, operand_src);
19516 return always_noreturn;19528 return;
19517 } else if (block.is_comptime) {19529 } else if (block.is_comptime) {
19518 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});19530 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
19519 } else if (sema.func_is_naked) {19531 } else if (sema.func_is_naked) {
...@@ -19538,8 +19550,6 @@ fn analyzeRet(...@@ -19538,8 +19550,6 @@ fn analyzeRet(
19538 }19550 }
1953919551
19540 _ = try block.addUnOp(air_tag, operand);19552 _ = try block.addUnOp(air_tag, operand);
19541
19542 return always_noreturn;
19543}19553}
1954419554
19545fn floatOpAllowed(tag: Zir.Inst.Tag) bool {19555fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
...@@ -19616,7 +19626,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19616,7 +19626,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19616 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {19626 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
19617 const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);19627 const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]);
19618 extra_i += 1;19628 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);
19620 } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic;19630 } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic;
1962119631
19622 const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: {19632 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...@@ -35737,7 +35747,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35737 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);35747 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
35738 } else {35748 } else {
35739 const body = zir.bodySlice(extra_index, backing_int_body_len);35749 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);
35741 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);35751 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
35742 }35752 }
35743 };35753 };
...@@ -36618,7 +36628,7 @@ fn semaStructFields(...@@ -36618,7 +36628,7 @@ fn semaStructFields(
36618 assert(zir_field.type_body_len != 0);36628 assert(zir_field.type_body_len != 0);
36619 const body = zir.bodySlice(extra_index, zir_field.type_body_len);36629 const body = zir.bodySlice(extra_index, zir_field.type_body_len);
36620 extra_index += body.len;36630 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);
36622 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {36632 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
36623 error.NeededSourceLocation => {36633 error.NeededSourceLocation => {
36624 const ty_src = mod.fieldSrcLoc(decl_index, .{36634 const ty_src = mod.fieldSrcLoc(decl_index, .{
...@@ -36704,7 +36714,7 @@ fn semaStructFields(...@@ -36704,7 +36714,7 @@ fn semaStructFields(
36704 if (zir_field.align_body_len > 0) {36714 if (zir_field.align_body_len > 0) {
36705 const body = zir.bodySlice(extra_index, zir_field.align_body_len);36715 const body = zir.bodySlice(extra_index, zir_field.align_body_len);
36706 extra_index += body.len;36716 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);
36708 const field_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {36718 const field_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
36709 error.NeededSourceLocation => {36719 error.NeededSourceLocation => {
36710 const align_src = mod.fieldSrcLoc(decl_index, .{36720 const align_src = mod.fieldSrcLoc(decl_index, .{
...@@ -36854,7 +36864,7 @@ fn semaStructFieldInits(...@@ -36854,7 +36864,7 @@ fn semaStructFieldInits(
36854 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index});36864 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index});
36855 sema.inst_map.putAssumeCapacity(zir_index, type_ref);36865 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);
36858 const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) {36868 const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) {
36859 error.NeededSourceLocation => {36869 error.NeededSourceLocation => {
36860 const init_src = mod.fieldSrcLoc(decl_index, .{36870 const init_src = mod.fieldSrcLoc(decl_index, .{
...@@ -36971,7 +36981,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -36971,7 +36981,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36971 defer assert(block_scope.instructions.items.len == 0);36981 defer assert(block_scope.instructions.items.len == 0);
3697236982
36973 if (body.len != 0) {36983 if (body.len != 0) {
36974 try sema.analyzeBody(&block_scope, body);36984 _ = try sema.analyzeInlineBody(&block_scope, body, zir_index);
36975 }36985 }
3697636986
36977 for (comptime_mutable_decls.items) |ct_decl_index| {36987 for (comptime_mutable_decls.items) |ct_decl_index| {
...@@ -37914,15 +37924,25 @@ pub const AddressSpaceContext = enum {...@@ -37914,15 +37924,25 @@ pub const AddressSpaceContext = enum {
37914 pointer,37924 pointer,
37915};37925};
3791637926
37917pub fn analyzeAddressSpace(37927fn resolveAddressSpace(
37918 sema: *Sema,37928 sema: *Sema,
37919 block: *Block,37929 block: *Block,
37920 src: LazySrcLoc,37930 src: LazySrcLoc,
37921 zir_ref: Zir.Inst.Ref,37931 zir_ref: Zir.Inst.Ref,
37922 ctx: AddressSpaceContext,37932 ctx: AddressSpaceContext,
37923) !std.builtin.AddressSpace {37933) !std.builtin.AddressSpace {
37924 const mod = sema.mod;
37925 const air_ref = try sema.resolveInst(zir_ref);37934 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;
37926 const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src);37946 const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src);
37927 const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{37947 const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{
37928 .needed_comptime_reason = "address space must be comptime-known",37948 .needed_comptime_reason = "address space must be comptime-known",