Sema: fix empty infinite loops

Closes #15284
This commit is contained in:
Jacob Young 2023-04-15 02:48:35 -04:00 committed by Veikka Tuominen
parent 7fad555e5e
commit 7e0c6d7edc
4 changed files with 29 additions and 4 deletions

View File

@ -5225,17 +5225,17 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
try sema.analyzeBody(&loop_block, body);
if (sema.typeOf(Air.indexToRef(loop_block.instructions.items[loop_block.instructions.items.len - 1])).isNoReturn()) {
const loop_block_len = loop_block.instructions.items.len;
if (loop_block_len > 0 and sema.typeOf(Air.indexToRef(loop_block.instructions.items[loop_block_len - 1])).isNoReturn()) {
// If the loop ended with a noreturn terminator, then there is no way for it to loop,
// so we can just use the block instead.
try child_block.instructions.appendSlice(gpa, loop_block.instructions.items);
} else {
try child_block.instructions.append(gpa, loop_inst);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
loop_block.instructions.items.len);
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + loop_block_len);
sema.air_instructions.items(.data)[loop_inst].ty_pl.payload = sema.addExtraAssumeCapacity(
Air.Block{ .body_len = @intCast(u32, loop_block.instructions.items.len) },
Air.Block{ .body_len = @intCast(u32, loop_block_len) },
);
sema.air_extra.appendSliceAssumeCapacity(loop_block.instructions.items);
}

View File

@ -218,6 +218,10 @@ pub const build_cases = [_]BuildCase{
// .build_root = "test/standalone/options",
// .import = @import("standalone/options/build.zig"),
//},
.{
.build_root = "test/standalone/strip_empty_loop",
.import = @import("standalone/strip_empty_loop/build.zig"),
},
};
const std = @import("std");

View File

@ -0,0 +1,18 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test the program");
b.default_step = test_step;
const optimize = std.builtin.OptimizeMode.Debug;
const target = std.zig.CrossTarget{};
const main = b.addExecutable(.{
.name = "main",
.root_source_file = .{ .path = "main.zig" },
.optimize = optimize,
.target = target,
});
main.strip = true;
test_step.dependOn(&main.step);
}

View File

@ -0,0 +1,3 @@
pub fn main() noreturn {
while (true) {} // When built without debug info, this produces an Air loop with no instructions
}