authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-09 18:38:39-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-19 18:41:12-04:00
loged37a1a33c2576c00697643463a4720728e04023
tree65ce43d8a48cbda27c0cdf68f072a4812608ace5
parente92b12906338207975ee73aa99db63cb9240bf04

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.

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

lib/compiler_rt/common.zig+3-3
...@@ -16,10 +16,10 @@ else...@@ -16,10 +16,10 @@ else
16/// Determines the symbol's visibility to other objects.16/// Determines the symbol's visibility to other objects.
17/// For WebAssembly this allows the symbol to be resolved to other modules, but will not17/// For WebAssembly this allows the symbol to be resolved to other modules, but will not
18/// export it to the host runtime.18/// export it to the host runtime.
19pub const visibility: std.builtin.SymbolVisibility = if (linkage != .internal)19pub const visibility: std.builtin.SymbolVisibility = if (linkage == .internal or builtin.link_mode == .dynamic)
20 .hidden20 .default
21else21else
22 .default;22 .hidden;
2323
24pub const PreferredLoadStoreElement = element: {24pub const PreferredLoadStoreElement = element: {
25 if (std.simd.suggestVectorLength(u8)) |vec_size| {25 if (std.simd.suggestVectorLength(u8)) |vec_size| {
src/Compilation.zig+43-3
...@@ -224,6 +224,8 @@ compiler_rt_lib: ?CrtFile = null,...@@ -224,6 +224,8 @@ compiler_rt_lib: ?CrtFile = null,
224/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated224/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
225/// by setting `queued_jobs.compiler_rt_obj` and resolved before calling linker.flush().225/// by setting `queued_jobs.compiler_rt_obj` and resolved before calling linker.flush().
226compiler_rt_obj: ?CrtFile = null,226compiler_rt_obj: ?CrtFile = null,
227/// hack for stage2_x86_64 + coff
228compiler_rt_dyn_lib: ?CrtFile = null,
227/// Populated when we build the libfuzzer static library. A Job to build this229/// Populated when we build the libfuzzer static library. A Job to build this
228/// is indicated by setting `queued_jobs.fuzzer_lib` and resolved before230/// is indicated by setting `queued_jobs.fuzzer_lib` and resolved before
229/// calling linker.flush().231/// calling linker.flush().
...@@ -291,6 +293,8 @@ emit_llvm_bc: ?[]const u8,...@@ -291,6 +293,8 @@ emit_llvm_bc: ?[]const u8,
291emit_docs: ?[]const u8,293emit_docs: ?[]const u8,
292294
293const QueuedJobs = struct {295const QueuedJobs = struct {
296 /// hack for stage2_x86_64 + coff
297 compiler_rt_dyn_lib: bool = false,
294 compiler_rt_lib: bool = false,298 compiler_rt_lib: bool = false,
295 compiler_rt_obj: bool = false,299 compiler_rt_obj: bool = false,
296 ubsan_rt_lib: bool = false,300 ubsan_rt_lib: bool = false,
...@@ -1753,7 +1757,7 @@ fn addModuleTableToCacheHash(...@@ -1753,7 +1757,7 @@ fn addModuleTableToCacheHash(
1753 }1757 }
1754}1758}
17551759
1756const RtStrat = enum { none, lib, obj, zcu };1760const RtStrat = enum { none, lib, obj, zcu, dyn_lib };
17571761
1758pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compilation {1762pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compilation {
1759 const output_mode = options.config.output_mode;1763 const output_mode = options.config.output_mode;
...@@ -1816,7 +1820,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1816,7 +1820,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1816 if (options.skip_linker_dependencies) break :s .none;1820 if (options.skip_linker_dependencies) break :s .none;
1817 const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;1821 const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;
1818 if (!want) break :s .none;1822 if (!want) break :s .none;
1819 if (have_zcu and output_mode == .Obj) break :s .zcu;1823 if (have_zcu) {
1824 if (output_mode == .Obj) break :s .zcu;
1825 if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64)
1826 break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
1827 }
1820 if (is_exe_or_dyn_lib) break :s .lib;1828 if (is_exe_or_dyn_lib) break :s .lib;
1821 break :s .obj;1829 break :s .obj;
1822 };1830 };
...@@ -2441,6 +2449,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -2441,6 +2449,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
2441 // for a compiler-rt object to put in it.2449 // for a compiler-rt object to put in it.
2442 comp.queued_jobs.compiler_rt_obj = true;2450 comp.queued_jobs.compiler_rt_obj = true;
2443 comp.link_task_queue.pending_prelink_tasks += 1;2451 comp.link_task_queue.pending_prelink_tasks += 1;
2452 } else if (comp.compiler_rt_strat == .dyn_lib) {
2453 // hack for stage2_x86_64 + coff
2454 log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
2455 comp.queued_jobs.compiler_rt_dyn_lib = true;
2456 comp.link_task_queue.pending_prelink_tasks += 1;
2444 }2457 }
24452458
2446 if (comp.ubsan_rt_strat == .lib) {2459 if (comp.ubsan_rt_strat == .lib) {
...@@ -4254,6 +4267,7 @@ fn performAllTheWork(...@@ -4254,6 +4267,7 @@ fn performAllTheWork(
4254 "compiler_rt.zig",4267 "compiler_rt.zig",
4255 "compiler_rt",4268 "compiler_rt",
4256 .Lib,4269 .Lib,
4270 .static,
4257 .compiler_rt,4271 .compiler_rt,
4258 main_progress_node,4272 main_progress_node,
4259 RtOptions{4273 RtOptions{
...@@ -4270,6 +4284,7 @@ fn performAllTheWork(...@@ -4270,6 +4284,7 @@ fn performAllTheWork(
4270 "compiler_rt.zig",4284 "compiler_rt.zig",
4271 "compiler_rt",4285 "compiler_rt",
4272 .Obj,4286 .Obj,
4287 .static,
4273 .compiler_rt,4288 .compiler_rt,
4274 main_progress_node,4289 main_progress_node,
4275 RtOptions{4290 RtOptions{
...@@ -4280,12 +4295,31 @@ fn performAllTheWork(...@@ -4280,12 +4295,31 @@ fn performAllTheWork(
4280 });4295 });
4281 }4296 }
42824297
4298 // hack for stage2_x86_64 + coff
4299 if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {
4300 comp.link_task_wait_group.spawnManager(buildRt, .{
4301 comp,
4302 "compiler_rt.zig",
4303 "compiler_rt",
4304 .Lib,
4305 .dynamic,
4306 .compiler_rt,
4307 main_progress_node,
4308 RtOptions{
4309 .checks_valgrind = true,
4310 .allow_lto = false,
4311 },
4312 &comp.compiler_rt_dyn_lib,
4313 });
4314 }
4315
4283 if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {4316 if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
4284 comp.link_task_wait_group.spawnManager(buildRt, .{4317 comp.link_task_wait_group.spawnManager(buildRt, .{
4285 comp,4318 comp,
4286 "fuzzer.zig",4319 "fuzzer.zig",
4287 "fuzzer",4320 "fuzzer",
4288 .Lib,4321 .Lib,
4322 .static,
4289 .libfuzzer,4323 .libfuzzer,
4290 main_progress_node,4324 main_progress_node,
4291 RtOptions{},4325 RtOptions{},
...@@ -4299,6 +4333,7 @@ fn performAllTheWork(...@@ -4299,6 +4333,7 @@ fn performAllTheWork(
4299 "ubsan_rt.zig",4333 "ubsan_rt.zig",
4300 "ubsan_rt",4334 "ubsan_rt",
4301 .Lib,4335 .Lib,
4336 .static,
4302 .libubsan,4337 .libubsan,
4303 main_progress_node,4338 main_progress_node,
4304 RtOptions{4339 RtOptions{
...@@ -4314,6 +4349,7 @@ fn performAllTheWork(...@@ -4314,6 +4349,7 @@ fn performAllTheWork(
4314 "ubsan_rt.zig",4349 "ubsan_rt.zig",
4315 "ubsan_rt",4350 "ubsan_rt",
4316 .Obj,4351 .Obj,
4352 .static,
4317 .libubsan,4353 .libubsan,
4318 main_progress_node,4354 main_progress_node,
4319 RtOptions{4355 RtOptions{
...@@ -5390,6 +5426,7 @@ fn buildRt(...@@ -5390,6 +5426,7 @@ fn buildRt(
5390 root_source_name: []const u8,5426 root_source_name: []const u8,
5391 root_name: []const u8,5427 root_name: []const u8,
5392 output_mode: std.builtin.OutputMode,5428 output_mode: std.builtin.OutputMode,
5429 link_mode: std.builtin.LinkMode,
5393 misc_task: MiscTask,5430 misc_task: MiscTask,
5394 prog_node: std.Progress.Node,5431 prog_node: std.Progress.Node,
5395 options: RtOptions,5432 options: RtOptions,
...@@ -5399,6 +5436,7 @@ fn buildRt(...@@ -5399,6 +5436,7 @@ fn buildRt(
5399 root_source_name,5436 root_source_name,
5400 root_name,5437 root_name,
5401 output_mode,5438 output_mode,
5439 link_mode,
5402 misc_task,5440 misc_task,
5403 prog_node,5441 prog_node,
5404 options,5442 options,
...@@ -5554,6 +5592,7 @@ fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {...@@ -5554,6 +5592,7 @@ fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {
5554 "c.zig",5592 "c.zig",
5555 "zigc",5593 "zigc",
5556 .Lib,5594 .Lib,
5595 .static,
5557 .libzigc,5596 .libzigc,
5558 prog_node,5597 prog_node,
5559 .{},5598 .{},
...@@ -7231,6 +7270,7 @@ fn buildOutputFromZig(...@@ -7231,6 +7270,7 @@ fn buildOutputFromZig(
7231 src_basename: []const u8,7270 src_basename: []const u8,
7232 root_name: []const u8,7271 root_name: []const u8,
7233 output_mode: std.builtin.OutputMode,7272 output_mode: std.builtin.OutputMode,
7273 link_mode: std.builtin.LinkMode,
7234 misc_task_tag: MiscTask,7274 misc_task_tag: MiscTask,
7235 prog_node: std.Progress.Node,7275 prog_node: std.Progress.Node,
7236 options: RtOptions,7276 options: RtOptions,
...@@ -7251,7 +7291,7 @@ fn buildOutputFromZig(...@@ -7251,7 +7291,7 @@ fn buildOutputFromZig(
72517291
7252 const config = try Config.resolve(.{7292 const config = try Config.resolve(.{
7253 .output_mode = output_mode,7293 .output_mode = output_mode,
7254 .link_mode = .static,7294 .link_mode = link_mode,
7255 .resolved_target = comp.root_mod.resolved_target,7295 .resolved_target = comp.root_mod.resolved_target,
7256 .is_test = false,7296 .is_test = false,
7257 .have_zcu = true,7297 .have_zcu = true,
src/link/Coff.zig+15
...@@ -1715,6 +1715,21 @@ fn flushInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -1715,6 +1715,21 @@ fn flushInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
1715 }1715 }
17161716
1717 assert(!coff.imports_count_dirty);1717 assert(!coff.imports_count_dirty);
1718
1719 // hack for stage2_x86_64 + coff
1720 if (comp.compiler_rt_dyn_lib) |crt_file| {
1721 const compiler_rt_sub_path = try std.fs.path.join(gpa, &.{
1722 std.fs.path.dirname(coff.base.emit.sub_path) orelse "",
1723 std.fs.path.basename(crt_file.full_object_path.sub_path),
1724 });
1725 defer gpa.free(compiler_rt_sub_path);
1726 try crt_file.full_object_path.root_dir.handle.copyFile(
1727 crt_file.full_object_path.sub_path,
1728 coff.base.emit.root_dir.handle,
1729 compiler_rt_sub_path,
1730 .{},
1731 );
1732 }
1718}1733}
17191734
1720pub fn getNavVAddr(1735pub fn getNavVAddr(