From fba33ee58cc3dcd832fe9422be4dc05228afce76 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 30 Nov 2022 19:12:05 +0200 Subject: [PATCH 1/3] Sema: print line column and path when using `--debug-compile-errors` --- src/Sema.zig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index be44ca6a5f70a426b1a0156669c9197116d41a29..f0b91553e26bfae87fa4799f856070ef2ee56da4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2189,10 +2189,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { @setCold(true); if (crash_report.is_enabled and sema.mod.comp.debug_compile_errors) { - std.debug.print("compile error during Sema: {s}, src: {s}:{}\n", .{ + const err_path = err_msg.src_loc.file_scope.fullPath(sema.mod.gpa) catch unreachable; + const err_source = err_msg.src_loc.file_scope.getSource(sema.mod.gpa) catch unreachable; + const err_span = err_msg.src_loc.span(sema.mod.gpa) catch unreachable; + const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main); + std.debug.print("compile error during Sema:\n{s}:{d}:{d}: error: {s}\n{s}\n\n", .{ + err_path, + err_loc.line + 1, + err_loc.column + 1, err_msg.msg, - err_msg.src_loc.file_scope.sub_file_path, - err_msg.src_loc.lazy, + err_loc.source_line, }); crash_report.compilerPanic("unexpected compile error occurred", null, null); } -- 2.54.0 From e4fd9acc2a7682d0d64d6d42e2882967cf3877aa Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 30 Nov 2022 19:14:04 +0200 Subject: [PATCH 2/3] CLI: allow using `--debug-compile-errors` with `zig build` --- lib/build_runner.zig | 2 ++ lib/std/build.zig | 5 +++++ src/main.zig | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/lib/build_runner.zig b/lib/build_runner.zig index f47822f0b7e2cae41ffbb12f5828670f82773285..510bae4a521ebaef01f9dd1c2a5e55c7143e6afe 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -142,6 +142,8 @@ pub fn main() !void { return usageAndErr(builder, false, stderr_stream); }; try debug_log_scopes.append(next_arg); + } else if (mem.eql(u8, arg, "--debug-compile-errors")) { + builder.debug_compile_errors = true; } else if (mem.eql(u8, arg, "--glibc-runtimes")) { builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse { std.debug.print("Expected argument after --glibc-runtimes\n\n", .{}); diff --git a/lib/std/build.zig b/lib/std/build.zig index 9169bcf3d0bacdc82024b5e65c20d1dfaab685cb..1320e749a22dfbf5201eba0c74f5eed2c8f84360 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -72,6 +72,7 @@ pub const Builder = struct { pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, args: ?[][]const u8 = null, debug_log_scopes: []const []const u8 = &.{}, + debug_compile_errors: bool = false, /// Experimental. Use system Darling installation to run cross compiled macOS build artifacts. enable_darling: bool = false, @@ -2686,6 +2687,10 @@ pub const LibExeObjStep = struct { try zig_args.append(log_scope); } + if (builder.debug_compile_errors) { + try zig_args.append("--debug-compile-errors"); + } + if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable; if (builder.verbose_air) zig_args.append("--verbose-air") catch unreachable; if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable; diff --git a/src/main.zig b/src/main.zig index b9467ac2bedcb138efbb90cc05d436c152a22c8f..3087187bd64b9122ea403b723ad2aa764a4644f4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3778,6 +3778,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi var override_local_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LOCAL_CACHE_DIR"); var child_argv = std.ArrayList([]const u8).init(arena); var reference_trace: ?u32 = null; + var debug_compile_errors = false; const argv_index_exe = child_argv.items.len; _ = try child_argv.addOne(); @@ -3839,6 +3840,9 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi } else if (mem.eql(u8, arg, "-fno-reference-trace")) { try child_argv.append(arg); reference_trace = null; + } else if (mem.eql(u8, arg, "--debug-compile-errors")) { + try child_argv.append(arg); + debug_compile_errors = true; } } try child_argv.append(arg); @@ -3973,6 +3977,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .use_stage1 = use_stage1, .cache_mode = .whole, .reference_trace = reference_trace, + .debug_compile_errors = debug_compile_errors, }) catch |err| { fatal("unable to create compilation: {s}", .{@errorName(err)}); }; -- 2.54.0 From fb4a5ccdeeddf56a0849b4168fe7a9525f36b107 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 30 Nov 2022 19:31:01 +0200 Subject: [PATCH 3/3] llvm: make debuggers actually usable `@llvm.dbg.value` is absolutely useless, adding a temporary alloca to store the constant in will make it actually show up in debuggers. The effect on performance should be minimal since there is only one store and it the change is not applied to ReleaseSafe builds. ```zig fn foo(a: u32, b: []const u8, c: bool, d: enum { yes, no }) void { _ = a; _ = b; _ = c; _ = d; } ``` before: ``` Breakpoint 1, a.foo (a=, b=..., c=, d=) at a.zig:18 18 _ = d; ``` after: ``` Breakpoint 1, a.foo (a=1, b=..., c=false, d=yes) at a.zig:15 15 _ = a; _ = b; _ = c; _ = d; (gdb) p b $1 = {ptr = 0x20854f "bar", len = 3} ``` --- src/codegen/llvm.zig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3a7d82e24f24d2ea60d7758e3bb5d95bb31f34e9..6215a11e6f7106ebc7c9e949e1fdbb80bcebf207 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -6088,6 +6088,12 @@ pub const FuncGen = struct { const insert_block = self.builder.getInsertBlock(); if (isByRef(operand_ty)) { _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); + } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { + const alignment = operand_ty.abiAlignment(self.dg.module.getTarget()); + const alloca = self.buildAlloca(operand.typeOf(), alignment); + const store_inst = self.builder.buildStore(operand, alloca); + store_inst.setAlignment(alignment); + _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); } else { _ = dib.insertDbgValueIntrinsicAtEnd(operand, di_local_var, debug_loc, insert_block); } @@ -8026,6 +8032,12 @@ pub const FuncGen = struct { const insert_block = self.builder.getInsertBlock(); if (isByRef(inst_ty)) { _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); + } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { + const alignment = inst_ty.abiAlignment(self.dg.module.getTarget()); + const alloca = self.buildAlloca(arg_val.typeOf(), alignment); + const store_inst = self.builder.buildStore(arg_val, alloca); + store_inst.setAlignment(alignment); + _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); } else { _ = dib.insertDbgValueIntrinsicAtEnd(arg_val, di_local_var, debug_loc, insert_block); } -- 2.54.0