From ed37a1a33c2576c00697643463a4720728e04023 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Mon, 9 Jun 2025 18:38:39 -0400 Subject: [PATCH] coff: add hack to build a compiler-rt dynamic library This is not meant to be a long-term solution, but it's the easiest thing to get working quickly at the moment. The main intention of this hack is to allow more tests to be enabled. By the time the coff linker is far enough along to be enabled by default, this will no longer be required. --- lib/compiler_rt/common.zig | 6 ++--- src/Compilation.zig | 46 +++++++++++++++++++++++++++++++++++--- src/link/Coff.zig | 15 +++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/lib/compiler_rt/common.zig b/lib/compiler_rt/common.zig index 747e74841e490ec3810f48e4692104882ee192a4..978e701130ec641e2381c8ee517e255296b45f42 100644 --- a/lib/compiler_rt/common.zig +++ b/lib/compiler_rt/common.zig @@ -16,10 +16,10 @@ else /// Determines the symbol's visibility to other objects. /// For WebAssembly this allows the symbol to be resolved to other modules, but will not /// export it to the host runtime. -pub const visibility: std.builtin.SymbolVisibility = if (linkage != .internal) - .hidden +pub const visibility: std.builtin.SymbolVisibility = if (linkage == .internal or builtin.link_mode == .dynamic) + .default else - .default; + .hidden; pub const PreferredLoadStoreElement = element: { if (std.simd.suggestVectorLength(u8)) |vec_size| { diff --git a/src/Compilation.zig b/src/Compilation.zig index e0f8cf5a56d26f85ea1243acadefe5af1d881edd..4136b21f61372712408a81b934956103b6f49e36 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -224,6 +224,8 @@ compiler_rt_lib: ?CrtFile = null, /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated /// by setting `queued_jobs.compiler_rt_obj` and resolved before calling linker.flush(). compiler_rt_obj: ?CrtFile = null, +/// hack for stage2_x86_64 + coff +compiler_rt_dyn_lib: ?CrtFile = null, /// Populated when we build the libfuzzer static library. A Job to build this /// is indicated by setting `queued_jobs.fuzzer_lib` and resolved before /// calling linker.flush(). @@ -291,6 +293,8 @@ emit_llvm_bc: ?[]const u8, emit_docs: ?[]const u8, const QueuedJobs = struct { + /// hack for stage2_x86_64 + coff + compiler_rt_dyn_lib: bool = false, compiler_rt_lib: bool = false, compiler_rt_obj: bool = false, ubsan_rt_lib: bool = false, @@ -1753,7 +1757,7 @@ fn addModuleTableToCacheHash( } } -const RtStrat = enum { none, lib, obj, zcu }; +const RtStrat = enum { none, lib, obj, zcu, dyn_lib }; pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compilation { const output_mode = options.config.output_mode; @@ -1816,7 +1820,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil if (options.skip_linker_dependencies) break :s .none; const want = options.want_compiler_rt orelse is_exe_or_dyn_lib; if (!want) break :s .none; - if (have_zcu and output_mode == .Obj) break :s .zcu; + if (have_zcu) { + if (output_mode == .Obj) break :s .zcu; + if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64) + break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu; + } if (is_exe_or_dyn_lib) break :s .lib; break :s .obj; }; @@ -2441,6 +2449,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil // for a compiler-rt object to put in it. comp.queued_jobs.compiler_rt_obj = true; comp.link_task_queue.pending_prelink_tasks += 1; + } else if (comp.compiler_rt_strat == .dyn_lib) { + // hack for stage2_x86_64 + coff + log.debug("queuing a job to build compiler_rt_dyn_lib", .{}); + comp.queued_jobs.compiler_rt_dyn_lib = true; + comp.link_task_queue.pending_prelink_tasks += 1; } if (comp.ubsan_rt_strat == .lib) { @@ -4254,6 +4267,7 @@ fn performAllTheWork( "compiler_rt.zig", "compiler_rt", .Lib, + .static, .compiler_rt, main_progress_node, RtOptions{ @@ -4270,6 +4284,7 @@ fn performAllTheWork( "compiler_rt.zig", "compiler_rt", .Obj, + .static, .compiler_rt, main_progress_node, RtOptions{ @@ -4280,12 +4295,31 @@ fn performAllTheWork( }); } + // hack for stage2_x86_64 + coff + if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) { + comp.link_task_wait_group.spawnManager(buildRt, .{ + comp, + "compiler_rt.zig", + "compiler_rt", + .Lib, + .dynamic, + .compiler_rt, + main_progress_node, + RtOptions{ + .checks_valgrind = true, + .allow_lto = false, + }, + &comp.compiler_rt_dyn_lib, + }); + } + if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) { comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "fuzzer.zig", "fuzzer", .Lib, + .static, .libfuzzer, main_progress_node, RtOptions{}, @@ -4299,6 +4333,7 @@ fn performAllTheWork( "ubsan_rt.zig", "ubsan_rt", .Lib, + .static, .libubsan, main_progress_node, RtOptions{ @@ -4314,6 +4349,7 @@ fn performAllTheWork( "ubsan_rt.zig", "ubsan_rt", .Obj, + .static, .libubsan, main_progress_node, RtOptions{ @@ -5390,6 +5426,7 @@ fn buildRt( root_source_name: []const u8, root_name: []const u8, output_mode: std.builtin.OutputMode, + link_mode: std.builtin.LinkMode, misc_task: MiscTask, prog_node: std.Progress.Node, options: RtOptions, @@ -5399,6 +5436,7 @@ fn buildRt( root_source_name, root_name, output_mode, + link_mode, misc_task, prog_node, options, @@ -5554,6 +5592,7 @@ fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void { "c.zig", "zigc", .Lib, + .static, .libzigc, prog_node, .{}, @@ -7231,6 +7270,7 @@ fn buildOutputFromZig( src_basename: []const u8, root_name: []const u8, output_mode: std.builtin.OutputMode, + link_mode: std.builtin.LinkMode, misc_task_tag: MiscTask, prog_node: std.Progress.Node, options: RtOptions, @@ -7251,7 +7291,7 @@ fn buildOutputFromZig( const config = try Config.resolve(.{ .output_mode = output_mode, - .link_mode = .static, + .link_mode = link_mode, .resolved_target = comp.root_mod.resolved_target, .is_test = false, .have_zcu = true, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index d774f14bf634b7ad34a5c3a1b4a46a34dcc94222..2ca7ec6de0fdb589c5f37a14de495aaf938758c3 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1715,6 +1715,21 @@ fn flushInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void { } assert(!coff.imports_count_dirty); + + // hack for stage2_x86_64 + coff + if (comp.compiler_rt_dyn_lib) |crt_file| { + const compiler_rt_sub_path = try std.fs.path.join(gpa, &.{ + std.fs.path.dirname(coff.base.emit.sub_path) orelse "", + std.fs.path.basename(crt_file.full_object_path.sub_path), + }); + defer gpa.free(compiler_rt_sub_path); + try crt_file.full_object_path.root_dir.handle.copyFile( + crt_file.full_object_path.sub_path, + coff.base.emit.root_dir.handle, + compiler_rt_sub_path, + .{}, + ); + } } pub fn getNavVAddr( -- 2.54.0