mirror of
https://github.com/ziglang/zig.git
synced 2026-01-19 13:55:20 +00:00
stage2: add compile log statement
This commit is contained in:
parent
38572ee894
commit
ab5f7b5156
@ -1351,6 +1351,9 @@ pub fn totalErrorCount(self: *Compilation) usize {
|
||||
module.failed_exports.items().len +
|
||||
module.failed_files.items().len +
|
||||
@boolToInt(module.failed_root_src_file != null);
|
||||
for (module.compile_log_decls.items()) |entry| {
|
||||
total += entry.value.items.len;
|
||||
}
|
||||
}
|
||||
|
||||
// The "no entry point found" error only counts if there are no other errors.
|
||||
@ -1407,6 +1410,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
|
||||
});
|
||||
try AllErrors.addPlain(&arena, &errors, msg);
|
||||
}
|
||||
for (module.compile_log_decls.items()) |entry| {
|
||||
const decl = entry.key;
|
||||
const path = decl.scope.subFilePath();
|
||||
const source = try decl.scope.getSource(module);
|
||||
for (entry.value.items) |src_loc| {
|
||||
const err_msg = ErrorMsg{ .byte_offset = src_loc, .msg = "found compile log statement" };
|
||||
try AllErrors.add(&arena, &errors, path, source, err_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {
|
||||
|
||||
@ -61,6 +61,8 @@ failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
|
||||
/// emit-h failing for that Decl. This table is also how we tell if a Decl has
|
||||
/// failed emit-h or succeeded.
|
||||
emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
|
||||
/// A Decl can have multiple compileLogs, but only one error, so we map a Decl to a the src locs of all the compileLogs
|
||||
compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, ArrayListUnmanaged(usize)) = .{},
|
||||
/// Using a map here for consistency with the other fields here.
|
||||
/// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator.
|
||||
failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{},
|
||||
@ -936,6 +938,11 @@ pub fn deinit(self: *Module) void {
|
||||
}
|
||||
self.failed_exports.deinit(gpa);
|
||||
|
||||
for (self.compile_log_decls.items()) |*entry| {
|
||||
entry.value.deinit(gpa);
|
||||
}
|
||||
self.compile_log_decls.deinit(gpa);
|
||||
|
||||
for (self.decl_exports.items()) |entry| {
|
||||
const export_list = entry.value;
|
||||
gpa.free(export_list);
|
||||
@ -1881,6 +1888,9 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void {
|
||||
if (self.emit_h_failed_decls.remove(decl)) |entry| {
|
||||
entry.value.destroy(self.gpa);
|
||||
}
|
||||
if (self.compile_log_decls.remove(decl)) |*entry| {
|
||||
entry.value.deinit(self.gpa);
|
||||
}
|
||||
self.deleteDeclExports(decl);
|
||||
self.comp.bin_file.freeDecl(decl);
|
||||
|
||||
@ -1971,6 +1981,9 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {
|
||||
if (self.emit_h_failed_decls.remove(decl)) |entry| {
|
||||
entry.value.destroy(self.gpa);
|
||||
}
|
||||
if (self.compile_log_decls.remove(decl)) |*entry| {
|
||||
entry.value.deinit(self.gpa);
|
||||
}
|
||||
decl.analysis = .outdated;
|
||||
}
|
||||
|
||||
@ -3151,6 +3164,44 @@ pub fn failNode(
|
||||
return self.fail(scope, src, format, args);
|
||||
}
|
||||
|
||||
fn addCompileLog(self: *Module, decl: *Decl, src: usize) error{OutOfMemory}!void {
|
||||
const entry = try self.compile_log_decls.getOrPutValue(self.gpa, decl, .{});
|
||||
try entry.value.append(self.gpa, src);
|
||||
}
|
||||
|
||||
pub fn failCompileLog(
|
||||
self: *Module,
|
||||
scope: *Scope,
|
||||
src: usize,
|
||||
) InnerError!void {
|
||||
switch (scope.tag) {
|
||||
.decl => {
|
||||
const decl = scope.cast(Scope.DeclAnalysis).?.decl;
|
||||
try self.addCompileLog(decl, src);
|
||||
},
|
||||
.block => {
|
||||
const block = scope.cast(Scope.Block).?;
|
||||
try self.addCompileLog(block.decl, src);
|
||||
},
|
||||
.gen_zir => {
|
||||
const gen_zir = scope.cast(Scope.GenZIR).?;
|
||||
try self.addCompileLog(gen_zir.decl, src);
|
||||
},
|
||||
.local_val => {
|
||||
const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir;
|
||||
try self.addCompileLog(gen_zir.decl, src);
|
||||
},
|
||||
.local_ptr => {
|
||||
const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir;
|
||||
try self.addCompileLog(gen_zir.decl, src);
|
||||
},
|
||||
.zir_module,
|
||||
.file,
|
||||
.container,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError {
|
||||
{
|
||||
errdefer err_msg.destroy(self.gpa);
|
||||
|
||||
@ -2346,6 +2346,16 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal
|
||||
items[param_i] = try expr(mod, scope, .none, param);
|
||||
return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{}));
|
||||
}
|
||||
fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const arena = scope.arena();
|
||||
const src = tree.token_locs[call.builtin_token].start;
|
||||
const params = call.params();
|
||||
var targets = try arena.alloc(*zir.Inst, params.len);
|
||||
for (params) |param, param_i|
|
||||
targets[param_i] = try expr(mod, scope, .none, param);
|
||||
return addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{});
|
||||
}
|
||||
|
||||
fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
@ -2377,6 +2387,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
|
||||
return compileError(mod, scope, call);
|
||||
} else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {
|
||||
return setEvalBranchQuota(mod, scope, call);
|
||||
} else if (mem.eql(u8, builtin_name, "@compileLog")) {
|
||||
return compileLog(mod, scope, call);
|
||||
} else {
|
||||
return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});
|
||||
}
|
||||
|
||||
23
src/zir.zig
23
src/zir.zig
@ -127,9 +127,8 @@ pub const Inst = struct {
|
||||
coerce_to_ptr_elem,
|
||||
/// Emit an error message and fail compilation.
|
||||
compileerror,
|
||||
/// Changes the maximum number of backwards branches that compile-time
|
||||
/// code execution can use before giving up and making a compile error.
|
||||
set_eval_branch_quota,
|
||||
/// Log compile time variables and emit an error message.
|
||||
compilelog,
|
||||
/// Conditional branch. Splits control flow based on a boolean condition value.
|
||||
condbr,
|
||||
/// Special case, has no textual representation.
|
||||
@ -223,6 +222,9 @@ pub const Inst = struct {
|
||||
@"return",
|
||||
/// Same as `return` but there is no operand; the operand is implicitly the void value.
|
||||
returnvoid,
|
||||
/// Changes the maximum number of backwards branches that compile-time
|
||||
/// code execution can use before giving up and making a compile error.
|
||||
set_eval_branch_quota,
|
||||
/// Integer shift-left. Zeroes are shifted in from the right hand side.
|
||||
shl,
|
||||
/// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
|
||||
@ -407,6 +409,7 @@ pub const Inst = struct {
|
||||
.declval => DeclVal,
|
||||
.declval_in_module => DeclValInModule,
|
||||
.coerce_result_block_ptr => CoerceResultBlockPtr,
|
||||
.compilelog => CompileLog,
|
||||
.loop => Loop,
|
||||
.@"const" => Const,
|
||||
.str => Str,
|
||||
@ -540,6 +543,7 @@ pub const Inst = struct {
|
||||
.typeof_peer,
|
||||
.resolve_inferred_alloc,
|
||||
.set_eval_branch_quota,
|
||||
.compilelog,
|
||||
=> false,
|
||||
|
||||
.@"break",
|
||||
@ -723,6 +727,19 @@ pub const Inst = struct {
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const CompileLog = struct {
|
||||
pub const base_tag = Tag.compilelog;
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {
|
||||
to_log: []*Inst,
|
||||
},
|
||||
kw_args: struct {
|
||||
/// If we have seen it already so don't make another error
|
||||
seen: bool = false,
|
||||
},
|
||||
};
|
||||
|
||||
pub const Const = struct {
|
||||
pub const base_tag = Tag.@"const";
|
||||
base: Inst,
|
||||
|
||||
@ -57,6 +57,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
|
||||
.coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),
|
||||
.coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),
|
||||
.compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),
|
||||
.compilelog => return analyzeInstCompileLog(mod, scope, old_inst.castTag(.compilelog).?),
|
||||
.@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),
|
||||
.dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),
|
||||
.declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),
|
||||
@ -630,6 +631,27 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
|
||||
return mod.fail(scope, inst.base.src, "{s}", .{msg});
|
||||
}
|
||||
|
||||
fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst {
|
||||
std.debug.print("| ", .{});
|
||||
for (inst.positionals.to_log) |item, i| {
|
||||
const to_log = try resolveInst(mod, scope, item);
|
||||
if (to_log.value()) |val| {
|
||||
std.debug.print("{}", .{val});
|
||||
} else {
|
||||
std.debug.print("(runtime value)", .{});
|
||||
}
|
||||
if (i != inst.positionals.to_log.len - 1) std.debug.print(", ", .{});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
if (!inst.kw_args.seen) {
|
||||
|
||||
// so that we do not give multiple compile errors if it gets evaled twice
|
||||
inst.kw_args.seen = true;
|
||||
try mod.failCompileLog(scope, inst.base.src);
|
||||
}
|
||||
return mod.constVoid(scope, inst.base.src);
|
||||
}
|
||||
|
||||
fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -1243,6 +1243,24 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\}
|
||||
, &[_][]const u8{":3:9: error: redefinition of 'testing'"});
|
||||
}
|
||||
ctx.compileError("compileLog", linux_x64,
|
||||
\\export fn _start() noreturn {
|
||||
\\ const b = true;
|
||||
\\ var f: u32 = 1;
|
||||
\\ @compileLog(b, 20, f, x);
|
||||
\\ @compileLog(1000);
|
||||
\\ var bruh: usize = true;
|
||||
\\ unreachable;
|
||||
\\}
|
||||
\\fn x() void {}
|
||||
, &[_][]const u8{
|
||||
":4:3: error: found compile log statement",
|
||||
":5:3: error: found compile log statement",
|
||||
":6:21: error: expected usize, found bool",
|
||||
});
|
||||
// TODO if this is here it invalidates the compile error checker:
|
||||
// "| true, 20, (runtime value), (function)"
|
||||
// "| 1000"
|
||||
|
||||
{
|
||||
var case = ctx.obj("extern variable has no type", linux_x64);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user