| author | |
| committer | |
| log | 25b1c00c72b51ef9e011867b3fc4f37b3e216223 |
| tree | c644ca68fe7ced4650bde28dca2d5d844ec07b75 |
| parent | c306392b4404a5a05dcb0958b88b50ecc9c7b6f5 |
4 files changed, 58 insertions(+), 32 deletions(-)
src-self-hosted/Module.zig+8-2| ... | ... | @@ -1210,6 +1210,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1210 | 1210 | |
| 1211 | 1211 | try self.astGenBlock(&gen_scope.base, body_block); |
| 1212 | 1212 | |
| 1213 | const last_inst = gen_scope.instructions.items[gen_scope.instructions.items.len - 1]; | |
| 1214 | if (!last_inst.tag.isNoReturn()) { | |
| 1215 | const src = tree.token_locs[body_block.rbrace].start; | |
| 1216 | _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); | |
| 1217 | } | |
| 1218 | ||
| 1213 | 1219 | const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR); |
| 1214 | 1220 | fn_zir.* = .{ |
| 1215 | 1221 | .body = .{ |
| ... | ... | @@ -2686,7 +2692,7 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr |
| 2686 | 2692 | |
| 2687 | 2693 | // Blocks must terminate with noreturn instruction. |
| 2688 | 2694 | assert(child_block.instructions.items.len != 0); |
| 2689 | assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn()); | |
| 2695 | assert(child_block.instructions.items[child_block.instructions.items.len - 1].ty.isNoReturn()); | |
| 2690 | 2696 | |
| 2691 | 2697 | // Need to set the type and emit the Block instruction. This allows machine code generation |
| 2692 | 2698 | // 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 |
| 3271 | 3277 | defer false_block.instructions.deinit(self.gpa); |
| 3272 | 3278 | try self.analyzeBody(&false_block.base, inst.positionals.false_body); |
| 3273 | 3279 | |
| 3274 | return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){ | |
| 3280 | return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.noreturn), Inst.CondBr, Inst.Args(Inst.CondBr){ | |
| 3275 | 3281 | .condition = cond, |
| 3276 | 3282 | .true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) }, |
| 3277 | 3283 | .false_body = .{ .instructions = try scope.arena().dupe(*Inst, false_block.instructions.items) }, |
src-self-hosted/ir.zig-30| ... | ... | @@ -60,36 +60,6 @@ pub const Inst = struct { |
| 60 | 60 | retvoid, |
| 61 | 61 | sub, |
| 62 | 62 | unreach, |
| 63 | ||
| 64 | /// Returns whether the instruction is one of the control flow "noreturn" types. | |
| 65 | /// Function calls do not count. When ZIR is generated, the compiler automatically | |
| 66 | /// emits an `Unreach` after a function call with the `noreturn` return type. | |
| 67 | pub fn isNoReturn(tag: Tag) bool { | |
| 68 | return switch (tag) { | |
| 69 | .add, | |
| 70 | .arg, | |
| 71 | .assembly, | |
| 72 | .bitcast, | |
| 73 | .block, | |
| 74 | .breakpoint, | |
| 75 | .call, | |
| 76 | .cmp, | |
| 77 | .constant, | |
| 78 | .isnonnull, | |
| 79 | .isnull, | |
| 80 | .ptrtoint, | |
| 81 | .sub, | |
| 82 | => false, | |
| 83 | ||
| 84 | .br, | |
| 85 | .brvoid, | |
| 86 | .condbr, | |
| 87 | .ret, | |
| 88 | .retvoid, | |
| 89 | .unreach, | |
| 90 | => true, | |
| 91 | }; | |
| 92 | } | |
| 93 | 63 | }; |
| 94 | 64 | |
| 95 | 65 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
src-self-hosted/type.zig+4| ... | ... | @@ -468,6 +468,10 @@ pub const Type = extern union { |
| 468 | 468 | }; |
| 469 | 469 | } |
| 470 | 470 | |
| 471 | pub fn isNoReturn(self: Type) bool { | |
| 472 | return self.zigTypeTag() == .NoReturn; | |
| 473 | } | |
| 474 | ||
| 471 | 475 | /// Asserts that hasCodeGenBits() is true. |
| 472 | 476 | pub fn abiAlignment(self: Type, target: Target) u32 { |
| 473 | 477 | return switch (self.tag()) { |
src-self-hosted/zir.zig+46| ... | ... | @@ -81,6 +81,52 @@ pub const Inst = struct { |
| 81 | 81 | condbr, |
| 82 | 82 | isnull, |
| 83 | 83 | isnonnull, |
| 84 | ||
| 85 | /// Returns whether the instruction is one of the control flow "noreturn" types. | |
| 86 | /// Function calls do not count. | |
| 87 | pub fn isNoReturn(tag: Tag) bool { | |
| 88 | return switch (tag) { | |
| 89 | .arg, | |
| 90 | .block, | |
| 91 | .breakpoint, | |
| 92 | .call, | |
| 93 | .@"const", | |
| 94 | .declref, | |
| 95 | .declref_str, | |
| 96 | .declval, | |
| 97 | .declval_in_module, | |
| 98 | .str, | |
| 99 | .int, | |
| 100 | .inttype, | |
| 101 | .ptrtoint, | |
| 102 | .fieldptr, | |
| 103 | .deref, | |
| 104 | .as, | |
| 105 | .@"asm", | |
| 106 | .@"fn", | |
| 107 | .fntype, | |
| 108 | .@"export", | |
| 109 | .primitive, | |
| 110 | .intcast, | |
| 111 | .bitcast, | |
| 112 | .elemptr, | |
| 113 | .add, | |
| 114 | .sub, | |
| 115 | .cmp, | |
| 116 | .isnull, | |
| 117 | .isnonnull, | |
| 118 | => false, | |
| 119 | ||
| 120 | .condbr, | |
| 121 | .@"unreachable", | |
| 122 | .@"return", | |
| 123 | .returnvoid, | |
| 124 | .@"break", | |
| 125 | .breakvoid, | |
| 126 | .compileerror, | |
| 127 | => true, | |
| 128 | }; | |
| 129 | } | |
| 84 | 130 | }; |
| 85 | 131 | |
| 86 | 132 | pub fn TagToType(tag: Tag) type { |