| author | |
| committer | |
| log | 5acfaa35d3320c7595262b4d97ba4cdc3a1afc7b |
| tree | 9732cd04d10c68630cd1c3669cd793c3f7daf972 |
| parent | 4cc4b54d25bcd1c1f472518a182b94411fb8cec6 |
| parent | af80240678112276cedd5c5247b843fa101186b0 |
| signature |
stage2: compileError builtin for zig code5 files changed, 88 insertions(+), 31 deletions(-)
src/astgen.zig+11| ... | @@ -2324,6 +2324,15 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* | ... | @@ -2324,6 +2324,15 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* |
| 2324 | return addZIRUnOp(mod, scope, src, .import, target); | 2324 | return addZIRUnOp(mod, scope, src, .import, target); |
| 2325 | } | 2325 | } |
| 2326 | 2326 | ||
| 2327 | fn compileError(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | ||
| 2328 | try ensureBuiltinParamCount(mod, scope, call, 1); | ||
| 2329 | const tree = scope.tree(); | ||
| 2330 | const src = tree.token_locs[call.builtin_token].start; | ||
| 2331 | const params = call.params(); | ||
| 2332 | const target = try expr(mod, scope, .none, params[0]); | ||
| 2333 | return addZIRUnOp(mod, scope, src, .compileerror, target); | ||
| 2334 | } | ||
| 2335 | |||
| 2327 | fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | 2336 | fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2328 | const tree = scope.tree(); | 2337 | const tree = scope.tree(); |
| 2329 | const arena = scope.arena(); | 2338 | const arena = scope.arena(); |
| ... | @@ -2378,6 +2387,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built | ... | @@ -2378,6 +2387,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 2378 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); | 2387 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); |
| 2379 | } else if (mem.eql(u8, builtin_name, "@import")) { | 2388 | } else if (mem.eql(u8, builtin_name, "@import")) { |
| 2380 | return rlWrap(mod, scope, rl, try import(mod, scope, call)); | 2389 | return rlWrap(mod, scope, rl, try import(mod, scope, call)); |
| 2390 | } else if (mem.eql(u8, builtin_name, "@compileError")) { | ||
| 2391 | return compileError(mod, scope, call); | ||
| 2381 | } else if (mem.eql(u8, builtin_name, "@compileLog")) { | 2392 | } else if (mem.eql(u8, builtin_name, "@compileLog")) { |
| 2382 | return compileLog(mod, scope, call); | 2393 | return compileLog(mod, scope, call); |
| 2383 | } else { | 2394 | } else { |
src/zir.zig+55-20| ... | @@ -300,6 +300,7 @@ pub const Inst = struct { | ... | @@ -300,6 +300,7 @@ pub const Inst = struct { |
| 300 | => NoOp, | 300 | => NoOp, |
| 301 | 301 | ||
| 302 | .boolnot, | 302 | .boolnot, |
| 303 | .compileerror, | ||
| 303 | .deref, | 304 | .deref, |
| 304 | .@"return", | 305 | .@"return", |
| 305 | .isnull, | 306 | .isnull, |
| ... | @@ -387,7 +388,6 @@ pub const Inst = struct { | ... | @@ -387,7 +388,6 @@ pub const Inst = struct { |
| 387 | .declval => DeclVal, | 388 | .declval => DeclVal, |
| 388 | .declval_in_module => DeclValInModule, | 389 | .declval_in_module => DeclValInModule, |
| 389 | .coerce_result_block_ptr => CoerceResultBlockPtr, | 390 | .coerce_result_block_ptr => CoerceResultBlockPtr, |
| 390 | .compileerror => CompileError, | ||
| 391 | .compilelog => CompileLog, | 391 | .compilelog => CompileLog, |
| 392 | .loop => Loop, | 392 | .loop => Loop, |
| 393 | .@"const" => Const, | 393 | .@"const" => Const, |
| ... | @@ -701,16 +701,6 @@ pub const Inst = struct { | ... | @@ -701,16 +701,6 @@ pub const Inst = struct { |
| 701 | kw_args: struct {}, | 701 | kw_args: struct {}, |
| 702 | }; | 702 | }; |
| 703 | 703 | ||
| 704 | pub const CompileError = struct { | ||
| 705 | pub const base_tag = Tag.compileerror; | ||
| 706 | base: Inst, | ||
| 707 | |||
| 708 | positionals: struct { | ||
| 709 | msg: []const u8, | ||
| 710 | }, | ||
| 711 | kw_args: struct {}, | ||
| 712 | }; | ||
| 713 | |||
| 714 | pub const CompileLog = struct { | 704 | pub const CompileLog = struct { |
| 715 | pub const base_tag = Tag.compilelog; | 705 | pub const base_tag = Tag.compilelog; |
| 716 | base: Inst, | 706 | base: Inst, |
| ... | @@ -1943,14 +1933,29 @@ const EmitZIR = struct { | ... | @@ -1943,14 +1933,29 @@ const EmitZIR = struct { |
| 1943 | .sema_failure_retryable, | 1933 | .sema_failure_retryable, |
| 1944 | .dependency_failure, | 1934 | .dependency_failure, |
| 1945 | => if (self.old_module.failed_decls.get(ir_decl)) |err_msg_list| { | 1935 | => if (self.old_module.failed_decls.get(ir_decl)) |err_msg_list| { |
| 1946 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | 1936 | const fail_inst = try self.arena.allocator.create(Inst.UnOp); |
| 1947 | fail_inst.* = .{ | 1937 | fail_inst.* = .{ |
| 1948 | .base = .{ | 1938 | .base = .{ |
| 1949 | .src = ir_decl.src(), | 1939 | .src = ir_decl.src(), |
| 1950 | .tag = Inst.CompileError.base_tag, | 1940 | .tag = .compileerror, |
| 1951 | }, | 1941 | }, |
| 1952 | .positionals = .{ | 1942 | .positionals = .{ |
| 1953 | .msg = try self.arena.allocator.dupe(u8, err_msg_list.items[0].msg), | 1943 | .operand = blk: { |
| 1944 | const msg_str = try self.arena.allocator.dupe(u8, err_msg_list.items[0].msg); | ||
| 1945 | |||
| 1946 | const str_inst = try self.arena.allocator.create(Inst.Str); | ||
| 1947 | str_inst.* = .{ | ||
| 1948 | .base = .{ | ||
| 1949 | .src = ir_decl.src(), | ||
| 1950 | .tag = Inst.Str.base_tag, | ||
| 1951 | }, | ||
| 1952 | .positionals = .{ | ||
| 1953 | .bytes = msg_str, | ||
| 1954 | }, | ||
| 1955 | .kw_args = .{}, | ||
| 1956 | }; | ||
| 1957 | break :blk &str_inst.base; | ||
| 1958 | }, | ||
| 1954 | }, | 1959 | }, |
| 1955 | .kw_args = .{}, | 1960 | .kw_args = .{}, |
| 1956 | }; | 1961 | }; |
| ... | @@ -2073,28 +2078,58 @@ const EmitZIR = struct { | ... | @@ -2073,28 +2078,58 @@ const EmitZIR = struct { |
| 2073 | }, | 2078 | }, |
| 2074 | .sema_failure => { | 2079 | .sema_failure => { |
| 2075 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?.items[0]; | 2080 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?.items[0]; |
| 2076 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | 2081 | const fail_inst = try self.arena.allocator.create(Inst.UnOp); |
| 2077 | fail_inst.* = .{ | 2082 | fail_inst.* = .{ |
| 2078 | .base = .{ | 2083 | .base = .{ |
| 2079 | .src = src, | 2084 | .src = src, |
| 2080 | .tag = Inst.CompileError.base_tag, | 2085 | .tag = .compileerror, |
| 2081 | }, | 2086 | }, |
| 2082 | .positionals = .{ | 2087 | .positionals = .{ |
| 2083 | .msg = try self.arena.allocator.dupe(u8, err_msg.msg), | 2088 | .operand = blk: { |
| 2089 | const msg_str = try self.arena.allocator.dupe(u8, err_msg.msg); | ||
| 2090 | |||
| 2091 | const str_inst = try self.arena.allocator.create(Inst.Str); | ||
| 2092 | str_inst.* = .{ | ||
| 2093 | .base = .{ | ||
| 2094 | .src = src, | ||
| 2095 | .tag = Inst.Str.base_tag, | ||
| 2096 | }, | ||
| 2097 | .positionals = .{ | ||
| 2098 | .bytes = msg_str, | ||
| 2099 | }, | ||
| 2100 | .kw_args = .{}, | ||
| 2101 | }; | ||
| 2102 | break :blk &str_inst.base; | ||
| 2103 | }, | ||
| 2084 | }, | 2104 | }, |
| 2085 | .kw_args = .{}, | 2105 | .kw_args = .{}, |
| 2086 | }; | 2106 | }; |
| 2087 | try instructions.append(&fail_inst.base); | 2107 | try instructions.append(&fail_inst.base); |
| 2088 | }, | 2108 | }, |
| 2089 | .dependency_failure => { | 2109 | .dependency_failure => { |
| 2090 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | 2110 | const fail_inst = try self.arena.allocator.create(Inst.UnOp); |
| 2091 | fail_inst.* = .{ | 2111 | fail_inst.* = .{ |
| 2092 | .base = .{ | 2112 | .base = .{ |
| 2093 | .src = src, | 2113 | .src = src, |
| 2094 | .tag = Inst.CompileError.base_tag, | 2114 | .tag = .compileerror, |
| 2095 | }, | 2115 | }, |
| 2096 | .positionals = .{ | 2116 | .positionals = .{ |
| 2097 | .msg = try self.arena.allocator.dupe(u8, "depends on another failed Decl"), | 2117 | .operand = blk: { |
| 2118 | const msg_str = try self.arena.allocator.dupe(u8, "depends on another failed Decl"); | ||
| 2119 | |||
| 2120 | const str_inst = try self.arena.allocator.create(Inst.Str); | ||
| 2121 | str_inst.* = .{ | ||
| 2122 | .base = .{ | ||
| 2123 | .src = src, | ||
| 2124 | .tag = Inst.Str.base_tag, | ||
| 2125 | }, | ||
| 2126 | .positionals = .{ | ||
| 2127 | .bytes = msg_str, | ||
| 2128 | }, | ||
| 2129 | .kw_args = .{}, | ||
| 2130 | }; | ||
| 2131 | break :blk &str_inst.base; | ||
| 2132 | }, | ||
| 2098 | }, | 2133 | }, |
| 2099 | .kw_args = .{}, | 2134 | .kw_args = .{}, |
| 2100 | }; | 2135 | }; |
src/zir_sema.zig+3-2| ... | @@ -486,8 +486,9 @@ fn analyzeInstExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export) | ... | @@ -486,8 +486,9 @@ fn analyzeInstExport(mod: *Module, scope: *Scope, export_inst: *zir.Inst.Export) |
| 486 | return mod.constVoid(scope, export_inst.base.src); | 486 | return mod.constVoid(scope, export_inst.base.src); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileError) InnerError!*Inst { | 489 | fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 490 | return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg}); | 490 | const msg = try resolveConstString(mod, scope, inst.positionals.operand); |
| 491 | return mod.fail(scope, inst.base.src, "{}", .{msg}); | ||
| 491 | } | 492 | } |
| 492 | 493 | ||
| 493 | fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst { | 494 | fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst { |
test/stage2/test.zig+6| ... | @@ -1186,6 +1186,12 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1186,6 +1186,12 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1186 | 1186 | ||
| 1187 | // "| true, 20, (runtime value), (function)" // TODO if this is here it invalidates the compile error checker. Need a way to check though. | 1187 | // "| true, 20, (runtime value), (function)" // TODO if this is here it invalidates the compile error checker. Need a way to check though. |
| 1188 | 1188 | ||
| 1189 | ctx.compileError("compileError", linux_x64, | ||
| 1190 | \\export fn _start() noreturn { | ||
| 1191 | \\ @compileError("this is an error"); | ||
| 1192 | \\ unreachable; | ||
| 1193 | \\} | ||
| 1194 | , &[_][]const u8{":2:3: error: this is an error"}); | ||
| 1189 | { | 1195 | { |
| 1190 | var case = ctx.obj("variable shadowing", linux_x64); | 1196 | var case = ctx.obj("variable shadowing", linux_x64); |
| 1191 | case.addError( | 1197 | case.addError( |
test/stage2/zir.zig+13-9| ... | @@ -150,18 +150,20 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -150,18 +150,20 @@ pub fn addCases(ctx: *TestContext) !void { |
| 150 | \\}) | 150 | \\}) |
| 151 | \\ | 151 | \\ |
| 152 | \\@a = fn(@fnty, { | 152 | \\@a = fn(@fnty, { |
| 153 | \\ %0 = call(@b, []) | 153 | \\ %0 = call(@c, []) |
| 154 | \\ %1 = returnvoid() | 154 | \\ %1 = returnvoid() |
| 155 | \\}) | 155 | \\}) |
| 156 | \\ | 156 | \\ |
| 157 | \\@b = fn(@fnty, { | 157 | \\@b = str("message") |
| 158 | \\ %9 = compileerror("message") | 158 | \\ |
| 159 | \\@c = fn(@fnty, { | ||
| 160 | \\ %9 = compileerror(@b) | ||
| 159 | \\ %0 = call(@a, []) | 161 | \\ %0 = call(@a, []) |
| 160 | \\ %1 = returnvoid() | 162 | \\ %1 = returnvoid() |
| 161 | \\}) | 163 | \\}) |
| 162 | , | 164 | , |
| 163 | &[_][]const u8{ | 165 | &[_][]const u8{ |
| 164 | ":18:21: error: message", | 166 | ":20:21: error: message", |
| 165 | }, | 167 | }, |
| 166 | ); | 168 | ); |
| 167 | // Now we remove the call to `a`. `a` and `b` form a cycle, but no entry points are | 169 | // Now we remove the call to `a`. `a` and `b` form a cycle, but no entry points are |
| ... | @@ -179,20 +181,22 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -179,20 +181,22 @@ pub fn addCases(ctx: *TestContext) !void { |
| 179 | \\}) | 181 | \\}) |
| 180 | \\ | 182 | \\ |
| 181 | \\@a = fn(@fnty, { | 183 | \\@a = fn(@fnty, { |
| 182 | \\ %0 = call(@b, []) | 184 | \\ %0 = call(@c, []) |
| 183 | \\ %1 = returnvoid() | 185 | \\ %1 = returnvoid() |
| 184 | \\}) | 186 | \\}) |
| 185 | \\ | 187 | \\ |
| 186 | \\@b = fn(@fnty, { | 188 | \\@b = str("message") |
| 187 | \\ %9 = compileerror("message") | 189 | \\ |
| 190 | \\@c = fn(@fnty, { | ||
| 191 | \\ %9 = compileerror(@b) | ||
| 188 | \\ %0 = call(@a, []) | 192 | \\ %0 = call(@a, []) |
| 189 | \\ %1 = returnvoid() | 193 | \\ %1 = returnvoid() |
| 190 | \\}) | 194 | \\}) |
| 191 | , | 195 | , |
| 192 | \\@void = primitive(void) | 196 | \\@void = primitive(void) |
| 193 | \\@fnty = fntype([], @void, cc=C) | 197 | \\@fnty = fntype([], @void, cc=C) |
| 194 | \\@9 = declref("9__anon_2") | 198 | \\@9 = declref("9__anon_3") |
| 195 | \\@9__anon_2 = str("entry") | 199 | \\@9__anon_3 = str("entry") |
| 196 | \\@unnamed$4 = str("entry") | 200 | \\@unnamed$4 = str("entry") |
| 197 | \\@unnamed$5 = export(@unnamed$4, "entry") | 201 | \\@unnamed$5 = export(@unnamed$4, "entry") |
| 198 | \\@11 = primitive(void_value) | 202 | \\@11 = primitive(void_value) |