From 6e0904504155d3cba80955c108116170fd739aec Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Oct 2023 16:58:23 -0700 Subject: [PATCH 1/4] compiler_rt: no need to put it in a static library It's simpler to link against compiler_rt.o directly. --- src/Compilation.zig | 19 +------------------ src/link/Coff/lld.zig | 4 ++-- src/link/Elf.zig | 2 -- src/link/MachO/zld.zig | 8 ++++---- src/link/Wasm.zig | 20 ++++++-------------- 5 files changed, 13 insertions(+), 40 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index cd4c6ea11b68..4e43c7fccb21 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -112,7 +112,6 @@ unwind_tables: bool, test_evented_io: bool, debug_compiler_runtime_libs: bool, debug_compile_errors: bool, -job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, alloc_failure_occurred: bool = false, formatted_panics: bool = false, @@ -158,9 +157,6 @@ libssp_static_lib: ?CRTFile = null, /// Populated when we build the libc static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). libc_static_lib: ?CRTFile = null, -/// Populated when we build the libcompiler_rt static library. A Job to build this is indicated -/// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush(). -compiler_rt_lib: ?CRTFile = null, /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). compiler_rt_obj: ?CRTFile = null, @@ -1877,13 +1873,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { - if (is_exe_or_dyn_lib) { - log.debug("queuing a job to build compiler_rt_lib", .{}); - comp.job_queued_compiler_rt_lib = true; - } else if (options.output_mode != .Obj) { + if (is_exe_or_dyn_lib or options.output_mode != .Obj) { log.debug("queuing a job to build compiler_rt_obj", .{}); - // In this case we are making a static library, so we ask - // for a compiler-rt object to put in it. comp.job_queued_compiler_rt_obj = true; } } @@ -1938,9 +1929,6 @@ pub fn destroy(self: *Compilation) void { if (self.libcxxabi_static_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.compiler_rt_lib) |*crt_file| { - crt_file.deinit(gpa); - } if (self.compiler_rt_obj) |*crt_file| { crt_file.deinit(gpa); } @@ -3407,11 +3395,6 @@ pub fn performAllTheWork( break; } - if (comp.job_queued_compiler_rt_lib) { - comp.job_queued_compiler_rt_lib = false; - buildCompilerRtOneShot(comp, .Lib, &comp.compiler_rt_lib, main_progress_node); - } - if (comp.job_queued_compiler_rt_obj) { comp.job_queued_compiler_rt_obj = false; buildCompilerRtOneShot(comp, .Obj, &comp.compiler_rt_obj, main_progress_node); diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 7675aa49f563..67e075f3f6dd 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -491,8 +491,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } // MSVC compiler_rt is missing some stuff, so we build it unconditionally but // and rely on weak linkage to allow MSVC compiler_rt functions to override ours. - if (comp.compiler_rt_lib) |lib| { - try argv.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| { + try argv.append(obj.full_object_path); } } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index f75047424a6f..fb112d6ecf6d 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1257,7 +1257,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // to be after the shared libraries, so they are picked up from the shared // libraries, not libcompiler_rt. const compiler_rt_path: ?[]const u8 = blk: { - if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; break :blk null; }; @@ -1957,7 +1956,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const stack_size = self.base.options.stack_size_override orelse 16777216; const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; const compiler_rt_path: ?[]const u8 = blk: { - if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; break :blk null; }; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 19339eb19ac6..002b4662e6ad 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -186,8 +186,8 @@ pub fn linkWithZld( try positionals.append(.{ .path = p }); } - if (comp.compiler_rt_lib) |lib| { - try positionals.append(.{ .path = lib.full_object_path }); + if (comp.compiler_rt_obj) |obj| { + try positionals.append(.{ .path = obj.full_object_path }); } // libc++ dep @@ -301,8 +301,8 @@ pub fn linkWithZld( try argv.append(p); } - if (comp.compiler_rt_lib) |lib| { - try argv.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| { + try argv.append(obj.full_object_path); } if (options.link_libcpp) { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 2116cd7708c2..2faa247e9142 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3257,11 +3257,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l sub_prog_node.activate(); defer sub_prog_node.end(); - const is_obj = options.output_mode == .Obj; - const compiler_rt_path: ?[]const u8 = if (options.include_compiler_rt and !is_obj) - comp.compiler_rt_lib.?.full_object_path - else - null; + const compiler_rt_path: ?[]const u8 = if (comp.compiler_rt_obj) |o| o.full_object_path else null; const id_symlink_basename = "zld.id"; var man: Cache.Manifest = undefined; @@ -3376,8 +3372,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try positionals.append(c_object.status.success.object_path); } - if (comp.compiler_rt_lib) |lib| { - try positionals.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| { + try positionals.append(obj.full_object_path); } try wasm.parseInputFiles(positionals.items); @@ -3463,8 +3459,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try positionals.append(c_object.status.success.object_path); } - if (comp.compiler_rt_lib) |lib| { - try positionals.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| { + try positionals.append(obj.full_object_path); } try wasm.parseInputFiles(positionals.items); @@ -4325,11 +4321,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! defer sub_prog_node.end(); const is_obj = wasm.base.options.output_mode == .Obj; - - const compiler_rt_path: ?[]const u8 = if (wasm.base.options.include_compiler_rt and !is_obj) - comp.compiler_rt_lib.?.full_object_path - else - null; + const compiler_rt_path: ?[]const u8 = if (comp.compiler_rt_obj) |o| o.full_object_path else null; const target = wasm.base.options.target; From 8679c7a6070c3aa38bcf8e3fad47ac041cb93c90 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Oct 2023 17:24:28 -0700 Subject: [PATCH 2/4] Compilation: default to self-hosted backend when not using libllvm When not using libllvm, it means the compiler is not capable of producing an object file or executable, making the self-hosted backends be a better default. --- src/Compilation.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Compilation.zig b/src/Compilation.zig index 4e43c7fccb21..b10adad01be8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -841,6 +841,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { if (options.main_mod == null) break :blk false; + // If we cannot use LLVM libraries, then our own backends will be a + // better default since the LLVM backend can only produce bitcode + // and not an object file or executable. + if (!use_lib_llvm) + break :blk false; + // If LLVM does not support the target, then we can't use it. if (!target_util.hasLlvmSupport(options.target, options.target.ofmt)) break :blk false; From 33ef01d16b91a537696272ca286d6423abbdd632 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 10 Oct 2023 12:17:11 +0200 Subject: [PATCH 3/4] macho: test for presence of _abc as export in 16308 test --- test/link/macho/bugs/16308/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/link/macho/bugs/16308/build.zig b/test/link/macho/bugs/16308/build.zig index a6329074a0f2..3d7a884bd028 100644 --- a/test/link/macho/bugs/16308/build.zig +++ b/test/link/macho/bugs/16308/build.zig @@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void { const check = lib.checkObject(); check.checkInSymtab(); - check.checkNotPresent("external"); + check.checkNotPresent("external _abc"); test_step.dependOn(&check.step); } From da7e4fb31a05f2063eb829c4c383a44b38ed21e1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 10 Oct 2023 11:23:39 -0700 Subject: [PATCH 4/4] revert compiler_rt: no need to put it in a static library This mostly reverts 6e0904504155d3cba80955c108116170fd739aec however it leaves intact the linker supporting both obj and lib files, and the frontend choosing which one to create. --- src/Compilation.zig | 19 ++++++++++++++++++- src/link/Coff/lld.zig | 5 ++--- src/link/Elf.zig | 2 ++ src/link/MachO/zld.zig | 10 ++++------ src/link/Wasm.zig | 23 +++++++++++++++-------- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index b10adad01be8..25d0d63b1eee 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -112,6 +112,7 @@ unwind_tables: bool, test_evented_io: bool, debug_compiler_runtime_libs: bool, debug_compile_errors: bool, +job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, alloc_failure_occurred: bool = false, formatted_panics: bool = false, @@ -157,6 +158,9 @@ libssp_static_lib: ?CRTFile = null, /// Populated when we build the libc static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). libc_static_lib: ?CRTFile = null, +/// Populated when we build the libcompiler_rt static library. A Job to build this is indicated +/// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush(). +compiler_rt_lib: ?CRTFile = null, /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). compiler_rt_obj: ?CRTFile = null, @@ -1879,8 +1883,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { - if (is_exe_or_dyn_lib or options.output_mode != .Obj) { + if (is_exe_or_dyn_lib) { + log.debug("queuing a job to build compiler_rt_lib", .{}); + comp.job_queued_compiler_rt_lib = true; + } else if (options.output_mode != .Obj) { log.debug("queuing a job to build compiler_rt_obj", .{}); + // In this case we are making a static library, so we ask + // for a compiler-rt object to put in it. comp.job_queued_compiler_rt_obj = true; } } @@ -1935,6 +1944,9 @@ pub fn destroy(self: *Compilation) void { if (self.libcxxabi_static_lib) |*crt_file| { crt_file.deinit(gpa); } + if (self.compiler_rt_lib) |*crt_file| { + crt_file.deinit(gpa); + } if (self.compiler_rt_obj) |*crt_file| { crt_file.deinit(gpa); } @@ -3401,6 +3413,11 @@ pub fn performAllTheWork( break; } + if (comp.job_queued_compiler_rt_lib) { + comp.job_queued_compiler_rt_lib = false; + buildCompilerRtOneShot(comp, .Lib, &comp.compiler_rt_lib, main_progress_node); + } + if (comp.job_queued_compiler_rt_obj) { comp.job_queued_compiler_rt_obj = false; buildCompilerRtOneShot(comp, .Obj, &comp.compiler_rt_obj, main_progress_node); diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 67e075f3f6dd..cbefcbd91e73 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -491,9 +491,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } // MSVC compiler_rt is missing some stuff, so we build it unconditionally but // and rely on weak linkage to allow MSVC compiler_rt functions to override ours. - if (comp.compiler_rt_obj) |obj| { - try argv.append(obj.full_object_path); - } + if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path); + if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); } try argv.ensureUnusedCapacity(self.base.options.system_libs.count()); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index fb112d6ecf6d..f75047424a6f 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1257,6 +1257,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // to be after the shared libraries, so they are picked up from the shared // libraries, not libcompiler_rt. const compiler_rt_path: ?[]const u8 = blk: { + if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; break :blk null; }; @@ -1956,6 +1957,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const stack_size = self.base.options.stack_size_override orelse 16777216; const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; const compiler_rt_path: ?[]const u8 = blk: { + if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; break :blk null; }; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 002b4662e6ad..595c64436d17 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -186,9 +186,8 @@ pub fn linkWithZld( try positionals.append(.{ .path = p }); } - if (comp.compiler_rt_obj) |obj| { - try positionals.append(.{ .path = obj.full_object_path }); - } + if (comp.compiler_rt_lib) |lib| try positionals.append(.{ .path = lib.full_object_path }); + if (comp.compiler_rt_obj) |obj| try positionals.append(.{ .path = obj.full_object_path }); // libc++ dep if (options.link_libcpp) { @@ -301,9 +300,8 @@ pub fn linkWithZld( try argv.append(p); } - if (comp.compiler_rt_obj) |obj| { - try argv.append(obj.full_object_path); - } + if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path); if (options.link_libcpp) { try argv.append(comp.libcxxabi_static_lib.?.full_object_path); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 2faa247e9142..92e7bbe5ea90 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3257,7 +3257,12 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l sub_prog_node.activate(); defer sub_prog_node.end(); - const compiler_rt_path: ?[]const u8 = if (comp.compiler_rt_obj) |o| o.full_object_path else null; + const compiler_rt_path: ?[]const u8 = blk: { + if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; + if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; + break :blk null; + }; + const id_symlink_basename = "zld.id"; var man: Cache.Manifest = undefined; @@ -3372,9 +3377,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try positionals.append(c_object.status.success.object_path); } - if (comp.compiler_rt_obj) |obj| { - try positionals.append(obj.full_object_path); - } + if (comp.compiler_rt_lib) |lib| try positionals.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| try positionals.append(obj.full_object_path); try wasm.parseInputFiles(positionals.items); @@ -3459,9 +3463,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try positionals.append(c_object.status.success.object_path); } - if (comp.compiler_rt_obj) |obj| { - try positionals.append(obj.full_object_path); - } + if (comp.compiler_rt_lib) |lib| try positionals.append(lib.full_object_path); + if (comp.compiler_rt_obj) |obj| try positionals.append(obj.full_object_path); try wasm.parseInputFiles(positionals.items); @@ -4321,7 +4324,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! defer sub_prog_node.end(); const is_obj = wasm.base.options.output_mode == .Obj; - const compiler_rt_path: ?[]const u8 = if (comp.compiler_rt_obj) |o| o.full_object_path else null; + const compiler_rt_path: ?[]const u8 = blk: { + if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; + if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; + break :blk null; + }; const target = wasm.base.options.target;