Commit 25b1c00c72
Changed files (4)
src-self-hosted
src-self-hosted/ir.zig
@@ -60,36 +60,6 @@ pub const Inst = struct {
retvoid,
sub,
unreach,
-
- /// Returns whether the instruction is one of the control flow "noreturn" types.
- /// Function calls do not count. When ZIR is generated, the compiler automatically
- /// emits an `Unreach` after a function call with the `noreturn` return type.
- pub fn isNoReturn(tag: Tag) bool {
- return switch (tag) {
- .add,
- .arg,
- .assembly,
- .bitcast,
- .block,
- .breakpoint,
- .call,
- .cmp,
- .constant,
- .isnonnull,
- .isnull,
- .ptrtoint,
- .sub,
- => false,
-
- .br,
- .brvoid,
- .condbr,
- .ret,
- .retvoid,
- .unreach,
- => true,
- };
- }
};
pub fn cast(base: *Inst, comptime T: type) ?*T {
src-self-hosted/Module.zig
@@ -1210,6 +1210,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
try self.astGenBlock(&gen_scope.base, body_block);
+ const last_inst = gen_scope.instructions.items[gen_scope.instructions.items.len - 1];
+ if (!last_inst.tag.isNoReturn()) {
+ const src = tree.token_locs[body_block.rbrace].start;
+ _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{});
+ }
+
const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR);
fn_zir.* = .{
.body = .{
@@ -2686,7 +2692,7 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr
// Blocks must terminate with noreturn instruction.
assert(child_block.instructions.items.len != 0);
- assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn());
+ assert(child_block.instructions.items[child_block.instructions.items.len - 1].ty.isNoReturn());
// Need to set the type and emit the Block instruction. This allows machine code generation
// to emit a jump instruction to after the block when it encounters the break.
@@ -3271,7 +3277,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner
defer false_block.instructions.deinit(self.gpa);
try self.analyzeBody(&false_block.base, inst.positionals.false_body);
- return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){
+ return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.noreturn), Inst.CondBr, Inst.Args(Inst.CondBr){
.condition = cond,
.true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) },
.false_body = .{ .instructions = try scope.arena().dupe(*Inst, false_block.instructions.items) },
src-self-hosted/type.zig
@@ -468,6 +468,10 @@ pub const Type = extern union {
};
}
+ pub fn isNoReturn(self: Type) bool {
+ return self.zigTypeTag() == .NoReturn;
+ }
+
/// Asserts that hasCodeGenBits() is true.
pub fn abiAlignment(self: Type, target: Target) u32 {
return switch (self.tag()) {
src-self-hosted/zir.zig
@@ -81,6 +81,52 @@ pub const Inst = struct {
condbr,
isnull,
isnonnull,
+
+ /// Returns whether the instruction is one of the control flow "noreturn" types.
+ /// Function calls do not count.
+ pub fn isNoReturn(tag: Tag) bool {
+ return switch (tag) {
+ .arg,
+ .block,
+ .breakpoint,
+ .call,
+ .@"const",
+ .declref,
+ .declref_str,
+ .declval,
+ .declval_in_module,
+ .str,
+ .int,
+ .inttype,
+ .ptrtoint,
+ .fieldptr,
+ .deref,
+ .as,
+ .@"asm",
+ .@"fn",
+ .fntype,
+ .@"export",
+ .primitive,
+ .intcast,
+ .bitcast,
+ .elemptr,
+ .add,
+ .sub,
+ .cmp,
+ .isnull,
+ .isnonnull,
+ => false,
+
+ .condbr,
+ .@"unreachable",
+ .@"return",
+ .returnvoid,
+ .@"break",
+ .breakvoid,
+ .compileerror,
+ => true,
+ };
+ }
};
pub fn TagToType(tag: Tag) type {