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 be44ca6a5f..f0b91553e2 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); } 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 f47822f0b7..510bae4a52 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 9169bcf3d0..1320e749a2 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 b9467ac2be..3087187bd6 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)}); }; 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 3a7d82e24f..6215a11e6f 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); }