From 33cdf33b95676dca9f91216e0f8742f9cf7e84fb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 18:28:00 -0700 Subject: [PATCH] compiler: update many references to bin_file.options --- src/Compilation.zig | 368 ++++++++++++++++--------------- src/Package/Module.zig | 17 ++ src/codegen/llvm.zig | 2 +- src/codegen/spirv.zig | 12 +- src/link.zig | 19 +- src/link/Coff.zig | 24 +- src/link/Elf.zig | 60 ++++- src/link/MachO/load_commands.zig | 2 +- src/link/MachO/zld.zig | 2 +- src/link/SpirV.zig | 2 + src/main.zig | 40 ++-- 11 files changed, 318 insertions(+), 230 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index be9fb2a989..5f99c85ba0 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -77,6 +77,7 @@ system_libs: std.StringArrayHashMapUnmanaged(SystemLib), version: ?std.SemanticVersion, libc_installation: ?*const LibCInstallation, skip_linker_dependencies: bool, +no_builtin: bool, c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = @@ -988,10 +989,9 @@ pub const InitOptions = struct { linker_tsaware: bool = false, linker_nxcompat: bool = false, linker_dynamicbase: bool = true, - linker_optimization: ?u8 = null, - linker_compress_debug_sections: ?link.CompressDebugSections = null, + linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null, linker_module_definition_file: ?[]const u8 = null, - linker_sort_section: ?link.SortSection = null, + linker_sort_section: ?link.File.Elf.SortSection = null, major_subsystem_version: ?u32 = null, minor_subsystem_version: ?u32 = null, clang_passthrough_mode: bool = false, @@ -1011,7 +1011,7 @@ pub const InitOptions = struct { /// building such dependencies themselves, this flag must be set to avoid /// infinite recursion. skip_linker_dependencies: bool = false, - hash_style: link.HashStyle = .both, + hash_style: link.File.Elf.HashStyle = .both, entry: ?[]const u8 = null, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, stack_size: ?u64 = null, @@ -1049,8 +1049,6 @@ pub const InitOptions = struct { /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, error_limit: ?Compilation.Module.ErrorInt = null, - /// (SPIR-V) whether to generate a structured control flow graph or not - want_structured_cfg: ?bool = null, }; fn addModuleTableToCacheHash( @@ -1277,10 +1275,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } } - const linker_optimization: u8 = options.linker_optimization orelse switch (options.root_mod.optimize_mode) { - .Debug => @as(u8, 0), - else => @as(u8, 3), - }; // TODO: https://github.com/ziglang/zig/issues/17969 const formatted_panics = options.formatted_panics orelse (options.root_mod.optimize_mode == .Debug); @@ -1359,7 +1353,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { hash.add(formatted_panics); hash.add(options.emit_h != null); hash.add(error_limit); - hash.addOptional(options.want_structured_cfg); // In the case of incremental cache mode, this `zig_cache_artifact_directory` // is computed based on a hash of non-linker inputs, and it is where all @@ -1641,13 +1634,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .framework_dirs = options.framework_dirs, .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit, .skip_linker_dependencies = options.skip_linker_dependencies, + .no_builtin = options.no_builtin, }; if (bin_file_emit) |emit| { comp.bin_file = try link.File.open(arena, .{ .comp = comp, .emit = emit, - .optimization = linker_optimization, .linker_script = options.linker_script, .z_nodelete = options.linker_z_nodelete, .z_notext = options.linker_z_notext, @@ -1666,7 +1659,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .symbol_wrap_set = options.symbol_wrap_set, .function_sections = options.function_sections, .data_sections = options.data_sections, - .no_builtin = options.no_builtin, .allow_shlib_undefined = options.linker_allow_shlib_undefined, .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, .compress_debug_sections = options.linker_compress_debug_sections orelse .none, @@ -1713,7 +1705,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .force_undefined_symbols = options.force_undefined_symbols, .pdb_source_path = options.pdb_source_path, .pdb_out_path = options.pdb_out_path, - .want_structured_cfg = options.want_structured_cfg, .entry_addr = null, // CLI does not expose this option (yet?) }); } @@ -2076,7 +2067,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void }; if (is_hit) { comp.last_update_was_cache_hit = true; - log.debug("CacheMode.whole cache hit for {s}", .{comp.bin_file.options.root_name}); + log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); const digest = man.final(); comp.wholeCacheModeSetBinFilePath(&digest); @@ -2085,7 +2076,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void comp.bin_file.lock = man.toOwnedLock(); return; } - log.debug("CacheMode.whole cache miss for {s}", .{comp.bin_file.options.root_name}); + log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name}); // Initialize `bin_file.emit` with a temporary Directory so that compilation can // continue on the same path as incremental, using the temporary Directory. @@ -2169,7 +2160,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // import_table here. // Likewise, in the case of `zig test`, the test runner is the root source file, // and so there is nothing to import the main file. - if (comp.bin_file.options.is_test) { + if (comp.config.is_test) { _ = try module.importPkg(module.main_mod); } @@ -2194,7 +2185,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } try comp.work_queue.writeItem(.{ .analyze_mod = std_mod }); - if (comp.bin_file.options.is_test) { + if (comp.config.is_test) { try comp.work_queue.writeItem(.{ .analyze_mod = module.main_mod }); } @@ -2208,20 +2199,20 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void if (comp.module) |module| { if (builtin.mode == .Debug and comp.verbose_intern_pool) { std.debug.print("intern pool stats for '{s}':\n", .{ - comp.bin_file.options.root_name, + comp.root_name, }); module.intern_pool.dump(); } if (builtin.mode == .Debug and comp.verbose_generic_instances) { std.debug.print("generic instances for '{s}:0x{x}':\n", .{ - comp.bin_file.options.root_name, + comp.root_name, @as(usize, @intFromPtr(module)), }); module.intern_pool.dumpGenericInstances(comp.gpa); } - if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) { + if (comp.config.is_test and comp.totalErrorCount() == 0) { // The `test_functions` decl has been intentionally postponed until now, // at which point we must populate it with the list of test functions that // have been discovered and not filtered out. @@ -2336,7 +2327,7 @@ fn maybeGenerateAutodocs(comp: *Compilation, prog_node: *std.Progress.Node) !voi // file copies at the end of generate() can also be extracted to // separate jobs if (!build_options.only_c and !build_options.only_core_functionality) { - if (comp.bin_file.options.docs_emit) |emit| { + if (comp.docs_emit) |emit| { var dir = try emit.directory.handle.makeOpenPath(emit.sub_path, .{}); defer dir.close(); @@ -2426,24 +2417,16 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.main_mod, .{ .files = man }); // Synchronize with other matching comments: ZigOnlyHashStuff - man.hash.add(comp.config.use_llvm); - man.hash.add(comp.config.use_lib_llvm); - man.hash.add(comp.bin_file.options.dll_export_fns); - man.hash.add(comp.bin_file.options.is_test); - man.hash.add(comp.test_evented_io); + man.hash.add(comp.config.test_evented_io); man.hash.addOptionalBytes(comp.test_filter); man.hash.addOptionalBytes(comp.test_name_prefix); man.hash.add(comp.skip_linker_dependencies); man.hash.add(comp.formatted_panics); man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); - man.hash.add(comp.bin_file.options.want_structured_cfg); } - try man.addOptionalFile(comp.bin_file.options.linker_script); - try man.addOptionalFile(comp.bin_file.options.version_script); - - for (comp.bin_file.options.objects) |obj| { + for (comp.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); man.hash.add(obj.loption); @@ -2469,39 +2452,19 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } } + man.hash.addOptionalBytes(comp.sysroot); + man.hash.addOptional(comp.version); man.hash.addListOfBytes(comp.rc_include_dir_list); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); - man.hash.add(comp.bin_file.stack_size); - man.hash.add(comp.bin_file.options.gc_sections); - man.hash.add(comp.bin_file.options.eh_frame_hdr); - man.hash.add(comp.bin_file.options.emit_relocs); - man.hash.add(comp.bin_file.options.rdynamic); - man.hash.addListOfBytes(comp.bin_file.options.lib_dirs); - man.hash.addListOfBytes(comp.bin_file.options.rpath_list); - man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys()); - man.hash.add(comp.bin_file.options.each_lib_rpath); - man.hash.add(comp.bin_file.build_id); man.hash.add(comp.skip_linker_dependencies); - man.hash.add(comp.bin_file.options.z_nodelete); - man.hash.add(comp.bin_file.options.z_notext); - man.hash.add(comp.bin_file.options.z_defs); - man.hash.add(comp.bin_file.options.z_origin); - man.hash.add(comp.bin_file.options.z_nocopyreloc); - man.hash.add(comp.bin_file.options.z_now); - man.hash.add(comp.bin_file.options.z_relro); - man.hash.add(comp.bin_file.options.z_common_page_size orelse 0); - man.hash.add(comp.bin_file.options.z_max_page_size orelse 0); - man.hash.add(comp.bin_file.options.hash_style); - man.hash.add(comp.bin_file.options.compress_debug_sections); man.hash.add(comp.include_compiler_rt); - man.hash.add(comp.bin_file.options.sort_section); if (comp.config.link_libc) { - man.hash.add(comp.bin_file.options.libc_installation != null); - if (comp.bin_file.options.libc_installation) |libc_installation| { + man.hash.add(comp.libc_installation != null); + if (comp.libc_installation) |libc_installation| { man.hash.addOptionalBytes(libc_installation.crt_dir); if (target.abi == .msvc) { man.hash.addOptionalBytes(libc_installation.msvc_lib_dir); @@ -2510,55 +2473,93 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } man.hash.addOptionalBytes(target.dynamic_linker.get()); } - man.hash.addOptionalBytes(comp.bin_file.options.soname); - man.hash.add(comp.bin_file.options.version); try link.hashAddSystemLibs(man, comp.system_libs); - man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys()); - man.hash.add(comp.bin_file.allow_shlib_undefined); - man.hash.add(comp.bin_file.options.bind_global_refs_locally); - man.hash.add(comp.bin_file.options.tsan); - man.hash.addOptionalBytes(comp.bin_file.options.sysroot); - man.hash.add(comp.bin_file.options.linker_optimization); - switch (comp.bin_file.tag) { - .elf => { - const elf = comp.bin_file.cast(link.File.Elf).?; - man.hash.add(elf.image_base); - }, - .wasm => { - const wasm = comp.bin_file.cast(link.File.Wasm).?; - man.hash.add(comp.config.import_memory); - man.hash.add(comp.config.export_memory); - man.hash.add(comp.config.shared_memory); - man.hash.add(wasm.initial_memory); - man.hash.add(wasm.max_memory); - man.hash.add(wasm.global_base); - }, - .macho => { - const macho = comp.bin_file.cast(link.File.MachO).?; - man.hash.addListOfBytes(comp.framework_dirs); - try link.hashAddFrameworks(man, macho.frameworks); - try man.addOptionalFile(macho.entitlements); - man.hash.add(macho.pagezero_size); - man.hash.add(macho.headerpad_size); - man.hash.add(macho.headerpad_max_install_names); - man.hash.add(macho.dead_strip_dylibs); - }, - .coff => { - const coff = comp.bin_file.cast(link.File.Coff).?; - man.hash.add(coff.image_base); - man.hash.add(coff.subsystem); - man.hash.add(coff.tsaware); - man.hash.add(coff.nxcompat); - man.hash.add(coff.dynamicbase); - man.hash.add(coff.major_subsystem_version); - man.hash.add(coff.minor_subsystem_version); - }, + man.hash.add(comp.config.use_llvm); + man.hash.add(comp.config.use_lib_llvm); + man.hash.add(comp.config.is_test); + man.hash.add(comp.config.import_memory); + man.hash.add(comp.config.export_memory); + man.hash.add(comp.config.shared_memory); + + if (comp.bin_file) |lf| { + man.hash.add(lf.stack_size); + man.hash.add(lf.gc_sections); + man.hash.addListOfBytes(lf.rpath_list); + man.hash.add(lf.build_id); + man.hash.addListOfBytes(lf.force_undefined_symbols.keys()); + man.hash.add(lf.allow_shlib_undefined); + + switch (lf.tag) { + .elf => { + const elf = lf.cast(link.File.Elf).?; + man.hash.add(elf.rdynamic); + man.hash.add(elf.eh_frame_hdr); + man.hash.add(elf.image_base); + man.hash.add(elf.emit_relocs); + man.hash.add(elf.z_nodelete); + man.hash.add(elf.z_notext); + man.hash.add(elf.z_defs); + man.hash.add(elf.z_origin); + man.hash.add(elf.z_nocopyreloc); + man.hash.add(elf.z_now); + man.hash.add(elf.z_relro); + man.hash.add(elf.z_common_page_size orelse 0); + man.hash.add(elf.z_max_page_size orelse 0); + man.hash.addListOfBytes(elf.lib_dirs); + man.hash.add(elf.hash_style); + man.hash.add(elf.compress_debug_sections); + man.hash.addListOfBytes(elf.symbol_wrap_set.keys()); + man.hash.add(elf.each_lib_rpath); + man.hash.addOptional(elf.sort_section); + man.hash.addOptionalBytes(elf.soname); + man.hash.add(elf.bind_global_refs_locally); + try man.addOptionalFile(elf.linker_script); + try man.addOptionalFile(elf.version_script); + }, + .wasm => { + const wasm = lf.cast(link.File.Wasm).?; + man.hash.add(wasm.rdynamic); + man.hash.add(wasm.initial_memory); + man.hash.add(wasm.max_memory); + man.hash.add(wasm.global_base); + }, + .macho => { + const macho = lf.cast(link.File.MachO).?; + man.hash.addListOfBytes(comp.framework_dirs); + try link.File.MachO.hashAddFrameworks(man, macho.frameworks); + try man.addOptionalFile(macho.entitlements); + man.hash.add(macho.pagezero_vmsize); + man.hash.add(macho.headerpad_size); + man.hash.add(macho.headerpad_max_install_names); + man.hash.add(macho.dead_strip_dylibs); + }, + .coff => { + const coff = lf.cast(link.File.Coff).?; + man.hash.add(coff.dll_export_fns); + man.hash.add(coff.image_base); + man.hash.addOptional(coff.subsystem); + man.hash.add(coff.tsaware); + man.hash.add(coff.nxcompat); + man.hash.add(coff.dynamicbase); + man.hash.add(coff.major_subsystem_version); + man.hash.add(coff.minor_subsystem_version); + man.hash.addListOfBytes(coff.lib_dirs); + }, + .spirv => { + const spirv = lf.cast(link.File.SpirV).?; + _ = spirv; + // TODO + }, + .c => {}, // TODO + .plan9 => {}, // TODO + .nvptx => {}, // TODO + } } } fn emitOthers(comp: *Compilation) void { - if (comp.bin_file.options.output_mode != .Obj or comp.module != null or + if (comp.config.output_mode != .Obj or comp.module != null or comp.c_object_table.count() == 0) { return; @@ -2724,10 +2725,10 @@ pub fn saveState(comp: *Compilation) !void { var bufs_list: [6]std.os.iovec_const = undefined; var bufs_len: usize = 0; - const emit = comp.bin_file.options.emit orelse return; + const lf = comp.bin_file orelse return; - if (comp.module) |mod| { - const ip = &mod.intern_pool; + if (comp.module) |zcu| { + const ip = &zcu.intern_pool; const header: Header = .{ .intern_pool = .{ .items_len = @intCast(ip.items.len), @@ -2751,7 +2752,7 @@ pub fn saveState(comp: *Compilation) !void { } var basename_buf: [255]u8 = undefined; const basename = std.fmt.bufPrint(&basename_buf, "{s}.zcs", .{ - comp.bin_file.options.root_name, + comp.root_name, }) catch o: { basename_buf[basename_buf.len - 4 ..].* = ".zcs".*; break :o &basename_buf; @@ -2759,7 +2760,7 @@ pub fn saveState(comp: *Compilation) !void { // Using an atomic file prevents a crash or power failure from corrupting // the previous incremental compilation state. - var af = try emit.directory.handle.atomicFile(basename, .{}); + var af = try lf.emit.directory.handle.atomicFile(basename, .{}); defer af.deinit(); try af.file.pwritevAll(bufs_list[0..bufs_len], 0); try af.finish(); @@ -3507,7 +3508,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v error.AnalysisFail => return, }; const decl = module.declPtr(decl_index); - if (decl.kind == .@"test" and comp.bin_file.options.is_test) { + if (decl.kind == .@"test" and comp.config.is_test) { // Tests are always emitted in test binaries. The decl_refs are created by // Module.populateTestFunctions, but this will not queue body analysis, so do // that now. @@ -3850,7 +3851,7 @@ pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest { // based on the zig library directory alone. The zig lib directory file // path is purposefully either in the cache or not in the cache. The // decision should not be overridden here. - if (comp.bin_file.options.libc_installation != null) { + if (comp.libc_installation != null) { man.hash.addListOfBytes(comp.libc_include_dir_list); } @@ -4248,9 +4249,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P // file and building an object we need to link them together, but with just one it should go // directly to the output file. const direct_o = comp.c_source_files.len == 1 and comp.module == null and - comp.bin_file.options.output_mode == .Obj and comp.bin_file.options.objects.len == 0; + comp.config.output_mode == .Obj and comp.objects.len == 0; const o_basename_noext = if (direct_o) - comp.bin_file.options.root_name + comp.root_name else c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len]; @@ -4304,8 +4305,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P try argv.appendSlice(c_object.src.extra_flags); try argv.appendSlice(c_object.src.cache_exempt_flags); - const out_obj_path = if (comp.bin_file.options.emit) |emit| - try emit.directory.join(arena, &.{emit.sub_path}) + const out_obj_path = if (comp.bin_file) |lf| + try lf.emit.directory.join(arena, &.{lf.emit.sub_path}) else "/dev/null"; @@ -4883,8 +4884,9 @@ pub fn addCCArgs( argv: *std.ArrayList([]const u8), ext: FileExt, out_dep_path: ?[]const u8, + mod: *Package.Module, ) !void { - const target = comp.getTarget(); + const target = mod.resolved_target.result; // As of Clang 16.x, it will by default read extra flags from /etc/clang. // I'm sure the person who implemented this means well, but they have a lot @@ -4905,15 +4907,15 @@ pub fn addCCArgs( try argv.append("-fno-caret-diagnostics"); } - if (comp.bin_file.options.function_sections) { + if (comp.bin_file.function_sections) { try argv.append("-ffunction-sections"); } - if (comp.bin_file.options.data_sections) { + if (comp.bin_file.data_sections) { try argv.append("-fdata-sections"); } - if (comp.bin_file.options.no_builtin) { + if (comp.no_builtin) { try argv.append("-fno-builtin"); } @@ -4953,7 +4955,7 @@ pub fn addCCArgs( })); } - if (comp.bin_file.options.link_libunwind) { + if (comp.config.link_libunwind) { const libunwind_include_path = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "libunwind", "include", }); @@ -4987,7 +4989,7 @@ pub fn addCCArgs( "-nostdinc", "-fno-spell-checking", }); - if (comp.bin_file.options.lto) { + if (comp.config.lto) { try argv.append("-flto"); } @@ -5042,9 +5044,8 @@ pub fn addCCArgs( argv.appendAssumeCapacity(arg); } } - const code_model = comp.bin_file.options.machine_code_model; - if (code_model != .default) { - try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(code_model)})); + if (mod.code_model != .default) { + try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)})); } switch (target.os.tag) { @@ -5093,7 +5094,7 @@ pub fn addCCArgs( try argv.append("-mthumb"); } - if (comp.sanitize_c and !comp.bin_file.options.tsan) { + if (mod.sanitize_c and !mod.sanitize_thread) { try argv.append("-fsanitize=undefined"); try argv.append("-fsanitize-trap=undefined"); // It is very common, and well-defined, for a pointer on one side of a C ABI @@ -5104,27 +5105,27 @@ pub fn addCCArgs( // Without this flag, Clang would invoke UBSAN when such an extern // function was called. try argv.append("-fno-sanitize=function"); - } else if (comp.sanitize_c and comp.bin_file.options.tsan) { + } else if (mod.sanitize_c and mod.sanitize_thread) { try argv.append("-fsanitize=undefined,thread"); try argv.append("-fsanitize-trap=undefined"); try argv.append("-fno-sanitize=function"); - } else if (!comp.sanitize_c and comp.bin_file.options.tsan) { + } else if (!mod.sanitize_c and mod.sanitize_thread) { try argv.append("-fsanitize=thread"); } - if (comp.bin_file.options.red_zone) { + if (mod.red_zone) { try argv.append("-mred-zone"); } else if (target_util.hasRedZone(target)) { try argv.append("-mno-red-zone"); } - if (comp.bin_file.options.omit_frame_pointer) { + if (mod.omit_frame_pointer) { try argv.append("-fomit-frame-pointer"); } else { try argv.append("-fno-omit-frame-pointer"); } - const ssp_buf_size = comp.bin_file.options.stack_protector; + const ssp_buf_size = mod.stack_protector; if (ssp_buf_size != 0) { try argv.appendSlice(&[_][]const u8{ "-fstack-protector-strong", @@ -5135,7 +5136,7 @@ pub fn addCCArgs( try argv.append("-fno-stack-protector"); } - switch (comp.bin_file.options.optimize_mode) { + switch (mod.optimize_mode) { .Debug => { // windows c runtime requires -D_DEBUG if using debug libraries try argv.append("-D_DEBUG"); @@ -5165,7 +5166,7 @@ pub fn addCCArgs( }, } - if (target_util.supports_fpic(target) and comp.bin_file.options.pic) { + if (target_util.supports_fpic(target) and mod.pic) { try argv.append("-fPIC"); } @@ -5940,7 +5941,7 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const { return comp.crt_files.get(basename).?.full_object_path; } - const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable; + const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable; const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename }); return full_path; @@ -6112,7 +6113,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool { pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend { const target = comp.root_mod.resolved_target.result; - return target_util.zigBackend(target, comp.bin_file.options.use_llvm); + return target_util.zigBackend(target, comp.config.use_llvm); } pub fn updateSubCompilation( @@ -6165,6 +6166,9 @@ fn buildOutputFromZig( assert(output_mode != .Exe); + const lf = comp.bin_file.?; + const unwind_tables = if (lf.cast(link.File.Elf)) |elf| elf.eh_frame_hdr else false; + const config = try Config.resolve(.{ .output_mode = output_mode, .resolved_target = comp.root_mod.resolved_target, @@ -6173,6 +6177,7 @@ fn buildOutputFromZig( .emit_bin = true, .root_optimize_mode = comp.compilerRtOptMode(), .link_libc = comp.config.link_libc, + .any_unwind_tables = unwind_tables, }); const root_mod = Package.Module.create(.{ @@ -6187,9 +6192,10 @@ fn buildOutputFromZig( .stack_protector = 0, .red_zone = comp.root_mod.red_zone, .omit_frame_pointer = comp.root_mod.omit_frame_pointer, - .unwind_tables = comp.bin_file.options.eh_frame_hdr, + .unwind_tables = unwind_tables, .pic = comp.root_mod.pic, .optimize_mode = comp.compilerRtOptMode(), + .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, .cc_argv = &.{}, @@ -6210,21 +6216,21 @@ fn buildOutputFromZig( .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .self_exe_path = comp.self_exe_path, .resolved = config, .root_mod = root_mod, .cache_mode = .whole, .root_name = root_name, .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.libc_installation, + .libc_installation = comp.libc_installation, .emit_bin = emit_bin, .link_mode = .Static, .function_sections = true, .data_sections = true, .no_builtin = true, .emit_h = null, - .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, - .verbose_link = comp.bin_file.options.verbose_link, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_intern_pool = comp.verbose_intern_pool, .verbose_generic_instances = comp.verbose_intern_pool, @@ -6234,7 +6240,6 @@ fn buildOutputFromZig( .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, - .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); @@ -6242,8 +6247,8 @@ fn buildOutputFromZig( assert(out.* == null); out.* = Compilation.CRTFile{ - .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.emit.?.sub_path, + .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(comp.gpa, &[_][]const u8{ + sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), }; @@ -6260,51 +6265,70 @@ pub fn build_crt_file( const tracy_trace = trace(@src()); defer tracy_trace.end(); - const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(comp.gpa, .{ + const gpa = comp.gpa; + const basename = try std.zig.binNameAlloc(gpa, .{ .root_name = root_name, - .target = target, + .target = comp.root_mod.resolved_target.result, .output_mode = output_mode, }); - errdefer comp.gpa.free(basename); + errdefer gpa.free(basename); - const sub_compilation = try Compilation.create(comp.gpa, .{ + const config = try Config.resolve(.{ + .output_mode = output_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = comp.compilerRtOptMode(), + .link_libc = false, + .lto = switch (output_mode) { + .Lib => comp.config.lto, + .Obj, .Exe => false, + }, + }); + const root_mod = Package.Module.create(.{ + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .strip = comp.compilerRtStrip(), + .stack_check = false, + .stack_protector = 0, + .sanitize_c = false, + .sanitize_thread = false, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .unwind_tables = false, + .pic = comp.root_mod.pic, + .optimize_mode = comp.compilerRtOptMode(), + .structured_cfg = comp.root_mod.structured_cfg, + }, + .global = config, + .cc_argv = &.{}, + }); + + const sub_compilation = try Compilation.create(gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .self_exe_path = comp.self_exe_path, .cache_mode = .whole, - .target = target, + .resolved = config, + .root_mod = root_mod, .root_name = root_name, - .main_mod = null, - .output_mode = output_mode, .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.libc_installation, + .libc_installation = comp.libc_installation, .emit_bin = .{ .directory = null, // Put it in the cache directory. .basename = basename, }, - .optimize_mode = comp.compilerRtOptMode(), - .want_sanitize_c = false, - .want_stack_check = false, - .want_stack_protector = 0, - .want_red_zone = comp.bin_file.options.red_zone, - .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer, - .want_valgrind = false, - .want_tsan = false, - .want_pic = comp.bin_file.options.pic, - .want_pie = null, - .want_lto = switch (output_mode) { - .Lib => comp.bin_file.options.lto, - .Obj, .Exe => false, - }, .emit_h = null, - .strip = comp.compilerRtStrip(), - .is_native_os = comp.bin_file.options.is_native_os, - .is_native_abi = comp.bin_file.options.is_native_abi, - .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files, .verbose_cc = comp.verbose_cc, - .verbose_link = comp.bin_file.options.verbose_link, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_intern_pool = comp.verbose_intern_pool, .verbose_generic_instances = comp.verbose_generic_instances, @@ -6314,17 +6338,16 @@ pub fn build_crt_file( .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, - .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); - try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1); + try comp.crt_files.ensureUnusedCapacity(gpa, 1); comp.crt_files.putAssumeCapacityNoClobber(basename, .{ - .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.emit.?.sub_path, + .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &[_][]const u8{ + sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), }); @@ -6357,10 +6380,11 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { /// compiler-rt, libcxx, libc, libunwind, etc. pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode { if (comp.debug_compiler_runtime_libs) { - return comp.bin_file.options.optimize_mode; + return comp.root_mod.optimize_mode; } - switch (comp.bin_file.options.optimize_mode) { - .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(comp.getTarget()), + const target = comp.root_mod.resolved_target.result; + switch (comp.root_mod.optimize_mode) { + .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(target), .ReleaseFast => return .ReleaseFast, .ReleaseSmall => return .ReleaseSmall, } @@ -6369,5 +6393,5 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode { /// This decides whether to strip debug info for all zig-provided libraries, including /// compiler-rt, libcxx, libc, libunwind, etc. pub fn compilerRtStrip(comp: Compilation) bool { - return comp.bin_file.options.strip; + return comp.root_mod.strip; } diff --git a/src/Package/Module.zig b/src/Package/Module.zig index f1e7091855..0916742876 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -30,6 +30,8 @@ sanitize_c: bool, sanitize_thread: bool, unwind_tables: bool, cc_argv: []const []const u8, +/// (SPIR-V) whether to generate a structured control flow graph or not +structured_cfg: bool, /// The contents of `@import("builtin")` for this module. generated_builtin_source: []const u8, @@ -82,6 +84,7 @@ pub const CreateOptions = struct { unwind_tables: ?bool = null, sanitize_c: ?bool = null, sanitize_thread: ?bool = null, + structured_cfg: ?bool = null, }; }; @@ -268,6 +271,17 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { break :sp target_util.default_stack_protector_buffer_size; }; + const structured_cfg = b: { + if (options.inherited.structured_cfg) |x| break :b x; + if (options.parent) |p| break :b p.structured_cfg; + // We always want a structured control flow in shaders. This option is + // only relevant for OpenCL kernels. + break :b switch (target.os.tag) { + .opencl => false, + else => true, + }; + }; + const llvm_cpu_features: ?[*:0]const u8 = b: { if (resolved_target.llvm_cpu_features) |x| break :b x; if (!options.global.use_llvm) break :b null; @@ -350,6 +364,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .sanitize_thread = sanitize_thread, .unwind_tables = unwind_tables, .cc_argv = &.{}, + .structured_cfg = structured_cfg, }; break :b new; }; @@ -381,6 +396,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .sanitize_thread = sanitize_thread, .unwind_tables = unwind_tables, .cc_argv = options.cc_argv, + .structured_cfg = structured_cfg, }; try mod.deps.ensureUnusedCapacity(arena, 1); @@ -422,6 +438,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P .unwind_tables = undefined, .cc_argv = undefined, .generated_builtin_source = undefined, + .structured_cfg = undefined, }; return mod; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index beb3e5e9f6..ee9e3de086 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3084,7 +3084,7 @@ pub const Object = struct { if (comp.unwind_tables) { try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); } - if (comp.skip_linker_dependencies or comp.bin_file.options.no_builtin) { + if (comp.skip_linker_dependencies or comp.no_builtin) { // The intent here is for compiler-rt and libc functions to not generate // infinite recursion. For example, if we are compiling the memcpy function, // and llvm detects that the body is equivalent to memcpy, it may replace the diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index fb1f2bb827..6b2587e3cb 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -191,13 +191,9 @@ pub const Object = struct { air: Air, liveness: Liveness, ) !void { - const target = mod.getTarget(); - // We always want a structured control flow in shaders. This option is only relevant - // for OpenCL kernels. - const want_structured_cfg = switch (target.os.tag) { - .opencl => mod.comp.bin_file.options.want_structured_cfg orelse false, - else => true, - }; + const decl = mod.declPtr(decl_index); + const namespace = mod.namespacePtr(decl.src_namespace); + const structured_cfg = namespace.file_scope.mod.structured_cfg; var decl_gen = DeclGen{ .gpa = self.gpa, @@ -208,7 +204,7 @@ pub const Object = struct { .air = air, .liveness = liveness, .type_map = &self.type_map, - .control_flow = switch (want_structured_cfg) { + .control_flow = switch (structured_cfg) { true => .{ .structured = .{} }, false => .{ .unstructured = .{} }, }, diff --git a/src/link.zig b/src/link.zig index 580b2d7daf..5908a07dec 100644 --- a/src/link.zig +++ b/src/link.zig @@ -32,8 +32,6 @@ pub const SystemLib = struct { path: ?[]const u8, }; -pub const SortSection = enum { name, alignment }; - pub const CacheMode = enum { incremental, whole }; pub fn hashAddSystemLibs( @@ -51,10 +49,6 @@ pub fn hashAddSystemLibs( pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; -pub const HashStyle = enum { sysv, gnu, both }; - -pub const CompressDebugSections = enum { none, zlib, zstd }; - pub const File = struct { tag: Tag, @@ -105,12 +99,9 @@ pub const File = struct { image_base: ?u64, function_sections: bool, data_sections: bool, - no_builtin: bool, eh_frame_hdr: bool, emit_relocs: bool, rdynamic: bool, - optimization: u8, - linker_script: ?[]const u8, z_nodelete: bool, z_notext: bool, z_defs: bool, @@ -123,7 +114,7 @@ pub const File = struct { tsaware: bool, nxcompat: bool, dynamicbase: bool, - compress_debug_sections: CompressDebugSections, + compress_debug_sections: Elf.CompressDebugSections, bind_global_refs_locally: bool, import_symbols: bool, import_table: bool, @@ -136,13 +127,14 @@ pub const File = struct { each_lib_rpath: bool, build_id: std.zig.BuildId, disable_lld_caching: bool, - hash_style: HashStyle, - sort_section: ?SortSection, + hash_style: Elf.HashStyle, + sort_section: ?Elf.SortSection, major_subsystem_version: ?u32, minor_subsystem_version: ?u32, gc_sections: ?bool, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, + linker_script: ?[]const u8, version_script: ?[]const u8, soname: ?[]const u8, print_gc_sections: bool, @@ -192,9 +184,6 @@ pub const File = struct { /// (Windows) .def file to specify when linking module_definition_file: ?[]const u8, - /// (SPIR-V) whether to generate a structured control flow graph or not - want_structured_cfg: ?bool, - wasi_emulated_libs: []const wasi_libc.CRTFile, }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 41cf524ec0..db99ba189c 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -10,6 +10,15 @@ base: link.File, image_base: u64, error_flags: link.File.ErrorFlags = .{}, dll_export_fns: bool, +subsystem: ?std.Target.SubSystem, +tsaware: bool, +nxcompat: bool, +dynamicbase: bool, +/// TODO this and minor_subsystem_version should be combined into one property and left as +/// default or populated together. They should not be separate fields. +major_subsystem_version: u32, +minor_subsystem_version: u32, +lib_dirs: []const []const u8, ptr_width: PtrWidth, page_size: u32, @@ -403,6 +412,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { }, .dll_export_fns = options.dll_export_fns, + .subsystem = options.subsystem, + .tsaware = options.tsaware, + .nxcompat = options.nxcompat, + .dynamicbase = options.dynamicbase, + .major_subsystem_version = options.major_subsystem_version orelse 6, + .minor_subsystem_version = options.minor_subsystem_version orelse 0, + .lib_dirs = options.lib_dirs, }; const use_llvm = comp.config.use_llvm; @@ -2305,8 +2321,8 @@ fn writeHeader(self: *Coff) !void { .minor_operating_system_version = 0, .major_image_version = 0, .minor_image_version = 0, - .major_subsystem_version = 6, - .minor_subsystem_version = 0, + .major_subsystem_version = self.major_subsystem_version, + .minor_subsystem_version = self.minor_subsystem_version, .win32_version_value = 0, .size_of_image = size_of_image, .size_of_headers = size_of_headers, @@ -2339,8 +2355,8 @@ fn writeHeader(self: *Coff) !void { .minor_operating_system_version = 0, .major_image_version = 0, .minor_image_version = 0, - .major_subsystem_version = 6, - .minor_subsystem_version = 0, + .major_subsystem_version = self.major_subsystem_version, + .minor_subsystem_version = self.minor_subsystem_version, .win32_version_value = 0, .size_of_image = size_of_image, .size_of_headers = size_of_headers, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index a116c46d2f..b54bde325f 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,6 +1,29 @@ base: link.File, image_base: u64, rdynamic: bool, +eh_frame_hdr: bool, +emit_relocs: bool, +z_nodelete: bool, +z_notext: bool, +z_defs: bool, +z_origin: bool, +z_nocopyreloc: bool, +z_now: bool, +z_relro: bool, +/// TODO make this non optional and resolve the default in open() +z_common_page_size: ?u64, +/// TODO make this non optional and resolve the default in open() +z_max_page_size: ?u64, +lib_dirs: []const []const u8, +hash_style: HashStyle, +compress_debug_sections: CompressDebugSections, +symbol_wrap_set: std.StringArrayHashMapUnmanaged(void), +each_lib_rpath: bool, +sort_section: ?SortSection, +soname: ?[]const u8, +bind_global_refs_locally: bool, +linker_script: ?[]const u8, +version_script: ?[]const u8, ptr_width: PtrWidth, @@ -201,6 +224,9 @@ const minimum_atom_size = 64; pub const min_text_capacity = padToIdeal(minimum_atom_size); pub const PtrWidth = enum { p32, p64 }; +pub const HashStyle = enum { sysv, gnu, both }; +pub const CompressDebugSections = enum { none, zlib, zstd }; +pub const SortSection = enum { name, alignment }; pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { if (build_options.only_c) unreachable; @@ -374,6 +400,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { }, .rdynamic = options.rdynamic, + .eh_frame_hdr = options.eh_frame_hdr, + .emit_relocs = options.emit_relocs, + .z_nodelete = options.z_nodelete, + .z_notext = options.z_notext, + .z_defs = options.z_defs, + .z_origin = options.z_origin, + .z_nocopyreloc = options.z_nocopyreloc, + .z_now = options.z_now, + .z_relro = options.z_relro, + .z_common_page_size = options.z_common_page_size, + .z_max_page_size = options.z_max_page_size, + .lib_dirs = options.lib_dirs, + .hash_style = options.hash_style, + .compress_debug_sections = options.compress_debug_sections, + .symbol_wrap_set = options.symbol_wrap_set, + .each_lib_rpath = options.each_lib_rpath, + .sort_section = options.sort_section, + .soname = options.soname, + .bind_global_refs_locally = options.bind_global_refs_locally, + .linker_script = options.linker_script, + .version_script = options.version_script, }; if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); @@ -2424,8 +2471,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.add(self.bind_global_refs_locally); man.hash.add(self.compress_debug_sections); man.hash.add(comp.config.any_sanitize_thread); - man.hash.addOptionalBytes(self.sysroot); - man.hash.add(self.optimization); + man.hash.addOptionalBytes(comp.sysroot); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try man.hit(); @@ -2500,7 +2546,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--error-limit=0"); - if (self.sysroot) |sysroot| { + if (comp.sysroot) |sysroot| { try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot})); } @@ -2511,9 +2557,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"), } } - try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{ - self.optimization, - })); + switch (comp.root_mod.optimize_mode) { + .Debug => {}, + .ReleaseSmall => try argv.append("-O2"), + .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), + } if (comp.config.entry) |entry| { try argv.append("--entry"); diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 3bffc7f73e..8bcf439354 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -476,7 +476,7 @@ pub fn inferSdkVersion(gpa: Allocator, comp: *const Compilation) ?std.SemanticVe const sdk_layout = macho_file.sdk_layout orelse return null; const sdk_dir = switch (sdk_layout) { - .sdk => macho_file.sysroot.?, + .sdk => comp.sysroot.?, .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null, }; if (readSdkVersionFromSettings(arena, sdk_dir)) |ver| { diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index f40aaea4db..06fede6e1b 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -249,7 +249,7 @@ pub fn linkWithZld( } } - if (macho_file.sysroot) |syslibroot| { + if (comp.sysroot) |syslibroot| { try argv.append("-syslibroot"); try argv.append(syslibroot); } diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index d8f78c32f1..bb278a8e4a 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -47,6 +47,8 @@ base: link.File, object: codegen.Object, +pub const base_tag: link.File.Tag = .spirv; + pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV { const gpa = options.comp.gpa; const target = options.comp.root_mod.resolved_target.result; diff --git a/src/main.zig b/src/main.zig index 5f65908b5c..9acad1a0ca 100644 --- a/src/main.zig +++ b/src/main.zig @@ -828,9 +828,9 @@ fn buildOutputType( var linker_script: ?[]const u8 = null; var version_script: ?[]const u8 = null; var disable_c_depfile = false; - var linker_sort_section: ?link.SortSection = null; + var linker_sort_section: ?link.File.Elf.SortSection = null; var linker_gc_sections: ?bool = null; - var linker_compress_debug_sections: ?link.CompressDebugSections = null; + var linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null; var linker_allow_shlib_undefined: ?bool = null; var linker_bind_global_refs_locally: ?bool = null; var linker_import_symbols: bool = false; @@ -855,7 +855,7 @@ fn buildOutputType( var linker_tsaware = false; var linker_nxcompat = false; var linker_dynamicbase = true; - var linker_optimization: ?u8 = null; + var linker_optimization: ?[]const u8 = null; var linker_module_definition_file: ?[]const u8 = null; var test_no_exec = false; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; @@ -881,7 +881,7 @@ fn buildOutputType( var enable_link_snapshots: bool = false; var debug_incremental: bool = false; var install_name: ?[]const u8 = null; - var hash_style: link.HashStyle = .both; + var hash_style: link.File.Elf.HashStyle = .both; var entitlements: ?[]const u8 = null; var pagezero_size: ?u64 = null; var lib_search_strategy: SystemLib.SearchStrategy = .paths_first; @@ -894,7 +894,6 @@ fn buildOutputType( var pdb_out_path: ?[]const u8 = null; var debug_format: ?link.File.DebugFormat = null; var error_limit: ?Module.ErrorInt = null; - var want_structured_cfg: ?bool = null; // These are before resolving sysroot. var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{}; var extra_cflags: std.ArrayListUnmanaged([]const u8) = .{}; @@ -1110,9 +1109,9 @@ fn buildOutputType( try extra_rcflags.append(arena, next_arg); } } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) { - want_structured_cfg = true; + mod_opts.structured_cfg = true; } else if (mem.startsWith(u8, arg, "-fno-structured-cfg")) { - want_structured_cfg = false; + mod_opts.structured_cfg = false; } else if (mem.eql(u8, arg, "--color")) { const next_arg = args_iter.next() orelse { fatal("expected [auto|on|off] after --color", .{}); @@ -1152,11 +1151,11 @@ fn buildOutputType( install_name = args_iter.nextOrFatal(); } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) { const param = arg["--compress-debug-sections=".len..]; - linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, param) orelse { + linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, param) orelse { fatal("expected --compress-debug-sections=[none|zlib|zstd], found '{s}'", .{param}); }; } else if (mem.eql(u8, arg, "--compress-debug-sections")) { - linker_compress_debug_sections = link.CompressDebugSections.zlib; + linker_compress_debug_sections = link.File.Elf.CompressDebugSections.zlib; } else if (mem.eql(u8, arg, "-pagezero_size")) { const next_arg = args_iter.nextOrFatal(); pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2067,7 +2066,7 @@ fn buildOutputType( if (it.only_arg.len == 0) { linker_compress_debug_sections = .zlib; } else { - linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, it.only_arg) orelse { + linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, it.only_arg) orelse { fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{it.only_arg}); }; } @@ -2138,14 +2137,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) { version_script = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "-O")) { - const opt = linker_args_it.nextOrFatal(); - linker_optimization = std.fmt.parseUnsigned(u8, opt, 10) catch |err| { - fatal("unable to parse optimization level '{s}': {s}", .{ opt, @errorName(err) }); - }; + linker_optimization = linker_args_it.nextOrFatal(); } else if (mem.startsWith(u8, arg, "-O")) { - linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| { - fatal("unable to parse optimization level '{s}': {s}", .{ arg, @errorName(err) }); - }; + linker_optimization = arg["-O".len..]; } else if (mem.eql(u8, arg, "-pagezero_size")) { const next_arg = linker_args_it.nextOrFatal(); pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2176,7 +2170,7 @@ fn buildOutputType( linker_print_map = true; } else if (mem.eql(u8, arg, "--sort-section")) { const arg1 = linker_args_it.nextOrFatal(); - linker_sort_section = std.meta.stringToEnum(link.SortSection, arg1) orelse { + linker_sort_section = std.meta.stringToEnum(link.File.Elf.SortSection, arg1) orelse { fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1}); }; } else if (mem.eql(u8, arg, "--allow-shlib-undefined") or @@ -2222,7 +2216,7 @@ fn buildOutputType( try linker_export_symbol_names.append(arena, linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--compress-debug-sections")) { const arg1 = linker_args_it.nextOrFatal(); - linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse { + linker_compress_debug_sections = std.meta.stringToEnum(link.File.Elf.CompressDebugSections, arg1) orelse { fatal("expected [none|zlib|zstd] after --compress-debug-sections, found '{s}'", .{arg1}); }; } else if (mem.startsWith(u8, arg, "-z")) { @@ -2405,7 +2399,7 @@ fn buildOutputType( mem.eql(u8, arg, "--hash-style")) { const next_arg = linker_args_it.nextOrFatal(); - hash_style = std.meta.stringToEnum(link.HashStyle, next_arg) orelse { + hash_style = std.meta.stringToEnum(link.File.Elf.HashStyle, next_arg) orelse { fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{ next_arg, }); @@ -2625,6 +2619,10 @@ fn buildOutputType( }; defer global_cache_directory.handle.close(); + if (linker_optimization) |o| { + warn("ignoring deprecated linker optimization setting '{s}'", .{o}); + } + create_module.global_cache_directory = global_cache_directory; create_module.opts.emit_llvm_ir = emit_llvm_ir != .no; create_module.opts.emit_llvm_bc = emit_llvm_bc != .no; @@ -3409,7 +3407,6 @@ fn buildOutputType( .linker_tsaware = linker_tsaware, .linker_nxcompat = linker_nxcompat, .linker_dynamicbase = linker_dynamicbase, - .linker_optimization = linker_optimization, .linker_compress_debug_sections = linker_compress_debug_sections, .linker_module_definition_file = linker_module_definition_file, .major_subsystem_version = major_subsystem_version, @@ -3458,7 +3455,6 @@ fn buildOutputType( .reference_trace = reference_trace, .pdb_out_path = pdb_out_path, .error_limit = error_limit, - .want_structured_cfg = want_structured_cfg, }) catch |err| switch (err) { error.LibCUnavailable => { const triple_name = try target.zigTriple(arena);