diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 1 | ||||
| -rw-r--r-- | src/Module.zig | 6 | ||||
| -rw-r--r-- | src/Sema.zig | 97 |
3 files changed, 66 insertions, 38 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index cb5fd161a7..bd8f06ae59 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -7646,6 +7646,7 @@ fn cImport( const block_inst = try gz.makeBlockInst(.c_import, node); const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); + _ = try gz.addUnNode(.ensure_result_used, block_result, node); if (!gz.refIsNoReturn(block_result)) { _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); } diff --git a/src/Module.zig b/src/Module.zig index b7299ebdab..936e912e59 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3739,9 +3739,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { const inst_data = zir_datas[zir_block_index].pl_node; const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index); const body = zir.extra[extra.end..][0..extra.data.body_len]; - const break_index = try sema.analyzeBody(&block_scope, body); + const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; try wip_captures.finalize(); - const result_ref = zir_datas[break_index].@"break".operand; const src: LazySrcLoc = .{ .node_offset = 0 }; const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref); const align_val = blk: { @@ -4681,12 +4680,11 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem func.state = .in_progress; log.debug("set {s} to in_progress", .{decl.name}); - _ = sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) { + sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) { // TODO make these unreachable instead of @panic error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"), error.GenericPoison => @panic("zig compiler bug: GenericPoison"), error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"), - error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"), else => |e| return e, }; diff --git a/src/Sema.zig b/src/Sema.zig index 87fd7d5e0e..c8b905f23f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -520,14 +520,14 @@ fn resolveBody( /// use to return from the body. body_inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const break_inst = try sema.analyzeBody(block, body); - const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, body)) orelse + return Air.Inst.Ref.unreachable_value; // For comptime control flow, we need to detect when `analyzeBody` reports // that we need to break from an outer block. In such case we // use Zig's error mechanism to send control flow up the stack until // we find the corresponding block to this break. if (block.is_comptime and break_data.block_inst != body_inst) { - sema.comptime_break_inst = break_inst; + sema.comptime_break_inst = break_data.inst; return error.ComptimeBreak; } return sema.resolveInst(break_data.operand); @@ -537,11 +537,37 @@ pub fn analyzeBody( sema: *Sema, block: *Block, body: []const Zir.Inst.Index, -) CompileError!Zir.Inst.Index { - return sema.analyzeBodyInner(block, body) catch |err| switch (err) { +) !void { + _ = sema.analyzeBodyInner(block, body) catch |err| switch (err) { + error.ComptimeBreak => unreachable, // unexpected comptime control flow + else => |e| return e, + }; +} + +const BreakData = struct { + block_inst: Zir.Inst.Index, + operand: Air.Inst.Ref, + inst: Air.Inst.Index, +}; + +pub fn analyzeBodyBreak( + sema: *Sema, + block: *Block, + body: []const Zir.Inst.Index, +) CompileError!?BreakData { + const break_inst = sema.analyzeBodyInner(block, body) catch |err| switch (err) { error.ComptimeBreak => sema.comptime_break_inst, else => |e| return e, }; + if (block.instructions.items.len != 0 and + sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn()) + return null; + const break_data = sema.code.instructions.items(.data)[break_inst].@"break"; + return BreakData{ + .block_inst = break_data.block_inst, + .operand = break_data.operand, + .inst = break_inst, + }; } /// ZIR instructions which are always `noreturn` return this. This matches the @@ -1045,12 +1071,12 @@ fn analyzeBodyInner( const inst_data = datas[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len]; - const break_inst = try sema.analyzeBody(block, inline_body); - const break_data = datas[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse + break always_noreturn; if (inst == break_data.block_inst) { break :blk sema.resolveInst(break_data.operand); } else { - break break_inst; + break break_data.inst; } }, .block => blk: { @@ -1068,12 +1094,12 @@ fn analyzeBodyInner( block.params.deinit(sema.gpa); block.params = prev_params; } - const break_inst = try sema.analyzeBody(block, inline_body); - const break_data = datas[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse + break always_noreturn; if (inst == break_data.block_inst) { break :blk sema.resolveInst(break_data.operand); } else { - break break_inst; + break break_data.inst; } }, .block_inline => blk: { @@ -1090,12 +1116,12 @@ fn analyzeBodyInner( block.params.deinit(sema.gpa); block.params = prev_params; } - const break_inst = try sema.analyzeBody(block, inline_body); - const break_data = datas[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse + break always_noreturn; if (inst == break_data.block_inst) { break :blk sema.resolveInst(break_data.operand); } else { - break break_inst; + break break_data.inst; } }, .condbr => blk: { @@ -1108,12 +1134,12 @@ fn analyzeBodyInner( const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); const inline_body = if (cond.val.toBool()) then_body else else_body; - const break_inst = try sema.analyzeBody(block, inline_body); - const break_data = datas[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse + break always_noreturn; if (inst == break_data.block_inst) { break :blk sema.resolveInst(break_data.operand); } else { - break break_inst; + break break_data.inst; } }, .condbr_inline => blk: { @@ -1124,12 +1150,12 @@ fn analyzeBodyInner( const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition); const inline_body = if (cond.val.toBool()) then_body else else_body; - const break_inst = try sema.analyzeBody(block, inline_body); - const break_data = datas[break_inst].@"break"; + const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse + break always_noreturn; if (inst == break_data.block_inst) { break :blk sema.resolveInst(break_data.operand); } else { - break break_inst; + break break_data.inst; } }, }; @@ -1915,7 +1941,7 @@ fn zirEnumDecl( defer assert(enum_block.instructions.items.len == 0); // should all be comptime instructions if (body.len != 0) { - _ = try sema.analyzeBody(&enum_block, body); + try sema.analyzeBody(&enum_block, body); } try wip_captures.finalize(); @@ -3639,7 +3665,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError var loop_block = child_block.makeSubBlock(); defer loop_block.instructions.deinit(gpa); - _ = try sema.analyzeBody(&loop_block, body); + try sema.analyzeBody(&loop_block, body); try child_block.instructions.append(gpa, loop_inst); @@ -3681,7 +3707,8 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr }; defer child_block.instructions.deinit(sema.gpa); - _ = try sema.analyzeBody(&child_block, body); + // Ignore the result, all the relevant operations have written to c_import_buf already. + _ = try sema.analyzeBodyBreak(&child_block, body); const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err| return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); @@ -4658,9 +4685,8 @@ fn analyzeCall( } const result = result: { - _ = sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { + sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { error.ComptimeReturn => break :result inlining.comptime_result, - error.ComptimeBreak => unreachable, // Can't break through a fn call. error.AnalysisFail => { const err_msg = inlining.err orelse return err; try sema.errNote(block, call_src, err_msg, "called from here", .{}); @@ -7313,7 +7339,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const item = sema.resolveInst(item_ref); // `item` is already guaranteed to be constant known. - _ = try sema.analyzeBody(&case_block, body); + try sema.analyzeBody(&case_block, body); try wip_captures.finalize(); @@ -7356,7 +7382,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; - _ = try sema.analyzeBody(&case_block, body); + try sema.analyzeBody(&case_block, body); try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + case_block.instructions.items.len); @@ -7431,7 +7457,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; - _ = try sema.analyzeBody(&case_block, body); + try sema.analyzeBody(&case_block, body); try wip_captures.finalize(); @@ -7468,7 +7494,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError case_block.wip_capture_scope = wip_captures.scope; if (special.body.len != 0) { - _ = try sema.analyzeBody(&case_block, special.body); + try sema.analyzeBody(&case_block, special.body); } else { // We still need a terminator in this block, but we have proven // that it is unreachable. @@ -10990,7 +11016,8 @@ fn zirTypeofPeer( .is_typeof = true, }; defer child_block.instructions.deinit(sema.gpa); - _ = try sema.analyzeBody(&child_block, body); + // Ignore the result, we only care about the instructions in `args`. + _ = try sema.analyzeBodyBreak(&child_block, body); const args = sema.code.refSlice(extra.end, extended.small); @@ -11186,6 +11213,8 @@ fn zirCondbr( if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| { const body = if (cond_val.toBool()) then_body else else_body; + // We use `analyzeBodyInner` since we want to propagate any possible + // `error.ComptimeBreak` to the caller. return sema.analyzeBodyInner(parent_block, body); } @@ -11199,11 +11228,11 @@ fn zirCondbr( sub_block.runtime_index += 1; defer sub_block.instructions.deinit(gpa); - _ = try sema.analyzeBody(&sub_block, then_body); + try sema.analyzeBody(&sub_block, then_body); const true_instructions = sub_block.instructions.toOwnedSlice(gpa); defer gpa.free(true_instructions); - _ = try sema.analyzeBody(&sub_block, else_body); + try sema.analyzeBody(&sub_block, else_body); try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + true_instructions.len + sub_block.instructions.items.len); _ = try parent_block.addInst(.{ @@ -19186,7 +19215,7 @@ fn semaStructFields( } if (body.len != 0) { - _ = try sema.analyzeBody(&block_scope, body); + try sema.analyzeBody(&block_scope, body); } try wip_captures.finalize(); @@ -19360,7 +19389,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { } if (body.len != 0) { - _ = try sema.analyzeBody(&block_scope, body); + try sema.analyzeBody(&block_scope, body); } try wip_captures.finalize(); |
