Commit d026202a26

David Gonzalez Martin <davidgm94.work@protonmail.com>
2023-04-06 10:16:20
Expose an option for producing 64-bit DWARF format
This commit enables producing 64-bit DWARF format for Zig executables that are produced through the LLVM backend. This is achieved by exposing both command-line flags and CompileStep flags. The production of the 64-bit format only affects binaries that use the DWARF format and it is disabled on MacOS due to it being problematic. This commit, despite generating the interface for the Zig user to be able to tell the compile which format is wanted, is just implemented for the LLVM backend, so clang and the self-hosted backends will need this to be implemented in a future commit. This is an effort to work around #7962, since the emission of the 64-bit format automatically produces 64-bit relocations. Further investigation will be needed to make DWARF 32-bit format to emit bigger relocations when needed and not make the linker angry.
1 parent fac120b
lib/std/Build/CompileStep.zig
@@ -69,6 +69,7 @@ disable_stack_probing: bool,
 disable_sanitize_c: bool,
 sanitize_thread: bool,
 rdynamic: bool,
+dwarf_format: ?std.dwarf.Format = null,
 import_memory: bool = false,
 /// For WebAssembly targets, this will allow for undefined symbols to
 /// be imported from the host environment.
@@ -1449,6 +1450,14 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
 
     try addFlag(&zig_args, "strip", self.strip);
     try addFlag(&zig_args, "unwind-tables", self.unwind_tables);
+    if (!self.producesPdbFile()) {
+        if (self.dwarf_format) |dwarf_format| {
+            try zig_args.append(switch (dwarf_format) {
+                .dwarf32 => "-gdwarf32",
+                .dwarf64 => "-gdwarf64",
+            });
+        }
+    }
 
     switch (self.compress_debug_sections) {
         .none => {},
lib/std/dwarf.zig
@@ -147,6 +147,11 @@ pub const CC = enum(u8) {
     GNU_borland_fastcall_i386 = 0x41,
 };
 
+pub const Format = enum {
+    dwarf32,
+    dwarf64,
+};
+
 const PcRange = struct {
     start: u64,
     end: u64,
src/codegen/llvm/bindings.zig
@@ -409,7 +409,7 @@ pub const Module = opaque {
     extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void;
 
     pub const addModuleDebugInfoFlag = ZigLLVMAddModuleDebugInfoFlag;
-    extern fn ZigLLVMAddModuleDebugInfoFlag(module: *Module) void;
+    extern fn ZigLLVMAddModuleDebugInfoFlag(module: *Module, dwarf64: bool) void;
 
     pub const addModuleCodeViewFlag = ZigLLVMAddModuleCodeViewFlag;
     extern fn ZigLLVMAddModuleCodeViewFlag(module: *Module) void;
src/codegen/llvm.zig
@@ -433,7 +433,14 @@ pub const Object = struct {
         if (!options.strip) {
             switch (options.target.ofmt) {
                 .coff => llvm_module.addModuleCodeViewFlag(),
-                else => llvm_module.addModuleDebugInfoFlag(),
+                else => {
+                    const dwarf_format = options.dwarf_format orelse .dwarf32;
+                    const produce_dwarf64 = switch (dwarf_format) {
+                        .dwarf32 => false,
+                        .dwarf64 => true,
+                    };
+                    llvm_module.addModuleDebugInfoFlag(produce_dwarf64);
+                },
             }
             const di_builder = llvm_module.createDIBuilder(true);
             opt_di_builder = di_builder;
src/Compilation.zig
@@ -620,6 +620,7 @@ pub const InitOptions = struct {
     test_name_prefix: ?[]const u8 = null,
     test_runner_path: ?[]const u8 = null,
     subsystem: ?std.Target.SubSystem = null,
+    dwarf_format: ?std.dwarf.Format = null,
     /// WASI-only. Type of WASI execution model ("command" or "reactor").
     wasi_exec_model: ?std.builtin.WasiExecModel = null,
     /// (Zig compiler development) Enable dumping linker's state as JSON.
@@ -1517,6 +1518,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
             .subsystem = options.subsystem,
             .is_test = options.is_test,
+            .dwarf_format = options.dwarf_format,
             .wasi_exec_model = wasi_exec_model,
             .hash_style = options.hash_style,
             .enable_link_snapshots = options.enable_link_snapshots,
src/link.zig
@@ -200,6 +200,8 @@ pub const Options = struct {
     compatibility_version: ?std.builtin.Version,
     libc_installation: ?*const LibCInstallation,
 
+    dwarf_format: ?std.dwarf.Format = null,
+
     /// WASI-only. Type of WASI execution model ("command" or "reactor").
     wasi_exec_model: std.builtin.WasiExecModel = undefined,
 
src/main.zig
@@ -844,6 +844,7 @@ fn buildOutputType(
     var reference_trace: ?u32 = null;
     var error_tracing: ?bool = null;
     var pdb_out_path: ?[]const u8 = null;
+    var dwarf_format: ?std.dwarf.Format = null;
 
     // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
     // This array is populated by zig cc frontend and then has to be converted to zig-style
@@ -1355,6 +1356,10 @@ fn buildOutputType(
                         strip = true;
                     } else if (mem.eql(u8, arg, "-fno-strip")) {
                         strip = false;
+                    } else if (mem.eql(u8, arg, "-gdwarf32")) {
+                        dwarf_format = .dwarf32;
+                    } else if (mem.eql(u8, arg, "-gdwarf64")) {
+                        dwarf_format = .dwarf64;
                     } else if (mem.eql(u8, arg, "-fformatted-panics")) {
                         formatted_panics = true;
                     } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
@@ -3145,6 +3150,7 @@ fn buildOutputType(
         .test_runner_path = test_runner_path,
         .disable_lld_caching = !output_to_cache,
         .subsystem = subsystem,
+        .dwarf_format = dwarf_format,
         .wasi_exec_model = wasi_exec_model,
         .debug_compile_errors = debug_compile_errors,
         .enable_link_snapshots = enable_link_snapshots,
src/zig_llvm.cpp
@@ -1163,9 +1163,13 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type,
     free(native_triple);
 }
 
-void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) {
+void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) {
     unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
     unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
+
+    if (produce_dwarf64) {
+        unwrap(module)->addModuleFlag(Module::Warning, "DWARF64", 1);
+    }
 }
 
 void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {
src/zig_llvm.h
@@ -238,7 +238,7 @@ ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void);
 
 ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
 ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder);
-ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
+ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64);
 ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
 ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module);
 ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module);