authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2020-11-21 21:12:33-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-05 18:43:41-07:00
logab5f7b51566ad2c8e635e81b8515a97206daf8ab
tree16b0fd8057df6d52f3b67ab56a12175847f1bdb9
parent38572ee89492d8499a5881d12c401d9bb0925167

stage2: add compile log statement


6 files changed, 135 insertions(+), 3 deletions(-)

src/Compilation.zig+12
...@@ -1351,6 +1351,9 @@ pub fn totalErrorCount(self: *Compilation) usize {...@@ -1351,6 +1351,9 @@ pub fn totalErrorCount(self: *Compilation) usize {
1351 module.failed_exports.items().len +1351 module.failed_exports.items().len +
1352 module.failed_files.items().len +1352 module.failed_files.items().len +
1353 @boolToInt(module.failed_root_src_file != null);1353 @boolToInt(module.failed_root_src_file != null);
1354 for (module.compile_log_decls.items()) |entry| {
1355 total += entry.value.items.len;
1356 }
1354 }1357 }
13551358
1356 // The "no entry point found" error only counts if there are no other errors.1359 // The "no entry point found" error only counts if there are no other errors.
...@@ -1407,6 +1410,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1407,6 +1410,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
1407 });1410 });
1408 try AllErrors.addPlain(&arena, &errors, msg);1411 try AllErrors.addPlain(&arena, &errors, msg);
1409 }1412 }
1413 for (module.compile_log_decls.items()) |entry| {
1414 const decl = entry.key;
1415 const path = decl.scope.subFilePath();
1416 const source = try decl.scope.getSource(module);
1417 for (entry.value.items) |src_loc| {
1418 const err_msg = ErrorMsg{ .byte_offset = src_loc, .msg = "found compile log statement" };
1419 try AllErrors.add(&arena, &errors, path, source, err_msg);
1420 }
1421 }
1410 }1422 }
14111423
1412 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {1424 if (errors.items.len == 0 and self.link_error_flags.no_entry_point_found) {
src/Module.zig+51
...@@ -61,6 +61,8 @@ failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},...@@ -61,6 +61,8 @@ failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
61/// emit-h failing for that Decl. This table is also how we tell if a Decl has61/// emit-h failing for that Decl. This table is also how we tell if a Decl has
62/// failed emit-h or succeeded.62/// failed emit-h or succeeded.
63emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},63emit_h_failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *Compilation.ErrorMsg) = .{},
64/// A Decl can have multiple compileLogs, but only one error, so we map a Decl to a the src locs of all the compileLogs
65compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, ArrayListUnmanaged(usize)) = .{},
64/// Using a map here for consistency with the other fields here.66/// Using a map here for consistency with the other fields here.
65/// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator.67/// The ErrorMsg memory is owned by the `Scope`, using Module's general purpose allocator.
66failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{},68failed_files: std.AutoArrayHashMapUnmanaged(*Scope, *Compilation.ErrorMsg) = .{},
...@@ -936,6 +938,11 @@ pub fn deinit(self: *Module) void {...@@ -936,6 +938,11 @@ pub fn deinit(self: *Module) void {
936 }938 }
937 self.failed_exports.deinit(gpa);939 self.failed_exports.deinit(gpa);
938940
941 for (self.compile_log_decls.items()) |*entry| {
942 entry.value.deinit(gpa);
943 }
944 self.compile_log_decls.deinit(gpa);
945
939 for (self.decl_exports.items()) |entry| {946 for (self.decl_exports.items()) |entry| {
940 const export_list = entry.value;947 const export_list = entry.value;
941 gpa.free(export_list);948 gpa.free(export_list);
...@@ -1881,6 +1888,9 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void {...@@ -1881,6 +1888,9 @@ pub fn deleteDecl(self: *Module, decl: *Decl) !void {
1881 if (self.emit_h_failed_decls.remove(decl)) |entry| {1888 if (self.emit_h_failed_decls.remove(decl)) |entry| {
1882 entry.value.destroy(self.gpa);1889 entry.value.destroy(self.gpa);
1883 }1890 }
1891 if (self.compile_log_decls.remove(decl)) |*entry| {
1892 entry.value.deinit(self.gpa);
1893 }
1884 self.deleteDeclExports(decl);1894 self.deleteDeclExports(decl);
1885 self.comp.bin_file.freeDecl(decl);1895 self.comp.bin_file.freeDecl(decl);
18861896
...@@ -1971,6 +1981,9 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {...@@ -1971,6 +1981,9 @@ fn markOutdatedDecl(self: *Module, decl: *Decl) !void {
1971 if (self.emit_h_failed_decls.remove(decl)) |entry| {1981 if (self.emit_h_failed_decls.remove(decl)) |entry| {
1972 entry.value.destroy(self.gpa);1982 entry.value.destroy(self.gpa);
1973 }1983 }
1984 if (self.compile_log_decls.remove(decl)) |*entry| {
1985 entry.value.deinit(self.gpa);
1986 }
1974 decl.analysis = .outdated;1987 decl.analysis = .outdated;
1975}1988}
19761989
...@@ -3151,6 +3164,44 @@ pub fn failNode(...@@ -3151,6 +3164,44 @@ pub fn failNode(
3151 return self.fail(scope, src, format, args);3164 return self.fail(scope, src, format, args);
3152}3165}
31533166
3167fn addCompileLog(self: *Module, decl: *Decl, src: usize) error{OutOfMemory}!void {
3168 const entry = try self.compile_log_decls.getOrPutValue(self.gpa, decl, .{});
3169 try entry.value.append(self.gpa, src);
3170}
3171
3172pub fn failCompileLog(
3173 self: *Module,
3174 scope: *Scope,
3175 src: usize,
3176) InnerError!void {
3177 switch (scope.tag) {
3178 .decl => {
3179 const decl = scope.cast(Scope.DeclAnalysis).?.decl;
3180 try self.addCompileLog(decl, src);
3181 },
3182 .block => {
3183 const block = scope.cast(Scope.Block).?;
3184 try self.addCompileLog(block.decl, src);
3185 },
3186 .gen_zir => {
3187 const gen_zir = scope.cast(Scope.GenZIR).?;
3188 try self.addCompileLog(gen_zir.decl, src);
3189 },
3190 .local_val => {
3191 const gen_zir = scope.cast(Scope.LocalVal).?.gen_zir;
3192 try self.addCompileLog(gen_zir.decl, src);
3193 },
3194 .local_ptr => {
3195 const gen_zir = scope.cast(Scope.LocalPtr).?.gen_zir;
3196 try self.addCompileLog(gen_zir.decl, src);
3197 },
3198 .zir_module,
3199 .file,
3200 .container,
3201 => unreachable,
3202 }
3203}
3204
3154fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError {3205fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Compilation.ErrorMsg) InnerError {
3155 {3206 {
3156 errdefer err_msg.destroy(self.gpa);3207 errdefer err_msg.destroy(self.gpa);
src/astgen.zig+12
...@@ -2346,6 +2346,16 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal...@@ -2346,6 +2346,16 @@ fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCal
2346 items[param_i] = try expr(mod, scope, .none, param);2346 items[param_i] = try expr(mod, scope, .none, param);
2347 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{}));2347 return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{}));
2348}2348}
2349fn compileLog(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
2350 const tree = scope.tree();
2351 const arena = scope.arena();
2352 const src = tree.token_locs[call.builtin_token].start;
2353 const params = call.params();
2354 var targets = try arena.alloc(*zir.Inst, params.len);
2355 for (params) |param, param_i|
2356 targets[param_i] = try expr(mod, scope, .none, param);
2357 return addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{});
2358}
23492359
2350fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {2360fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
2351 const tree = scope.tree();2361 const tree = scope.tree();
...@@ -2377,6 +2387,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built...@@ -2377,6 +2387,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
2377 return compileError(mod, scope, call);2387 return compileError(mod, scope, call);
2378 } else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {2388 } else if (mem.eql(u8, builtin_name, "@setEvalBranchQuota")) {
2379 return setEvalBranchQuota(mod, scope, call);2389 return setEvalBranchQuota(mod, scope, call);
2390 } else if (mem.eql(u8, builtin_name, "@compileLog")) {
2391 return compileLog(mod, scope, call);
2380 } else {2392 } else {
2381 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});2393 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});
2382 }2394 }
src/zir.zig+20-3
...@@ -127,9 +127,8 @@ pub const Inst = struct {...@@ -127,9 +127,8 @@ pub const Inst = struct {
127 coerce_to_ptr_elem,127 coerce_to_ptr_elem,
128 /// Emit an error message and fail compilation.128 /// Emit an error message and fail compilation.
129 compileerror,129 compileerror,
130 /// Changes the maximum number of backwards branches that compile-time130 /// Log compile time variables and emit an error message.
131 /// code execution can use before giving up and making a compile error.131 compilelog,
132 set_eval_branch_quota,
133 /// Conditional branch. Splits control flow based on a boolean condition value.132 /// Conditional branch. Splits control flow based on a boolean condition value.
134 condbr,133 condbr,
135 /// Special case, has no textual representation.134 /// Special case, has no textual representation.
...@@ -223,6 +222,9 @@ pub const Inst = struct {...@@ -223,6 +222,9 @@ pub const Inst = struct {
223 @"return",222 @"return",
224 /// Same as `return` but there is no operand; the operand is implicitly the void value.223 /// Same as `return` but there is no operand; the operand is implicitly the void value.
225 returnvoid,224 returnvoid,
225 /// Changes the maximum number of backwards branches that compile-time
226 /// code execution can use before giving up and making a compile error.
227 set_eval_branch_quota,
226 /// Integer shift-left. Zeroes are shifted in from the right hand side.228 /// Integer shift-left. Zeroes are shifted in from the right hand side.
227 shl,229 shl,
228 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.230 /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
...@@ -407,6 +409,7 @@ pub const Inst = struct {...@@ -407,6 +409,7 @@ pub const Inst = struct {
407 .declval => DeclVal,409 .declval => DeclVal,
408 .declval_in_module => DeclValInModule,410 .declval_in_module => DeclValInModule,
409 .coerce_result_block_ptr => CoerceResultBlockPtr,411 .coerce_result_block_ptr => CoerceResultBlockPtr,
412 .compilelog => CompileLog,
410 .loop => Loop,413 .loop => Loop,
411 .@"const" => Const,414 .@"const" => Const,
412 .str => Str,415 .str => Str,
...@@ -540,6 +543,7 @@ pub const Inst = struct {...@@ -540,6 +543,7 @@ pub const Inst = struct {
540 .typeof_peer,543 .typeof_peer,
541 .resolve_inferred_alloc,544 .resolve_inferred_alloc,
542 .set_eval_branch_quota,545 .set_eval_branch_quota,
546 .compilelog,
543 => false,547 => false,
544548
545 .@"break",549 .@"break",
...@@ -723,6 +727,19 @@ pub const Inst = struct {...@@ -723,6 +727,19 @@ pub const Inst = struct {
723 kw_args: struct {},727 kw_args: struct {},
724 };728 };
725729
730 pub const CompileLog = struct {
731 pub const base_tag = Tag.compilelog;
732 base: Inst,
733
734 positionals: struct {
735 to_log: []*Inst,
736 },
737 kw_args: struct {
738 /// If we have seen it already so don't make another error
739 seen: bool = false,
740 },
741 };
742
726 pub const Const = struct {743 pub const Const = struct {
727 pub const base_tag = Tag.@"const";744 pub const base_tag = Tag.@"const";
728 base: Inst,745 base: Inst,
src/zir_sema.zig+22
...@@ -57,6 +57,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -57,6 +57,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
57 .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),57 .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),
58 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),58 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),
59 .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),59 .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),
60 .compilelog => return analyzeInstCompileLog(mod, scope, old_inst.castTag(.compilelog).?),
60 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),61 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),
61 .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),62 .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),
62 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),63 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),
...@@ -630,6 +631,27 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In...@@ -630,6 +631,27 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) In
630 return mod.fail(scope, inst.base.src, "{s}", .{msg});631 return mod.fail(scope, inst.base.src, "{s}", .{msg});
631}632}
632633
634fn analyzeInstCompileLog(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileLog) InnerError!*Inst {
635 std.debug.print("| ", .{});
636 for (inst.positionals.to_log) |item, i| {
637 const to_log = try resolveInst(mod, scope, item);
638 if (to_log.value()) |val| {
639 std.debug.print("{}", .{val});
640 } else {
641 std.debug.print("(runtime value)", .{});
642 }
643 if (i != inst.positionals.to_log.len - 1) std.debug.print(", ", .{});
644 }
645 std.debug.print("\n", .{});
646 if (!inst.kw_args.seen) {
647
648 // so that we do not give multiple compile errors if it gets evaled twice
649 inst.kw_args.seen = true;
650 try mod.failCompileLog(scope, inst.base.src);
651 }
652 return mod.constVoid(scope, inst.base.src);
653}
654
633fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {655fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
634 const tracy = trace(@src());656 const tracy = trace(@src());
635 defer tracy.end();657 defer tracy.end();
test/stage2/test.zig+18
...@@ -1243,6 +1243,24 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1243,6 +1243,24 @@ pub fn addCases(ctx: *TestContext) !void {
1243 \\}1243 \\}
1244 , &[_][]const u8{":3:9: error: redefinition of 'testing'"});1244 , &[_][]const u8{":3:9: error: redefinition of 'testing'"});
1245 }1245 }
1246 ctx.compileError("compileLog", linux_x64,
1247 \\export fn _start() noreturn {
1248 \\ const b = true;
1249 \\ var f: u32 = 1;
1250 \\ @compileLog(b, 20, f, x);
1251 \\ @compileLog(1000);
1252 \\ var bruh: usize = true;
1253 \\ unreachable;
1254 \\}
1255 \\fn x() void {}
1256 , &[_][]const u8{
1257 ":4:3: error: found compile log statement",
1258 ":5:3: error: found compile log statement",
1259 ":6:21: error: expected usize, found bool",
1260 });
1261 // TODO if this is here it invalidates the compile error checker:
1262 // "| true, 20, (runtime value), (function)"
1263 // "| 1000"
12461264
1247 {1265 {
1248 var case = ctx.obj("extern variable has no type", linux_x64);1266 var case = ctx.obj("extern variable has no type", linux_x64);