aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-09-15 13:43:22 +0100
committerMatthew Lugg <mlugg@mlugg.co.uk>2024-10-28 02:24:59 +0000
commit05b445a276536f6d62c20786d816f9f6444d20d8 (patch)
treeb68085bc0ea55e0816018a70c726ba1a0aa5c663 /src
parente9f3d18b57d973b795354dab8541ea2c4277d022 (diff)
downloadzig-05b445a276536f6d62c20786d816f9f6444d20d8.tar.gz
zig-05b445a276536f6d62c20786d816f9f6444d20d8.zip
Sema: add missing coercion to bool for condbr_inline
Also, start using labeled switch statements when dispatching maybe-runtime instructions like condbr to comptime-only variants like condbr_inline. This can't be merged until we get a zig1.wasm update due to #21385. Resolves: #21405
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig118
1 files changed, 27 insertions, 91 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index b0ce7729cf..987fbe4c2c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1043,7 +1043,7 @@ fn analyzeBodyInner(
}, inst });
}
- const air_inst: Air.Inst.Ref = switch (tags[@intFromEnum(inst)]) {
+ const air_inst: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) {
// zig fmt: off
.alloc => try sema.zirAlloc(block, inst),
.alloc_inferred => try sema.zirAllocInferred(block, true),
@@ -1591,56 +1591,19 @@ fn analyzeBodyInner(
try sema.zirSwitchContinue(block, inst);
break;
},
- .loop => blk: {
- if (!block.is_comptime) break :blk try sema.zirLoop(block, inst);
- // Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
- const inst_data = datas[@intFromEnum(inst)].pl_node;
- const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
- const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
- // Create a temporary child block so that this loop is properly
- // labeled for any .restore_err_ret_index instructions
- var child_block = block.makeSubBlock();
+ .loop => if (block.is_comptime) {
+ continue :inst .block_inline;
+ } else try sema.zirLoop(block, inst),
- var label: Block.Label = .{
- .zir_block = inst,
- .merges = undefined,
- };
- child_block.label = &label;
-
- // Write these instructions directly into the parent block
- child_block.instructions = block.instructions;
- defer block.instructions = child_block.instructions;
-
- const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
- break :blk result;
- },
- .block, .block_comptime => blk: {
- if (!block.is_comptime) {
- break :blk try sema.zirBlock(block, inst, tags[@intFromEnum(inst)] == .block_comptime);
- }
- // Same as `block_inline`. TODO https://github.com/ziglang/zig/issues/8220
- const inst_data = datas[@intFromEnum(inst)].pl_node;
- const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
- const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
+ .block => if (block.is_comptime) {
+ continue :inst .block_inline;
+ } else try sema.zirBlock(block, inst, false),
- // Create a temporary child block so that this block is properly
- // labeled for any .restore_err_ret_index instructions
- var child_block = block.makeSubBlock();
+ .block_comptime => if (block.is_comptime) {
+ continue :inst .block_inline;
+ } else try sema.zirBlock(block, inst, true),
- var label: Block.Label = .{
- .zir_block = inst,
- .merges = undefined,
- };
- child_block.label = &label;
-
- // Write these instructions directly into the parent block
- child_block.instructions = block.instructions;
- defer block.instructions = child_block.instructions;
-
- const result = try sema.analyzeInlineBody(&child_block, inline_body, inst) orelse break;
- break :blk result;
- },
.block_inline => blk: {
// Directly analyze the block body without introducing a new block.
// However, in the case of a corresponding break_inline which reaches
@@ -1749,32 +1712,13 @@ fn analyzeBodyInner(
return error.ComptimeBreak;
}
},
- .condbr => blk: {
- if (!block.is_comptime) {
- try sema.zirCondbr(block, inst);
- break;
- }
- // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220
- const inst_data = datas[@intFromEnum(inst)].pl_node;
- const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
- const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
- const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len);
- const else_body = sema.code.bodySlice(
- extra.end + then_body.len,
- extra.data.else_body_len,
- );
- const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
- .needed_comptime_reason = "condition in comptime branch must be comptime-known",
- .block_comptime_reason = block.comptime_reason,
- });
- const inline_body = if (cond.toBool()) then_body else else_body;
-
- try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
-
- const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
- break :blk result;
+ .condbr => if (block.is_comptime) {
+ continue :inst .condbr_inline;
+ } else {
+ try sema.zirCondbr(block, inst);
+ break;
},
- .condbr_inline => blk: {
+ .condbr_inline => {
const inst_data = datas[@intFromEnum(inst)].pl_node;
const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node });
const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
@@ -1783,18 +1727,20 @@ fn analyzeBodyInner(
extra.end + then_body.len,
extra.data.else_body_len,
);
- const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, .{
+ const uncasted_cond = try sema.resolveInst(extra.data.condition);
+ const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src);
+ const cond_val = try sema.resolveConstDefinedValue(block, cond_src, cond, .{
.needed_comptime_reason = "condition in comptime branch must be comptime-known",
.block_comptime_reason = block.comptime_reason,
});
- const inline_body = if (cond.toBool()) then_body else else_body;
+ const inline_body = if (cond_val.toBool()) then_body else else_body;
try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
const old_runtime_index = block.runtime_index;
defer block.runtime_index = old_runtime_index;
const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break;
- break :blk result;
+ break :inst result;
},
.@"try" => blk: {
if (!block.is_comptime) break :blk try sema.zirTry(block, inst);
@@ -2251,18 +2197,6 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val
return val;
}
-/// Returns a compile error if the value has tag `variable`.
-fn resolveInstConst(
- sema: *Sema,
- block: *Block,
- src: LazySrcLoc,
- zir_ref: Zir.Inst.Ref,
- reason: NeededComptimeReason,
-) CompileError!Value {
- const air_ref = try sema.resolveInst(zir_ref);
- return sema.resolveConstDefinedValue(block, src, air_ref, reason);
-}
-
/// Value Tag may be `undef` or `variable`.
pub fn resolveFinalDeclValue(
sema: *Sema,
@@ -26824,12 +26758,14 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_ret_ty_ref) blk: {
const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const ret_ty_val = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{
+ const ret_ty_air_ref = sema.resolveInst(ret_ty_ref) catch |err| switch (err) {
+ error.GenericPoison => break :blk Type.generic_poison,
+ else => |e| return e,
+ };
+ const ret_ty_val = sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{
.needed_comptime_reason = "return type must be comptime-known",
}) catch |err| switch (err) {
- error.GenericPoison => {
- break :blk Type.generic_poison;
- },
+ error.GenericPoison => break :blk Type.generic_poison,
else => |e| return e,
};
break :blk ret_ty_val.toType();