authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-12 16:25:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:19-07:00
log0789e91eeb08495c5084067df2b2dab410197364
treebf5bdee3e86bf182abd95c98d6811a3f5beace99
parent3b6cb257dfbcfe7217cdb00819615d1cf1e6b89c

linkers: update references to "options" field


22 files changed, 511 insertions(+), 429 deletions(-)

src/Compilation.zig+50-41
...@@ -76,6 +76,7 @@ framework_dirs: []const []const u8,...@@ -76,6 +76,7 @@ framework_dirs: []const []const u8,
76system_libs: std.StringArrayHashMapUnmanaged(SystemLib),76system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
77version: ?std.SemanticVersion,77version: ?std.SemanticVersion,
78libc_installation: ?*const LibCInstallation,78libc_installation: ?*const LibCInstallation,
79skip_linker_dependencies: bool,
7980
80c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},81c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
81win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =82win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
...@@ -940,7 +941,7 @@ pub const InitOptions = struct {...@@ -940,7 +941,7 @@ pub const InitOptions = struct {
940 /// * getpid941 /// * getpid
941 /// * mman942 /// * mman
942 /// * signal943 /// * signal
943 wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{},944 wasi_emulated_libs: []const wasi_libc.CRTFile = &.{},
944 /// This means that if the output mode is an executable it will be a945 /// This means that if the output mode is an executable it will be a
945 /// Position Independent Executable. If the output mode is not an946 /// Position Independent Executable. If the output mode is not an
946 /// executable this field is ignored.947 /// executable this field is ignored.
...@@ -1238,7 +1239,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1238,7 +1239,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1238 const sysroot = options.sysroot orelse libc_dirs.sysroot;1239 const sysroot = options.sysroot orelse libc_dirs.sysroot;
12391240
1240 const include_compiler_rt = options.want_compiler_rt orelse1241 const include_compiler_rt = options.want_compiler_rt orelse
1241 (!options.skip_linker_dependencies and is_exe_or_dyn_lib);1242 (!comp.skip_linker_dependencies and is_exe_or_dyn_lib);
12421243
1243 if (include_compiler_rt and output_mode == .Obj) {1244 if (include_compiler_rt and output_mode == .Obj) {
1244 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`1245 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`
...@@ -1639,6 +1640,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1639,6 +1640,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1639 .objects = options.link_objects,1640 .objects = options.link_objects,
1640 .framework_dirs = options.framework_dirs,1641 .framework_dirs = options.framework_dirs,
1641 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,1642 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
1643 .skip_linker_dependencies = options.skip_linker_dependencies,
1642 };1644 };
16431645
1644 if (bin_file_emit) |emit| {1646 if (bin_file_emit) |emit| {
...@@ -1695,7 +1697,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1695,7 +1697,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1695 .soname = options.soname,1697 .soname = options.soname,
1696 .compatibility_version = options.compatibility_version,1698 .compatibility_version = options.compatibility_version,
1697 .dll_export_fns = dll_export_fns,1699 .dll_export_fns = dll_export_fns,
1698 .skip_linker_dependencies = options.skip_linker_dependencies,
1699 .parent_compilation_link_libc = options.parent_compilation_link_libc,1700 .parent_compilation_link_libc = options.parent_compilation_link_libc,
1700 .each_lib_rpath = each_lib_rpath,1701 .each_lib_rpath = each_lib_rpath,
1701 .build_id = build_id,1702 .build_id = build_id,
...@@ -1765,9 +1766,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1765,9 +1766,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1765 }1766 }
1766 }1767 }
17671768
1768 const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;1769 const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null;
17691770
1770 if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies and target.ofmt != .c) {1771 if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {
1771 if (target.isDarwin()) {1772 if (target.isDarwin()) {
1772 switch (target.abi) {1773 switch (target.abi) {
1773 .none,1774 .none,
...@@ -1808,27 +1809,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1808,27 +1809,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1808 .{ .musl_crt_file = .crt1_o },1809 .{ .musl_crt_file = .crt1_o },
1809 .{ .musl_crt_file = .scrt1_o },1810 .{ .musl_crt_file = .scrt1_o },
1810 .{ .musl_crt_file = .rcrt1_o },1811 .{ .musl_crt_file = .rcrt1_o },
1811 switch (comp.bin_file.options.link_mode) {1812 switch (comp.config.link_mode) {
1812 .Static => .{ .musl_crt_file = .libc_a },1813 .Static => .{ .musl_crt_file = .libc_a },
1813 .Dynamic => .{ .musl_crt_file = .libc_so },1814 .Dynamic => .{ .musl_crt_file = .libc_so },
1814 },1815 },
1815 });1816 });
1816 }1817 }
1817 if (comp.wantBuildWasiLibcFromSource()) {
1818 if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
18191818
1820 const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs;1819 if (comp.bin_file) |lf| {
1821 try comp.work_queue.ensureUnusedCapacity(wasi_emulated_libs.len + 2); // worst-case we need all components1820 if (lf.cast(link.File.Wasm)) |wasm| {
1822 for (wasi_emulated_libs) |crt_file| {1821 if (comp.wantBuildWasiLibcFromSource()) {
1823 comp.work_queue.writeItemAssumeCapacity(.{1822 if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
1824 .wasi_libc_crt_file = crt_file,1823
1825 });1824 // worst-case we need all components
1825 try comp.work_queue.ensureUnusedCapacity(wasm.wasi_emulated_libs.len + 2);
1826
1827 for (wasm.wasi_emulated_libs) |crt_file| {
1828 comp.work_queue.writeItemAssumeCapacity(.{
1829 .wasi_libc_crt_file = crt_file,
1830 });
1831 }
1832 comp.work_queue.writeAssumeCapacity(&[_]Job{
1833 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) },
1834 .{ .wasi_libc_crt_file = .libc_a },
1835 });
1836 }
1826 }1837 }
1827 comp.work_queue.writeAssumeCapacity(&[_]Job{
1828 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) },
1829 .{ .wasi_libc_crt_file = .libc_a },
1830 });
1831 }1838 }
1839
1832 if (comp.wantBuildMinGWFromSource()) {1840 if (comp.wantBuildMinGWFromSource()) {
1833 if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;1841 if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
18341842
...@@ -1863,27 +1871,29 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1863,27 +1871,29 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1863 if (comp.wantBuildLibUnwindFromSource()) {1871 if (comp.wantBuildLibUnwindFromSource()) {
1864 try comp.work_queue.writeItem(.{ .libunwind = {} });1872 try comp.work_queue.writeItem(.{ .libunwind = {} });
1865 }1873 }
1866 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.bin_file.options.link_libcpp) {1874 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
1867 try comp.work_queue.writeItem(.libcxx);1875 try comp.work_queue.writeItem(.libcxx);
1868 try comp.work_queue.writeItem(.libcxxabi);1876 try comp.work_queue.writeItem(.libcxxabi);
1869 }1877 }
1870 if (build_options.have_llvm and comp.bin_file.options.tsan) {1878 if (build_options.have_llvm and comp.config.any_sanitize_thread) {
1871 try comp.work_queue.writeItem(.libtsan);1879 try comp.work_queue.writeItem(.libtsan);
1872 }1880 }
18731881
1874 if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) {1882 if (comp.bin_file) |lf| {
1875 // LLD might drop some symbols as unused during LTO and GCing, therefore,1883 if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) {
1876 // we force mark them for resolution here.1884 // LLD might drop some symbols as unused during LTO and GCing, therefore,
1885 // we force mark them for resolution here.
18771886
1878 const tls_index_sym = switch (comp.getTarget().cpu.arch) {1887 const tls_index_sym = switch (comp.getTarget().cpu.arch) {
1879 .x86 => "__tls_index",1888 .x86 => "__tls_index",
1880 else => "_tls_index",1889 else => "_tls_index",
1881 };1890 };
18821891
1883 try comp.bin_file.options.force_undefined_symbols.put(comp.gpa, tls_index_sym, {});1892 try lf.force_undefined_symbols.put(comp.gpa, tls_index_sym, {});
1893 }
1884 }1894 }
18851895
1886 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {1896 if (comp.include_compiler_rt and capable_of_building_compiler_rt) {
1887 if (is_exe_or_dyn_lib) {1897 if (is_exe_or_dyn_lib) {
1888 log.debug("queuing a job to build compiler_rt_lib", .{});1898 log.debug("queuing a job to build compiler_rt_lib", .{});
1889 comp.job_queued_compiler_rt_lib = true;1899 comp.job_queued_compiler_rt_lib = true;
...@@ -1895,8 +1905,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1895,8 +1905,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1895 }1905 }
1896 }1906 }
18971907
1898 if (!comp.bin_file.options.skip_linker_dependencies and is_exe_or_dyn_lib and1908 if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and
1899 !comp.bin_file.options.link_libc and capable_of_building_zig_libc)1909 !comp.config.link_libc and capable_of_building_zig_libc)
1900 {1910 {
1901 try comp.work_queue.writeItem(.{ .zig_libc = {} });1911 try comp.work_queue.writeItem(.{ .zig_libc = {} });
1902 }1912 }
...@@ -2425,7 +2435,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2425,7 +2435,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2425 man.hash.add(comp.test_evented_io);2435 man.hash.add(comp.test_evented_io);
2426 man.hash.addOptionalBytes(comp.test_filter);2436 man.hash.addOptionalBytes(comp.test_filter);
2427 man.hash.addOptionalBytes(comp.test_name_prefix);2437 man.hash.addOptionalBytes(comp.test_name_prefix);
2428 man.hash.add(comp.bin_file.options.skip_linker_dependencies);2438 man.hash.add(comp.skip_linker_dependencies);
2429 man.hash.add(comp.formatted_panics);2439 man.hash.add(comp.formatted_panics);
2430 man.hash.add(mod.emit_h != null);2440 man.hash.add(mod.emit_h != null);
2431 man.hash.add(mod.error_limit);2441 man.hash.add(mod.error_limit);
...@@ -2477,7 +2487,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2477,7 +2487,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2477 man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());2487 man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());
2478 man.hash.add(comp.bin_file.options.each_lib_rpath);2488 man.hash.add(comp.bin_file.options.each_lib_rpath);
2479 man.hash.add(comp.bin_file.build_id);2489 man.hash.add(comp.bin_file.build_id);
2480 man.hash.add(comp.bin_file.options.skip_linker_dependencies);2490 man.hash.add(comp.skip_linker_dependencies);
2481 man.hash.add(comp.bin_file.options.z_nodelete);2491 man.hash.add(comp.bin_file.options.z_nodelete);
2482 man.hash.add(comp.bin_file.options.z_notext);2492 man.hash.add(comp.bin_file.options.z_notext);
2483 man.hash.add(comp.bin_file.options.z_defs);2493 man.hash.add(comp.bin_file.options.z_defs);
...@@ -2489,7 +2499,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2489,7 +2499,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2489 man.hash.add(comp.bin_file.options.z_max_page_size orelse 0);2499 man.hash.add(comp.bin_file.options.z_max_page_size orelse 0);
2490 man.hash.add(comp.bin_file.options.hash_style);2500 man.hash.add(comp.bin_file.options.hash_style);
2491 man.hash.add(comp.bin_file.options.compress_debug_sections);2501 man.hash.add(comp.bin_file.options.compress_debug_sections);
2492 man.hash.add(comp.bin_file.options.include_compiler_rt);2502 man.hash.add(comp.include_compiler_rt);
2493 man.hash.add(comp.bin_file.options.sort_section);2503 man.hash.add(comp.bin_file.options.sort_section);
2494 if (comp.config.link_libc) {2504 if (comp.config.link_libc) {
2495 man.hash.add(comp.bin_file.options.libc_installation != null);2505 man.hash.add(comp.bin_file.options.libc_installation != null);
...@@ -3836,7 +3846,7 @@ pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {...@@ -3836,7 +3846,7 @@ pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {
3836 // Also nothing that applies only to compiling .zig code.3846 // Also nothing that applies only to compiling .zig code.
3837 man.hash.add(comp.sanitize_c);3847 man.hash.add(comp.sanitize_c);
3838 man.hash.addListOfBytes(comp.clang_argv);3848 man.hash.addListOfBytes(comp.clang_argv);
3839 man.hash.add(comp.bin_file.options.link_libcpp);3849 man.hash.add(comp.config.link_libcpp);
38403850
3841 // When libc_installation is null it means that Zig generated this dir list3851 // When libc_installation is null it means that Zig generated this dir list
3842 // based on the zig library directory alone. The zig lib directory file3852 // based on the zig library directory alone. The zig lib directory file
...@@ -4909,7 +4919,7 @@ pub fn addCCArgs(...@@ -4909,7 +4919,7 @@ pub fn addCCArgs(
4909 try argv.append("-fno-builtin");4919 try argv.append("-fno-builtin");
4910 }4920 }
49114921
4912 if (comp.bin_file.options.link_libcpp) {4922 if (comp.config.link_libcpp) {
4913 const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{4923 const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{
4914 comp.zig_lib_directory.path.?, "libcxx", "include",4924 comp.zig_lib_directory.path.?, "libcxx", "include",
4915 });4925 });
...@@ -4954,7 +4964,7 @@ pub fn addCCArgs(...@@ -4954,7 +4964,7 @@ pub fn addCCArgs(
4954 try argv.append(libunwind_include_path);4964 try argv.append(libunwind_include_path);
4955 }4965 }
49564966
4957 if (comp.bin_file.options.link_libc and target.isGnuLibC()) {4967 if (comp.config.link_libc and target.isGnuLibC()) {
4958 const target_version = target.os.version_range.linux.glibc;4968 const target_version = target.os.version_range.linux.glibc;
4959 const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{4969 const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
4960 target_version.minor,4970 target_version.minor,
...@@ -5944,7 +5954,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {...@@ -5944,7 +5954,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
5944 .Lib => comp.bin_file.options.link_mode == .Dynamic,5954 .Lib => comp.bin_file.options.link_mode == .Dynamic,
5945 .Exe => true,5955 .Exe => true,
5946 };5956 };
5947 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and5957 return comp.config.link_libc and is_exe_or_dyn_lib and
5948 comp.bin_file.options.libc_installation == null and5958 comp.bin_file.options.libc_installation == null and
5949 comp.bin_file.options.target.ofmt != .c;5959 comp.bin_file.options.target.ofmt != .c;
5950}5960}
...@@ -6164,6 +6174,7 @@ fn buildOutputFromZig(...@@ -6164,6 +6174,7 @@ fn buildOutputFromZig(
6164 .have_zcu = true,6174 .have_zcu = true,
6165 .emit_bin = true,6175 .emit_bin = true,
6166 .root_optimize_mode = comp.compilerRtOptMode(),6176 .root_optimize_mode = comp.compilerRtOptMode(),
6177 .link_libc = comp.config.link_libc,
6167 });6178 });
61686179
6169 const root_mod = Package.Module.create(.{6180 const root_mod = Package.Module.create(.{
...@@ -6224,7 +6235,6 @@ fn buildOutputFromZig(...@@ -6224,7 +6235,6 @@ fn buildOutputFromZig(
6224 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,6235 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
6225 .clang_passthrough_mode = comp.clang_passthrough_mode,6236 .clang_passthrough_mode = comp.clang_passthrough_mode,
6226 .skip_linker_dependencies = true,6237 .skip_linker_dependencies = true,
6227 .link_libc = comp.bin_file.options.link_libc,
6228 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,6238 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
6229 });6239 });
6230 defer sub_compilation.destroy();6240 defer sub_compilation.destroy();
...@@ -6305,7 +6315,6 @@ pub fn build_crt_file(...@@ -6305,7 +6315,6 @@ pub fn build_crt_file(
6305 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,6315 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
6306 .clang_passthrough_mode = comp.clang_passthrough_mode,6316 .clang_passthrough_mode = comp.clang_passthrough_mode,
6307 .skip_linker_dependencies = true,6317 .skip_linker_dependencies = true,
6308 .link_libc = comp.bin_file.options.link_libc,
6309 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,6318 .want_structured_cfg = comp.bin_file.options.want_structured_cfg,
6310 });6319 });
6311 defer sub_compilation.destroy();6320 defer sub_compilation.destroy();
...@@ -6327,7 +6336,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -6327,7 +6336,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
6327 // This can happen when the user uses `build-exe foo.obj -lkernel32` and6336 // This can happen when the user uses `build-exe foo.obj -lkernel32` and
6328 // then when we create a sub-Compilation for zig libc, it also tries to6337 // then when we create a sub-Compilation for zig libc, it also tries to
6329 // build kernel32.lib.6338 // build kernel32.lib.
6330 if (comp.bin_file.options.skip_linker_dependencies) return;6339 if (comp.skip_linker_dependencies) return;
63316340
6332 // This happens when an `extern "foo"` function is referenced.6341 // This happens when an `extern "foo"` function is referenced.
6333 // If we haven't seen this library yet and we're targeting Windows, we need6342 // If we haven't seen this library yet and we're targeting Windows, we need
src/Compilation/Config.zig+1-1
...@@ -335,7 +335,7 @@ pub fn resolve(options: Options) !Config {...@@ -335,7 +335,7 @@ pub fn resolve(options: Options) !Config {
335 break :b .Static;335 break :b .Static;
336 };336 };
337337
338 const import_memory = options.import_memory orelse false;338 const import_memory = options.import_memory orelse (options.output_mode == .Obj);
339 const export_memory = b: {339 const export_memory = b: {
340 if (link_mode == .Dynamic) {340 if (link_mode == .Dynamic) {
341 if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible;341 if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible;
src/Sema.zig+15-12
...@@ -5742,7 +5742,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5742,7 +5742,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5742 const msg = try sema.errMsg(&child_block, src, "C import failed", .{});5742 const msg = try sema.errMsg(&child_block, src, "C import failed", .{});
5743 errdefer msg.destroy(gpa);5743 errdefer msg.destroy(gpa);
57445744
5745 if (!comp.bin_file.options.link_libc)5745 if (!comp.config.link_libc)
5746 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});5746 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});
57475747
5748 const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index);5748 const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index);
...@@ -9058,7 +9058,7 @@ fn resolveGenericBody(...@@ -9058,7 +9058,7 @@ fn resolveGenericBody(
90589058
9059/// Given a library name, examines if the library name should end up in9059/// Given a library name, examines if the library name should end up in
9060/// `link.File.Options.system_libs` table (for example, libc is always9060/// `link.File.Options.system_libs` table (for example, libc is always
9061/// specified via dedicated flag `link.File.Options.link_libc` instead),9061/// specified via dedicated flag `link_libc` instead),
9062/// and puts it there if it doesn't exist.9062/// and puts it there if it doesn't exist.
9063/// It also dupes the library name which can then be saved as part of the9063/// It also dupes the library name which can then be saved as part of the
9064/// respective `Decl` (either `ExternFn` or `Var`).9064/// respective `Decl` (either `ExternFn` or `Var`).
...@@ -9076,7 +9076,7 @@ fn handleExternLibName(...@@ -9076,7 +9076,7 @@ fn handleExternLibName(
9076 const target = mod.getTarget();9076 const target = mod.getTarget();
9077 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});9077 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
9078 if (target.is_libc_lib_name(lib_name)) {9078 if (target.is_libc_lib_name(lib_name)) {
9079 if (!comp.bin_file.options.link_libc) {9079 if (!comp.config.link_libc) {
9080 return sema.fail(9080 return sema.fail(
9081 block,9081 block,
9082 src_loc,9082 src_loc,
...@@ -9087,18 +9087,21 @@ fn handleExternLibName(...@@ -9087,18 +9087,21 @@ fn handleExternLibName(
9087 break :blk;9087 break :blk;
9088 }9088 }
9089 if (target.is_libcpp_lib_name(lib_name)) {9089 if (target.is_libcpp_lib_name(lib_name)) {
9090 if (!comp.bin_file.options.link_libcpp) {9090 if (!comp.config.link_libcpp) return sema.fail(
9091 return sema.fail(9091 block,
9092 block,9092 src_loc,
9093 src_loc,9093 "dependency on libc++ must be explicitly specified in the build command",
9094 "dependency on libc++ must be explicitly specified in the build command",9094 .{},
9095 .{},9095 );
9096 );
9097 }
9098 break :blk;9096 break :blk;
9099 }9097 }
9100 if (mem.eql(u8, lib_name, "unwind")) {9098 if (mem.eql(u8, lib_name, "unwind")) {
9101 comp.bin_file.options.link_libunwind = true;9099 if (!comp.config.link_libunwind) return sema.fail(
9100 block,
9101 src_loc,
9102 "dependency on libunwind must be explicitly specified in the build command",
9103 .{},
9104 );
9102 break :blk;9105 break :blk;
9103 }9106 }
9104 if (!target.isWasm() and !comp.bin_file.options.pic) {9107 if (!target.isWasm() and !comp.bin_file.options.pic) {
src/codegen/llvm.zig+1-3
...@@ -3083,9 +3083,7 @@ pub const Object = struct {...@@ -3083,9 +3083,7 @@ pub const Object = struct {
3083 if (comp.unwind_tables) {3083 if (comp.unwind_tables) {
3084 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);3084 try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
3085 }3085 }
3086 if (comp.bin_file.options.skip_linker_dependencies or3086 if (comp.skip_linker_dependencies or comp.bin_file.options.no_builtin) {
3087 comp.bin_file.options.no_builtin)
3088 {
3089 // The intent here is for compiler-rt and libc functions to not generate3087 // The intent here is for compiler-rt and libc functions to not generate
3090 // infinite recursion. For example, if we are compiling the memcpy function,3088 // infinite recursion. For example, if we are compiling the memcpy function,
3091 // and llvm detects that the body is equivalent to memcpy, it may replace the3089 // and llvm detects that the body is equivalent to memcpy, it may replace the
src/libtsan.zig+1-1
...@@ -119,7 +119,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void {...@@ -119,7 +119,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void {
119 });119 });
120 }120 }
121121
122 const to_c_or_not_to_c_sources = if (comp.bin_file.options.link_libc)122 const to_c_or_not_to_c_sources = if (comp.config.link_libc)
123 &sanitizer_libcdep_sources123 &sanitizer_libcdep_sources
124 else124 else
125 &sanitizer_nolibc_sources;125 &sanitizer_nolibc_sources;
src/link.zig+1-2
...@@ -133,7 +133,6 @@ pub const File = struct {...@@ -133,7 +133,6 @@ pub const File = struct {
133 export_symbol_names: []const []const u8,133 export_symbol_names: []const []const u8,
134 global_base: ?u64,134 global_base: ?u64,
135 dll_export_fns: bool,135 dll_export_fns: bool,
136 skip_linker_dependencies: bool,
137 parent_compilation_link_libc: bool,136 parent_compilation_link_libc: bool,
138 each_lib_rpath: bool,137 each_lib_rpath: bool,
139 build_id: std.zig.BuildId,138 build_id: std.zig.BuildId,
...@@ -1099,7 +1098,7 @@ pub const File = struct {...@@ -1099,7 +1098,7 @@ pub const File = struct {
1099 }1098 }
11001099
1101 pub fn isStatic(self: File) bool {1100 pub fn isStatic(self: File) bool {
1102 return self.base.comp.config.link_mode == .Static;1101 return self.comp.config.link_mode == .Static;
1103 }1102 }
11041103
1105 pub fn isObject(self: File) bool {1104 pub fn isObject(self: File) bool {
src/link/Coff/lld.zig+47-47
...@@ -48,7 +48,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -48,7 +48,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
48 const is_lib = self.base.comp.config.output_mode == .Lib;48 const is_lib = self.base.comp.config.output_mode == .Lib;
49 const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib;49 const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib;
50 const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe;50 const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe;
51 const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib;51 const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
52 const target = self.base.comp.root_mod.resolved_target.result;52 const target = self.base.comp.root_mod.resolved_target.result;
53 const optimize_mode = self.base.comp.root_mod.optimize_mode;53 const optimize_mode = self.base.comp.root_mod.optimize_mode;
5454
...@@ -56,17 +56,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -56,17 +56,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
56 const id_symlink_basename = "lld.id";56 const id_symlink_basename = "lld.id";
5757
58 var man: Cache.Manifest = undefined;58 var man: Cache.Manifest = undefined;
59 defer if (!self.base.options.disable_lld_caching) man.deinit();59 defer if (!self.base.disable_lld_caching) man.deinit();
6060
61 var digest: [Cache.hex_digest_len]u8 = undefined;61 var digest: [Cache.hex_digest_len]u8 = undefined;
6262
63 if (!self.base.options.disable_lld_caching) {63 if (!self.base.disable_lld_caching) {
64 man = comp.cache_parent.obtain();64 man = comp.cache_parent.obtain();
65 self.base.releaseLock();65 self.base.releaseLock();
6666
67 comptime assert(Compilation.link_hash_implementation_version == 10);67 comptime assert(Compilation.link_hash_implementation_version == 10);
6868
69 for (self.base.options.objects) |obj| {69 for (comp.objects) |obj| {
70 _ = try man.addFile(obj.path, null);70 _ = try man.addFile(obj.path, null);
71 man.hash.add(obj.must_link);71 man.hash.add(obj.must_link);
72 }72 }
...@@ -79,12 +79,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -79,12 +79,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
79 }79 }
80 }80 }
81 try man.addOptionalFile(module_obj_path);81 try man.addOptionalFile(module_obj_path);
82 man.hash.addOptionalBytes(self.base.options.entry);82 man.hash.addOptionalBytes(comp.config.entry);
83 man.hash.add(self.base.stack_size);83 man.hash.add(self.base.stack_size);
84 man.hash.addOptional(self.image_base);84 man.hash.addOptional(self.image_base);
85 man.hash.addListOfBytes(self.base.options.lib_dirs);85 man.hash.addListOfBytes(self.lib_dirs);
86 man.hash.add(self.base.options.skip_linker_dependencies);86 man.hash.add(comp.skip_linker_dependencies);
87 if (self.base.options.link_libc) {87 if (comp.config.link_libc) {
88 man.hash.add(self.base.comp.libc_installation != null);88 man.hash.add(self.base.comp.libc_installation != null);
89 if (self.base.comp.libc_installation) |libc_installation| {89 if (self.base.comp.libc_installation) |libc_installation| {
90 man.hash.addBytes(libc_installation.crt_dir.?);90 man.hash.addBytes(libc_installation.crt_dir.?);
...@@ -95,18 +95,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -95,18 +95,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
95 }95 }
96 }96 }
97 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);97 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
98 man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());98 man.hash.addListOfBytes(self.base.force_undefined_symbols.keys());
99 man.hash.addOptional(self.base.options.subsystem);99 man.hash.addOptional(self.subsystem);
100 man.hash.add(self.base.options.is_test);100 man.hash.add(comp.config.is_test);
101 man.hash.add(self.base.options.tsaware);101 man.hash.add(self.tsaware);
102 man.hash.add(self.base.options.nxcompat);102 man.hash.add(self.nxcompat);
103 man.hash.add(self.base.options.dynamicbase);103 man.hash.add(self.dynamicbase);
104 man.hash.addOptional(self.base.allow_shlib_undefined);104 man.hash.addOptional(self.base.allow_shlib_undefined);
105 // strip does not need to go into the linker hash because it is part of the hash namespace105 // strip does not need to go into the linker hash because it is part of the hash namespace
106 man.hash.addOptional(self.base.options.major_subsystem_version);106 man.hash.addOptional(self.major_subsystem_version);
107 man.hash.addOptional(self.base.options.minor_subsystem_version);107 man.hash.addOptional(self.minor_subsystem_version);
108 man.hash.addOptional(self.base.options.version);108 man.hash.addOptional(comp.version);
109 try man.addOptionalFile(self.base.options.module_definition_file);109 try man.addOptionalFile(self.module_definition_file);
110110
111 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.111 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
112 _ = try man.hit();112 _ = try man.hit();
...@@ -141,8 +141,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -141,8 +141,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
141 // here. TODO: think carefully about how we can avoid this redundant operation when doing141 // here. TODO: think carefully about how we can avoid this redundant operation when doing
142 // build-obj. See also the corresponding TODO in linkAsArchive.142 // build-obj. See also the corresponding TODO in linkAsArchive.
143 const the_object_path = blk: {143 const the_object_path = blk: {
144 if (self.base.options.objects.len != 0)144 if (comp.objects.len != 0)
145 break :blk self.base.options.objects[0].path;145 break :blk comp.objects[0].path;
146146
147 if (comp.c_object_table.count() != 0)147 if (comp.c_object_table.count() != 0)
148 break :blk comp.c_object_table.keys()[0].status.success.object_path;148 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -171,21 +171,21 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -171,21 +171,21 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
171171
172 try argv.append("-ERRORLIMIT:0");172 try argv.append("-ERRORLIMIT:0");
173 try argv.append("-NOLOGO");173 try argv.append("-NOLOGO");
174 if (!self.base.options.strip) {174 if (self.base.debug_format != .strip) {
175 try argv.append("-DEBUG");175 try argv.append("-DEBUG");
176176
177 const out_ext = std.fs.path.extension(full_out_path);177 const out_ext = std.fs.path.extension(full_out_path);
178 const out_pdb = self.base.options.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{178 const out_pdb = self.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
179 full_out_path[0 .. full_out_path.len - out_ext.len],179 full_out_path[0 .. full_out_path.len - out_ext.len],
180 });180 });
181181
182 try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));182 try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
183 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));183 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));
184 }184 }
185 if (self.base.options.version) |version| {185 if (comp.version) |version| {
186 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));186 try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
187 }187 }
188 if (self.base.options.lto) {188 if (comp.config.lto) {
189 switch (optimize_mode) {189 switch (optimize_mode) {
190 .Debug => {},190 .Debug => {},
191 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),191 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
...@@ -209,7 +209,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -209,7 +209,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
209 }209 }
210 }210 }
211211
212 for (self.base.options.force_undefined_symbols.keys()) |symbol| {212 for (self.base.force_undefined_symbols.keys()) |symbol| {
213 try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));213 try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
214 }214 }
215215
...@@ -217,17 +217,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -217,17 +217,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
217 try argv.append("-DLL");217 try argv.append("-DLL");
218 }218 }
219219
220 if (self.base.options.entry) |entry| {220 if (comp.config.entry) |entry| {
221 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry}));221 try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry}));
222 }222 }
223223
224 if (self.base.options.tsaware) {224 if (self.tsaware) {
225 try argv.append("-tsaware");225 try argv.append("-tsaware");
226 }226 }
227 if (self.base.options.nxcompat) {227 if (self.nxcompat) {
228 try argv.append("-nxcompat");228 try argv.append("-nxcompat");
229 }229 }
230 if (!self.base.options.dynamicbase) {230 if (!self.dynamicbase) {
231 try argv.append("-dynamicbase:NO");231 try argv.append("-dynamicbase:NO");
232 }232 }
233 if (self.base.allow_shlib_undefined) {233 if (self.base.allow_shlib_undefined) {
...@@ -236,12 +236,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -236,12 +236,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
236236
237 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));237 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
238238
239 if (self.base.options.implib_emit) |emit| {239 if (self.implib_emit) |emit| {
240 const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});240 const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
241 try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));241 try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
242 }242 }
243243
244 if (self.base.options.link_libc) {244 if (comp.config.link_libc) {
245 if (self.base.comp.libc_installation) |libc_installation| {245 if (self.base.comp.libc_installation) |libc_installation| {
246 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));246 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
247247
...@@ -252,12 +252,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -252,12 +252,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
252 }252 }
253 }253 }
254254
255 for (self.base.options.lib_dirs) |lib_dir| {255 for (self.lib_dirs) |lib_dir| {
256 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));256 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
257 }257 }
258258
259 try argv.ensureUnusedCapacity(self.base.options.objects.len);259 try argv.ensureUnusedCapacity(comp.objects.len);
260 for (self.base.options.objects) |obj| {260 for (comp.objects) |obj| {
261 if (obj.must_link) {261 if (obj.must_link) {
262 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{s}", .{obj.path}));262 argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{s}", .{obj.path}));
263 } else {263 } else {
...@@ -279,18 +279,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -279,18 +279,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
279 try argv.append(p);279 try argv.append(p);
280 }280 }
281281
282 if (self.base.options.module_definition_file) |def| {282 if (self.module_definition_file) |def| {
283 try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));283 try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
284 }284 }
285285
286 const resolved_subsystem: ?std.Target.SubSystem = blk: {286 const resolved_subsystem: ?std.Target.SubSystem = blk: {
287 if (self.base.options.subsystem) |explicit| break :blk explicit;287 if (self.subsystem) |explicit| break :blk explicit;
288 switch (target.os.tag) {288 switch (target.os.tag) {
289 .windows => {289 .windows => {
290 if (self.base.comp.module) |module| {290 if (self.base.comp.module) |module| {
291 if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)291 if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
292 break :blk null;292 break :blk null;
293 if (module.stage1_flags.have_c_main or self.base.options.is_test or293 if (module.stage1_flags.have_c_main or comp.config.is_test or
294 module.stage1_flags.have_winmain_crt_startup or294 module.stage1_flags.have_winmain_crt_startup or
295 module.stage1_flags.have_wwinmain_crt_startup)295 module.stage1_flags.have_wwinmain_crt_startup)
296 {296 {
...@@ -310,8 +310,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -310,8 +310,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
310 const mode: Mode = mode: {310 const mode: Mode = mode: {
311 if (resolved_subsystem) |subsystem| {311 if (resolved_subsystem) |subsystem| {
312 const subsystem_suffix = ss: {312 const subsystem_suffix = ss: {
313 if (self.base.options.major_subsystem_version) |major| {313 if (self.major_subsystem_version) |major| {
314 if (self.base.options.minor_subsystem_version) |minor| {314 if (self.minor_subsystem_version) |minor| {
315 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });315 break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
316 } else {316 } else {
317 break :ss try allocPrint(arena, ",{d}", .{major});317 break :ss try allocPrint(arena, ",{d}", .{major});
...@@ -447,7 +447,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -447,7 +447,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
447 }447 }
448 } else {448 } else {
449 try argv.append("-NODEFAULTLIB");449 try argv.append("-NODEFAULTLIB");
450 if (!is_lib and self.base.options.entry == null) {450 if (!is_lib and comp.config.entry == null) {
451 if (self.base.comp.module) |module| {451 if (self.base.comp.module) |module| {
452 if (module.stage1_flags.have_winmain_crt_startup) {452 if (module.stage1_flags.have_winmain_crt_startup) {
453 try argv.append("-ENTRY:WinMainCRTStartup");453 try argv.append("-ENTRY:WinMainCRTStartup");
...@@ -463,18 +463,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -463,18 +463,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
463 }463 }
464464
465 // libc++ dep465 // libc++ dep
466 if (self.base.options.link_libcpp) {466 if (comp.config.link_libcpp) {
467 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);467 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
468 try argv.append(comp.libcxx_static_lib.?.full_object_path);468 try argv.append(comp.libcxx_static_lib.?.full_object_path);
469 }469 }
470470
471 // libunwind dep471 // libunwind dep
472 if (self.base.options.link_libunwind) {472 if (comp.config.link_libunwind) {
473 try argv.append(comp.libunwind_static_lib.?.full_object_path);473 try argv.append(comp.libunwind_static_lib.?.full_object_path);
474 }474 }
475475
476 if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) {476 if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
477 if (!self.base.options.link_libc) {477 if (!comp.config.link_libc) {
478 if (comp.libc_static_lib) |lib| {478 if (comp.libc_static_lib) |lib| {
479 try argv.append(lib.full_object_path);479 try argv.append(lib.full_object_path);
480 }480 }
...@@ -492,13 +492,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -492,13 +492,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
492 argv.appendAssumeCapacity(crt_file.full_object_path);492 argv.appendAssumeCapacity(crt_file.full_object_path);
493 continue;493 continue;
494 }494 }
495 if (try findLib(arena, lib_basename, self.base.options.lib_dirs)) |full_path| {495 if (try findLib(arena, lib_basename, self.lib_dirs)) |full_path| {
496 argv.appendAssumeCapacity(full_path);496 argv.appendAssumeCapacity(full_path);
497 continue;497 continue;
498 }498 }
499 if (target.abi.isGnu()) {499 if (target.abi.isGnu()) {
500 const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});500 const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
501 if (try findLib(arena, fallback_name, self.base.options.lib_dirs)) |full_path| {501 if (try findLib(arena, fallback_name, self.lib_dirs)) |full_path| {
502 argv.appendAssumeCapacity(full_path);502 argv.appendAssumeCapacity(full_path);
503 continue;503 continue;
504 }504 }
...@@ -582,7 +582,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -582,7 +582,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
582 }582 }
583 }583 }
584584
585 if (!self.base.options.disable_lld_caching) {585 if (!self.base.disable_lld_caching) {
586 // Update the file with the digest. If it fails we can continue; it only586 // Update the file with the digest. If it fails we can continue; it only
587 // means that the next invocation will have an unnecessary cache miss.587 // means that the next invocation will have an unnecessary cache miss.
588 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {588 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
src/link/Dwarf.zig+6-4
...@@ -1022,16 +1022,18 @@ const min_nop_size = 2;...@@ -1022,16 +1022,18 @@ const min_nop_size = 2;
1022/// actual_capacity + (actual_capacity / ideal_factor)1022/// actual_capacity + (actual_capacity / ideal_factor)
1023const ideal_factor = 3;1023const ideal_factor = 3;
10241024
1025pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {1025pub fn init(lf: *File, format: Format) Dwarf {
1026 const target = &bin_file.options.target;1026 const comp = lf.comp;
1027 const gpa = comp.gpa;
1028 const target = comp.root_mod.resolved_target.result;
1027 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {1029 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
1028 0...32 => .p32,1030 0...32 => .p32,
1029 33...64 => .p64,1031 33...64 => .p64,
1030 else => unreachable,1032 else => unreachable,
1031 };1033 };
1032 return .{1034 return .{
1033 .allocator = allocator,1035 .allocator = gpa,
1034 .bin_file = bin_file,1036 .bin_file = lf,
1035 .format = format,1037 .format = format,
1036 .ptr_width = ptr_width,1038 .ptr_width = ptr_width,
1037 .dbg_line_header = switch (target.cpu.arch) {1039 .dbg_line_header = switch (target.cpu.arch) {
src/link/Elf.zig+146-149
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1base: link.File,1base: link.File,
2image_base: u64,2image_base: u64,
3rdynamic: bool,
34
4ptr_width: PtrWidth,5ptr_width: PtrWidth,
56
...@@ -358,19 +359,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -358,19 +359,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
358 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },359 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
359 .function_sections = options.function_sections,360 .function_sections = options.function_sections,
360 .data_sections = options.data_sections,361 .data_sections = options.data_sections,
361
362 .image_base = b: {
363 if (is_dyn_lib) break :b 0;
364 if (output_mode == .Exe and comp.config.pie) return 0;
365 return options.image_base orelse switch (ptr_width) {
366 .p32 => 0x1000,
367 .p64 => 0x1000000,
368 };
369 },
370 },362 },
371 .ptr_width = ptr_width,363 .ptr_width = ptr_width,
372 .page_size = page_size,364 .page_size = page_size,
373 .default_sym_version = default_sym_version,365 .default_sym_version = default_sym_version,
366
367 .image_base = b: {
368 if (is_dyn_lib) break :b 0;
369 if (output_mode == .Exe and comp.config.pie) break :b 0;
370 break :b options.image_base orelse switch (ptr_width) {
371 .p32 => 0x1000,
372 .p64 => 0x1000000,
373 };
374 },
375
376 .rdynamic = options.rdynamic,
374 };377 };
375 if (use_llvm and comp.config.have_zcu) {378 if (use_llvm and comp.config.have_zcu) {
376 self.llvm_object = try LlvmObject.create(arena, options);379 self.llvm_object = try LlvmObject.create(arena, options);
...@@ -1006,7 +1009,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1006,7 +1009,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1006 break :blk path;1009 break :blk path;
1007 }1010 }
1008 } else null;1011 } else null;
1009 const gc_sections = self.base.gc_sections;
10101012
1011 // --verbose-link1013 // --verbose-link
1012 if (self.base.comp.verbose_link) try self.dumpArgv(comp);1014 if (self.base.comp.verbose_link) try self.dumpArgv(comp);
...@@ -1047,14 +1049,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1047,14 +1049,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1047 var rpath_table = std.StringArrayHashMap(void).init(gpa);1049 var rpath_table = std.StringArrayHashMap(void).init(gpa);
1048 defer rpath_table.deinit();1050 defer rpath_table.deinit();
10491051
1050 for (self.base.options.rpath_list) |rpath| {1052 for (self.base.rpath_list) |rpath| {
1051 _ = try rpath_table.put(rpath, {});1053 _ = try rpath_table.put(rpath, {});
1052 }1054 }
10531055
1054 if (self.base.options.each_lib_rpath) {1056 if (self.each_lib_rpath) {
1055 var test_path = std.ArrayList(u8).init(gpa);1057 var test_path = std.ArrayList(u8).init(gpa);
1056 defer test_path.deinit();1058 defer test_path.deinit();
1057 for (self.base.options.lib_dirs) |lib_dir_path| {1059 for (self.lib_dirs) |lib_dir_path| {
1058 for (self.base.comp.system_libs.keys()) |link_lib| {1060 for (self.base.comp.system_libs.keys()) |link_lib| {
1059 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))1061 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
1060 continue;1062 continue;
...@@ -1076,9 +1078,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1076,9 +1078,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1076 }1078 }
10771079
1078 // libc1080 // libc
1079 if (!self.base.options.skip_linker_dependencies and1081 if (!comp.skip_linker_dependencies and !comp.config.link_libc) {
1080 !self.base.options.link_libc)
1081 {
1082 if (comp.libc_static_lib) |lib| {1082 if (comp.libc_static_lib) |lib| {
1083 try positionals.append(.{ .path = lib.full_object_path });1083 try positionals.append(.{ .path = lib.full_object_path });
1084 }1084 }
...@@ -1263,10 +1263,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1263,10 +1263,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1263 self.entry_index = if (entry) |name| self.globalByName(name) else null;1263 self.entry_index = if (entry) |name| self.globalByName(name) else null;
1264 }1264 }
12651265
1266 if (gc_sections) {1266 if (self.base.gc_sections) {
1267 try gc.gcAtoms(self);1267 try gc.gcAtoms(self);
12681268
1269 if (self.base.options.print_gc_sections) {1269 if (self.base.print_gc_sections) {
1270 try gc.dumpPrunedAtoms(self);1270 try gc.dumpPrunedAtoms(self);
1271 }1271 }
1272 }1272 }
...@@ -1347,13 +1347,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1347,13 +1347,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1347}1347}
13481348
1349pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {1349pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
1350 const gpa = self.base.comp.gpa;1350 const gpa = comp.gpa;
13511351
1352 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);1352 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
1353 defer positionals.deinit();1353 defer positionals.deinit();
13541354
1355 try positionals.ensureUnusedCapacity(self.base.options.objects.len);1355 try positionals.ensureUnusedCapacity(comp.objects.len);
1356 positionals.appendSliceAssumeCapacity(self.base.options.objects);1356 positionals.appendSliceAssumeCapacity(comp.objects);
13571357
1358 // This is a set of object files emitted by clang in a single `build-exe` invocation.1358 // This is a set of object files emitted by clang in a single `build-exe` invocation.
1359 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up1359 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
...@@ -1495,8 +1495,8 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)...@@ -1495,8 +1495,8 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)
14951495
1496 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);1496 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
1497 defer positionals.deinit();1497 defer positionals.deinit();
1498 try positionals.ensureUnusedCapacity(self.base.options.objects.len);1498 try positionals.ensureUnusedCapacity(comp.objects.len);
1499 positionals.appendSliceAssumeCapacity(self.base.options.objects);1499 positionals.appendSliceAssumeCapacity(comp.objects);
15001500
1501 // This is a set of object files emitted by clang in a single `build-exe` invocation.1501 // This is a set of object files emitted by clang in a single `build-exe` invocation.
1502 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up1502 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
...@@ -1606,7 +1606,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1606,7 +1606,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1606 try argv.append(full_out_path);1606 try argv.append(full_out_path);
16071607
1608 if (self.base.isRelocatable()) {1608 if (self.base.isRelocatable()) {
1609 for (self.base.options.objects) |obj| {1609 for (comp.objects) |obj| {
1610 try argv.append(obj.path);1610 try argv.append(obj.path);
1611 }1611 }
16121612
...@@ -1626,28 +1626,28 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1626,28 +1626,28 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1626 }1626 }
16271627
1628 if (self.base.isDynLib()) {1628 if (self.base.isDynLib()) {
1629 if (self.base.options.soname) |name| {1629 if (self.soname) |name| {
1630 try argv.append("-soname");1630 try argv.append("-soname");
1631 try argv.append(name);1631 try argv.append(name);
1632 }1632 }
1633 }1633 }
16341634
1635 if (self.base.options.entry) |entry| {1635 if (comp.config.entry) |entry| {
1636 try argv.append("--entry");1636 try argv.append("--entry");
1637 try argv.append(entry);1637 try argv.append(entry);
1638 }1638 }
16391639
1640 for (self.base.options.rpath_list) |rpath| {1640 for (self.base.rpath_list) |rpath| {
1641 try argv.append("-rpath");1641 try argv.append("-rpath");
1642 try argv.append(rpath);1642 try argv.append(rpath);
1643 }1643 }
16441644
1645 if (self.base.options.each_lib_rpath) {1645 if (self.each_lib_rpath) {
1646 for (self.base.options.lib_dirs) |lib_dir_path| {1646 for (self.lib_dirs) |lib_dir_path| {
1647 try argv.append("-rpath");1647 try argv.append("-rpath");
1648 try argv.append(lib_dir_path);1648 try argv.append(lib_dir_path);
1649 }1649 }
1650 for (self.base.options.objects) |obj| {1650 for (comp.objects) |obj| {
1651 if (Compilation.classifyFileExt(obj.path) == .shared_library) {1651 if (Compilation.classifyFileExt(obj.path) == .shared_library) {
1652 const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;1652 const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
1653 if (obj.loption) continue;1653 if (obj.loption) continue;
...@@ -1669,29 +1669,29 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1669,29 +1669,29 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1669 try argv.append("--gc-sections");1669 try argv.append("--gc-sections");
1670 }1670 }
16711671
1672 if (self.base.options.print_gc_sections) {1672 if (self.base.print_gc_sections) {
1673 try argv.append("--print-gc-sections");1673 try argv.append("--print-gc-sections");
1674 }1674 }
16751675
1676 if (self.base.options.eh_frame_hdr) {1676 if (self.eh_frame_hdr) {
1677 try argv.append("--eh-frame-hdr");1677 try argv.append("--eh-frame-hdr");
1678 }1678 }
16791679
1680 if (self.base.options.rdynamic) {1680 if (self.rdynamic) {
1681 try argv.append("--export-dynamic");1681 try argv.append("--export-dynamic");
1682 }1682 }
16831683
1684 if (self.base.options.z_notext) {1684 if (self.z_notext) {
1685 try argv.append("-z");1685 try argv.append("-z");
1686 try argv.append("notext");1686 try argv.append("notext");
1687 }1687 }
16881688
1689 if (self.base.options.z_nocopyreloc) {1689 if (self.z_nocopyreloc) {
1690 try argv.append("-z");1690 try argv.append("-z");
1691 try argv.append("nocopyreloc");1691 try argv.append("nocopyreloc");
1692 }1692 }
16931693
1694 if (self.base.options.z_now) {1694 if (self.z_now) {
1695 try argv.append("-z");1695 try argv.append("-z");
1696 try argv.append("now");1696 try argv.append("now");
1697 }1697 }
...@@ -1702,11 +1702,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1702,11 +1702,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1702 try argv.append("-shared");1702 try argv.append("-shared");
1703 }1703 }
17041704
1705 if (self.base.options.pie and self.base.isExe()) {1705 if (comp.config.pie and self.base.isExe()) {
1706 try argv.append("-pie");1706 try argv.append("-pie");
1707 }1707 }
17081708
1709 if (self.base.options.strip) {1709 if (self.base.debug_format == .strip) {
1710 try argv.append("-s");1710 try argv.append("-s");
1711 }1711 }
17121712
...@@ -1715,12 +1715,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1715,12 +1715,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1715 if (csu.crti) |v| try argv.append(v);1715 if (csu.crti) |v| try argv.append(v);
1716 if (csu.crtbegin) |v| try argv.append(v);1716 if (csu.crtbegin) |v| try argv.append(v);
17171717
1718 for (self.base.options.lib_dirs) |lib_dir| {1718 for (self.lib_dirs) |lib_dir| {
1719 try argv.append("-L");1719 try argv.append("-L");
1720 try argv.append(lib_dir);1720 try argv.append(lib_dir);
1721 }1721 }
17221722
1723 if (self.base.options.link_libc) {1723 if (comp.config.link_libc) {
1724 if (self.base.comp.libc_installation) |libc_installation| {1724 if (self.base.comp.libc_installation) |libc_installation| {
1725 try argv.append("-L");1725 try argv.append("-L");
1726 try argv.append(libc_installation.crt_dir.?);1726 try argv.append(libc_installation.crt_dir.?);
...@@ -1728,7 +1728,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1728,7 +1728,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1728 }1728 }
17291729
1730 var whole_archive = false;1730 var whole_archive = false;
1731 for (self.base.options.objects) |obj| {1731 for (comp.objects) |obj| {
1732 if (obj.must_link and !whole_archive) {1732 if (obj.must_link and !whole_archive) {
1733 try argv.append("-whole-archive");1733 try argv.append("-whole-archive");
1734 whole_archive = true;1734 whole_archive = true;
...@@ -1756,15 +1756,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1756,15 +1756,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1756 try argv.append(p);1756 try argv.append(p);
1757 }1757 }
17581758
1759 // TSAN1759 if (comp.config.any_sanitize_thread) {
1760 if (self.base.options.tsan) {
1761 try argv.append(comp.tsan_static_lib.?.full_object_path);1760 try argv.append(comp.tsan_static_lib.?.full_object_path);
1762 }1761 }
17631762
1764 // libc1763 // libc
1765 if (!self.base.options.skip_linker_dependencies and1764 if (!comp.skip_linker_dependencies and !comp.config.link_libc) {
1766 !self.base.options.link_libc)
1767 {
1768 if (comp.libc_static_lib) |lib| {1765 if (comp.libc_static_lib) |lib| {
1769 try argv.append(lib.full_object_path);1766 try argv.append(lib.full_object_path);
1770 }1767 }
...@@ -1799,18 +1796,18 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1799,18 +1796,18 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1799 }1796 }
18001797
1801 // libc++ dep1798 // libc++ dep
1802 if (self.base.options.link_libcpp) {1799 if (comp.config.link_libcpp) {
1803 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);1800 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
1804 try argv.append(comp.libcxx_static_lib.?.full_object_path);1801 try argv.append(comp.libcxx_static_lib.?.full_object_path);
1805 }1802 }
18061803
1807 // libunwind dep1804 // libunwind dep
1808 if (self.base.options.link_libunwind) {1805 if (comp.config.link_libunwind) {
1809 try argv.append(comp.libunwind_static_lib.?.full_object_path);1806 try argv.append(comp.libunwind_static_lib.?.full_object_path);
1810 }1807 }
18111808
1812 // libc dep1809 // libc dep
1813 if (self.base.options.link_libc) {1810 if (comp.config.link_libc) {
1814 if (self.base.comp.libc_installation != null) {1811 if (self.base.comp.libc_installation != null) {
1815 const needs_grouping = link_mode == .Static;1812 const needs_grouping = link_mode == .Static;
1816 if (needs_grouping) try argv.append("--start-group");1813 if (needs_grouping) try argv.append("--start-group");
...@@ -1963,8 +1960,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1963,8 +1960,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
1963 defer script.deinit(gpa);1960 defer script.deinit(gpa);
1964 try script.parse(data, self);1961 try script.parse(data, self);
19651962
1966 const lib_dirs = self.base.options.lib_dirs;
1967
1968 var arena_allocator = std.heap.ArenaAllocator.init(gpa);1963 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
1969 defer arena_allocator.deinit();1964 defer arena_allocator.deinit();
1970 const arena = arena_allocator.allocator();1965 const arena = arena_allocator.allocator();
...@@ -1981,7 +1976,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1981,7 +1976,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
19811976
1982 // TODO I think technically we should re-use the mechanism used by the frontend here.1977 // TODO I think technically we should re-use the mechanism used by the frontend here.
1983 // Maybe we should hoist search-strategy all the way here?1978 // Maybe we should hoist search-strategy all the way here?
1984 for (lib_dirs) |lib_dir| {1979 for (self.lib_dirs) |lib_dir| {
1985 if (!self.isStatic()) {1980 if (!self.isStatic()) {
1986 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic))1981 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic))
1987 break :success;1982 break :success;
...@@ -1998,7 +1993,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1998,7 +1993,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
1998 } else |_| {}1993 } else |_| {}
19991994
2000 try checked_paths.append(try gpa.dupe(u8, scr_obj.path));1995 try checked_paths.append(try gpa.dupe(u8, scr_obj.path));
2001 for (lib_dirs) |lib_dir| {1996 for (self.lib_dirs) |lib_dir| {
2002 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, scr_obj.path, null))1997 if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, scr_obj.path, null))
2003 break :success;1998 break :success;
2004 }1999 }
...@@ -2338,7 +2333,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2338,7 +2333,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2338 const link_mode = self.base.comp.config.link_mode;2333 const link_mode = self.base.comp.config.link_mode;
2339 const is_dyn_lib = link_mode == .Dynamic and is_lib;2334 const is_dyn_lib = link_mode == .Dynamic and is_lib;
2340 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;2335 const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
2341 const have_dynamic_linker = self.base.options.link_libc and2336 const have_dynamic_linker = comp.config.link_libc and
2342 link_mode == .Dynamic and is_exe_or_dyn_lib;2337 link_mode == .Dynamic and is_exe_or_dyn_lib;
2343 const target = self.base.comp.root_mod.resolved_target.result;2338 const target = self.base.comp.root_mod.resolved_target.result;
2344 const compiler_rt_path: ?[]const u8 = blk: {2339 const compiler_rt_path: ?[]const u8 = blk: {
...@@ -2358,11 +2353,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2358,11 +2353,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2358 const id_symlink_basename = "lld.id";2353 const id_symlink_basename = "lld.id";
23592354
2360 var man: Cache.Manifest = undefined;2355 var man: Cache.Manifest = undefined;
2361 defer if (!self.base.options.disable_lld_caching) man.deinit();2356 defer if (!self.base.disable_lld_caching) man.deinit();
23622357
2363 var digest: [Cache.hex_digest_len]u8 = undefined;2358 var digest: [Cache.hex_digest_len]u8 = undefined;
23642359
2365 if (!self.base.options.disable_lld_caching) {2360 if (!self.base.disable_lld_caching) {
2366 man = comp.cache_parent.obtain();2361 man = comp.cache_parent.obtain();
23672362
2368 // We are about to obtain this lock, so here we give other processes a chance first.2363 // We are about to obtain this lock, so here we give other processes a chance first.
...@@ -2370,9 +2365,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2370,9 +2365,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
23702365
2371 comptime assert(Compilation.link_hash_implementation_version == 10);2366 comptime assert(Compilation.link_hash_implementation_version == 10);
23722367
2373 try man.addOptionalFile(self.base.options.linker_script);2368 try man.addOptionalFile(self.linker_script);
2374 try man.addOptionalFile(self.base.options.version_script);2369 try man.addOptionalFile(self.version_script);
2375 for (self.base.options.objects) |obj| {2370 for (comp.objects) |obj| {
2376 _ = try man.addFile(obj.path, null);2371 _ = try man.addFile(obj.path, null);
2377 man.hash.add(obj.must_link);2372 man.hash.add(obj.must_link);
2378 man.hash.add(obj.loption);2373 man.hash.add(obj.loption);
...@@ -2385,34 +2380,34 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2385,34 +2380,34 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
23852380
2386 // We can skip hashing libc and libc++ components that we are in charge of building from Zig2381 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
2387 // installation sources because they are always a product of the compiler version + target information.2382 // installation sources because they are always a product of the compiler version + target information.
2388 man.hash.addOptionalBytes(self.base.options.entry);2383 man.hash.addOptionalBytes(comp.config.entry);
2389 man.hash.addOptional(self.image_base);2384 man.hash.addOptional(self.image_base);
2390 man.hash.add(self.base.gc_sections);2385 man.hash.add(self.base.gc_sections);
2391 man.hash.addOptional(self.base.options.sort_section);2386 man.hash.addOptional(self.sort_section);
2392 man.hash.add(self.base.options.eh_frame_hdr);2387 man.hash.add(self.eh_frame_hdr);
2393 man.hash.add(self.base.options.emit_relocs);2388 man.hash.add(self.emit_relocs);
2394 man.hash.add(self.base.options.rdynamic);2389 man.hash.add(self.rdynamic);
2395 man.hash.addListOfBytes(self.base.options.lib_dirs);2390 man.hash.addListOfBytes(self.lib_dirs);
2396 man.hash.addListOfBytes(self.base.options.rpath_list);2391 man.hash.addListOfBytes(self.base.rpath_list);
2397 man.hash.add(self.base.options.each_lib_rpath);2392 man.hash.add(self.each_lib_rpath);
2398 if (output_mode == .Exe) {2393 if (output_mode == .Exe) {
2399 man.hash.add(self.base.stack_size);2394 man.hash.add(self.base.stack_size);
2400 man.hash.add(self.base.build_id);2395 man.hash.add(self.base.build_id);
2401 }2396 }
2402 man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys());2397 man.hash.addListOfBytes(self.symbol_wrap_set.keys());
2403 man.hash.add(self.base.options.skip_linker_dependencies);2398 man.hash.add(comp.skip_linker_dependencies);
2404 man.hash.add(self.base.options.z_nodelete);2399 man.hash.add(self.z_nodelete);
2405 man.hash.add(self.base.options.z_notext);2400 man.hash.add(self.z_notext);
2406 man.hash.add(self.base.options.z_defs);2401 man.hash.add(self.z_defs);
2407 man.hash.add(self.base.options.z_origin);2402 man.hash.add(self.z_origin);
2408 man.hash.add(self.base.options.z_nocopyreloc);2403 man.hash.add(self.z_nocopyreloc);
2409 man.hash.add(self.base.options.z_now);2404 man.hash.add(self.z_now);
2410 man.hash.add(self.base.options.z_relro);2405 man.hash.add(self.z_relro);
2411 man.hash.add(self.base.options.z_common_page_size orelse 0);2406 man.hash.add(self.z_common_page_size orelse 0);
2412 man.hash.add(self.base.options.z_max_page_size orelse 0);2407 man.hash.add(self.z_max_page_size orelse 0);
2413 man.hash.add(self.base.options.hash_style);2408 man.hash.add(self.hash_style);
2414 // strip does not need to go into the linker hash because it is part of the hash namespace2409 // strip does not need to go into the linker hash because it is part of the hash namespace
2415 if (self.base.options.link_libc) {2410 if (comp.config.link_libc) {
2416 man.hash.add(self.base.comp.libc_installation != null);2411 man.hash.add(self.base.comp.libc_installation != null);
2417 if (self.base.comp.libc_installation) |libc_installation| {2412 if (self.base.comp.libc_installation) |libc_installation| {
2418 man.hash.addBytes(libc_installation.crt_dir.?);2413 man.hash.addBytes(libc_installation.crt_dir.?);
...@@ -2421,16 +2416,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2421,16 +2416,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2421 man.hash.addOptionalBytes(target.dynamic_linker.get());2416 man.hash.addOptionalBytes(target.dynamic_linker.get());
2422 }2417 }
2423 }2418 }
2424 man.hash.addOptionalBytes(self.base.options.soname);2419 man.hash.addOptionalBytes(self.soname);
2425 man.hash.addOptional(self.base.options.version);2420 man.hash.addOptional(comp.version);
2426 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);2421 try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
2427 man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());2422 man.hash.addListOfBytes(self.base.force_undefined_symbols.keys());
2428 man.hash.add(self.base.allow_shlib_undefined);2423 man.hash.add(self.base.allow_shlib_undefined);
2429 man.hash.add(self.base.options.bind_global_refs_locally);2424 man.hash.add(self.bind_global_refs_locally);
2430 man.hash.add(self.base.options.compress_debug_sections);2425 man.hash.add(self.compress_debug_sections);
2431 man.hash.add(self.base.options.tsan);2426 man.hash.add(comp.config.any_sanitize_thread);
2432 man.hash.addOptionalBytes(self.base.options.sysroot);2427 man.hash.addOptionalBytes(self.sysroot);
2433 man.hash.add(self.base.options.linker_optimization);2428 man.hash.add(self.optimization);
24342429
2435 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.2430 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
2436 _ = try man.hit();2431 _ = try man.hit();
...@@ -2466,14 +2461,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2466,14 +2461,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2466 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails2461 // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
2467 // before even generating the relocatable.2462 // before even generating the relocatable.
2468 if (output_mode == .Obj and2463 if (output_mode == .Obj and
2469 (self.base.options.lto or target.isBpfFreestanding()))2464 (comp.config.lto or target.isBpfFreestanding()))
2470 {2465 {
2471 // In this case we must do a simple file copy2466 // In this case we must do a simple file copy
2472 // here. TODO: think carefully about how we can avoid this redundant operation when doing2467 // here. TODO: think carefully about how we can avoid this redundant operation when doing
2473 // build-obj. See also the corresponding TODO in linkAsArchive.2468 // build-obj. See also the corresponding TODO in linkAsArchive.
2474 const the_object_path = blk: {2469 const the_object_path = blk: {
2475 if (self.base.options.objects.len != 0)2470 if (comp.objects.len != 0)
2476 break :blk self.base.options.objects[0].path;2471 break :blk comp.objects[0].path;
24772472
2478 if (comp.c_object_table.count() != 0)2473 if (comp.c_object_table.count() != 0)
2479 break :blk comp.c_object_table.keys()[0].status.success.object_path;2474 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -2505,32 +2500,32 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2505,32 +2500,32 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
25052500
2506 try argv.append("--error-limit=0");2501 try argv.append("--error-limit=0");
25072502
2508 if (self.base.options.sysroot) |sysroot| {2503 if (self.sysroot) |sysroot| {
2509 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));2504 try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
2510 }2505 }
25112506
2512 if (self.base.options.lto) {2507 if (comp.config.lto) {
2513 switch (self.base.options.optimize_mode) {2508 switch (comp.root_mod.optimize_mode) {
2514 .Debug => {},2509 .Debug => {},
2515 .ReleaseSmall => try argv.append("--lto-O2"),2510 .ReleaseSmall => try argv.append("--lto-O2"),
2516 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),2511 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
2517 }2512 }
2518 }2513 }
2519 try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{2514 try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{
2520 self.base.options.linker_optimization,2515 self.optimization,
2521 }));2516 }));
25222517
2523 if (self.base.options.entry) |entry| {2518 if (comp.config.entry) |entry| {
2524 try argv.append("--entry");2519 try argv.append("--entry");
2525 try argv.append(entry);2520 try argv.append(entry);
2526 }2521 }
25272522
2528 for (self.base.options.force_undefined_symbols.keys()) |sym| {2523 for (self.base.force_undefined_symbols.keys()) |sym| {
2529 try argv.append("-u");2524 try argv.append("-u");
2530 try argv.append(sym);2525 try argv.append(sym);
2531 }2526 }
25322527
2533 switch (self.base.options.hash_style) {2528 switch (self.hash_style) {
2534 .gnu => try argv.append("--hash-style=gnu"),2529 .gnu => try argv.append("--hash-style=gnu"),
2535 .sysv => try argv.append("--hash-style=sysv"),2530 .sysv => try argv.append("--hash-style=sysv"),
2536 .both => {}, // this is the default2531 .both => {}, // this is the default
...@@ -2559,12 +2554,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2559,12 +2554,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
25592554
2560 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));2555 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
25612556
2562 if (self.base.options.linker_script) |linker_script| {2557 if (self.linker_script) |linker_script| {
2563 try argv.append("-T");2558 try argv.append("-T");
2564 try argv.append(linker_script);2559 try argv.append(linker_script);
2565 }2560 }
25662561
2567 if (self.base.options.sort_section) |how| {2562 if (self.sort_section) |how| {
2568 const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});2563 const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
2569 try argv.append(arg);2564 try argv.append(arg);
2570 }2565 }
...@@ -2573,67 +2568,67 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2573,67 +2568,67 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2573 try argv.append("--gc-sections");2568 try argv.append("--gc-sections");
2574 }2569 }
25752570
2576 if (self.base.options.print_gc_sections) {2571 if (self.base.print_gc_sections) {
2577 try argv.append("--print-gc-sections");2572 try argv.append("--print-gc-sections");
2578 }2573 }
25792574
2580 if (self.base.options.print_icf_sections) {2575 if (self.print_icf_sections) {
2581 try argv.append("--print-icf-sections");2576 try argv.append("--print-icf-sections");
2582 }2577 }
25832578
2584 if (self.base.options.print_map) {2579 if (self.print_map) {
2585 try argv.append("--print-map");2580 try argv.append("--print-map");
2586 }2581 }
25872582
2588 if (self.base.options.eh_frame_hdr) {2583 if (self.eh_frame_hdr) {
2589 try argv.append("--eh-frame-hdr");2584 try argv.append("--eh-frame-hdr");
2590 }2585 }
25912586
2592 if (self.base.options.emit_relocs) {2587 if (self.emit_relocs) {
2593 try argv.append("--emit-relocs");2588 try argv.append("--emit-relocs");
2594 }2589 }
25952590
2596 if (self.base.options.rdynamic) {2591 if (self.rdynamic) {
2597 try argv.append("--export-dynamic");2592 try argv.append("--export-dynamic");
2598 }2593 }
25992594
2600 if (self.base.options.strip) {2595 if (self.base.debug_format == .strip) {
2601 try argv.append("-s");2596 try argv.append("-s");
2602 }2597 }
26032598
2604 if (self.base.options.z_nodelete) {2599 if (self.z_nodelete) {
2605 try argv.append("-z");2600 try argv.append("-z");
2606 try argv.append("nodelete");2601 try argv.append("nodelete");
2607 }2602 }
2608 if (self.base.options.z_notext) {2603 if (self.z_notext) {
2609 try argv.append("-z");2604 try argv.append("-z");
2610 try argv.append("notext");2605 try argv.append("notext");
2611 }2606 }
2612 if (self.base.options.z_defs) {2607 if (self.z_defs) {
2613 try argv.append("-z");2608 try argv.append("-z");
2614 try argv.append("defs");2609 try argv.append("defs");
2615 }2610 }
2616 if (self.base.options.z_origin) {2611 if (self.z_origin) {
2617 try argv.append("-z");2612 try argv.append("-z");
2618 try argv.append("origin");2613 try argv.append("origin");
2619 }2614 }
2620 if (self.base.options.z_nocopyreloc) {2615 if (self.z_nocopyreloc) {
2621 try argv.append("-z");2616 try argv.append("-z");
2622 try argv.append("nocopyreloc");2617 try argv.append("nocopyreloc");
2623 }2618 }
2624 if (self.base.options.z_now) {2619 if (self.z_now) {
2625 // LLD defaults to -zlazy2620 // LLD defaults to -zlazy
2626 try argv.append("-znow");2621 try argv.append("-znow");
2627 }2622 }
2628 if (!self.base.options.z_relro) {2623 if (!self.z_relro) {
2629 // LLD defaults to -zrelro2624 // LLD defaults to -zrelro
2630 try argv.append("-znorelro");2625 try argv.append("-znorelro");
2631 }2626 }
2632 if (self.base.options.z_common_page_size) |size| {2627 if (self.z_common_page_size) |size| {
2633 try argv.append("-z");2628 try argv.append("-z");
2634 try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));2629 try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
2635 }2630 }
2636 if (self.base.options.z_max_page_size) |size| {2631 if (self.z_max_page_size) |size| {
2637 try argv.append("-z");2632 try argv.append("-z");
2638 try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));2633 try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
2639 }2634 }
...@@ -2658,7 +2653,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2658,7 +2653,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2658 try argv.append("-shared");2653 try argv.append("-shared");
2659 }2654 }
26602655
2661 if (self.base.options.pie and output_mode == .Exe) {2656 if (comp.config.pie and output_mode == .Exe) {
2662 try argv.append("-pie");2657 try argv.append("-pie");
2663 }2658 }
26642659
...@@ -2683,20 +2678,20 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2683,20 +2678,20 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2683 // rpaths2678 // rpaths
2684 var rpath_table = std.StringHashMap(void).init(gpa);2679 var rpath_table = std.StringHashMap(void).init(gpa);
2685 defer rpath_table.deinit();2680 defer rpath_table.deinit();
2686 for (self.base.options.rpath_list) |rpath| {2681 for (self.base.rpath_list) |rpath| {
2687 if ((try rpath_table.fetchPut(rpath, {})) == null) {2682 if ((try rpath_table.fetchPut(rpath, {})) == null) {
2688 try argv.append("-rpath");2683 try argv.append("-rpath");
2689 try argv.append(rpath);2684 try argv.append(rpath);
2690 }2685 }
2691 }2686 }
26922687
2693 for (self.base.options.symbol_wrap_set.keys()) |symbol_name| {2688 for (self.symbol_wrap_set.keys()) |symbol_name| {
2694 try argv.appendSlice(&.{ "-wrap", symbol_name });2689 try argv.appendSlice(&.{ "-wrap", symbol_name });
2695 }2690 }
26962691
2697 if (self.base.options.each_lib_rpath) {2692 if (self.each_lib_rpath) {
2698 var test_path = std.ArrayList(u8).init(arena);2693 var test_path = std.ArrayList(u8).init(arena);
2699 for (self.base.options.lib_dirs) |lib_dir_path| {2694 for (self.lib_dirs) |lib_dir_path| {
2700 for (self.base.comp.system_libs.keys()) |link_lib| {2695 for (self.base.comp.system_libs.keys()) |link_lib| {
2701 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))2696 if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
2702 continue;2697 continue;
...@@ -2706,7 +2701,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2706,7 +2701,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2706 }2701 }
2707 }2702 }
2708 }2703 }
2709 for (self.base.options.objects) |obj| {2704 for (comp.objects) |obj| {
2710 if (Compilation.classifyFileExt(obj.path) == .shared_library) {2705 if (Compilation.classifyFileExt(obj.path) == .shared_library) {
2711 const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;2706 const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
2712 if (obj.loption) continue;2707 if (obj.loption) continue;
...@@ -2719,12 +2714,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2719,12 +2714,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2719 }2714 }
2720 }2715 }
27212716
2722 for (self.base.options.lib_dirs) |lib_dir| {2717 for (self.lib_dirs) |lib_dir| {
2723 try argv.append("-L");2718 try argv.append("-L");
2724 try argv.append(lib_dir);2719 try argv.append(lib_dir);
2725 }2720 }
27262721
2727 if (self.base.options.link_libc) {2722 if (comp.config.link_libc) {
2728 if (self.base.comp.libc_installation) |libc_installation| {2723 if (self.base.comp.libc_installation) |libc_installation| {
2729 try argv.append("-L");2724 try argv.append("-L");
2730 try argv.append(libc_installation.crt_dir.?);2725 try argv.append(libc_installation.crt_dir.?);
...@@ -2739,11 +2734,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2739,11 +2734,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2739 }2734 }
27402735
2741 if (is_dyn_lib) {2736 if (is_dyn_lib) {
2742 if (self.base.options.soname) |soname| {2737 if (self.soname) |soname| {
2743 try argv.append("-soname");2738 try argv.append("-soname");
2744 try argv.append(soname);2739 try argv.append(soname);
2745 }2740 }
2746 if (self.base.options.version_script) |version_script| {2741 if (self.version_script) |version_script| {
2747 try argv.append("-version-script");2742 try argv.append("-version-script");
2748 try argv.append(version_script);2743 try argv.append(version_script);
2749 }2744 }
...@@ -2751,7 +2746,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2751,7 +2746,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
27512746
2752 // Positional arguments to the linker such as object files.2747 // Positional arguments to the linker such as object files.
2753 var whole_archive = false;2748 var whole_archive = false;
2754 for (self.base.options.objects) |obj| {2749 for (comp.objects) |obj| {
2755 if (obj.must_link and !whole_archive) {2750 if (obj.must_link and !whole_archive) {
2756 try argv.append("-whole-archive");2751 try argv.append("-whole-archive");
2757 whole_archive = true;2752 whole_archive = true;
...@@ -2779,15 +2774,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2779,15 +2774,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2779 try argv.append(p);2774 try argv.append(p);
2780 }2775 }
27812776
2782 // TSAN2777 if (comp.config.any_sanitize_thread) {
2783 if (self.base.options.tsan) {
2784 try argv.append(comp.tsan_static_lib.?.full_object_path);2778 try argv.append(comp.tsan_static_lib.?.full_object_path);
2785 }2779 }
27862780
2787 // libc2781 // libc
2788 if (is_exe_or_dyn_lib and2782 if (is_exe_or_dyn_lib and
2789 !self.base.options.skip_linker_dependencies and2783 !comp.skip_linker_dependencies and
2790 !self.base.options.link_libc)2784 !comp.config.link_libc)
2791 {2785 {
2792 if (comp.libc_static_lib) |lib| {2786 if (comp.libc_static_lib) |lib| {
2793 try argv.append(lib.full_object_path);2787 try argv.append(lib.full_object_path);
...@@ -2832,19 +2826,19 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2832,19 +2826,19 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2832 }2826 }
28332827
2834 // libc++ dep2828 // libc++ dep
2835 if (self.base.options.link_libcpp) {2829 if (comp.config.link_libcpp) {
2836 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);2830 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
2837 try argv.append(comp.libcxx_static_lib.?.full_object_path);2831 try argv.append(comp.libcxx_static_lib.?.full_object_path);
2838 }2832 }
28392833
2840 // libunwind dep2834 // libunwind dep
2841 if (self.base.options.link_libunwind) {2835 if (comp.config.link_libunwind) {
2842 try argv.append(comp.libunwind_static_lib.?.full_object_path);2836 try argv.append(comp.libunwind_static_lib.?.full_object_path);
2843 }2837 }
28442838
2845 // libc dep2839 // libc dep
2846 self.error_flags.missing_libc = false;2840 self.error_flags.missing_libc = false;
2847 if (self.base.options.link_libc) {2841 if (comp.config.link_libc) {
2848 if (self.base.comp.libc_installation != null) {2842 if (self.base.comp.libc_installation != null) {
2849 const needs_grouping = link_mode == .Static;2843 const needs_grouping = link_mode == .Static;
2850 if (needs_grouping) try argv.append("--start-group");2844 if (needs_grouping) try argv.append("--start-group");
...@@ -2884,13 +2878,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2884,13 +2878,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2884 try argv.append("--allow-shlib-undefined");2878 try argv.append("--allow-shlib-undefined");
2885 }2879 }
28862880
2887 switch (self.base.options.compress_debug_sections) {2881 switch (self.compress_debug_sections) {
2888 .none => {},2882 .none => {},
2889 .zlib => try argv.append("--compress-debug-sections=zlib"),2883 .zlib => try argv.append("--compress-debug-sections=zlib"),
2890 .zstd => try argv.append("--compress-debug-sections=zstd"),2884 .zstd => try argv.append("--compress-debug-sections=zstd"),
2891 }2885 }
28922886
2893 if (self.base.options.bind_global_refs_locally) {2887 if (self.bind_global_refs_locally) {
2894 try argv.append("-Bsymbolic");2888 try argv.append("-Bsymbolic");
2895 }2889 }
28962890
...@@ -2964,7 +2958,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2964,7 +2958,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2964 }2958 }
2965 }2959 }
29662960
2967 if (!self.base.options.disable_lld_caching) {2961 if (!self.base.disable_lld_caching) {
2968 // Update the file with the digest. If it fails we can continue; it only2962 // Update the file with the digest. If it fails we can continue; it only
2969 // means that the next invocation will have an unnecessary cache miss.2963 // means that the next invocation will have an unnecessary cache miss.
2970 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {2964 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
...@@ -3101,7 +3095,8 @@ fn writeElfHeader(self: *Elf) !void {...@@ -3101,7 +3095,8 @@ fn writeElfHeader(self: *Elf) !void {
3101 };3095 };
3102 index += 1;3096 index += 1;
31033097
3104 const target = self.base.comp.root_mod.resolved_target.result;3098 const comp = self.base.comp;
3099 const target = comp.root_mod.resolved_target.result;
3105 const endian = target.cpu.arch.endian();3100 const endian = target.cpu.arch.endian();
3106 hdr_buf[index] = switch (endian) {3101 hdr_buf[index] = switch (endian) {
3107 .little => elf.ELFDATA2LSB,3102 .little => elf.ELFDATA2LSB,
...@@ -3120,10 +3115,10 @@ fn writeElfHeader(self: *Elf) !void {...@@ -3120,10 +3115,10 @@ fn writeElfHeader(self: *Elf) !void {
31203115
3121 assert(index == 16);3116 assert(index == 16);
31223117
3123 const output_mode = self.base.comp.config.output_mode;3118 const output_mode = comp.config.output_mode;
3124 const link_mode = self.base.comp.config.link_mode;3119 const link_mode = comp.config.link_mode;
3125 const elf_type: elf.ET = switch (output_mode) {3120 const elf_type: elf.ET = switch (output_mode) {
3126 .Exe => if (self.base.options.pie) .DYN else .EXEC,3121 .Exe => if (comp.config.pie) .DYN else .EXEC,
3127 .Obj => .REL,3122 .Obj => .REL,
3128 .Lib => switch (link_mode) {3123 .Lib => switch (link_mode) {
3129 .Static => @as(elf.ET, .REL),3124 .Static => @as(elf.ET, .REL),
...@@ -3283,7 +3278,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -3283,7 +3278,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
3283 self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self);3278 self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self);
3284 self.end_index = try linker_defined.addGlobal("_end", self);3279 self.end_index = try linker_defined.addGlobal("_end", self);
32853280
3286 if (self.base.options.eh_frame_hdr) {3281 if (self.eh_frame_hdr) {
3287 self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self);3282 self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self);
3288 }3283 }
32893284
...@@ -3314,7 +3309,8 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -3314,7 +3309,8 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
3314}3309}
33153310
3316fn allocateLinkerDefinedSymbols(self: *Elf) void {3311fn allocateLinkerDefinedSymbols(self: *Elf) void {
3317 const link_mode = self.base.comp.config.link_mode;3312 const comp = self.base.comp;
3313 const link_mode = comp.config.link_mode;
33183314
3319 // _DYNAMIC3315 // _DYNAMIC
3320 if (self.dynamic_section_index) |shndx| {3316 if (self.dynamic_section_index) |shndx| {
...@@ -3398,7 +3394,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -3398,7 +3394,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
33983394
3399 // __rela_iplt_start, __rela_iplt_end3395 // __rela_iplt_start, __rela_iplt_end
3400 if (self.rela_dyn_section_index) |shndx| blk: {3396 if (self.rela_dyn_section_index) |shndx| blk: {
3401 if (link_mode != .Static or self.base.options.pie) break :blk;3397 if (link_mode != .Static or comp.config.pie) break :blk;
3402 const shdr = &self.shdrs.items[shndx];3398 const shdr = &self.shdrs.items[shndx];
3403 const end_addr = shdr.sh_addr + shdr.sh_size;3399 const end_addr = shdr.sh_addr + shdr.sh_size;
3404 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);3400 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
...@@ -3445,7 +3441,8 @@ fn initOutputSections(self: *Elf) !void {...@@ -3445,7 +3441,8 @@ fn initOutputSections(self: *Elf) !void {
3445}3441}
34463442
3447fn initSyntheticSections(self: *Elf) !void {3443fn initSyntheticSections(self: *Elf) !void {
3448 const target = self.base.comp.root_mod.resolved_target.result;3444 const comp = self.base.comp;
3445 const target = comp.root_mod.resolved_target.result;
3449 const ptr_size = self.ptrWidthBytes();3446 const ptr_size = self.ptrWidthBytes();
34503447
3451 const needs_eh_frame = for (self.objects.items) |index| {3448 const needs_eh_frame = for (self.objects.items) |index| {
...@@ -3460,7 +3457,7 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3460,7 +3457,7 @@ fn initSyntheticSections(self: *Elf) !void {
3460 .offset = std.math.maxInt(u64),3457 .offset = std.math.maxInt(u64),
3461 });3458 });
34623459
3463 if (self.base.options.eh_frame_hdr) {3460 if (self.eh_frame_hdr) {
3464 self.eh_frame_hdr_section_index = try self.addSection(.{3461 self.eh_frame_hdr_section_index = try self.addSection(.{
3465 .name = ".eh_frame_hdr",3462 .name = ".eh_frame_hdr",
3466 .type = elf.SHT_PROGBITS,3463 .type = elf.SHT_PROGBITS,
...@@ -3554,7 +3551,7 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3554,7 +3551,7 @@ fn initSyntheticSections(self: *Elf) !void {
3554 // In this case, if we do generate .interp section and segment, we will get3551 // In this case, if we do generate .interp section and segment, we will get
3555 // a segfault in the dynamic linker trying to load a binary that is static3552 // a segfault in the dynamic linker trying to load a binary that is static
3556 // and doesn't contain .dynamic section.3553 // and doesn't contain .dynamic section.
3557 if (self.isStatic() and !self.base.options.pie) break :blk false;3554 if (self.isStatic() and !comp.config.pie) break :blk false;
3558 break :blk target.dynamic_linker.get() != null;3555 break :blk target.dynamic_linker.get() != null;
3559 };3556 };
3560 if (needs_interp) {3557 if (needs_interp) {
...@@ -3567,7 +3564,7 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3567,7 +3564,7 @@ fn initSyntheticSections(self: *Elf) !void {
3567 });3564 });
3568 }3565 }
35693566
3570 if (self.base.isDynLib() or self.shared_objects.items.len > 0 or self.base.options.pie) {3567 if (self.base.isDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
3571 self.dynstrtab_section_index = try self.addSection(.{3568 self.dynstrtab_section_index = try self.addSection(.{
3572 .name = ".dynstr",3569 .name = ".dynstr",
3573 .flags = elf.SHF_ALLOC,3570 .flags = elf.SHF_ALLOC,
...@@ -3859,7 +3856,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {...@@ -3859,7 +3856,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
3859 }3856 }
38603857
3861 if (self.base.isDynLib()) {3858 if (self.base.isDynLib()) {
3862 if (self.base.options.soname) |soname| {3859 if (self.soname) |soname| {
3863 try self.dynamic.setSoname(soname, self);3860 try self.dynamic.setSoname(soname, self);
3864 }3861 }
3865 }3862 }
src/link/Elf/Atom.zig+7-6
...@@ -543,7 +543,7 @@ fn scanReloc(...@@ -543,7 +543,7 @@ fn scanReloc(
543 try self.reportPicError(symbol, rel, elf_file),543 try self.reportPicError(symbol, rel, elf_file),
544544
545 .copyrel => {545 .copyrel => {
546 if (elf_file.base.options.z_nocopyreloc) {546 if (elf_file.z_nocopyreloc) {
547 if (symbol.isAbs(elf_file))547 if (symbol.isAbs(elf_file))
548 try self.reportNoPicError(symbol, rel, elf_file)548 try self.reportNoPicError(symbol, rel, elf_file)
549 else549 else
...@@ -553,9 +553,9 @@ fn scanReloc(...@@ -553,9 +553,9 @@ fn scanReloc(
553 },553 },
554554
555 .dyn_copyrel => {555 .dyn_copyrel => {
556 if (is_writeable or elf_file.base.options.z_nocopyreloc) {556 if (is_writeable or elf_file.z_nocopyreloc) {
557 if (!is_writeable) {557 if (!is_writeable) {
558 if (elf_file.base.options.z_notext) {558 if (elf_file.z_notext) {
559 elf_file.has_text_reloc = true;559 elf_file.has_text_reloc = true;
560 } else {560 } else {
561 try self.reportTextRelocError(symbol, rel, elf_file);561 try self.reportTextRelocError(symbol, rel, elf_file);
...@@ -587,7 +587,7 @@ fn scanReloc(...@@ -587,7 +587,7 @@ fn scanReloc(
587587
588 .dynrel, .baserel, .ifunc => {588 .dynrel, .baserel, .ifunc => {
589 if (!is_writeable) {589 if (!is_writeable) {
590 if (elf_file.base.options.z_notext) {590 if (elf_file.z_notext) {
591 elf_file.has_text_reloc = true;591 elf_file.has_text_reloc = true;
592 } else {592 } else {
593 try self.reportTextRelocError(symbol, rel, elf_file);593 try self.reportTextRelocError(symbol, rel, elf_file);
...@@ -657,11 +657,12 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {...@@ -657,11 +657,12 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {
657}657}
658658
659fn outputType(elf_file: *Elf) u2 {659fn outputType(elf_file: *Elf) u2 {
660 const comp = elf_file.base.comp;
660 assert(!elf_file.isRelocatable());661 assert(!elf_file.isRelocatable());
661 return switch (elf_file.base.comp.config.output_mode) {662 return switch (elf_file.base.comp.config.output_mode) {
662 .Obj => unreachable,663 .Obj => unreachable,
663 .Lib => 0,664 .Lib => 0,
664 .Exe => if (elf_file.base.options.pie) 1 else 2,665 .Exe => if (comp.config.pie) 1 else 2,
665 };666 };
666}667}
667668
...@@ -979,7 +980,7 @@ fn resolveDynAbsReloc(...@@ -979,7 +980,7 @@ fn resolveDynAbsReloc(
979 => try writer.writeInt(i32, @as(i32, @truncate(S + A)), .little),980 => try writer.writeInt(i32, @as(i32, @truncate(S + A)), .little),
980981
981 .dyn_copyrel => {982 .dyn_copyrel => {
982 if (is_writeable or elf_file.base.options.z_nocopyreloc) {983 if (is_writeable or elf_file.z_nocopyreloc) {
983 elf_file.addRelaDynAssumeCapacity(.{984 elf_file.addRelaDynAssumeCapacity(.{
984 .offset = P,985 .offset = P,
985 .sym = target.extra(elf_file).?.dynamic,986 .sym = target.extra(elf_file).?.dynamic,
src/link/Elf/Object.zig+1-1
...@@ -299,7 +299,7 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {...@@ -299,7 +299,7 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
299 if (mem.startsWith(u8, name, ".note")) break :blk true;299 if (mem.startsWith(u8, name, ".note")) break :blk true;
300 if (mem.startsWith(u8, name, ".comment")) break :blk true;300 if (mem.startsWith(u8, name, ".comment")) break :blk true;
301 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;301 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
302 if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and302 if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
303 mem.startsWith(u8, name, ".debug")) break :blk true;303 mem.startsWith(u8, name, ".debug")) break :blk true;
304 break :blk false;304 break :blk false;
305 };305 };
src/link/Elf/ZigObject.zig+1-1
...@@ -97,7 +97,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {...@@ -97,7 +97,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
97 symbol_ptr.esym_index = esym_index;97 symbol_ptr.esym_index = esym_index;
9898
99 if (elf_file.base.debug_format != .strip) {99 if (elf_file.base.debug_format != .strip) {
100 self.dwarf = Dwarf.init(gpa, &elf_file.base, .dwarf32);100 self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
101 }101 }
102}102}
103103
src/link/Elf/synthetic_sections.zig+15-9
...@@ -32,7 +32,7 @@ pub const DynamicSection = struct {...@@ -32,7 +32,7 @@ pub const DynamicSection = struct {
32 fn getFlags(dt: DynamicSection, elf_file: *Elf) ?u64 {32 fn getFlags(dt: DynamicSection, elf_file: *Elf) ?u64 {
33 _ = dt;33 _ = dt;
34 var flags: u64 = 0;34 var flags: u64 = 0;
35 if (elf_file.base.options.z_now) {35 if (elf_file.z_now) {
36 flags |= elf.DF_BIND_NOW;36 flags |= elf.DF_BIND_NOW;
37 }37 }
38 for (elf_file.got.entries.items) |entry| switch (entry.tag) {38 for (elf_file.got.entries.items) |entry| switch (entry.tag) {
...@@ -49,15 +49,16 @@ pub const DynamicSection = struct {...@@ -49,15 +49,16 @@ pub const DynamicSection = struct {
49 }49 }
5050
51 fn getFlags1(dt: DynamicSection, elf_file: *Elf) ?u64 {51 fn getFlags1(dt: DynamicSection, elf_file: *Elf) ?u64 {
52 const comp = elf_file.base.comp;
52 _ = dt;53 _ = dt;
53 var flags_1: u64 = 0;54 var flags_1: u64 = 0;
54 if (elf_file.base.options.z_now) {55 if (elf_file.z_now) {
55 flags_1 |= elf.DF_1_NOW;56 flags_1 |= elf.DF_1_NOW;
56 }57 }
57 if (elf_file.isExe() and elf_file.base.options.pie) {58 if (elf_file.isExe() and comp.config.pie) {
58 flags_1 |= elf.DF_1_PIE;59 flags_1 |= elf.DF_1_PIE;
59 }60 }
60 // if (elf_file.base.options.z_nodlopen) {61 // if (elf_file.z_nodlopen) {
61 // flags_1 |= elf.DF_1_NOOPEN;62 // flags_1 |= elf.DF_1_NOOPEN;
62 // }63 // }
63 return if (flags_1 > 0) flags_1 else null;64 return if (flags_1 > 0) flags_1 else null;
...@@ -246,12 +247,13 @@ pub const ZigGotSection = struct {...@@ -246,12 +247,13 @@ pub const ZigGotSection = struct {
246 }247 }
247248
248 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {249 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
250 const comp = elf_file.base.comp;
249 const index = try zig_got.allocateEntry(elf_file.base.allocator);251 const index = try zig_got.allocateEntry(elf_file.base.allocator);
250 const entry = &zig_got.entries.items[index];252 const entry = &zig_got.entries.items[index];
251 entry.* = sym_index;253 entry.* = sym_index;
252 const symbol = elf_file.symbol(sym_index);254 const symbol = elf_file.symbol(sym_index);
253 symbol.flags.has_zig_got = true;255 symbol.flags.has_zig_got = true;
254 if (elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) {256 if (elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) {
255 zig_got.flags.needs_rela = true;257 zig_got.flags.needs_rela = true;
256 }258 }
257 if (symbol.extra(elf_file)) |extra| {259 if (symbol.extra(elf_file)) |extra| {
...@@ -478,6 +480,7 @@ pub const GotSection = struct {...@@ -478,6 +480,7 @@ pub const GotSection = struct {
478 }480 }
479481
480 pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {482 pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
483 const comp = elf_file.base.comp;
481 const index = try got.allocateEntry(elf_file.base.allocator);484 const index = try got.allocateEntry(elf_file.base.allocator);
482 const entry = &got.entries.items[index];485 const entry = &got.entries.items[index];
483 entry.tag = .got;486 entry.tag = .got;
...@@ -485,7 +488,7 @@ pub const GotSection = struct {...@@ -485,7 +488,7 @@ pub const GotSection = struct {
485 const symbol = elf_file.symbol(sym_index);488 const symbol = elf_file.symbol(sym_index);
486 symbol.flags.has_got = true;489 symbol.flags.has_got = true;
487 if (symbol.flags.import or symbol.isIFunc(elf_file) or490 if (symbol.flags.import or symbol.isIFunc(elf_file) or
488 ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and !symbol.isAbs(elf_file)))491 ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
489 {492 {
490 got.flags.needs_rela = true;493 got.flags.needs_rela = true;
491 }494 }
...@@ -561,6 +564,7 @@ pub const GotSection = struct {...@@ -561,6 +564,7 @@ pub const GotSection = struct {
561 }564 }
562565
563 pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {566 pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {
567 const comp = elf_file.base.comp;
564 const is_dyn_lib = elf_file.isDynLib();568 const is_dyn_lib = elf_file.isDynLib();
565 const apply_relocs = true; // TODO add user option for this569 const apply_relocs = true; // TODO add user option for this
566570
...@@ -576,7 +580,7 @@ pub const GotSection = struct {...@@ -576,7 +580,7 @@ pub const GotSection = struct {
576 if (symbol.?.flags.import) break :blk 0;580 if (symbol.?.flags.import) break :blk 0;
577 if (symbol.?.isIFunc(elf_file))581 if (symbol.?.isIFunc(elf_file))
578 break :blk if (apply_relocs) value else 0;582 break :blk if (apply_relocs) value else 0;
579 if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and583 if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
580 !symbol.?.isAbs(elf_file))584 !symbol.?.isAbs(elf_file))
581 {585 {
582 break :blk if (apply_relocs) value else 0;586 break :blk if (apply_relocs) value else 0;
...@@ -623,6 +627,7 @@ pub const GotSection = struct {...@@ -623,6 +627,7 @@ pub const GotSection = struct {
623 }627 }
624628
625 pub fn addRela(got: GotSection, elf_file: *Elf) !void {629 pub fn addRela(got: GotSection, elf_file: *Elf) !void {
630 const comp = elf_file.base.comp;
626 const is_dyn_lib = elf_file.isDynLib();631 const is_dyn_lib = elf_file.isDynLib();
627 try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file));632 try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file));
628633
...@@ -652,7 +657,7 @@ pub const GotSection = struct {...@@ -652,7 +657,7 @@ pub const GotSection = struct {
652 });657 });
653 continue;658 continue;
654 }659 }
655 if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and660 if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
656 !symbol.?.isAbs(elf_file))661 !symbol.?.isAbs(elf_file))
657 {662 {
658 elf_file.addRelaDynAssumeCapacity(.{663 elf_file.addRelaDynAssumeCapacity(.{
...@@ -725,6 +730,7 @@ pub const GotSection = struct {...@@ -725,6 +730,7 @@ pub const GotSection = struct {
725 }730 }
726731
727 pub fn numRela(got: GotSection, elf_file: *Elf) usize {732 pub fn numRela(got: GotSection, elf_file: *Elf) usize {
733 const comp = elf_file.base.comp;
728 const is_dyn_lib = elf_file.isDynLib();734 const is_dyn_lib = elf_file.isDynLib();
729 var num: usize = 0;735 var num: usize = 0;
730 for (got.entries.items) |entry| {736 for (got.entries.items) |entry| {
...@@ -734,7 +740,7 @@ pub const GotSection = struct {...@@ -734,7 +740,7 @@ pub const GotSection = struct {
734 };740 };
735 switch (entry.tag) {741 switch (entry.tag) {
736 .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or742 .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
737 ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and743 ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
738 !symbol.?.isAbs(elf_file)))744 !symbol.?.isAbs(elf_file)))
739 {745 {
740 num += 1;746 num += 1;
src/link/MachO.zig+20-16
...@@ -252,7 +252,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {...@@ -252,7 +252,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
252252
253 self.d_sym = .{253 self.d_sym = .{
254 .allocator = gpa,254 .allocator = gpa,
255 .dwarf = link.File.Dwarf.init(gpa, &self.base, .dwarf32),255 .dwarf = link.File.Dwarf.init(&self.base, .dwarf32),
256 .file = d_sym_file,256 .file = d_sym_file,
257 };257 };
258 }258 }
...@@ -573,7 +573,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -573,7 +573,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
573573
574 try self.writeLinkeditSegmentData();574 try self.writeLinkeditSegmentData();
575575
576 var codesig: ?CodeSignature = if (requiresCodeSignature(&self.base.options)) blk: {576 var codesig: ?CodeSignature = if (self.requiresCodeSignature()) blk: {
577 // Preallocate space for the code signature.577 // Preallocate space for the code signature.
578 // We need to do this at this stage so that we have the load commands with proper values578 // We need to do this at this stage so that we have the load commands with proper values
579 // written out to the file.579 // written out to the file.
...@@ -619,12 +619,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -619,12 +619,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
619 });619 });
620 },620 },
621 .Lib => if (self.base.comp.config.link_mode == .Dynamic) {621 .Lib => if (self.base.comp.config.link_mode == .Dynamic) {
622 try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer);622 try load_commands.writeDylibIdLC(self, lc_writer);
623 },623 },
624 else => {},624 else => {},
625 }625 }
626626
627 try load_commands.writeRpathLCs(gpa, &self.base.options, lc_writer);627 try load_commands.writeRpathLCs(self, lc_writer);
628 try lc_writer.writeStruct(macho.source_version_command{628 try lc_writer.writeStruct(macho.source_version_command{
629 .version = 0,629 .version = 0,
630 });630 });
...@@ -713,7 +713,7 @@ pub fn resolveLibSystem(...@@ -713,7 +713,7 @@ pub fn resolveLibSystem(
713 success: {713 success: {
714 if (self.sdk_layout) |sdk_layout| switch (sdk_layout) {714 if (self.sdk_layout) |sdk_layout| switch (sdk_layout) {
715 .sdk => {715 .sdk => {
716 const dir = try fs.path.join(arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" });716 const dir = try fs.path.join(arena, &[_][]const u8{ comp.sysroot.?, "usr", "lib" });
717 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success;717 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
718 },718 },
719 .vendored => {719 .vendored => {
...@@ -1156,7 +1156,8 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {...@@ -1156,7 +1156,8 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {
1156 // 2) afterwards, we parse dependents of the included dylibs1156 // 2) afterwards, we parse dependents of the included dylibs
1157 // TODO this should not be performed if the user specifies `-flat_namespace` flag.1157 // TODO this should not be performed if the user specifies `-flat_namespace` flag.
1158 // See ld64 manpages.1158 // See ld64 manpages.
1159 const gpa = self.base.comp.gpa;1159 const comp = self.base.comp;
1160 const gpa = comp.gpa;
11601161
1161 while (dependent_libs.readItem()) |dep_id| {1162 while (dependent_libs.readItem()) |dep_id| {
1162 defer dep_id.id.deinit(gpa);1163 defer dep_id.id.deinit(gpa);
...@@ -1176,7 +1177,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {...@@ -1176,7 +1177,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {
1176 var checked_paths = std.ArrayList([]const u8).init(arena);1177 var checked_paths = std.ArrayList([]const u8).init(arena);
11771178
1178 success: {1179 success: {
1179 if (self.base.options.sysroot) |root| {1180 if (comp.sysroot) |root| {
1180 const dir = try fs.path.join(arena, &[_][]const u8{ root, dirname });1181 const dir = try fs.path.join(arena, &[_][]const u8{ root, dirname });
1181 if (try accessLibPath(gpa, &test_path, &checked_paths, dir, stem)) break :success;1182 if (try accessLibPath(gpa, &test_path, &checked_paths, dir, stem)) break :success;
1182 }1183 }
...@@ -1713,12 +1714,12 @@ pub fn resolveSymbols(self: *MachO) !void {...@@ -1713,12 +1714,12 @@ pub fn resolveSymbols(self: *MachO) !void {
1713 // we search for it in libraries should there be no object files specified1714 // we search for it in libraries should there be no object files specified
1714 // on the linker line.1715 // on the linker line.
1715 if (output_mode == .Exe) {1716 if (output_mode == .Exe) {
1716 const entry_name = self.base.options.entry orelse load_commands.default_entry_point;1717 const entry_name = comp.config.entry.?;
1717 _ = try self.addUndefined(entry_name, .{});1718 _ = try self.addUndefined(entry_name, .{});
1718 }1719 }
17191720
1720 // Force resolution of any symbols requested by the user.1721 // Force resolution of any symbols requested by the user.
1721 for (self.base.options.force_undefined_symbols.keys()) |sym_name| {1722 for (self.base.force_undefined_symbols.keys()) |sym_name| {
1722 _ = try self.addUndefined(sym_name, .{});1723 _ = try self.addUndefined(sym_name, .{});
1723 }1724 }
17241725
...@@ -4367,7 +4368,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {...@@ -4367,7 +4368,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
43674368
4368 // We generate stabs last in order to ensure that the strtab always has debug info4369 // We generate stabs last in order to ensure that the strtab always has debug info
4369 // strings trailing4370 // strings trailing
4370 if (!self.base.options.strip) {4371 if (self.base.debug_format != .strip) {
4371 for (self.objects.items) |object| {4372 for (self.objects.items) |object| {
4372 assert(self.d_sym == null); // TODO4373 assert(self.d_sym == null); // TODO
4373 try self.generateSymbolStabs(object, &locals);4374 try self.generateSymbolStabs(object, &locals);
...@@ -5171,7 +5172,8 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 {...@@ -5171,7 +5172,8 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 {
5171/// Returns symbol location corresponding to the set entrypoint if any.5172/// Returns symbol location corresponding to the set entrypoint if any.
5172/// Asserts output mode is executable.5173/// Asserts output mode is executable.
5173pub fn getEntryPoint(self: MachO) ?SymbolWithLoc {5174pub fn getEntryPoint(self: MachO) ?SymbolWithLoc {
5174 const entry_name = self.base.options.entry orelse load_commands.default_entry_point;5175 const comp = self.base.comp;
5176 const entry_name = comp.config.entry orelse return null;
5175 const global = self.getGlobal(entry_name) orelse return null;5177 const global = self.getGlobal(entry_name) orelse return null;
5176 return global;5178 return global;
5177}5179}
...@@ -5189,11 +5191,13 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {...@@ -5189,11 +5191,13 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {
5189 };5191 };
5190}5192}
51915193
5192pub fn requiresCodeSignature(options: *const link.Options) bool {5194pub fn requiresCodeSignature(m: *MachO) bool {
5193 if (options.entitlements) |_| return true;5195 if (m.entitlements) |_| return true;
5194 const cpu_arch = options.target.cpu.arch;5196 const comp = m.base.comp;
5195 const os_tag = options.target.os.tag;5197 const target = comp.root_mod.resolved_target.result;
5196 const abi = options.target.abi;5198 const cpu_arch = target.cpu.arch;
5199 const os_tag = target.os.tag;
5200 const abi = target.abi;
5197 if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) return true;5201 if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) return true;
5198 return false;5202 return false;
5199}5203}
src/link/MachO/DebugSymbols.zig+3-4
...@@ -198,10 +198,10 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64...@@ -198,10 +198,10 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64
198}198}
199199
200pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {200pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
201 const comp = macho_file.base.comp;
201 // TODO This linker code currently assumes there is only 1 compilation unit202 // TODO This linker code currently assumes there is only 1 compilation unit
202 // and it corresponds to the Zig source code.203 // and it corresponds to the Zig source code.
203 const options = macho_file.base.options;204 const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
204 const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
205205
206 for (self.relocs.items) |*reloc| {206 for (self.relocs.items) |*reloc| {
207 const sym = switch (reloc.type) {207 const sym = switch (reloc.type) {
...@@ -245,7 +245,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -245,7 +245,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
245 const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];245 const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
246 const low_pc = text_section.addr;246 const low_pc = text_section.addr;
247 const high_pc = text_section.addr + text_section.size;247 const high_pc = text_section.addr + text_section.size;
248 try self.dwarf.writeDbgInfoHeader(module, low_pc, high_pc);248 try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);
249 self.debug_info_header_dirty = false;249 self.debug_info_header_dirty = false;
250 }250 }
251251
...@@ -572,6 +572,5 @@ const trace = @import("../../tracy.zig").trace;...@@ -572,6 +572,5 @@ const trace = @import("../../tracy.zig").trace;
572const Allocator = mem.Allocator;572const Allocator = mem.Allocator;
573const Dwarf = @import("../Dwarf.zig");573const Dwarf = @import("../Dwarf.zig");
574const MachO = @import("../MachO.zig");574const MachO = @import("../MachO.zig");
575const Module = @import("../../Module.zig");
576const StringTable = @import("../StringTable.zig");575const StringTable = @import("../StringTable.zig");
577const Type = @import("../../type.zig").Type;576const Type = @import("../../type.zig").Type;
src/link/MachO/dead_strip.zig+1-1
...@@ -60,7 +60,7 @@ fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void {...@@ -60,7 +60,7 @@ fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void {
60 }60 }
6161
62 // Add all symbols force-defined by the user.62 // Add all symbols force-defined by the user.
63 for (macho_file.base.options.force_undefined_symbols.keys()) |sym_name| {63 for (macho_file.base.force_undefined_symbols.keys()) |sym_name| {
64 const global_index = macho_file.resolver.get(sym_name).?;64 const global_index = macho_file.resolver.get(sym_name).?;
65 const global = macho_file.globals.items[global_index];65 const global = macho_file.globals.items[global_index];
66 const sym = macho_file.getSymbol(global);66 const sym = macho_file.getSymbol(global);
src/link/MachO/load_commands.zig+17-17
...@@ -1,6 +1,3 @@...@@ -1,6 +1,3 @@
1/// Default implicit entrypoint symbol name.
2pub const default_entry_point: []const u8 = "_main";
3
4/// Default path to dyld.1/// Default path to dyld.
5pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";2pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
63
...@@ -17,7 +14,9 @@ const CalcLCsSizeCtx = struct {...@@ -17,7 +14,9 @@ const CalcLCsSizeCtx = struct {
17 wants_function_starts: bool = true,14 wants_function_starts: bool = true,
18};15};
1916
20fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 {17fn calcLCsSize(m: *MachO, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 {
18 const comp = m.base.comp;
19 const gpa = comp.gpa;
21 var has_text_segment: bool = false;20 var has_text_segment: bool = false;
22 var sizeofcmds: u64 = 0;21 var sizeofcmds: u64 = 0;
23 for (ctx.segments) |seg| {22 for (ctx.segments) |seg| {
...@@ -46,15 +45,15 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx...@@ -46,15 +45,15 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
46 false,45 false,
47 );46 );
48 // LC_MAIN47 // LC_MAIN
49 if (options.output_mode == .Exe) {48 if (comp.config.output_mode == .Exe) {
50 sizeofcmds += @sizeOf(macho.entry_point_command);49 sizeofcmds += @sizeOf(macho.entry_point_command);
51 }50 }
52 // LC_ID_DYLIB51 // LC_ID_DYLIB
53 if (options.output_mode == .Lib and options.link_mode == .Dynamic) {52 if (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic) {
54 sizeofcmds += blk: {53 sizeofcmds += blk: {
55 const emit = options.emit.?;54 const emit = m.base.emit;
56 const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path});55 const install_name = m.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path});
57 defer if (options.install_name == null) gpa.free(install_name);56 defer if (m.install_name == null) gpa.free(install_name);
58 break :blk calcInstallNameLen(57 break :blk calcInstallNameLen(
59 @sizeOf(macho.dylib_command),58 @sizeOf(macho.dylib_command),
60 install_name,59 install_name,
...@@ -64,7 +63,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx...@@ -64,7 +63,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
64 }63 }
65 // LC_RPATH64 // LC_RPATH
66 {65 {
67 var it = RpathIterator.init(gpa, options.rpath_list);66 var it = RpathIterator.init(gpa, m.rpath_list);
68 defer it.deinit();67 defer it.deinit();
69 while (try it.next()) |rpath| {68 while (try it.next()) |rpath| {
70 sizeofcmds += calcInstallNameLen(69 sizeofcmds += calcInstallNameLen(
...@@ -78,7 +77,8 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx...@@ -78,7 +77,8 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
78 sizeofcmds += @sizeOf(macho.source_version_command);77 sizeofcmds += @sizeOf(macho.source_version_command);
79 // LC_BUILD_VERSION or LC_VERSION_MIN_ or nothing78 // LC_BUILD_VERSION or LC_VERSION_MIN_ or nothing
80 {79 {
81 const platform = Platform.fromTarget(options.target);80 const target = comp.root_mod.resolved_target.result;
81 const platform = Platform.fromTarget(target);
82 if (platform.isBuildVersionCompatible()) {82 if (platform.isBuildVersionCompatible()) {
83 // LC_BUILD_VERSION83 // LC_BUILD_VERSION
84 sizeofcmds += @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);84 sizeofcmds += @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
...@@ -100,19 +100,19 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx...@@ -100,19 +100,19 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
100 );100 );
101 }101 }
102 // LC_CODE_SIGNATURE102 // LC_CODE_SIGNATURE
103 if (MachO.requiresCodeSignature(options)) {103 if (m.requiresCodeSignature()) {
104 sizeofcmds += @sizeOf(macho.linkedit_data_command);104 sizeofcmds += @sizeOf(macho.linkedit_data_command);
105 }105 }
106106
107 return @as(u32, @intCast(sizeofcmds));107 return @intCast(sizeofcmds);
108}108}
109109
110pub fn calcMinHeaderPad(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx) !u64 {110pub fn calcMinHeaderPad(m: *MachO, ctx: CalcLCsSizeCtx) !u64 {
111 var padding: u32 = (try calcLCsSize(gpa, options, ctx, false)) + (options.headerpad_size orelse 0);111 var padding: u32 = (try calcLCsSize(m, ctx, false)) + m.headerpad_size;
112 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});112 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
113113
114 if (options.headerpad_max_install_names) {114 if (m.headerpad_max_install_names) {
115 const min_headerpad_size: u32 = try calcLCsSize(gpa, options, ctx, true);115 const min_headerpad_size: u32 = try calcLCsSize(m, ctx, true);
116 log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{116 log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{
117 min_headerpad_size + @sizeOf(macho.mach_header_64),117 min_headerpad_size + @sizeOf(macho.mach_header_64),
118 });118 });
src/link/MachO/zld.zig+4-5
...@@ -499,7 +499,7 @@ pub fn linkWithZld(...@@ -499,7 +499,7 @@ pub fn linkWithZld(
499 }499 }
500500
501 // Write code signature padding if required501 // Write code signature padding if required
502 var codesig: ?CodeSignature = if (MachO.requiresCodeSignature(&macho_file.base.options)) blk: {502 var codesig: ?CodeSignature = if (macho_file.requiresCodeSignature()) blk: {
503 // Preallocate space for the code signature.503 // Preallocate space for the code signature.
504 // We need to do this at this stage so that we have the load commands with proper values504 // We need to do this at this stage so that we have the load commands with proper values
505 // written out to the file.505 // written out to the file.
...@@ -547,12 +547,12 @@ pub fn linkWithZld(...@@ -547,12 +547,12 @@ pub fn linkWithZld(
547 });547 });
548 },548 },
549 .Lib => if (link_mode == .Dynamic) {549 .Lib => if (link_mode == .Dynamic) {
550 try load_commands.writeDylibIdLC(gpa, &macho_file.base.options, lc_writer);550 try load_commands.writeDylibIdLC(macho_file, lc_writer);
551 },551 },
552 else => {},552 else => {},
553 }553 }
554554
555 try load_commands.writeRpathLCs(gpa, &macho_file.base.options, lc_writer);555 try load_commands.writeRpathLCs(macho_file, lc_writer);
556 try lc_writer.writeStruct(macho.source_version_command{556 try lc_writer.writeStruct(macho.source_version_command{
557 .version = 0,557 .version = 0,
558 });558 });
...@@ -1072,11 +1072,10 @@ fn calcSectionSizes(macho_file: *MachO) !void {...@@ -1072,11 +1072,10 @@ fn calcSectionSizes(macho_file: *MachO) !void {
1072}1072}
10731073
1074fn allocateSegments(macho_file: *MachO) !void {1074fn allocateSegments(macho_file: *MachO) !void {
1075 const gpa = macho_file.base.allocator;
1076 for (macho_file.segments.items, 0..) |*segment, segment_index| {1075 for (macho_file.segments.items, 0..) |*segment, segment_index| {
1077 const is_text_segment = mem.eql(u8, segment.segName(), "__TEXT");1076 const is_text_segment = mem.eql(u8, segment.segName(), "__TEXT");
1078 const base_size = if (is_text_segment)1077 const base_size = if (is_text_segment)
1079 try load_commands.calcMinHeaderPad(gpa, &macho_file.base.options, .{1078 try load_commands.calcMinHeaderPad(macho_file, .{
1080 .segments = macho_file.segments.items,1079 .segments = macho_file.segments.items,
1081 .dylibs = macho_file.dylibs.items,1080 .dylibs = macho_file.dylibs.items,
1082 .referenced_dylibs = macho_file.referenced_dylibs.keys(),1081 .referenced_dylibs = macho_file.referenced_dylibs.keys(),
src/link/NvPtx.zig+2-1
...@@ -57,6 +57,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {...@@ -57,6 +57,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
57 .build_id = options.build_id,57 .build_id = options.build_id,
58 .rpath_list = options.rpath_list,58 .rpath_list = options.rpath_list,
59 .force_undefined_symbols = options.force_undefined_symbols,59 .force_undefined_symbols = options.force_undefined_symbols,
60 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
60 .function_sections = options.function_sections,61 .function_sections = options.function_sections,
61 .data_sections = options.data_sections,62 .data_sections = options.data_sections,
62 },63 },
...@@ -66,7 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {...@@ -66,7 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
66 return nvptx;67 return nvptx;
67}68}
6869
69pub fn open(arena: Allocator, options: link.FileOpenOptions) !*NvPtx {70pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
70 const target = options.comp.root_mod.resolved_target.result;71 const target = options.comp.root_mod.resolved_target.result;
71 assert(target.ofmt == .nvptx);72 assert(target.ofmt == .nvptx);
72 return createEmpty(arena, options);73 return createEmpty(arena, options);
src/link/Plan9.zig+21-11
...@@ -295,26 +295,36 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {...@@ -295,26 +295,36 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
295}295}
296296
297pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {297pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
298 _ = arena;298 const comp = options.comp;
299 const target = options.comp.root_mod.resolved_target.result;299 const target = comp.root_mod.resolved_target.result;
300 const gpa = options.comp.gpa;300 const gpa = comp.gpa;
301 const optimize_mode = comp.root_mod.optimize_mode;
302 const output_mode = comp.config.output_mode;
301303
302 const sixtyfour_bit: bool = switch (options.target.ptrBitWidth()) {304 const sixtyfour_bit: bool = switch (target.ptrBitWidth()) {
303 0...32 => false,305 0...32 => false,
304 33...64 => true,306 33...64 => true,
305 else => return error.UnsupportedP9Architecture,307 else => return error.UnsupportedP9Architecture,
306 };308 };
307309
308 const arena_allocator = std.heap.ArenaAllocator.init(gpa);310 const self = try arena.create(Plan9);
309
310 const self = try gpa.create(Plan9);
311 self.* = .{311 self.* = .{
312 .path_arena = arena_allocator,312 .path_arena = std.heap.ArenaAllocator.init(gpa),
313 .base = .{313 .base = .{
314 .tag = .plan9,314 .tag = .plan9,
315 .options = options,315 .comp = comp,
316 .allocator = gpa,316 .emit = options.emit,
317 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
318 .stack_size = options.stack_size orelse 16777216,
319 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
317 .file = null,320 .file = null,
321 .disable_lld_caching = options.disable_lld_caching,
322 .build_id = options.build_id,
323 .rpath_list = options.rpath_list,
324 .force_undefined_symbols = options.force_undefined_symbols,
325 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
326 .function_sections = options.function_sections,
327 .data_sections = options.data_sections,
318 },328 },
319 .sixtyfour_bit = sixtyfour_bit,329 .sixtyfour_bit = sixtyfour_bit,
320 .bases = undefined,330 .bases = undefined,
...@@ -602,7 +612,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li...@@ -602,7 +612,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li
602 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;612 const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
603 assert(!use_lld);613 assert(!use_lld);
604614
605 switch (self.base.options.effectiveOutputMode()) {615 switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {
606 .Exe => {},616 .Exe => {},
607 // plan9 object files are totally different617 // plan9 object files are totally different
608 .Obj => return error.TODOImplementPlan9Objs,618 .Obj => return error.TODOImplementPlan9Objs,
src/link/SpirV.zig+2-1
...@@ -67,6 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {...@@ -67,6 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
67 .force_undefined_symbols = options.force_undefined_symbols,67 .force_undefined_symbols = options.force_undefined_symbols,
68 .function_sections = options.function_sections,68 .function_sections = options.function_sections,
69 .data_sections = options.data_sections,69 .data_sections = options.data_sections,
70 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
70 },71 },
71 .object = codegen.Object.init(gpa),72 .object = codegen.Object.init(gpa),
72 };73 };
...@@ -102,7 +103,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV {...@@ -102,7 +103,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
102 errdefer spirv.base.destroy();103 errdefer spirv.base.destroy();
103104
104 // TODO: read the file and keep valid parts instead of truncating105 // TODO: read the file and keep valid parts instead of truncating
105 const file = try options.emit.?.directory.handle.createFile(options.emit.sub_path, .{106 const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
106 .truncate = true,107 .truncate = true,
107 .read = true,108 .read = true,
108 });109 });
src/link/Wasm.zig+149-96
...@@ -37,6 +37,13 @@ pub const Relocation = types.Relocation;...@@ -37,6 +37,13 @@ pub const Relocation = types.Relocation;
37pub const base_tag: link.File.Tag = .wasm;37pub const base_tag: link.File.Tag = .wasm;
3838
39base: link.File,39base: link.File,
40import_symbols: bool,
41export_symbol_names: []const []const u8,
42rdynamic: bool,
43global_base: ?u64,
44initial_memory: ?u64,
45max_memory: ?u64,
46wasi_emulated_libs: []const wasi_libc.CRTFile,
40/// Output name of the file47/// Output name of the file
41name: []const u8,48name: []const u8,
42/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.49/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
...@@ -368,13 +375,15 @@ pub const StringTable = struct {...@@ -368,13 +375,15 @@ pub const StringTable = struct {
368375
369pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {376pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
370 if (build_options.only_c) unreachable;377 if (build_options.only_c) unreachable;
371 const gpa = options.comp.gpa;378 const comp = options.comp;
372 const target = options.comp.root_mod.resolved_target.result;379 const gpa = comp.gpa;
380 const target = comp.root_mod.resolved_target.result;
373 assert(target.ofmt == .wasm);381 assert(target.ofmt == .wasm);
374382
375 const use_lld = build_options.have_llvm and options.comp.config.use_lld;383 const use_lld = build_options.have_llvm and comp.config.use_lld;
376 const use_llvm = options.comp.config.use_llvm;384 const use_llvm = comp.config.use_llvm;
377 const output_mode = options.comp.config.output_mode;385 const output_mode = comp.config.output_mode;
386 const shared_memory = comp.config.shared_memory;
378387
379 const wasm = try createEmpty(arena, options);388 const wasm = try createEmpty(arena, options);
380 errdefer wasm.base.destroy();389 errdefer wasm.base.destroy();
...@@ -395,7 +404,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -395,7 +404,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
395 };404 };
396405
397 // TODO: read the file and keep valid parts instead of truncating406 // TODO: read the file and keep valid parts instead of truncating
398 const file = try options.emit.?.directory.handle.createFile(sub_path, .{407 const file = try options.emit.directory.handle.createFile(sub_path, .{
399 .truncate = true,408 .truncate = true,
400 .read = true,409 .read = true,
401 .mode = if (fs.has_executable_bit)410 .mode = if (fs.has_executable_bit)
...@@ -480,7 +489,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -480,7 +489,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
480 }489 }
481490
482 // shared-memory symbols for TLS support491 // shared-memory symbols for TLS support
483 if (wasm.base.options.shared_memory) {492 if (shared_memory) {
484 {493 {
485 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);494 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);
486 const symbol = loc.getSymbol(wasm);495 const symbol = loc.getSymbol(wasm);
...@@ -522,14 +531,15 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -522,14 +531,15 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
522}531}
523532
524pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {533pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
525 const use_llvm = options.comp.config.use_llvm;534 const comp = options.comp;
526 const output_mode = options.comp.config.output_mode;535 const use_llvm = comp.config.use_llvm;
536 const output_mode = comp.config.output_mode;
527537
528 const wasm = try arena.create(Wasm);538 const wasm = try arena.create(Wasm);
529 wasm.* = .{539 wasm.* = .{
530 .base = .{540 .base = .{
531 .tag = .wasm,541 .tag = .wasm,
532 .comp = options.comp,542 .comp = comp,
533 .emit = options.emit,543 .emit = options.emit,
534 .gc_sections = options.gc_sections orelse (output_mode != .Obj),544 .gc_sections = options.gc_sections orelse (output_mode != .Obj),
535 .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB545 .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB
...@@ -546,6 +556,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {...@@ -546,6 +556,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
546 .name = undefined,556 .name = undefined,
547 .import_table = options.import_table,557 .import_table = options.import_table,
548 .export_table = options.export_table,558 .export_table = options.export_table,
559 .import_symbols = options.import_symbols,
560 .export_symbol_names = options.export_symbol_names,
561 .rdynamic = options.rdynamic,
562 .global_base = options.global_base,
563 .initial_memory = options.initial_memory,
564 .max_memory = options.max_memory,
565 .wasi_emulated_libs = options.wasi_emulated_libs,
549 };566 };
550567
551 if (use_llvm) {568 if (use_llvm) {
...@@ -909,7 +926,10 @@ fn writeI32Const(writer: anytype, val: u32) !void {...@@ -909,7 +926,10 @@ fn writeI32Const(writer: anytype, val: u32) !void {
909}926}
910927
911fn setupInitMemoryFunction(wasm: *Wasm) !void {928fn setupInitMemoryFunction(wasm: *Wasm) !void {
912 const gpa = wasm.base.comp.gpa;929 const comp = wasm.base.comp;
930 const gpa = comp.gpa;
931 const shared_memory = comp.config.shared_memory;
932 const import_memory = comp.config.import_memory;
913933
914 // Passive segments are used to avoid memory being reinitialized on each934 // Passive segments are used to avoid memory being reinitialized on each
915 // thread's instantiation. These passive segments are initialized and935 // thread's instantiation. These passive segments are initialized and
...@@ -920,7 +940,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -920,7 +940,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
920 return;940 return;
921 }941 }
922942
923 const flag_address: u32 = if (wasm.base.options.shared_memory) address: {943 const flag_address: u32 = if (shared_memory) address: {
924 // when we have passive initialization segments and shared memory944 // when we have passive initialization segments and shared memory
925 // `setupMemory` will create this symbol and set its virtual address.945 // `setupMemory` will create this symbol and set its virtual address.
926 const loc = wasm.findGlobalSymbol("__wasm_init_memory_flag").?;946 const loc = wasm.findGlobalSymbol("__wasm_init_memory_flag").?;
...@@ -934,7 +954,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -934,7 +954,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
934 // we have 0 locals954 // we have 0 locals
935 try leb.writeULEB128(writer, @as(u32, 0));955 try leb.writeULEB128(writer, @as(u32, 0));
936956
937 if (wasm.base.options.shared_memory) {957 if (shared_memory) {
938 // destination blocks958 // destination blocks
939 // based on values we jump to corresponding label959 // based on values we jump to corresponding label
940 try writer.writeByte(std.wasm.opcode(.block)); // $drop960 try writer.writeByte(std.wasm.opcode(.block)); // $drop
...@@ -968,14 +988,14 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -968,14 +988,14 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
968 var segment_index: u32 = 0;988 var segment_index: u32 = 0;
969 while (it.next()) |entry| : (segment_index += 1) {989 while (it.next()) |entry| : (segment_index += 1) {
970 const segment: Segment = wasm.segments.items[entry.value_ptr.*];990 const segment: Segment = wasm.segments.items[entry.value_ptr.*];
971 if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) {991 if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) {
972 // For passive BSS segments we can simple issue a memory.fill(0).992 // For passive BSS segments we can simple issue a memory.fill(0).
973 // For non-BSS segments we do a memory.init. Both these993 // For non-BSS segments we do a memory.init. Both these
974 // instructions take as their first argument the destination994 // instructions take as their first argument the destination
975 // address.995 // address.
976 try writeI32Const(writer, segment.offset);996 try writeI32Const(writer, segment.offset);
977997
978 if (wasm.base.options.shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) {998 if (shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) {
979 // When we initialize the TLS segment we also set the `__tls_base`999 // When we initialize the TLS segment we also set the `__tls_base`
980 // global. This allows the runtime to use this static copy of the1000 // global. This allows the runtime to use this static copy of the
981 // TLS data for the first/main thread.1001 // TLS data for the first/main thread.
...@@ -1000,7 +1020,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -1000,7 +1020,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
1000 }1020 }
1001 }1021 }
10021022
1003 if (wasm.base.options.shared_memory) {1023 if (shared_memory) {
1004 // we set the init memory flag to value '2'1024 // we set the init memory flag to value '2'
1005 try writeI32Const(writer, flag_address);1025 try writeI32Const(writer, flag_address);
1006 try writeI32Const(writer, 2);1026 try writeI32Const(writer, 2);
...@@ -1043,12 +1063,12 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -1043,12 +1063,12 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
1043 while (it.next()) |entry| : (segment_index += 1) {1063 while (it.next()) |entry| : (segment_index += 1) {
1044 const name = entry.key_ptr.*;1064 const name = entry.key_ptr.*;
1045 const segment: Segment = wasm.segments.items[entry.value_ptr.*];1065 const segment: Segment = wasm.segments.items[entry.value_ptr.*];
1046 if (segment.needsPassiveInitialization(wasm.base.options.import_memory, name) and1066 if (segment.needsPassiveInitialization(import_memory, name) and
1047 !std.mem.eql(u8, name, ".bss"))1067 !std.mem.eql(u8, name, ".bss"))
1048 {1068 {
1049 // The TLS region should not be dropped since its is needed1069 // The TLS region should not be dropped since its is needed
1050 // during the initialization of each thread (__wasm_init_tls).1070 // during the initialization of each thread (__wasm_init_tls).
1051 if (wasm.base.options.shared_memory and std.mem.eql(u8, name, ".tdata")) {1071 if (shared_memory and std.mem.eql(u8, name, ".tdata")) {
1052 continue;1072 continue;
1053 }1073 }
10541074
...@@ -1071,11 +1091,13 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {...@@ -1071,11 +1091,13 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
1071/// Constructs a synthetic function that performs runtime relocations for1091/// Constructs a synthetic function that performs runtime relocations for
1072/// TLS symbols. This function is called by `__wasm_init_tls`.1092/// TLS symbols. This function is called by `__wasm_init_tls`.
1073fn setupTLSRelocationsFunction(wasm: *Wasm) !void {1093fn setupTLSRelocationsFunction(wasm: *Wasm) !void {
1074 const gpa = wasm.base.comp.gpa;1094 const comp = wasm.base.comp;
1095 const gpa = comp.gpa;
1096 const shared_memory = comp.config.shared_memory;
10751097
1076 // When we have TLS GOT entries and shared memory is enabled,1098 // When we have TLS GOT entries and shared memory is enabled,
1077 // we must perform runtime relocations or else we don't create the function.1099 // we must perform runtime relocations or else we don't create the function.
1078 if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) {1100 if (!shared_memory or !wasm.requiresTLSReloc()) {
1079 return;1101 return;
1080 }1102 }
10811103
...@@ -1119,7 +1141,9 @@ fn validateFeatures(...@@ -1119,7 +1141,9 @@ fn validateFeatures(
1119 to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool,1141 to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool,
1120 emit_features_count: *u32,1142 emit_features_count: *u32,
1121) !void {1143) !void {
1122 const target = wasm.base.comp.root_mod.resolved_target.result;1144 const comp = wasm.base.comp;
1145 const target = comp.root_mod.resolved_target.result;
1146 const shared_memory = comp.config.shared_memory;
1123 const cpu_features = target.cpu.features;1147 const cpu_features = target.cpu.features;
1124 const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects.1148 const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects.
1125 const known_features_count = @typeInfo(types.Feature.Tag).Enum.fields.len;1149 const known_features_count = @typeInfo(types.Feature.Tag).Enum.fields.len;
...@@ -1190,7 +1214,7 @@ fn validateFeatures(...@@ -1190,7 +1214,7 @@ fn validateFeatures(
1190 return error.InvalidFeatureSet;1214 return error.InvalidFeatureSet;
1191 }1215 }
11921216
1193 if (wasm.base.options.shared_memory) {1217 if (shared_memory) {
1194 const disallowed_feature = disallowed[@intFromEnum(types.Feature.Tag.shared_mem)];1218 const disallowed_feature = disallowed[@intFromEnum(types.Feature.Tag.shared_mem)];
1195 if (@as(u1, @truncate(disallowed_feature)) != 0) {1219 if (@as(u1, @truncate(disallowed_feature)) != 0) {
1196 log.err(1220 log.err(
...@@ -1255,7 +1279,9 @@ fn validateFeatures(...@@ -1255,7 +1279,9 @@ fn validateFeatures(
1255/// if one or multiple undefined references exist. When none exist, the symbol will1279/// if one or multiple undefined references exist. When none exist, the symbol will
1256/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.1280/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
1257fn resolveLazySymbols(wasm: *Wasm) !void {1281fn resolveLazySymbols(wasm: *Wasm) !void {
1258 const gpa = wasm.base.comp.gpa;1282 const comp = wasm.base.comp;
1283 const gpa = comp.gpa;
1284 const shared_memory = comp.config.shared_memory;
12591285
1260 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {1286 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
1261 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {1287 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
...@@ -1273,7 +1299,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void {...@@ -1273,7 +1299,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
1273 }1299 }
1274 }1300 }
12751301
1276 if (!wasm.base.options.shared_memory) {1302 if (!shared_memory) {
1277 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {1303 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
1278 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {1304 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1279 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);1305 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
...@@ -1306,8 +1332,9 @@ pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc {...@@ -1306,8 +1332,9 @@ pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc {
1306}1332}
13071333
1308fn checkUndefinedSymbols(wasm: *const Wasm) !void {1334fn checkUndefinedSymbols(wasm: *const Wasm) !void {
1309 if (wasm.base.comp.config.output_mode == .Obj) return;1335 const comp = wasm.base.comp;
1310 if (wasm.base.options.import_symbols) return;1336 if (comp.config.output_mode == .Obj) return;
1337 if (wasm.import_symbols) return;
13111338
1312 var found_undefined_symbols = false;1339 var found_undefined_symbols = false;
1313 for (wasm.undefs.values()) |undef| {1340 for (wasm.undefs.values()) |undef| {
...@@ -2182,7 +2209,10 @@ const Kind = union(enum) {...@@ -2182,7 +2209,10 @@ const Kind = union(enum) {
21822209
2183/// Parses an Atom and inserts its metadata into the corresponding sections.2210/// Parses an Atom and inserts its metadata into the corresponding sections.
2184fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {2211fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
2185 const gpa = wasm.base.comp.gpa;2212 const comp = wasm.base.comp;
2213 const gpa = comp.gpa;
2214 const shared_memory = comp.config.shared_memory;
2215 const import_memory = comp.config.import_memory;
2186 const atom = wasm.getAtomPtr(atom_index);2216 const atom = wasm.getAtomPtr(atom_index);
2187 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);2217 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);
2188 const do_garbage_collect = wasm.base.gc_sections;2218 const do_garbage_collect = wasm.base.gc_sections;
...@@ -2233,7 +2263,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {...@@ -2233,7 +2263,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
2233 // we set the entire region of it to zeroes.2263 // we set the entire region of it to zeroes.
2234 // We do not have to do this when exporting the memory (the default) because the runtime2264 // We do not have to do this when exporting the memory (the default) because the runtime
2235 // will do it for us, and we do not emit the bss segment at all.2265 // will do it for us, and we do not emit the bss segment at all.
2236 if ((wasm.base.comp.config.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) {2266 if ((wasm.base.comp.config.output_mode == .Obj or import_memory) and kind.data == .uninitialized) {
2237 @memset(atom.code.items, 0);2267 @memset(atom.code.items, 0);
2238 }2268 }
22392269
...@@ -2250,7 +2280,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {...@@ -2250,7 +2280,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
2250 } else {2280 } else {
2251 const index: u32 = @intCast(wasm.segments.items.len);2281 const index: u32 = @intCast(wasm.segments.items.len);
2252 var flags: u32 = 0;2282 var flags: u32 = 0;
2253 if (wasm.base.options.shared_memory) {2283 if (shared_memory) {
2254 flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);2284 flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);
2255 }2285 }
2256 try wasm.segments.append(gpa, .{2286 try wasm.segments.append(gpa, .{
...@@ -2679,9 +2709,11 @@ fn setupStartSection(wasm: *Wasm) !void {...@@ -2679,9 +2709,11 @@ fn setupStartSection(wasm: *Wasm) !void {
2679}2709}
26802710
2681fn initializeTLSFunction(wasm: *Wasm) !void {2711fn initializeTLSFunction(wasm: *Wasm) !void {
2682 const gpa = wasm.base.comp.gpa;2712 const comp = wasm.base.comp;
2713 const gpa = comp.gpa;
2714 const shared_memory = comp.config.shared_memory;
26832715
2684 if (!wasm.base.options.shared_memory) return;2716 if (!shared_memory) return;
26852717
2686 var function_body = std.ArrayList(u8).init(gpa);2718 var function_body = std.ArrayList(u8).init(gpa);
2687 defer function_body.deinit();2719 defer function_body.deinit();
...@@ -2940,7 +2972,7 @@ fn setupExports(wasm: *Wasm) !void {...@@ -2940,7 +2972,7 @@ fn setupExports(wasm: *Wasm) !void {
2940 if (wasm.base.comp.config.output_mode == .Obj) return;2972 if (wasm.base.comp.config.output_mode == .Obj) return;
2941 log.debug("Building exports from symbols", .{});2973 log.debug("Building exports from symbols", .{});
29422974
2943 const force_exp_names = wasm.base.options.export_symbol_names;2975 const force_exp_names = wasm.export_symbol_names;
2944 if (force_exp_names.len > 0) {2976 if (force_exp_names.len > 0) {
2945 var failed_exports = false;2977 var failed_exports = false;
29462978
...@@ -2962,7 +2994,7 @@ fn setupExports(wasm: *Wasm) !void {...@@ -2962,7 +2994,7 @@ fn setupExports(wasm: *Wasm) !void {
29622994
2963 for (wasm.resolved_symbols.keys()) |sym_loc| {2995 for (wasm.resolved_symbols.keys()) |sym_loc| {
2964 const symbol = sym_loc.getSymbol(wasm);2996 const symbol = sym_loc.getSymbol(wasm);
2965 if (!symbol.isExported(wasm.base.options.rdynamic)) continue;2997 if (!symbol.isExported(wasm.rdynamic)) continue;
29662998
2967 const sym_name = sym_loc.getName(wasm);2999 const sym_name = sym_loc.getName(wasm);
2968 const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {3000 const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {
...@@ -2997,8 +3029,9 @@ fn setupExports(wasm: *Wasm) !void {...@@ -2997,8 +3029,9 @@ fn setupExports(wasm: *Wasm) !void {
2997}3029}
29983030
2999fn setupStart(wasm: *Wasm) !void {3031fn setupStart(wasm: *Wasm) !void {
3032 const comp = wasm.base.comp;
3000 // do not export entry point if user set none or no default was set.3033 // do not export entry point if user set none or no default was set.
3001 const entry_name = wasm.base.options.entry orelse return;3034 const entry_name = comp.config.entry orelse return;
30023035
3003 const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse {3036 const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse {
3004 log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name});3037 log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name});
...@@ -3012,13 +3045,15 @@ fn setupStart(wasm: *Wasm) !void {...@@ -3012,13 +3045,15 @@ fn setupStart(wasm: *Wasm) !void {
3012 }3045 }
30133046
3014 // Ensure the symbol is exported so host environment can access it3047 // Ensure the symbol is exported so host environment can access it
3015 if (wasm.base.comp.config.output_mode != .Obj) {3048 if (comp.config.output_mode != .Obj) {
3016 symbol.setFlag(.WASM_SYM_EXPORTED);3049 symbol.setFlag(.WASM_SYM_EXPORTED);
3017 }3050 }
3018}3051}
30193052
3020/// Sets up the memory section of the wasm module, as well as the stack.3053/// Sets up the memory section of the wasm module, as well as the stack.
3021fn setupMemory(wasm: *Wasm) !void {3054fn setupMemory(wasm: *Wasm) !void {
3055 const comp = wasm.base.comp;
3056 const shared_memory = comp.config.shared_memory;
3022 log.debug("Setting up memory layout", .{});3057 log.debug("Setting up memory layout", .{});
3023 const page_size = std.wasm.page_size; // 64kb3058 const page_size = std.wasm.page_size; // 64kb
3024 const stack_alignment: Alignment = .@"16"; // wasm's stack alignment as specified by tool-convention3059 const stack_alignment: Alignment = .@"16"; // wasm's stack alignment as specified by tool-convention
...@@ -3027,12 +3062,12 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3027,12 +3062,12 @@ fn setupMemory(wasm: *Wasm) !void {
3027 // Always place the stack at the start by default3062 // Always place the stack at the start by default
3028 // unless the user specified the global-base flag3063 // unless the user specified the global-base flag
3029 var place_stack_first = true;3064 var place_stack_first = true;
3030 var memory_ptr: u64 = if (wasm.base.options.global_base) |base| blk: {3065 var memory_ptr: u64 = if (wasm.global_base) |base| blk: {
3031 place_stack_first = false;3066 place_stack_first = false;
3032 break :blk base;3067 break :blk base;
3033 } else 0;3068 } else 0;
30343069
3035 const is_obj = wasm.base.comp.config.output_mode == .Obj;3070 const is_obj = comp.config.output_mode == .Obj;
30363071
3037 if (place_stack_first and !is_obj) {3072 if (place_stack_first and !is_obj) {
3038 memory_ptr = stack_alignment.forward(memory_ptr);3073 memory_ptr = stack_alignment.forward(memory_ptr);
...@@ -3059,7 +3094,7 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3059,7 +3094,7 @@ fn setupMemory(wasm: *Wasm) !void {
3059 }3094 }
3060 if (wasm.findGlobalSymbol("__tls_base")) |loc| {3095 if (wasm.findGlobalSymbol("__tls_base")) |loc| {
3061 const sym = loc.getSymbol(wasm);3096 const sym = loc.getSymbol(wasm);
3062 wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (wasm.base.options.shared_memory)3097 wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (shared_memory)
3063 @as(i32, 0)3098 @as(i32, 0)
3064 else3099 else
3065 @as(i32, @intCast(memory_ptr));3100 @as(i32, @intCast(memory_ptr));
...@@ -3072,7 +3107,7 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3072,7 +3107,7 @@ fn setupMemory(wasm: *Wasm) !void {
3072 }3107 }
30733108
3074 // create the memory init flag which is used by the init memory function3109 // create the memory init flag which is used by the init memory function
3075 if (wasm.base.options.shared_memory and wasm.hasPassiveInitializationSegments()) {3110 if (shared_memory and wasm.hasPassiveInitializationSegments()) {
3076 // align to pointer size3111 // align to pointer size
3077 memory_ptr = mem.alignForward(u64, memory_ptr, 4);3112 memory_ptr = mem.alignForward(u64, memory_ptr, 4);
3078 const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data);3113 const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data);
...@@ -3098,7 +3133,7 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3098,7 +3133,7 @@ fn setupMemory(wasm: *Wasm) !void {
3098 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-13133 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1
3099 const max_memory_allowed: u64 = (1 << 32) - 1;3134 const max_memory_allowed: u64 = (1 << 32) - 1;
31003135
3101 if (wasm.base.options.initial_memory) |initial_memory| {3136 if (wasm.initial_memory) |initial_memory| {
3102 if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {3137 if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {
3103 log.err("Initial memory must be {d}-byte aligned", .{page_size});3138 log.err("Initial memory must be {d}-byte aligned", .{page_size});
3104 return error.MissAlignment;3139 return error.MissAlignment;
...@@ -3124,7 +3159,7 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3124,7 +3159,7 @@ fn setupMemory(wasm: *Wasm) !void {
3124 symbol.virtual_address = @as(u32, @intCast(memory_ptr));3159 symbol.virtual_address = @as(u32, @intCast(memory_ptr));
3125 }3160 }
31263161
3127 if (wasm.base.options.max_memory) |max_memory| {3162 if (wasm.max_memory) |max_memory| {
3128 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {3163 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {
3129 log.err("Maximum memory must be {d}-byte aligned", .{page_size});3164 log.err("Maximum memory must be {d}-byte aligned", .{page_size});
3130 return error.MissAlignment;3165 return error.MissAlignment;
...@@ -3139,7 +3174,7 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3139,7 +3174,7 @@ fn setupMemory(wasm: *Wasm) !void {
3139 }3174 }
3140 wasm.memories.limits.max = @as(u32, @intCast(max_memory / page_size));3175 wasm.memories.limits.max = @as(u32, @intCast(max_memory / page_size));
3141 wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_HAS_MAX);3176 wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_HAS_MAX);
3142 if (wasm.base.options.shared_memory) {3177 if (shared_memory) {
3143 wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_IS_SHARED);3178 wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_IS_SHARED);
3144 }3179 }
3145 log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max});3180 log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max});
...@@ -3150,20 +3185,22 @@ fn setupMemory(wasm: *Wasm) !void {...@@ -3150,20 +3185,22 @@ fn setupMemory(wasm: *Wasm) !void {
3150/// index of the segment within the final data section. When the segment does not yet3185/// index of the segment within the final data section. When the segment does not yet
3151/// exist, a new one will be initialized and appended. The new index will be returned in that case.3186/// exist, a new one will be initialized and appended. The new index will be returned in that case.
3152pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u32 {3187pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u32 {
3153 const gpa = wasm.base.comp.gpa;3188 const comp = wasm.base.comp;
3189 const gpa = comp.gpa;
3154 const object: Object = wasm.objects.items[object_index];3190 const object: Object = wasm.objects.items[object_index];
3155 const symbol = object.symtable[symbol_index];3191 const symbol = object.symtable[symbol_index];
3156 const index: u32 = @intCast(wasm.segments.items.len);3192 const index: u32 = @intCast(wasm.segments.items.len);
3193 const shared_memory = comp.config.shared_memory;
31573194
3158 switch (symbol.tag) {3195 switch (symbol.tag) {
3159 .data => {3196 .data => {
3160 const segment_info = object.segment_info[symbol.index];3197 const segment_info = object.segment_info[symbol.index];
3161 const merge_segment = wasm.base.comp.config.output_mode != .Obj;3198 const merge_segment = comp.config.output_mode != .Obj;
3162 const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment));3199 const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment));
3163 if (!result.found_existing) {3200 if (!result.found_existing) {
3164 result.value_ptr.* = index;3201 result.value_ptr.* = index;
3165 var flags: u32 = 0;3202 var flags: u32 = 0;
3166 if (wasm.base.options.shared_memory) {3203 if (shared_memory) {
3167 flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);3204 flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);
3168 }3205 }
3169 try wasm.segments.append(gpa, .{3206 try wasm.segments.append(gpa, .{
...@@ -3445,6 +3482,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -3445,6 +3482,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
3445 defer tracy.end();3482 defer tracy.end();
34463483
3447 const gpa = wasm.base.comp.gpa;3484 const gpa = wasm.base.comp.gpa;
3485 const shared_memory = comp.config.shared_memory;
3486 const import_memory = comp.config.import_memory;
34483487
3449 // Used for all temporary memory allocated during flushin3488 // Used for all temporary memory allocated during flushin
3450 var arena_instance = std.heap.ArenaAllocator.init(gpa);3489 var arena_instance = std.heap.ArenaAllocator.init(gpa);
...@@ -3509,8 +3548,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l...@@ -3509,8 +3548,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
3509 man.hash.addOptionalBytes(wasm.base.comp.config.entry);3548 man.hash.addOptionalBytes(wasm.base.comp.config.entry);
3510 man.hash.add(wasm.base.stack_size);3549 man.hash.add(wasm.base.stack_size);
3511 man.hash.add(wasm.base.build_id);3550 man.hash.add(wasm.base.build_id);
3512 man.hash.add(wasm.base.comp.config.import_memory);3551 man.hash.add(import_memory);
3513 man.hash.add(wasm.base.comp.config.shared_memory);3552 man.hash.add(shared_memory);
3514 man.hash.add(wasm.import_table);3553 man.hash.add(wasm.import_table);
3515 man.hash.add(wasm.export_table);3554 man.hash.add(wasm.export_table);
3516 man.hash.addOptional(wasm.initial_memory);3555 man.hash.addOptional(wasm.initial_memory);
...@@ -3726,8 +3765,12 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -3726,8 +3765,12 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
3726 } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) {3765 } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
3727 // for safe build modes, we store the atom in the data segment,3766 // for safe build modes, we store the atom in the data segment,
3728 // whereas for unsafe build modes we store it in bss.3767 // whereas for unsafe build modes we store it in bss.
3729 const is_initialized = wasm.base.options.optimize_mode == .Debug or3768 const decl_namespace = mod.namespacePtr(decl.src_namespace);
3730 wasm.base.options.optimize_mode == .ReleaseSafe;3769 const optimize_mode = decl_namespace.file_scope.mod.optimize_mode;
3770 const is_initialized = switch (optimize_mode) {
3771 .Debug, .ReleaseSafe => true,
3772 .ReleaseFast, .ReleaseSmall => false,
3773 };
3731 try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized });3774 try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized });
3732 } else {3775 } else {
3733 // when the decl is all zeroes, we store the atom in the bss segment,3776 // when the decl is all zeroes, we store the atom in the bss segment,
...@@ -3788,9 +3831,13 @@ fn writeToFile(...@@ -3788,9 +3831,13 @@ fn writeToFile(
3788 feature_count: u32,3831 feature_count: u32,
3789 arena: Allocator,3832 arena: Allocator,
3790) !void {3833) !void {
3791 const gpa = wasm.base.comp.gpa;3834 const comp = wasm.base.comp;
3792 const use_llvm = wasm.base.comp.config.use_llvm;3835 const gpa = comp.gpa;
3793 const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld;3836 const use_llvm = comp.config.use_llvm;
3837 const use_lld = build_options.have_llvm and comp.config.use_lld;
3838 const shared_memory = comp.config.shared_memory;
3839 const import_memory = comp.config.import_memory;
3840 const export_memory = comp.config.export_memory;
37943841
3795 // Size of each section header3842 // Size of each section header
3796 const header_size = 5 + 1;3843 const header_size = 5 + 1;
...@@ -3800,7 +3847,7 @@ fn writeToFile(...@@ -3800,7 +3847,7 @@ fn writeToFile(
3800 var code_section_index: ?u32 = null;3847 var code_section_index: ?u32 = null;
3801 // Index of the data section. Used to tell relocation table where the section lives.3848 // Index of the data section. Used to tell relocation table where the section lives.
3802 var data_section_index: ?u32 = null;3849 var data_section_index: ?u32 = null;
3803 const is_obj = wasm.base.comp.config.output_mode == .Obj or (!use_llvm and use_lld);3850 const is_obj = comp.config.output_mode == .Obj or (!use_llvm and use_lld);
38043851
3805 var binary_bytes = std.ArrayList(u8).init(gpa);3852 var binary_bytes = std.ArrayList(u8).init(gpa);
3806 defer binary_bytes.deinit();3853 defer binary_bytes.deinit();
...@@ -3840,8 +3887,6 @@ fn writeToFile(...@@ -3840,8 +3887,6 @@ fn writeToFile(
3840 }3887 }
38413888
3842 // Import section3889 // Import section
3843 const import_memory = wasm.base.options.import_memory or is_obj;
3844 const export_memory = wasm.base.options.export_memory;
3845 if (wasm.imports.count() != 0 or import_memory) {3890 if (wasm.imports.count() != 0 or import_memory) {
3846 const header_offset = try reserveVecSectionHeader(&binary_bytes);3891 const header_offset = try reserveVecSectionHeader(&binary_bytes);
38473892
...@@ -4018,7 +4063,7 @@ fn writeToFile(...@@ -4018,7 +4063,7 @@ fn writeToFile(
40184063
4019 // When the shared-memory option is enabled, we *must* emit the 'data count' section.4064 // When the shared-memory option is enabled, we *must* emit the 'data count' section.
4020 const data_segments_count = wasm.data_segments.count() - @intFromBool(wasm.data_segments.contains(".bss") and !import_memory);4065 const data_segments_count = wasm.data_segments.count() - @intFromBool(wasm.data_segments.contains(".bss") and !import_memory);
4021 if (data_segments_count != 0 and wasm.base.options.shared_memory) {4066 if (data_segments_count != 0 and shared_memory) {
4022 const header_offset = try reserveVecSectionHeader(&binary_bytes);4067 const header_offset = try reserveVecSectionHeader(&binary_bytes);
4023 try writeVecSectionHeader(4068 try writeVecSectionHeader(
4024 binary_bytes.items,4069 binary_bytes.items,
...@@ -4160,11 +4205,11 @@ fn writeToFile(...@@ -4160,11 +4205,11 @@ fn writeToFile(
4160 if (data_section_index) |data_index| {4205 if (data_section_index) |data_index| {
4161 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);4206 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
4162 }4207 }
4163 } else if (!wasm.base.options.strip) {4208 } else if (wasm.base.debug_format != .strip) {
4164 try wasm.emitNameSection(&binary_bytes, arena);4209 try wasm.emitNameSection(&binary_bytes, arena);
4165 }4210 }
41664211
4167 if (!wasm.base.options.strip) {4212 if (wasm.base.debug_format != .strip) {
4168 // The build id must be computed on the main sections only,4213 // The build id must be computed on the main sections only,
4169 // so we have to do it now, before the debug sections.4214 // so we have to do it now, before the debug sections.
4170 switch (wasm.base.build_id) {4215 switch (wasm.base.build_id) {
...@@ -4193,7 +4238,7 @@ fn writeToFile(...@@ -4193,7 +4238,7 @@ fn writeToFile(
4193 }4238 }
41944239
4195 // if (wasm.dwarf) |*dwarf| {4240 // if (wasm.dwarf) |*dwarf| {
4196 // const mod = wasm.base.comp.module.?;4241 // const mod = comp.module.?;
4197 // try dwarf.writeDbgAbbrev();4242 // try dwarf.writeDbgAbbrev();
4198 // // for debug info and ranges, the address is always 0,4243 // // for debug info and ranges, the address is always 0,
4199 // // as locations are always offsets relative to 'code' section.4244 // // as locations are always offsets relative to 'code' section.
...@@ -4380,6 +4425,8 @@ fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []con...@@ -4380,6 +4425,8 @@ fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []con
4380}4425}
43814426
4382fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {4427fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
4428 const comp = wasm.base.comp;
4429 const import_memory = comp.config.import_memory;
4383 const Name = struct {4430 const Name = struct {
4384 index: u32,4431 index: u32,
4385 name: []const u8,4432 name: []const u8,
...@@ -4418,7 +4465,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem...@@ -4418,7 +4465,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
4418 for (wasm.data_segments.keys()) |key| {4465 for (wasm.data_segments.keys()) |key| {
4419 // bss section is not emitted when this condition holds true, so we also4466 // bss section is not emitted when this condition holds true, so we also
4420 // do not output a name for it.4467 // do not output a name for it.
4421 if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue;4468 if (!import_memory and std.mem.eql(u8, key, ".bss")) continue;
4422 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });4469 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });
4423 data_segment_index += 1;4470 data_segment_index += 1;
4424 }4471 }
...@@ -4528,6 +4575,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4528,6 +4575,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4528 const tracy = trace(@src());4575 const tracy = trace(@src());
4529 defer tracy.end();4576 defer tracy.end();
45304577
4578 const shared_memory = comp.config.shared_memory;
4579 const export_memory = comp.config.export_memory;
4580 const import_memory = comp.config.import_memory;
4581 const target = comp.root_mod.resolved_target.result;
4582
4531 const gpa = wasm.base.comp.gpa;4583 const gpa = wasm.base.comp.gpa;
4532 var arena_allocator = std.heap.ArenaAllocator.init(gpa);4584 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
4533 defer arena_allocator.deinit();4585 defer arena_allocator.deinit();
...@@ -4560,8 +4612,6 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4560,8 +4612,6 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4560 break :blk null;4612 break :blk null;
4561 };4613 };
45624614
4563 const target = wasm.base.comp.root_mod.resolved_target.result;
4564
4565 const id_symlink_basename = "lld.id";4615 const id_symlink_basename = "lld.id";
45664616
4567 var man: Cache.Manifest = undefined;4617 var man: Cache.Manifest = undefined;
...@@ -4577,7 +4627,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4577,7 +4627,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
45774627
4578 comptime assert(Compilation.link_hash_implementation_version == 10);4628 comptime assert(Compilation.link_hash_implementation_version == 10);
45794629
4580 for (wasm.base.options.objects) |obj| {4630 for (comp.objects) |obj| {
4581 _ = try man.addFile(obj.path, null);4631 _ = try man.addFile(obj.path, null);
4582 man.hash.add(obj.must_link);4632 man.hash.add(obj.must_link);
4583 }4633 }
...@@ -4589,17 +4639,17 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4589,17 +4639,17 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4589 man.hash.addOptionalBytes(wasm.base.comp.config.entry);4639 man.hash.addOptionalBytes(wasm.base.comp.config.entry);
4590 man.hash.add(wasm.base.stack_size);4640 man.hash.add(wasm.base.stack_size);
4591 man.hash.add(wasm.base.build_id);4641 man.hash.add(wasm.base.build_id);
4592 man.hash.add(wasm.base.options.import_memory);4642 man.hash.add(import_memory);
4593 man.hash.add(wasm.base.options.export_memory);4643 man.hash.add(export_memory);
4594 man.hash.add(wasm.import_table);4644 man.hash.add(wasm.import_table);
4595 man.hash.add(wasm.export_table);4645 man.hash.add(wasm.export_table);
4596 man.hash.addOptional(wasm.base.options.initial_memory);4646 man.hash.addOptional(wasm.initial_memory);
4597 man.hash.addOptional(wasm.base.options.max_memory);4647 man.hash.addOptional(wasm.max_memory);
4598 man.hash.add(wasm.base.options.shared_memory);4648 man.hash.add(shared_memory);
4599 man.hash.addOptional(wasm.base.options.global_base);4649 man.hash.addOptional(wasm.global_base);
4600 man.hash.add(wasm.base.options.export_symbol_names.len);4650 man.hash.add(wasm.export_symbol_names.len);
4601 // strip does not need to go into the linker hash because it is part of the hash namespace4651 // strip does not need to go into the linker hash because it is part of the hash namespace
4602 for (wasm.base.options.export_symbol_names) |symbol_name| {4652 for (wasm.export_symbol_names) |symbol_name| {
4603 man.hash.addBytes(symbol_name);4653 man.hash.addBytes(symbol_name);
4604 }4654 }
46054655
...@@ -4637,8 +4687,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4637,8 +4687,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4637 // here. TODO: think carefully about how we can avoid this redundant operation when doing4687 // here. TODO: think carefully about how we can avoid this redundant operation when doing
4638 // build-obj. See also the corresponding TODO in linkAsArchive.4688 // build-obj. See also the corresponding TODO in linkAsArchive.
4639 const the_object_path = blk: {4689 const the_object_path = blk: {
4640 if (wasm.base.options.objects.len != 0)4690 if (comp.objects.len != 0)
4641 break :blk wasm.base.options.objects[0].path;4691 break :blk comp.objects[0].path;
46424692
4643 if (comp.c_object_table.count() != 0)4693 if (comp.c_object_table.count() != 0)
4644 break :blk comp.c_object_table.keys()[0].status.success.object_path;4694 break :blk comp.c_object_table.keys()[0].status.success.object_path;
...@@ -4666,19 +4716,19 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4666,19 +4716,19 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4666 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });4716 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
4667 try argv.append("--error-limit=0");4717 try argv.append("--error-limit=0");
46684718
4669 if (wasm.base.options.lto) {4719 if (comp.config.lto) {
4670 switch (wasm.base.options.optimize_mode) {4720 switch (comp.root_mod.optimize_mode) {
4671 .Debug => {},4721 .Debug => {},
4672 .ReleaseSmall => try argv.append("-O2"),4722 .ReleaseSmall => try argv.append("-O2"),
4673 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),4723 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
4674 }4724 }
4675 }4725 }
46764726
4677 if (wasm.base.options.import_memory) {4727 if (import_memory) {
4678 try argv.append("--import-memory");4728 try argv.append("--import-memory");
4679 }4729 }
46804730
4681 if (wasm.base.options.export_memory) {4731 if (export_memory) {
4682 try argv.append("--export-memory");4732 try argv.append("--export-memory");
4683 }4733 }
46844734
...@@ -4698,25 +4748,25 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4698,25 +4748,25 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4698 try argv.append("--no-gc-sections");4748 try argv.append("--no-gc-sections");
4699 }4749 }
47004750
4701 if (wasm.base.options.strip) {4751 if (wasm.base.debug_format == .strip) {
4702 try argv.append("-s");4752 try argv.append("-s");
4703 }4753 }
47044754
4705 if (wasm.base.options.initial_memory) |initial_memory| {4755 if (wasm.initial_memory) |initial_memory| {
4706 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});4756 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
4707 try argv.append(arg);4757 try argv.append(arg);
4708 }4758 }
47094759
4710 if (wasm.base.options.max_memory) |max_memory| {4760 if (wasm.max_memory) |max_memory| {
4711 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});4761 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
4712 try argv.append(arg);4762 try argv.append(arg);
4713 }4763 }
47144764
4715 if (wasm.base.options.shared_memory) {4765 if (shared_memory) {
4716 try argv.append("--shared-memory");4766 try argv.append("--shared-memory");
4717 }4767 }
47184768
4719 if (wasm.base.options.global_base) |global_base| {4769 if (wasm.global_base) |global_base| {
4720 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});4770 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
4721 try argv.append(arg);4771 try argv.append(arg);
4722 } else {4772 } else {
...@@ -4728,16 +4778,16 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4728,16 +4778,16 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4728 }4778 }
47294779
4730 // Users are allowed to specify which symbols they want to export to the wasm host.4780 // Users are allowed to specify which symbols they want to export to the wasm host.
4731 for (wasm.base.options.export_symbol_names) |symbol_name| {4781 for (wasm.export_symbol_names) |symbol_name| {
4732 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});4782 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
4733 try argv.append(arg);4783 try argv.append(arg);
4734 }4784 }
47354785
4736 if (wasm.base.options.rdynamic) {4786 if (wasm.rdynamic) {
4737 try argv.append("--export-dynamic");4787 try argv.append("--export-dynamic");
4738 }4788 }
47394789
4740 if (wasm.base.options.entry) |entry| {4790 if (comp.config.entry) |entry| {
4741 try argv.append("--entry");4791 try argv.append("--entry");
4742 try argv.append(entry);4792 try argv.append(entry);
4743 } else {4793 } else {
...@@ -4749,14 +4799,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4749,14 +4799,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4749 try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}),4799 try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}),
4750 });4800 });
47514801
4752 if (wasm.base.options.import_symbols) {4802 if (wasm.import_symbols) {
4753 try argv.append("--allow-undefined");4803 try argv.append("--allow-undefined");
4754 }4804 }
47554805
4756 if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) {4806 if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) {
4757 try argv.append("--shared");4807 try argv.append("--shared");
4758 }4808 }
4759 if (wasm.base.options.pie) {4809 if (comp.config.pie) {
4760 try argv.append("--pie");4810 try argv.append("--pie");
4761 }4811 }
47624812
...@@ -4782,15 +4832,15 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4782,15 +4832,15 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4782 ));4832 ));
4783 }4833 }
47844834
4785 if (wasm.base.options.link_libc) {4835 if (comp.config.link_libc) {
4786 try argv.append(try comp.get_libc_crt_file(4836 try argv.append(try comp.get_libc_crt_file(
4787 arena,4837 arena,
4788 wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model),4838 wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
4789 ));4839 ));
4790 try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));4840 try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));
4791 }4841 }
47924842
4793 if (wasm.base.options.link_libcpp) {4843 if (comp.config.link_libcpp) {
4794 try argv.append(comp.libcxx_static_lib.?.full_object_path);4844 try argv.append(comp.libcxx_static_lib.?.full_object_path);
4795 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);4845 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
4796 }4846 }
...@@ -4799,7 +4849,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4799,7 +4849,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
47994849
4800 // Positional arguments to the linker such as object files.4850 // Positional arguments to the linker such as object files.
4801 var whole_archive = false;4851 var whole_archive = false;
4802 for (wasm.base.options.objects) |obj| {4852 for (comp.objects) |obj| {
4803 if (obj.must_link and !whole_archive) {4853 if (obj.must_link and !whole_archive) {
4804 try argv.append("-whole-archive");4854 try argv.append("-whole-archive");
4805 whole_archive = true;4855 whole_archive = true;
...@@ -4822,8 +4872,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -4822,8 +4872,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
4822 }4872 }
48234873
4824 if (wasm.base.comp.config.output_mode != .Obj and4874 if (wasm.base.comp.config.output_mode != .Obj and
4825 !wasm.base.options.skip_linker_dependencies and4875 !comp.skip_linker_dependencies and
4826 !wasm.base.options.link_libc)4876 !comp.config.link_libc)
4827 {4877 {
4828 try argv.append(comp.libc_static_lib.?.full_object_path);4878 try argv.append(comp.libc_static_lib.?.full_object_path);
4829 }4879 }
...@@ -5168,10 +5218,13 @@ fn emitDataRelocations(...@@ -5168,10 +5218,13 @@ fn emitDataRelocations(
5168}5218}
51695219
5170fn hasPassiveInitializationSegments(wasm: *const Wasm) bool {5220fn hasPassiveInitializationSegments(wasm: *const Wasm) bool {
5221 const comp = wasm.base.comp;
5222 const import_memory = comp.config.import_memory;
5223
5171 var it = wasm.data_segments.iterator();5224 var it = wasm.data_segments.iterator();
5172 while (it.next()) |entry| {5225 while (it.next()) |entry| {
5173 const segment: Segment = wasm.segments.items[entry.value_ptr.*];5226 const segment: Segment = wasm.segments.items[entry.value_ptr.*];
5174 if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) {5227 if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) {
5175 return true;5228 return true;
5176 }5229 }
5177 }5230 }
...@@ -5227,14 +5280,14 @@ fn markReferences(wasm: *Wasm) !void {...@@ -5227,14 +5280,14 @@ fn markReferences(wasm: *Wasm) !void {
52275280
5228 for (wasm.resolved_symbols.keys()) |sym_loc| {5281 for (wasm.resolved_symbols.keys()) |sym_loc| {
5229 const sym = sym_loc.getSymbol(wasm);5282 const sym = sym_loc.getSymbol(wasm);
5230 if (sym.isExported(wasm.base.options.rdynamic) or sym.isNoStrip() or !do_garbage_collect) {5283 if (sym.isExported(wasm.rdynamic) or sym.isNoStrip() or !do_garbage_collect) {
5231 try wasm.mark(sym_loc);5284 try wasm.mark(sym_loc);
5232 continue;5285 continue;
5233 }5286 }
52345287
5235 // Debug sections may require to be parsed and marked when it contains5288 // Debug sections may require to be parsed and marked when it contains
5236 // relocations to alive symbols.5289 // relocations to alive symbols.
5237 if (sym.tag == .section and !wasm.base.options.strip) {5290 if (sym.tag == .section and wasm.base.debug_format != .strip) {
5238 const file = sym_loc.file orelse continue; // Incremental debug info is done independently5291 const file = sym_loc.file orelse continue; // Incremental debug info is done independently
5239 const object = &wasm.objects.items[file];5292 const object = &wasm.objects.items[file];
5240 const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);5293 const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);