authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-12 23:50:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-13 00:08:21-07:00
log25b1c00c72b51ef9e011867b3fc4f37b3e216223
treec644ca68fe7ced4650bde28dca2d5d844ec07b75
parentc306392b4404a5a05dcb0958b88b50ecc9c7b6f5

stage2: add implicit return void where applicable


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 {
12101210
12111211 try self.astGenBlock(&gen_scope.base, body_block);
12121212
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
12131219 const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR);
12141220 fn_zir.* = .{
12151221 .body = .{
......@@ -2686,7 +2692,7 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr
26862692
26872693 // Blocks must terminate with noreturn instruction.
26882694 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());
26902696
26912697 // Need to set the type and emit the Block instruction. This allows machine code generation
26922698 // 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
32713277 defer false_block.instructions.deinit(self.gpa);
32723278 try self.analyzeBody(&false_block.base, inst.positionals.false_body);
32733279
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){
32753281 .condition = cond,
32763282 .true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) },
32773283 .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 {
6060 retvoid,
6161 sub,
6262 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 }
9363 };
9464
9565 pub fn cast(base: *Inst, comptime T: type) ?*T {
src-self-hosted/type.zig+4
......@@ -468,6 +468,10 @@ pub const Type = extern union {
468468 };
469469 }
470470
471 pub fn isNoReturn(self: Type) bool {
472 return self.zigTypeTag() == .NoReturn;
473 }
474
471475 /// Asserts that hasCodeGenBits() is true.
472476 pub fn abiAlignment(self: Type, target: Target) u32 {
473477 return switch (self.tag()) {
src-self-hosted/zir.zig+46
......@@ -81,6 +81,52 @@ pub const Inst = struct {
8181 condbr,
8282 isnull,
8383 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 }
84130 };
85131
86132 pub fn TagToType(tag: Tag) type {