From 1a3e0d6709cec285045ff95911a5b961151c8efe Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Nov 2023 22:44:37 -0700 Subject: [PATCH 001/133] std.Uri: default some fields to null so that it becomes practical to initialize Uri objects directly rather than relying on unnecessary text parsing. --- lib/std/Uri.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index a88a102bd426..c79007b87a5b 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -6,13 +6,13 @@ const std = @import("std.zig"); const testing = std.testing; scheme: []const u8, -user: ?[]const u8, -password: ?[]const u8, -host: ?[]const u8, -port: ?u16, +user: ?[]const u8 = null, +password: ?[]const u8 = null, +host: ?[]const u8 = null, +port: ?u16 = null, path: []const u8, -query: ?[]const u8, -fragment: ?[]const u8, +query: ?[]const u8 = null, +fragment: ?[]const u8 = null, /// Applies URI encoding and replaces all reserved characters with their respective %XX code. pub fn escapeString(allocator: std.mem.Allocator, input: []const u8) error{OutOfMemory}![]u8 { From 134e8cf76a6664ebd028fbcbfbd7a1b85ad031f5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Nov 2023 22:46:49 -0700 Subject: [PATCH 002/133] move is_libcpp_lib_name and is_libc_lib_name to std.Target --- lib/std/target.zig | 90 ++++++++++++++++++++++++++++++++++++++++++++++ src/Sema.zig | 4 +-- src/main.zig | 4 +-- src/target.zig | 90 ---------------------------------------------- 4 files changed, 94 insertions(+), 94 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index bb03c8e0cd93..dc2ea3d740c4 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -2601,8 +2601,98 @@ pub const Target = struct { }, ); } + + pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { + const ignore_case = target.os.tag == .macos or target.os.tag == .windows; + + if (eqlIgnoreCase(ignore_case, name, "c")) + return true; + + if (target.isMinGW()) { + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "uuid")) + return true; + if (eqlIgnoreCase(ignore_case, name, "mingw32")) + return true; + if (eqlIgnoreCase(ignore_case, name, "msvcrt-os")) + return true; + if (eqlIgnoreCase(ignore_case, name, "mingwex")) + return true; + + return false; + } + + if (target.abi.isGnu() or target.abi.isMusl()) { + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "rt")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "util")) + return true; + if (eqlIgnoreCase(ignore_case, name, "xnet")) + return true; + if (eqlIgnoreCase(ignore_case, name, "resolv")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dl")) + return true; + } + + if (target.abi.isMusl()) { + if (eqlIgnoreCase(ignore_case, name, "crypt")) + return true; + } + + if (target.os.tag.isDarwin()) { + if (eqlIgnoreCase(ignore_case, name, "System")) + return true; + if (eqlIgnoreCase(ignore_case, name, "c")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dbm")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dl")) + return true; + if (eqlIgnoreCase(ignore_case, name, "info")) + return true; + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "poll")) + return true; + if (eqlIgnoreCase(ignore_case, name, "proc")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "rpcsvc")) + return true; + } + + if (target.os.isAtLeast(.macos, .{ .major = 10, .minor = 8, .patch = 0 }) orelse false) { + if (eqlIgnoreCase(ignore_case, name, "mx")) + return true; + } + + return false; + } + + pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { + const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; + + return eqlIgnoreCase(ignore_case, name, "c++") or + eqlIgnoreCase(ignore_case, name, "stdc++") or + eqlIgnoreCase(ignore_case, name, "c++abi"); + } }; +fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { + if (ignore_case) { + return std.ascii.eqlIgnoreCase(a, b); + } else { + return std.mem.eql(u8, a, b); + } +} + test { std.testing.refAllDecls(Target.Cpu.Arch); } diff --git a/src/Sema.zig b/src/Sema.zig index 2f1dc0732829..516fee4543da 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9075,7 +9075,7 @@ fn handleExternLibName( const comp = mod.comp; const target = mod.getTarget(); log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); - if (target_util.is_libc_lib_name(target, lib_name)) { + if (target.is_libc_lib_name(lib_name)) { if (!comp.bin_file.options.link_libc) { return sema.fail( block, @@ -9086,7 +9086,7 @@ fn handleExternLibName( } break :blk; } - if (target_util.is_libcpp_lib_name(target, lib_name)) { + if (target.is_libcpp_lib_name(lib_name)) { if (!comp.bin_file.options.link_libcpp) { return sema.fail( block, diff --git a/src/main.zig b/src/main.zig index 3f22d8575643..73316c6e653b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2778,11 +2778,11 @@ fn buildOutputType( } for (system_libs.keys(), system_libs.values()) |lib_name, info| { - if (target_util.is_libc_lib_name(target_info.target, lib_name)) { + if (target_info.target.is_libc_lib_name(lib_name)) { link_libc = true; continue; } - if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { + if (target_info.target.is_libcpp_lib_name(lib_name)) { link_libcpp = true; continue; } diff --git a/src/target.zig b/src/target.zig index cac9aa11b064..624a67d043f0 100644 --- a/src/target.zig +++ b/src/target.zig @@ -356,96 +356,6 @@ pub fn supportsReturnAddress(target: std.Target) bool { }; } -fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { - if (ignore_case) { - return std.ascii.eqlIgnoreCase(a, b); - } else { - return std.mem.eql(u8, a, b); - } -} - -pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { - const ignore_case = target.os.tag == .macos or target.os.tag == .windows; - - if (eqlIgnoreCase(ignore_case, name, "c")) - return true; - - if (target.isMinGW()) { - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "uuid")) - return true; - if (eqlIgnoreCase(ignore_case, name, "mingw32")) - return true; - if (eqlIgnoreCase(ignore_case, name, "msvcrt-os")) - return true; - if (eqlIgnoreCase(ignore_case, name, "mingwex")) - return true; - - return false; - } - - if (target.abi.isGnu() or target.abi.isMusl()) { - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "rt")) - return true; - if (eqlIgnoreCase(ignore_case, name, "pthread")) - return true; - if (eqlIgnoreCase(ignore_case, name, "util")) - return true; - if (eqlIgnoreCase(ignore_case, name, "xnet")) - return true; - if (eqlIgnoreCase(ignore_case, name, "resolv")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dl")) - return true; - } - - if (target.abi.isMusl()) { - if (eqlIgnoreCase(ignore_case, name, "crypt")) - return true; - } - - if (target.os.tag.isDarwin()) { - if (eqlIgnoreCase(ignore_case, name, "System")) - return true; - if (eqlIgnoreCase(ignore_case, name, "c")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dbm")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dl")) - return true; - if (eqlIgnoreCase(ignore_case, name, "info")) - return true; - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "poll")) - return true; - if (eqlIgnoreCase(ignore_case, name, "proc")) - return true; - if (eqlIgnoreCase(ignore_case, name, "pthread")) - return true; - if (eqlIgnoreCase(ignore_case, name, "rpcsvc")) - return true; - } - - if (target.os.isAtLeast(.macos, .{ .major = 10, .minor = 8, .patch = 0 }) orelse false) { - if (eqlIgnoreCase(ignore_case, name, "mx")) - return true; - } - - return false; -} - -pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { - const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; - - return eqlIgnoreCase(ignore_case, name, "c++") or - eqlIgnoreCase(ignore_case, name, "stdc++") or - eqlIgnoreCase(ignore_case, name, "c++abi"); -} - pub const CompilerRtClassification = enum { none, only_compiler_rt, only_libunwind, both }; pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerRtClassification { From c20ad51c621ba18d2c90cc96d1b550831dc5d7a3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 28 Nov 2023 22:47:34 -0700 Subject: [PATCH 003/133] introduce std.Build.Module and extract some logic into it This moves many settings from `std.Build.Step.Compile` and into `std.Build.Module`, and then makes them transitive. In other words, it adds support for exposing Zig modules in packages, which are configured in various ways, such as depending on other link objects, include paths, or even a different optimization mode. Now, transitive dependencies will be included in the compilation, so you can, for example, make a Zig module depend on some C source code, and expose that Zig module in a package. Currently, the compiler frontend autogenerates only one `@import("builtin")` module for the entire compilation, however, a future enhancement will be to make it honor the differences in modules, so that modules can be compiled with different optimization modes, code model, valgrind integration, or even target CPU feature set. closes #14719 --- lib/std/Build.zig | 164 ++--- lib/std/Build/Module.zig | 616 +++++++++++++++++ lib/std/Build/Step/Compile.zig | 1125 +++++++++----------------------- lib/std/Build/Step/Run.zig | 36 +- 4 files changed, 991 insertions(+), 950 deletions(-) create mode 100644 lib/std/Build/Module.zig diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 7ace95947368..590ac5aadf6a 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -29,36 +29,7 @@ pub const Builder = Build; pub const InstallDirectoryOptions = Step.InstallDir.Options; pub const Step = @import("Build/Step.zig"); -/// deprecated: use `Step.CheckFile`. -pub const CheckFileStep = @import("Build/Step/CheckFile.zig"); -/// deprecated: use `Step.CheckObject`. -pub const CheckObjectStep = @import("Build/Step/CheckObject.zig"); -/// deprecated: use `Step.ConfigHeader`. -pub const ConfigHeaderStep = @import("Build/Step/ConfigHeader.zig"); -/// deprecated: use `Step.Fmt`. -pub const FmtStep = @import("Build/Step/Fmt.zig"); -/// deprecated: use `Step.InstallArtifact`. -pub const InstallArtifactStep = @import("Build/Step/InstallArtifact.zig"); -/// deprecated: use `Step.InstallDir`. -pub const InstallDirStep = @import("Build/Step/InstallDir.zig"); -/// deprecated: use `Step.InstallFile`. -pub const InstallFileStep = @import("Build/Step/InstallFile.zig"); -/// deprecated: use `Step.ObjCopy`. -pub const ObjCopyStep = @import("Build/Step/ObjCopy.zig"); -/// deprecated: use `Step.Compile`. -pub const CompileStep = @import("Build/Step/Compile.zig"); -/// deprecated: use `Step.Options`. -pub const OptionsStep = @import("Build/Step/Options.zig"); -/// deprecated: use `Step.RemoveDir`. -pub const RemoveDirStep = @import("Build/Step/RemoveDir.zig"); -/// deprecated: use `Step.Run`. -pub const RunStep = @import("Build/Step/Run.zig"); -/// deprecated: use `Step.TranslateC`. -pub const TranslateCStep = @import("Build/Step/TranslateC.zig"); -/// deprecated: use `Step.WriteFile`. -pub const WriteFileStep = @import("Build/Step/WriteFile.zig"); -/// deprecated: use `LazyPath`. -pub const FileSource = LazyPath; +pub const Module = @import("Build/Module.zig"); install_tls: TopLevelStep, uninstall_tls: TopLevelStep, @@ -634,34 +605,31 @@ pub const ExecutableOptions = struct { use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, /// Embed a `.manifest` file in the compilation if the object format supports it. /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference /// Manifest files must have the extension `.manifest`. /// Can be set regardless of target. The `.manifest` file will be ignored /// if the target object format does not support embedded manifests. win32_manifest: ?LazyPath = null, - - /// Deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { return Step.Compile.create(b, .{ .name = options.name, - .root_source_file = options.root_source_file, + .root_module = .{ + .root_source_file = options.root_source_file, + .target = options.target, + .optimize = options.optimize, + .link_libc = options.link_libc, + .single_threaded = options.single_threaded, + }, .version = options.version, - .target = options.target, - .optimize = options.optimize, .kind = .exe, .linkage = options.linkage, .max_rss = options.max_rss, - .link_libc = options.link_libc, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, - .main_mod_path = options.main_mod_path orelse options.main_pkg_path, .win32_manifest = options.win32_manifest, }); } @@ -677,26 +645,23 @@ pub const ObjectOptions = struct { use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, - - /// Deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { return Step.Compile.create(b, .{ .name = options.name, - .root_source_file = options.root_source_file, - .target = options.target, - .optimize = options.optimize, + .root_module = .{ + .root_source_file = options.root_source_file, + .target = options.target, + .optimize = options.optimize, + .link_libc = options.link_libc, + .single_threaded = options.single_threaded, + }, .kind = .obj, .max_rss = options.max_rss, - .link_libc = options.link_libc, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, - .main_mod_path = options.main_mod_path orelse options.main_pkg_path, }); } @@ -712,34 +677,31 @@ pub const SharedLibraryOptions = struct { use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, /// Embed a `.manifest` file in the compilation if the object format supports it. /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference /// Manifest files must have the extension `.manifest`. /// Can be set regardless of target. The `.manifest` file will be ignored /// if the target object format does not support embedded manifests. win32_manifest: ?LazyPath = null, - - /// Deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile { return Step.Compile.create(b, .{ .name = options.name, - .root_source_file = options.root_source_file, + .root_module = .{ + .target = options.target, + .optimize = options.optimize, + .root_source_file = options.root_source_file, + .link_libc = options.link_libc, + .single_threaded = options.single_threaded, + }, .kind = .lib, .linkage = .dynamic, .version = options.version, - .target = options.target, - .optimize = options.optimize, .max_rss = options.max_rss, - .link_libc = options.link_libc, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, - .main_mod_path = options.main_mod_path orelse options.main_pkg_path, .win32_manifest = options.win32_manifest, }); } @@ -756,28 +718,25 @@ pub const StaticLibraryOptions = struct { use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, - - /// Deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile { return Step.Compile.create(b, .{ .name = options.name, - .root_source_file = options.root_source_file, + .root_module = .{ + .target = options.target, + .optimize = options.optimize, + .root_source_file = options.root_source_file, + .link_libc = options.link_libc, + .single_threaded = options.single_threaded, + }, .kind = .lib, .linkage = .static, .version = options.version, - .target = options.target, - .optimize = options.optimize, .max_rss = options.max_rss, - .link_libc = options.link_libc, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, - .main_mod_path = options.main_mod_path orelse options.main_pkg_path, }); } @@ -795,28 +754,25 @@ pub const TestOptions = struct { use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, - - /// Deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { return Step.Compile.create(b, .{ .name = options.name, .kind = .@"test", - .root_source_file = options.root_source_file, - .target = options.target, - .optimize = options.optimize, + .root_module = .{ + .root_source_file = options.root_source_file, + .target = options.target, + .optimize = options.optimize, + .link_libc = options.link_libc, + .single_threaded = options.single_threaded, + }, .max_rss = options.max_rss, .filter = options.filter, .test_runner = options.test_runner, - .link_libc = options.link_libc, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, - .main_mod_path = options.main_mod_path orelse options.main_pkg_path, }); } @@ -833,9 +789,10 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile { const obj_step = Step.Compile.create(b, .{ .name = options.name, .kind = .obj, - .root_source_file = null, - .target = options.target, - .optimize = options.optimize, + .root_module = .{ + .target = options.target, + .optimize = options.optimize, + }, .max_rss = options.max_rss, .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, }); @@ -846,41 +803,17 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile { /// This function creates a module and adds it to the package's module set, making /// it available to other packages which depend on this one. /// `createModule` can be used instead to create a private module. -pub fn addModule(b: *Build, name: []const u8, options: CreateModuleOptions) *Module { - const module = b.createModule(options); +pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module { + const module = Module.create(b, options); b.modules.put(b.dupe(name), module) catch @panic("OOM"); return module; } -pub const ModuleDependency = struct { - name: []const u8, - module: *Module, -}; - -pub const CreateModuleOptions = struct { - source_file: LazyPath, - dependencies: []const ModuleDependency = &.{}, -}; - /// This function creates a private module, to be used by the current package, /// but not exposed to other packages depending on this one. /// `addModule` can be used instead to create a public module. -pub fn createModule(b: *Build, options: CreateModuleOptions) *Module { - const module = b.allocator.create(Module) catch @panic("OOM"); - module.* = .{ - .builder = b, - .source_file = options.source_file.dupe(b), - .dependencies = moduleDependenciesToArrayHashMap(b.allocator, options.dependencies), - }; - return module; -} - -fn moduleDependenciesToArrayHashMap(arena: Allocator, deps: []const ModuleDependency) std.StringArrayHashMap(*Module) { - var result = std.StringArrayHashMap(*Module).init(arena); - for (deps) |dep| { - result.put(dep.name, dep.module) catch @panic("OOM"); - } - return result; +pub fn createModule(b: *Build, options: Module.CreateOptions) *Module { + return Module.create(b, options); } /// Initializes a `Step.Run` with argv, which must at least have the path to the @@ -1885,15 +1818,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void { } } -pub const Module = struct { - builder: *Build, - /// This could either be a generated file, in which case the module - /// contains exactly one file, or it could be a path to the root source - /// file of directory of files which constitute the module. - source_file: LazyPath, - dependencies: std.StringArrayHashMap(*Module), -}; - /// A file that is generated by a build step. /// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic. pub const GeneratedFile = struct { diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig new file mode 100644 index 000000000000..31db0ad6894b --- /dev/null +++ b/lib/std/Build/Module.zig @@ -0,0 +1,616 @@ +/// The one responsible for creating this module. +owner: *std.Build, +/// Tracks the set of steps that depend on this `Module`. This ensures that +/// when making this `Module` depend on other `Module` objects and `Step` +/// objects, respective `Step` dependencies can be added. +depending_steps: std.AutoArrayHashMapUnmanaged(*std.Build.Step.Compile, void), +/// This could either be a generated file, in which case the module +/// contains exactly one file, or it could be a path to the root source +/// file of directory of files which constitute the module. +/// If `null`, it means this module is made up of only `link_objects`. +root_source_file: ?LazyPath, +/// The modules that are mapped into this module's import table. +import_table: std.StringArrayHashMap(*Module), + +target: std.zig.CrossTarget, +target_info: NativeTargetInfo, +optimize: std.builtin.OptimizeMode, +dwarf_format: ?std.dwarf.Format, + +c_macros: std.ArrayList([]const u8), +include_dirs: std.ArrayList(IncludeDir), +lib_paths: std.ArrayList(LazyPath), +rpaths: std.ArrayList(LazyPath), +frameworks: std.StringArrayHashMapUnmanaged(FrameworkLinkInfo), +c_std: std.Build.CStd, +link_objects: std.ArrayList(LinkObject), + +strip: ?bool, +unwind_tables: ?bool, +single_threaded: ?bool, +stack_protector: ?bool, +stack_check: ?bool, +sanitize_c: ?bool, +sanitize_thread: ?bool, +code_model: std.builtin.CodeModel, +/// Whether to emit machine code that integrates with Valgrind. +valgrind: ?bool, +/// Position Independent Code +pic: ?bool, +red_zone: ?bool, +/// Whether to omit the stack frame pointer. Frees up a register and makes it +/// more more difficiult to obtain stack traces. Has target-dependent effects. +omit_frame_pointer: ?bool, +/// `true` requires a compilation that includes this Module to link libc. +/// `false` causes a build failure if a compilation that includes this Module would link libc. +/// `null` neither requires nor prevents libc from being linked. +link_libc: ?bool, +/// `true` requires a compilation that includes this Module to link libc++. +/// `false` causes a build failure if a compilation that includes this Module would link libc++. +/// `null` neither requires nor prevents libc++ from being linked. +link_libcpp: ?bool, + +/// Symbols to be exported when compiling to WebAssembly. +export_symbol_names: []const []const u8 = &.{}, + +pub const LinkObject = union(enum) { + static_path: LazyPath, + other_step: *std.Build.Step.Compile, + system_lib: SystemLib, + assembly_file: LazyPath, + c_source_file: *CSourceFile, + c_source_files: *CSourceFiles, + win32_resource_file: *RcSourceFile, +}; + +pub const SystemLib = struct { + name: []const u8, + needed: bool, + weak: bool, + use_pkg_config: UsePkgConfig, + preferred_link_mode: std.builtin.LinkMode, + search_strategy: SystemLib.SearchStrategy, + + pub const UsePkgConfig = enum { + /// Don't use pkg-config, just pass -lfoo where foo is name. + no, + /// Try to get information on how to link the library from pkg-config. + /// If that fails, fall back to passing -lfoo where foo is name. + yes, + /// Try to get information on how to link the library from pkg-config. + /// If that fails, error out. + force, + }; + + pub const SearchStrategy = enum { paths_first, mode_first, no_fallback }; +}; + +pub const CSourceFiles = struct { + dependency: ?*std.Build.Dependency, + /// If `dependency` is not null relative to it, + /// else relative to the build root. + files: []const []const u8, + flags: []const []const u8, +}; + +pub const CSourceFile = struct { + file: LazyPath, + flags: []const []const u8, + + pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile { + return .{ + .file = self.file.dupe(b), + .flags = b.dupeStrings(self.flags), + }; + } +}; + +pub const RcSourceFile = struct { + file: LazyPath, + /// Any option that rc.exe accepts will work here, with the exception of: + /// - `/fo`: The output filename is set by the build system + /// - `/p`: Only running the preprocessor is not supported in this context + /// - `/:no-preprocess` (non-standard option): Not supported in this context + /// - Any MUI-related option + /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line- + /// + /// Implicitly defined options: + /// /x (ignore the INCLUDE environment variable) + /// /D_DEBUG or /DNDEBUG depending on the optimization mode + flags: []const []const u8 = &.{}, + + pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile { + return .{ + .file = self.file.dupe(b), + .flags = b.dupeStrings(self.flags), + }; + } +}; + +pub const IncludeDir = union(enum) { + path: LazyPath, + path_system: LazyPath, + path_after: LazyPath, + framework_path: LazyPath, + framework_path_system: LazyPath, + other_step: *std.Build.Step.Compile, + config_header_step: *std.Build.Step.ConfigHeader, +}; + +pub const FrameworkLinkInfo = struct { + needed: bool = false, + weak: bool = false, +}; + +pub const CreateOptions = struct { + target: std.zig.CrossTarget, + target_info: ?NativeTargetInfo = null, + optimize: std.builtin.OptimizeMode, + root_source_file: ?LazyPath = null, + import_table: []const Import = &.{}, + link_libc: ?bool = null, + link_libcpp: ?bool = null, + single_threaded: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + dwarf_format: ?std.dwarf.Format = null, + c_std: std.Build.CStd = .C99, + code_model: std.builtin.CodeModel = .default, + stack_protector: ?bool = null, + stack_check: ?bool = null, + sanitize_c: ?bool = null, + sanitize_thread: ?bool = null, + valgrind: ?bool = null, + pic: ?bool = null, + red_zone: ?bool = null, + /// Whether to omit the stack frame pointer. Frees up a register and makes it + /// more more difficiult to obtain stack traces. Has target-dependent effects. + omit_frame_pointer: ?bool = null, +}; + +pub const Import = struct { + name: []const u8, + module: *Module, +}; + +pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step.Compile) Module { + var m: Module = .{ + .owner = owner, + .depending_steps = .{}, + .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, + .import_table = std.StringArrayHashMap(*Module).init(owner.allocator), + .target = options.target, + .target_info = options.target_info orelse + NativeTargetInfo.detect(options.target) catch @panic("unhandled error"), + .optimize = options.optimize, + .link_libc = options.link_libc, + .link_libcpp = options.link_libcpp, + .dwarf_format = options.dwarf_format, + .c_macros = std.ArrayList([]const u8).init(owner.allocator), + .include_dirs = std.ArrayList(IncludeDir).init(owner.allocator), + .lib_paths = std.ArrayList(LazyPath).init(owner.allocator), + .rpaths = std.ArrayList(LazyPath).init(owner.allocator), + .frameworks = .{}, + .c_std = options.c_std, + .link_objects = std.ArrayList(LinkObject).init(owner.allocator), + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .single_threaded = options.single_threaded, + .stack_protector = options.stack_protector, + .stack_check = options.stack_check, + .sanitize_c = options.sanitize_c, + .sanitize_thread = options.sanitize_thread, + .code_model = options.code_model, + .valgrind = options.valgrind, + .pic = options.pic, + .red_zone = options.red_zone, + .omit_frame_pointer = options.omit_frame_pointer, + .export_symbol_names = &.{}, + }; + + if (compile) |c| { + m.depending_steps.put(owner.allocator, c, {}) catch @panic("OOM"); + } + + m.import_table.ensureUnusedCapacity(options.import_table.len) catch @panic("OOM"); + for (options.import_table) |dep| { + m.import_table.putAssumeCapacity(dep.name, dep.module); + } + + var it = m.iterateDependencies(null); + while (it.next()) |item| addShallowDependencies(&m, item.module); + + return m; +} + +pub fn create(owner: *std.Build, options: CreateOptions) *Module { + const m = owner.allocator.create(Module) catch @panic("OOM"); + m.* = init(owner, options, null); + return m; +} + +/// Adds an existing module to be used with `@import`. +pub fn addImport(m: *Module, name: []const u8, module: *Module) void { + const b = m.owner; + m.import_table.put(b.dupe(name), module) catch @panic("OOM"); + + var it = module.iterateDependencies(null); + while (it.next()) |item| addShallowDependencies(m, item.module); +} + +/// Creates step dependencies and updates `depending_steps` of `dependee` so that +/// subsequent calls to `addImport` on `dependee` will additionally create step +/// dependencies on `m`'s `depending_steps`. +fn addShallowDependencies(m: *Module, dependee: *Module) void { + if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path); + for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path); + for (dependee.rpaths.items) |rpath| addLazyPathDependencies(m, dependee, rpath); + + for (dependee.link_objects.items) |link_object| switch (link_object) { + .other_step => |compile| addStepDependencies(m, dependee, &compile.step), + + .static_path, + .assembly_file, + => |lp| addLazyPathDependencies(m, dependee, lp), + + .c_source_file => |x| addLazyPathDependencies(m, dependee, x.file), + .win32_resource_file => |x| addLazyPathDependencies(m, dependee, x.file), + + .c_source_files, + .system_lib, + => {}, + }; +} + +fn addLazyPathDependencies(m: *Module, module: *Module, lazy_path: LazyPath) void { + addLazyPathDependenciesOnly(m, lazy_path); + if (m != module) { + for (m.depending_steps.keys()) |compile| { + module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM"); + } + } +} + +fn addLazyPathDependenciesOnly(m: *Module, lazy_path: LazyPath) void { + for (m.depending_steps.keys()) |compile| { + lazy_path.addStepDependencies(&compile.step); + } +} + +fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) void { + addStepDependenciesOnly(m, dependee); + if (m != module) { + for (m.depending_steps.keys()) |compile| { + module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM"); + } + } +} + +fn addStepDependenciesOnly(m: *Module, dependee: *std.Build.Step) void { + for (m.depending_steps.keys()) |compile| { + compile.step.dependOn(dependee); + } +} + +/// Creates a new module and adds it to be used with `@import`. +pub fn addAnonymousImport(m: *Module, name: []const u8, options: std.Build.CreateModuleOptions) void { + const b = m.step.owner; + const module = b.createModule(options); + return addImport(m, name, module); +} + +pub fn addOptions(m: *Module, module_name: []const u8, options: *std.Build.Step.Options) void { + addImport(m, module_name, options.createModule()); +} + +pub const DependencyIterator = struct { + allocator: std.mem.Allocator, + index: usize, + set: std.AutoArrayHashMapUnmanaged(Key, []const u8), + + pub const Key = struct { + /// The compilation that contains the `Module`. Note that a `Module` might be + /// used by more than one compilation. + compile: ?*std.Build.Step.Compile, + module: *Module, + }; + + pub const Item = struct { + /// The compilation that contains the `Module`. Note that a `Module` might be + /// used by more than one compilation. + compile: ?*std.Build.Step.Compile, + module: *Module, + name: []const u8, + }; + + pub fn deinit(it: *DependencyIterator) void { + it.set.deinit(it.allocator); + it.* = undefined; + } + + pub fn next(it: *DependencyIterator) ?Item { + if (it.index >= it.set.count()) { + it.set.clearAndFree(it.allocator); + return null; + } + const key = it.set.keys()[it.index]; + const name = it.set.values()[it.index]; + it.index += 1; + const module = key.module; + it.set.ensureUnusedCapacity(it.allocator, module.import_table.count()) catch + @panic("OOM"); + for (module.import_table.keys(), module.import_table.values()) |dep_name, dep| { + it.set.putAssumeCapacity(.{ + .module = dep, + .compile = key.compile, + }, dep_name); + } + + if (key.compile != null) { + for (module.link_objects.items) |link_object| switch (link_object) { + .other_step => |compile| { + it.set.put(it.allocator, .{ + .module = &compile.root_module, + .compile = compile, + }, "root") catch @panic("OOM"); + }, + else => {}, + }; + } + + return .{ + .compile = key.compile, + .module = key.module, + .name = name, + }; + } +}; + +pub fn iterateDependencies( + m: *Module, + chase_steps: ?*std.Build.Step.Compile, +) DependencyIterator { + var it: DependencyIterator = .{ + .allocator = m.owner.allocator, + .index = 0, + .set = .{}, + }; + it.set.ensureUnusedCapacity(m.owner.allocator, m.import_table.count() + 1) catch @panic("OOM"); + it.set.putAssumeCapacity(.{ + .module = m, + .compile = chase_steps, + }, "root"); + return it; +} + +pub const LinkSystemLibraryOptions = struct { + needed: bool = false, + weak: bool = false, + use_pkg_config: SystemLib.UsePkgConfig = .yes, + preferred_link_mode: std.builtin.LinkMode = .Dynamic, + search_strategy: SystemLib.SearchStrategy = .paths_first, +}; + +pub fn linkSystemLibrary( + m: *Module, + name: []const u8, + options: LinkSystemLibraryOptions, +) void { + const b = m.owner; + if (m.target_info.target.is_libc_lib_name(name)) { + m.link_libc = true; + return; + } + if (m.target_info.target.is_libcpp_lib_name(name)) { + m.link_libcpp = true; + return; + } + + m.link_objects.append(.{ + .system_lib = .{ + .name = b.dupe(name), + .needed = options.needed, + .weak = options.weak, + .use_pkg_config = options.use_pkg_config, + .preferred_link_mode = options.preferred_link_mode, + .search_strategy = options.search_strategy, + }, + }) catch @panic("OOM"); +} + +pub const AddCSourceFilesOptions = struct { + /// When provided, `files` are relative to `dependency` rather than the + /// package that owns the `Compile` step. + dependency: ?*std.Build.Dependency = null, + files: []const []const u8, + flags: []const []const u8 = &.{}, +}; + +/// Handy when you have many C/C++ source files and want them all to have the same flags. +pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void { + const c_source_files = m.owner.allocator.create(CSourceFiles) catch @panic("OOM"); + c_source_files.* = .{ + .dependency = options.dependency, + .files = m.owner.dupeStrings(options.files), + .flags = m.owner.dupeStrings(options.flags), + }; + m.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM"); +} + +pub fn addCSourceFile(m: *Module, source: CSourceFile) void { + const c_source_file = m.owner.allocator.create(CSourceFile) catch @panic("OOM"); + c_source_file.* = source.dupe(m.owner); + m.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, source.file); +} + +/// Resource files must have the extension `.rc`. +/// Can be called regardless of target. The .rc file will be ignored +/// if the target object format does not support embedded resources. +pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void { + // Only the PE/COFF format has a Resource Table, so for any other target + // the resource file is ignored. + if (m.target_info.target.ofmt != .coff) return; + + const rc_source_file = m.owner.allocator.create(RcSourceFile) catch @panic("OOM"); + rc_source_file.* = source.dupe(m.owner); + m.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, source.file); +} + +pub fn addAssemblyFile(m: *Module, source: LazyPath) void { + m.link_objects.append(.{ .assembly_file = source.dupe(m.owner) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, source); +} + +pub fn addObjectFile(m: *Module, source: LazyPath) void { + m.link_objects.append(.{ .static_path = source.dupe(m.owner) }) catch @panic("OOM"); + addLazyPathDependencies(m, source); +} + +pub fn appendZigProcessFlags( + m: *Module, + zig_args: *std.ArrayList([]const u8), + asking_step: ?*std.Build.Step, +) !void { + const b = m.owner; + + try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip"); + try addFlag(zig_args, m.unwind_tables, "-funwind-tables", "-fno-unwind-tables"); + try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded"); + try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check"); + try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector"); + try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer"); + try addFlag(zig_args, m.sanitize_c, "-fsanitize-c", "-fno-sanitize-c"); + try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread"); + try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind"); + try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC"); + try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone"); + + if (m.dwarf_format) |dwarf_format| { + try zig_args.append(switch (dwarf_format) { + .@"32" => "-gdwarf32", + .@"64" => "-gdwarf64", + }); + } + + try zig_args.ensureUnusedCapacity(1); + switch (m.optimize) { + .Debug => {}, // Skip since it's the default. + .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"), + .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"), + .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"), + } + + if (m.code_model != .default) { + try zig_args.append("-mcmodel"); + try zig_args.append(@tagName(m.code_model)); + } + + if (!m.target.isNative()) { + try zig_args.appendSlice(&.{ + "-target", try m.target.zigTriple(b.allocator), + "-mcpu", try std.Build.serializeCpu(b.allocator, m.target.getCpu()), + }); + + if (m.target.dynamic_linker.get()) |dynamic_linker| { + try zig_args.append("--dynamic-linker"); + try zig_args.append(dynamic_linker); + } + } + + for (m.export_symbol_names) |symbol_name| { + try zig_args.append(b.fmt("--export={s}", .{symbol_name})); + } + + for (m.include_dirs.items) |include_dir| { + switch (include_dir) { + .path => |include_path| { + try zig_args.append("-I"); + try zig_args.append(include_path.getPath(b)); + }, + .path_system => |include_path| { + try zig_args.append("-isystem"); + try zig_args.append(include_path.getPath(b)); + }, + .path_after => |include_path| { + try zig_args.append("-idirafter"); + try zig_args.append(include_path.getPath(b)); + }, + .framework_path => |include_path| { + try zig_args.append("-F"); + try zig_args.append(include_path.getPath2(b, asking_step)); + }, + .framework_path_system => |include_path| { + try zig_args.append("-iframework"); + try zig_args.append(include_path.getPath2(b, asking_step)); + }, + .other_step => |other| { + if (other.generated_h) |header| { + try zig_args.append("-isystem"); + try zig_args.append(std.fs.path.dirname(header.path.?).?); + } + if (other.installed_headers.items.len > 0) { + try zig_args.append("-I"); + try zig_args.append(b.pathJoin(&.{ + other.step.owner.install_prefix, "include", + })); + } + }, + .config_header_step => |config_header| { + const full_file_path = config_header.output_file.path.?; + const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len]; + try zig_args.appendSlice(&.{ "-I", header_dir_path }); + }, + } + } + + for (m.c_macros.items) |c_macro| { + try zig_args.append("-D"); + try zig_args.append(c_macro); + } + + try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len); + for (m.lib_paths.items) |lib_path| { + zig_args.appendAssumeCapacity("-L"); + zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step)); + } + + try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len); + for (m.rpaths.items) |rpath| { + zig_args.appendAssumeCapacity("-rpath"); + + if (m.target_info.target.isDarwin()) switch (rpath) { + .path, .cwd_relative => |path| { + // On Darwin, we should not try to expand special runtime paths such as + // * @executable_path + // * @loader_path + if (std.mem.startsWith(u8, path, "@executable_path") or + std.mem.startsWith(u8, path, "@loader_path")) + { + zig_args.appendAssumeCapacity(path); + continue; + } + }, + .generated, .dependency => {}, + }; + + zig_args.appendAssumeCapacity(rpath.getPath2(b, asking_step)); + } +} + +fn addFlag( + args: *std.ArrayList([]const u8), + opt: ?bool, + then_name: []const u8, + else_name: []const u8, +) !void { + const cond = opt orelse return; + return args.append(if (cond) then_name else else_name); +} + +const Module = @This(); +const std = @import("std"); +const assert = std.debug.assert; +const LazyPath = std.Build.LazyPath; +const NativeTargetInfo = std.zig.system.NativeTargetInfo; diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index c90f0cb1033e..31d07a43596b 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -24,36 +24,24 @@ const Compile = @This(); pub const base_id: Step.Id = .compile; step: Step, +root_module: Module, + name: []const u8, -target: CrossTarget, -target_info: NativeTargetInfo, -optimize: std.builtin.OptimizeMode, linker_script: ?LazyPath = null, version_script: ?[]const u8 = null, out_filename: []const u8, +out_lib_filename: []const u8, linkage: ?Linkage = null, version: ?std.SemanticVersion, kind: Kind, major_only_filename: ?[]const u8, name_only_filename: ?[]const u8, -strip: ?bool, -formatted_panics: ?bool = null, -unwind_tables: ?bool, // keep in sync with src/link.zig:CompressDebugSections compress_debug_sections: enum { none, zlib, zstd } = .none, -lib_paths: ArrayList(LazyPath), -rpaths: ArrayList(LazyPath), -frameworks: StringHashMap(FrameworkLinkInfo), verbose_link: bool, verbose_cc: bool, bundle_compiler_rt: ?bool = null, -single_threaded: ?bool, -stack_protector: ?bool = null, -disable_stack_probing: bool, -disable_sanitize_c: bool, -sanitize_thread: bool, rdynamic: bool, -dwarf_format: ?std.dwarf.Format = null, import_memory: bool = false, export_memory: bool = false, /// For WebAssembly targets, this will allow for undefined symbols to @@ -65,31 +53,16 @@ initial_memory: ?u64 = null, max_memory: ?u64 = null, shared_memory: bool = false, global_base: ?u64 = null, -c_std: std.Build.CStd, /// Set via options; intended to be read-only after that. zig_lib_dir: ?LazyPath, -/// Set via options; intended to be read-only after that. -main_mod_path: ?LazyPath, exec_cmd_args: ?[]const ?[]const u8, filter: ?[]const u8, test_evented_io: bool = false, test_runner: ?[]const u8, test_server_mode: bool, -code_model: std.builtin.CodeModel = .default, wasi_exec_model: ?std.builtin.WasiExecModel = null, -/// Symbols to be exported when compiling to wasm -export_symbol_names: []const []const u8 = &.{}, - -root_src: ?LazyPath, -out_lib_filename: []const u8, -modules: std.StringArrayHashMap(*Module), -link_objects: ArrayList(LinkObject), -include_dirs: ArrayList(IncludeDir), -c_macros: ArrayList([]const u8), installed_headers: ArrayList(*Step), -is_linking_libc: bool, -is_linking_libcpp: bool, vcpkg_bin_path: ?[]const u8 = null, // keep in sync with src/Compilation.zig:RcIncludes @@ -111,7 +84,6 @@ image_base: ?u64 = null, libc_file: ?LazyPath = null, -valgrind_support: ?bool = null, each_lib_rpath: ?bool = null, /// On ELF targets, this will emit a link section called ".note.gnu.build-id" /// which can be used to coordinate a stripped binary with its debug symbols. @@ -177,15 +149,9 @@ headerpad_max_install_names: bool = false, /// (Darwin) Remove dylibs that are unreachable by the entry point or exported symbols. dead_strip_dylibs: bool = false, -/// Position Independent Code -force_pic: ?bool = null, - /// Position Independent Executable pie: ?bool = null, -red_zone: ?bool = null, - -omit_frame_pointer: ?bool = null, dll_export_fns: ?bool = null, subsystem: ?std.Target.SubSystem = null, @@ -226,90 +192,16 @@ generated_h: ?*GeneratedFile, /// Defaults to `std.math.maxInt(u16)` error_limit: ?u32 = null, +/// Computed during make(). +is_linking_libc: bool = false, +/// Computed during make(). +is_linking_libcpp: bool = false, + pub const ExpectedCompileErrors = union(enum) { contains: []const u8, exact: []const []const u8, }; -pub const CSourceFiles = struct { - dependency: ?*std.Build.Dependency, - /// If `dependency` is not null relative to it, - /// else relative to the build root. - files: []const []const u8, - flags: []const []const u8, -}; - -pub const CSourceFile = struct { - file: LazyPath, - flags: []const []const u8, - - pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile { - return .{ - .file = self.file.dupe(b), - .flags = b.dupeStrings(self.flags), - }; - } -}; - -pub const RcSourceFile = struct { - file: LazyPath, - /// Any option that rc.exe accepts will work here, with the exception of: - /// - `/fo`: The output filename is set by the build system - /// - `/p`: Only running the preprocessor is not supported in this context - /// - `/:no-preprocess` (non-standard option): Not supported in this context - /// - Any MUI-related option - /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line- - /// - /// Implicitly defined options: - /// /x (ignore the INCLUDE environment variable) - /// /D_DEBUG or /DNDEBUG depending on the optimization mode - flags: []const []const u8 = &.{}, - - pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile { - return .{ - .file = self.file.dupe(b), - .flags = b.dupeStrings(self.flags), - }; - } -}; - -pub const LinkObject = union(enum) { - static_path: LazyPath, - other_step: *Compile, - system_lib: SystemLib, - assembly_file: LazyPath, - c_source_file: *CSourceFile, - c_source_files: *CSourceFiles, - win32_resource_file: *RcSourceFile, -}; - -pub const SystemLib = struct { - name: []const u8, - needed: bool, - weak: bool, - use_pkg_config: UsePkgConfig, - preferred_link_mode: std.builtin.LinkMode, - search_strategy: SystemLib.SearchStrategy, - - pub const UsePkgConfig = enum { - /// Don't use pkg-config, just pass -lfoo where foo is name. - no, - /// Try to get information on how to link the library from pkg-config. - /// If that fails, fall back to passing -lfoo where foo is name. - yes, - /// Try to get information on how to link the library from pkg-config. - /// If that fails, error out. - force, - }; - - pub const SearchStrategy = enum { paths_first, mode_first, no_fallback }; -}; - -const FrameworkLinkInfo = struct { - needed: bool = false, - weak: bool = false, -}; - const Entry = union(enum) { /// Let the compiler decide whether to make an entry point and what to name /// it. @@ -322,42 +214,24 @@ const Entry = union(enum) { symbol_name: []const u8, }; -pub const IncludeDir = union(enum) { - path: LazyPath, - path_system: LazyPath, - path_after: LazyPath, - framework_path: LazyPath, - framework_path_system: LazyPath, - other_step: *Compile, - config_header_step: *Step.ConfigHeader, -}; - pub const Options = struct { name: []const u8, - root_source_file: ?LazyPath = null, - target: CrossTarget, - optimize: std.builtin.OptimizeMode, + root_module: Module.CreateOptions, kind: Kind, linkage: ?Linkage = null, version: ?std.SemanticVersion = null, max_rss: usize = 0, filter: ?[]const u8 = null, test_runner: ?[]const u8 = null, - link_libc: ?bool = null, - single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, - main_mod_path: ?LazyPath = null, /// Embed a `.manifest` file in the compilation if the object format supports it. /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference /// Manifest files must have the extension `.manifest`. /// Can be set regardless of target. The `.manifest` file will be ignored /// if the target object format does not support embedded manifests. win32_manifest: ?LazyPath = null, - - /// deprecated; use `main_mod_path`. - main_pkg_path: ?LazyPath = null, }; pub const BuildId = union(enum) { @@ -447,7 +321,6 @@ pub const Linkage = enum { dynamic, static }; pub fn create(owner: *std.Build, options: Options) *Compile { const name = owner.dupe(options.name); - const root_src: ?LazyPath = if (options.root_source_file) |rsrc| rsrc.dupe(owner) else null; if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) { panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name}); } @@ -466,11 +339,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .@"test" => "zig test", }, name_adjusted, - @tagName(options.optimize), - options.target.zigTriple(owner.allocator) catch @panic("OOM"), + @tagName(options.root_module.optimize), + options.root_module.target.zigTriple(owner.allocator) catch @panic("OOM"), }); - const target_info = NativeTargetInfo.detect(options.target) catch @panic("unhandled error"); + const target_info = NativeTargetInfo.detect(options.root_module.target) catch + @panic("unhandled error"); const out_filename = std.zig.binNameAlloc(owner.allocator, .{ .root_name = name, @@ -489,17 +363,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile { const self = owner.allocator.create(Compile) catch @panic("OOM"); self.* = .{ - .strip = null, - .unwind_tables = null, + .root_module = Module.init(owner, options.root_module, self), .verbose_link = false, .verbose_cc = false, - .optimize = options.optimize, - .target = options.target, .linkage = options.linkage, .kind = options.kind, - .root_src = root_src, .name = name, - .frameworks = StringHashMap(FrameworkLinkInfo).init(owner.allocator), .step = Step.init(.{ .id = base_id, .name = step_name, @@ -512,23 +381,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .out_lib_filename = undefined, .major_only_filename = null, .name_only_filename = null, - .modules = std.StringArrayHashMap(*Module).init(owner.allocator), - .include_dirs = ArrayList(IncludeDir).init(owner.allocator), - .link_objects = ArrayList(LinkObject).init(owner.allocator), - .c_macros = ArrayList([]const u8).init(owner.allocator), - .lib_paths = ArrayList(LazyPath).init(owner.allocator), - .rpaths = ArrayList(LazyPath).init(owner.allocator), .installed_headers = ArrayList(*Step).init(owner.allocator), - .c_std = std.Build.CStd.C99, .zig_lib_dir = null, - .main_mod_path = null, .exec_cmd_args = null, .filter = options.filter, .test_runner = options.test_runner, .test_server_mode = options.test_runner == null, - .disable_stack_probing = false, - .disable_sanitize_c = false, - .sanitize_thread = false, .rdynamic = false, .installed_path = null, .force_undefined_symbols = StringHashMap(void).init(owner.allocator), @@ -543,11 +401,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .generated_llvm_ir = null, .generated_h = null, - .target_info = target_info, - - .is_linking_libc = options.link_libc orelse false, - .is_linking_libcpp = false, - .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, }; @@ -557,14 +410,9 @@ pub fn create(owner: *std.Build, options: Options) *Compile { lp.addStepDependencies(&self.step); } - if (options.main_mod_path orelse options.main_pkg_path) |lp| { - self.main_mod_path = lp.dupe(self.step.owner); - lp.addStepDependencies(&self.step); - } - // Only the PE/COFF format has a Resource Table which is where the manifest // gets embedded, so for any other target the manifest file is just ignored. - if (self.target.getObjectFormat() == .coff) { + if (target_info.target.ofmt == .coff) { if (options.win32_manifest) |lp| { self.win32_manifest = lp.dupe(self.step.owner); lp.addStepDependencies(&self.step); @@ -600,8 +448,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile { } } - if (root_src) |rs| rs.addStepDependencies(&self.step); - return self; } @@ -738,19 +584,30 @@ pub fn linkFrameworkWeak(self: *Compile, framework_name: []const u8) void { } /// Returns whether the library, executable, or object depends on a particular system library. -pub fn dependsOnSystemLibrary(self: Compile, name: []const u8) bool { - if (isLibCLibrary(name)) { - return self.is_linking_libc; +pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { + var is_linking_libc = false; + var is_linking_libcpp = false; + + var it = self.root_module.iterateDependencies(self); + while (it.next()) |module| { + for (module.link_objects.items) |link_object| { + switch (link_object) { + .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true, + else => continue, + } + } + is_linking_libc = is_linking_libc or module.link_libcpp == true; + is_linking_libcpp = is_linking_libcpp or module.link_libcpp == true; } - if (isLibCppLibrary(name)) { - return self.is_linking_libcpp; + + if (self.root_module.target_info.target.is_libc_lib_name(name)) { + return is_linking_libc; } - for (self.link_objects.items) |link_object| { - switch (link_object) { - .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true, - else => continue, - } + + if (self.root_module.target_info.target.is_libcpp_lib_name(name)) { + return is_linking_libcpp; } + return false; } @@ -759,11 +616,11 @@ pub fn linkLibrary(self: *Compile, lib: *Compile) void { self.linkLibraryOrObject(lib); } -pub fn isDynamicLibrary(self: *Compile) bool { +pub fn isDynamicLibrary(self: *const Compile) bool { return self.kind == .lib and self.linkage == Linkage.dynamic; } -pub fn isStaticLibrary(self: *Compile) bool { +pub fn isStaticLibrary(self: *const Compile) bool { return self.kind == .lib and self.linkage != Linkage.dynamic; } @@ -777,15 +634,15 @@ pub fn producesPdbFile(self: *Compile) bool { } pub fn producesImplib(self: *Compile) bool { - return self.isDynamicLibrary() and self.target.isWindows(); + return self.isDynamicLibrary() and self.root_module.target_info.target.os.tag == .windows; } pub fn linkLibC(self: *Compile) void { - self.is_linking_libc = true; + self.root_module.link_libc = true; } pub fn linkLibCpp(self: *Compile) void { - self.is_linking_libcpp = true; + self.root_module.link_libcpp = true; } /// If the value is omitted, it is set to 1. @@ -802,31 +659,6 @@ pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void { self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM"); } -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .use_pkg_config = .no }); -} - -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .needed = true, .use_pkg_config = .no }); -} - -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .weak = true, .use_pkg_config = .no }); -} - -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void { - return linkSystemLibrary2(self, lib_name, .{ .use_pkg_config = .force }); -} - -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void { - return linkSystemLibrary2(self, lib_name, .{ .needed = true, .use_pkg_config = .force }); -} - /// Run pkg-config for the given library name and parse the output, returning the arguments /// that should be passed to zig to link the given library. fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 { @@ -924,98 +756,31 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 { } pub fn linkSystemLibrary(self: *Compile, name: []const u8) void { - self.linkSystemLibrary2(name, .{}); -} - -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryNeeded(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .needed = true }); + return self.root_module.linkSystemLibrary(name, .{}); } -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryWeak(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .weak = true }); -} - -pub const LinkSystemLibraryOptions = struct { - needed: bool = false, - weak: bool = false, - use_pkg_config: SystemLib.UsePkgConfig = .yes, - preferred_link_mode: std.builtin.LinkMode = .Dynamic, - search_strategy: SystemLib.SearchStrategy = .paths_first, -}; - pub fn linkSystemLibrary2( self: *Compile, name: []const u8, - options: LinkSystemLibraryOptions, + options: Module.LinkSystemLibraryOptions, ) void { - const b = self.step.owner; - if (isLibCLibrary(name)) { - self.linkLibC(); - return; - } - if (isLibCppLibrary(name)) { - self.linkLibCpp(); - return; - } - - self.link_objects.append(.{ - .system_lib = .{ - .name = b.dupe(name), - .needed = options.needed, - .weak = options.weak, - .use_pkg_config = options.use_pkg_config, - .preferred_link_mode = options.preferred_link_mode, - .search_strategy = options.search_strategy, - }, - }) catch @panic("OOM"); + return self.root_module.linkSystemLibrary(name, options); } -pub const AddCSourceFilesOptions = struct { - /// When provided, `files` are relative to `dependency` rather than the package that owns the `Compile` step. - dependency: ?*std.Build.Dependency = null, - files: []const []const u8, - flags: []const []const u8 = &.{}, -}; - /// Handy when you have many C/C++ source files and want them all to have the same flags. -pub fn addCSourceFiles(self: *Compile, options: AddCSourceFilesOptions) void { - const b = self.step.owner; - const c_source_files = b.allocator.create(CSourceFiles) catch @panic("OOM"); - - const files_copy = b.dupeStrings(options.files); - const flags_copy = b.dupeStrings(options.flags); - - c_source_files.* = .{ - .dependency = options.dependency, - .files = files_copy, - .flags = flags_copy, - }; - self.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM"); +pub fn addCSourceFiles(self: *Compile, options: Module.AddCSourceFilesOptions) void { + self.root_module.addCSourceFiles(options); } -pub fn addCSourceFile(self: *Compile, source: CSourceFile) void { - const b = self.step.owner; - const c_source_file = b.allocator.create(CSourceFile) catch @panic("OOM"); - c_source_file.* = source.dupe(b); - self.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM"); - source.file.addStepDependencies(&self.step); +pub fn addCSourceFile(self: *Compile, source: Module.CSourceFile) void { + self.root_module.addCSourceFile(source); } /// Resource files must have the extension `.rc`. /// Can be called regardless of target. The .rc file will be ignored /// if the target object format does not support embedded resources. -pub fn addWin32ResourceFile(self: *Compile, source: RcSourceFile) void { - // Only the PE/COFF format has a Resource Table, so for any other target - // the resource file is just ignored. - if (self.target.getObjectFormat() != .coff) return; - - const b = self.step.owner; - const rc_source_file = b.allocator.create(RcSourceFile) catch @panic("OOM"); - rc_source_file.* = source.dupe(b); - self.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); - source.file.addStepDependencies(&self.step); +pub fn addWin32ResourceFile(self: *Compile, source: Module.RcSourceFile) void { + self.root_module.addWin32ResourceFile(source); } pub fn setVerboseLink(self: *Compile, value: bool) void { @@ -1112,16 +877,11 @@ pub fn getEmittedLlvmBc(self: *Compile) LazyPath { } pub fn addAssemblyFile(self: *Compile, source: LazyPath) void { - const b = self.step.owner; - const source_duped = source.dupe(b); - self.link_objects.append(.{ .assembly_file = source_duped }) catch @panic("OOM"); - source_duped.addStepDependencies(&self.step); + self.root_module.addAssemblyFile(source); } pub fn addObjectFile(self: *Compile, source: LazyPath) void { - const b = self.step.owner; - self.link_objects.append(.{ .static_path = source.dupe(b) }) catch @panic("OOM"); - source.addStepDependencies(&self.step); + self.root_module.addObjectFile(source); } pub fn addObject(self: *Compile, obj: *Compile) void { @@ -1131,19 +891,19 @@ pub fn addObject(self: *Compile, obj: *Compile) void { pub fn addAfterIncludePath(self: *Compile, path: LazyPath) void { const b = self.step.owner; - self.include_dirs.append(IncludeDir{ .path_after = path.dupe(b) }) catch @panic("OOM"); + self.include_dirs.append(.{ .path_after = path.dupe(b) }) catch @panic("OOM"); path.addStepDependencies(&self.step); } pub fn addSystemIncludePath(self: *Compile, path: LazyPath) void { const b = self.step.owner; - self.include_dirs.append(IncludeDir{ .path_system = path.dupe(b) }) catch @panic("OOM"); + self.include_dirs.append(.{ .path_system = path.dupe(b) }) catch @panic("OOM"); path.addStepDependencies(&self.step); } pub fn addIncludePath(self: *Compile, path: LazyPath) void { const b = self.step.owner; - self.include_dirs.append(IncludeDir{ .path = path.dupe(b) }) catch @panic("OOM"); + self.include_dirs.append(.{ .path = path.dupe(b) }) catch @panic("OOM"); path.addStepDependencies(&self.step); } @@ -1166,48 +926,16 @@ pub fn addRPath(self: *Compile, directory_source: LazyPath) void { pub fn addSystemFrameworkPath(self: *Compile, directory_source: LazyPath) void { const b = self.step.owner; - self.include_dirs.append(IncludeDir{ .framework_path_system = directory_source.dupe(b) }) catch @panic("OOM"); + self.include_dirs.append(.{ .framework_path_system = directory_source.dupe(b) }) catch @panic("OOM"); directory_source.addStepDependencies(&self.step); } pub fn addFrameworkPath(self: *Compile, directory_source: LazyPath) void { const b = self.step.owner; - self.include_dirs.append(IncludeDir{ .framework_path = directory_source.dupe(b) }) catch @panic("OOM"); + self.include_dirs.append(.{ .framework_path = directory_source.dupe(b) }) catch @panic("OOM"); directory_source.addStepDependencies(&self.step); } -/// Adds a module to be used with `@import` and exposing it in the current -/// package's module table using `name`. -pub fn addModule(cs: *Compile, name: []const u8, module: *Module) void { - const b = cs.step.owner; - cs.modules.put(b.dupe(name), module) catch @panic("OOM"); - - var done = std.AutoHashMap(*Module, void).init(b.allocator); - defer done.deinit(); - cs.addRecursiveBuildDeps(module, &done) catch @panic("OOM"); -} - -/// Adds a module to be used with `@import` without exposing it in the current -/// package's module table. -pub fn addAnonymousModule(cs: *Compile, name: []const u8, options: std.Build.CreateModuleOptions) void { - const b = cs.step.owner; - const module = b.createModule(options); - return addModule(cs, name, module); -} - -pub fn addOptions(cs: *Compile, module_name: []const u8, options: *Step.Options) void { - addModule(cs, module_name, options.createModule()); -} - -fn addRecursiveBuildDeps(cs: *Compile, module: *Module, done: *std.AutoHashMap(*Module, void)) !void { - if (done.contains(module)) return; - try done.put(module, {}); - module.source_file.addStepDependencies(&cs.step); - for (module.dependencies.values()) |dep| { - try cs.addRecursiveBuildDeps(dep, done); - } -} - /// If Vcpkg was found on the system, it will be added to include and lib /// paths for the specified target. pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void { @@ -1236,7 +964,7 @@ pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void { const include_path = b.pathJoin(&.{ root, "installed", triplet, "include" }); errdefer allocator.free(include_path); - try self.include_dirs.append(IncludeDir{ .path = .{ .path = include_path } }); + try self.include_dirs.append(.{ .path = .{ .path = include_path } }); const lib_path = b.pathJoin(&.{ root, "installed", triplet, "lib" }); try self.lib_paths.append(.{ .path = lib_path }); @@ -1270,87 +998,53 @@ fn linkLibraryOrObject(self: *Compile, other: *Compile) void { } } -fn appendModuleArgs( - cs: *Compile, - zig_args: *ArrayList([]const u8), -) error{OutOfMemory}!void { +fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { const b = cs.step.owner; - // First, traverse the whole dependency graph and give every module a unique name, ideally one - // named after what it's called somewhere in the graph. It will help here to have both a mapping - // from module to name and a set of all the currently-used names. - var mod_names = std.AutoHashMap(*Module, []const u8).init(b.allocator); + // First, traverse the whole dependency graph and give every module a + // unique name, ideally one named after what it's called somewhere in the + // graph. It will help here to have both a mapping from module to name and + // a set of all the currently-used names. + var mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8) = .{}; var names = std.StringHashMap(void).init(b.allocator); - var to_name = std.ArrayList(struct { - name: []const u8, - mod: *Module, - }).init(b.allocator); { - var it = cs.modules.iterator(); - while (it.next()) |kv| { + var it = cs.root_module.iterateDependencies(null); + _ = it.next(); // Skip over the root module. + while (it.next()) |item| { // While we're traversing the root dependencies, let's make sure that no module names // have colons in them, since the CLI forbids it. We handle this for transitive // dependencies further down. - if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) { - @panic("Module names cannot contain colons"); + if (std.mem.indexOfScalar(u8, item.name, ':') != null) { + return cs.step.fail("module '{s}' contains a colon", .{item.name}); } - try to_name.append(.{ - .name = kv.key_ptr.*, - .mod = kv.value_ptr.*, - }); - } - } - - while (to_name.popOrNull()) |dep| { - if (mod_names.contains(dep.mod)) continue; - // We'll use this buffer to store the name we decide on - var buf = try b.allocator.alloc(u8, dep.name.len + 32); - // First, try just the exposed dependency name - @memcpy(buf[0..dep.name.len], dep.name); - var name = buf[0..dep.name.len]; - var n: usize = 0; - while (names.contains(name)) { - // If that failed, append an incrementing number to the end - name = std.fmt.bufPrint(buf, "{s}{}", .{ dep.name, n }) catch unreachable; - n += 1; - } - - try mod_names.put(dep.mod, name); - try names.put(name, {}); - - var it = dep.mod.dependencies.iterator(); - while (it.next()) |kv| { - // Same colon-in-name check as above, but for transitive dependencies. - if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) { - @panic("Module names cannot contain colons"); + var name = item.name; + var n: usize = 0; + while (names.contains(name)) { + name = b.fmt("{s}{d}", .{ item.name, n }); + n += 1; } - try to_name.append(.{ - .name = kv.key_ptr.*, - .mod = kv.value_ptr.*, - }); + + try mod_names.put(b.allocator, item.module, name); + try names.put(name, {}); } } - // Since the module names given to the CLI are based off of the exposed names, we already know - // that none of the CLI names have colons in them, so there's no need to check that explicitly. + // Since the module names given to the CLI are based off of the exposed + // names, we already know that none of the CLI names have colons in them, + // so there's no need to check that explicitly. // Every module in the graph is now named; output their definitions - { - var it = mod_names.iterator(); - while (it.next()) |kv| { - const mod = kv.key_ptr.*; - const name = kv.value_ptr.*; - - const deps_str = try constructDepString(b.allocator, mod_names, mod.dependencies); - const src = mod.source_file.getPath(mod.builder); - try zig_args.append("--mod"); - try zig_args.append(try std.fmt.allocPrint(b.allocator, "{s}:{s}:{s}", .{ name, deps_str, src })); - } + for (mod_names.keys(), mod_names.values()) |mod, name| { + const root_src = mod.root_source_file orelse continue; + const deps_str = try constructDepString(b.allocator, mod_names, mod.import_table); + const src = root_src.getPath2(mod.owner, &cs.step); + try zig_args.append("--mod"); + try zig_args.append(b.fmt("{s}:{s}:{s}", .{ name, deps_str, src })); } // Lastly, output the root dependencies - const deps_str = try constructDepString(b.allocator, mod_names, cs.modules); + const deps_str = try constructDepString(b.allocator, mod_names, cs.root_module.import_table); if (deps_str.len > 0) { try zig_args.append("--deps"); try zig_args.append(deps_str); @@ -1359,7 +1053,7 @@ fn appendModuleArgs( fn constructDepString( allocator: std.mem.Allocator, - mod_names: std.AutoHashMap(*Module, []const u8), + mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8), deps: std.StringArrayHashMap(*Module), ) ![]const u8 { var deps_str = std.ArrayList(u8).init(allocator); @@ -1408,10 +1102,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { const b = step.owner; const self = @fieldParentPtr(Compile, "step", step); - if (self.root_src == null and self.link_objects.items.len == 0) { - return step.fail("the linker needs one or more objects to link", .{}); - } - var zig_args = ArrayList([]const u8).init(b.allocator); defer zig_args.deinit(); @@ -1432,7 +1122,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try addFlag(&zig_args, "llvm", self.use_llvm); try addFlag(&zig_args, "lld", self.use_lld); - if (self.target.ofmt) |ofmt| { + if (self.root_module.target.ofmt) |ofmt| { try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); } @@ -1458,204 +1148,248 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(try std.fmt.allocPrint(b.allocator, "{}", .{stack_size})); } - if (self.root_src) |root_src| try zig_args.append(root_src.getPath(b)); + { + var seen_system_libs: std.StringHashMapUnmanaged(void) = .{}; + var frameworks: std.StringArrayHashMapUnmanaged(Module.FrameworkLinkInfo) = .{}; + + var prev_has_cflags = false; + var prev_has_rcflags = false; + var prev_search_strategy: Module.SystemLib.SearchStrategy = .paths_first; + var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic; + // Track the number of positional arguments so that a nice error can be + // emitted if there is nothing to link. + var total_linker_objects: usize = 0; + + if (self.root_module.root_source_file) |lp| { + try zig_args.append(lp.getPath(b)); + total_linker_objects += 1; + } - // We will add link objects from transitive dependencies, but we want to keep - // all link objects in the same order provided. - // This array is used to keep self.link_objects immutable. - var transitive_deps: TransitiveDeps = .{ - .link_objects = ArrayList(LinkObject).init(b.allocator), - .seen_system_libs = StringHashMap(void).init(b.allocator), - .seen_steps = std.AutoHashMap(*const Step, void).init(b.allocator), - .is_linking_libcpp = self.is_linking_libcpp, - .is_linking_libc = self.is_linking_libc, - .frameworks = &self.frameworks, - }; + try self.root_module.appendZigProcessFlags(&zig_args, step); - try transitive_deps.seen_steps.put(&self.step, {}); - try transitive_deps.add(self.link_objects.items); - - var prev_has_cflags = false; - var prev_has_rcflags = false; - var prev_search_strategy: SystemLib.SearchStrategy = .paths_first; - var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic; - - for (transitive_deps.link_objects.items) |link_object| { - switch (link_object) { - .static_path => |static_path| try zig_args.append(static_path.getPath(b)), - - .other_step => |other| switch (other.kind) { - .exe => @panic("Cannot link with an executable build artifact"), - .@"test" => @panic("Cannot link with a test"), - .obj => { - try zig_args.append(other.getEmittedBin().getPath(b)); - }, - .lib => l: { - if (self.isStaticLibrary() and other.isStaticLibrary()) { - // Avoid putting a static library inside a static library. - break :l; - } + var it = self.root_module.iterateDependencies(self); + while (it.next()) |key| { + const module = key.module; + const compile = key.compile.?; + const dyn = compile.isDynamicLibrary(); - // For DLLs, we gotta link against the implib. For - // everything else, we directly link against the library file. - const full_path_lib = if (other.producesImplib()) - other.getGeneratedFilePath("generated_implib", &self.step) - else - other.getGeneratedFilePath("generated_bin", &self.step); - try zig_args.append(full_path_lib); - - if (other.linkage == Linkage.dynamic and !self.target.isWindows()) { - if (fs.path.dirname(full_path_lib)) |dirname| { - try zig_args.append("-rpath"); - try zig_args.append(dirname); - } - } - }, - }, + // Inherit dependency on libc and libc++. + if (module.link_libc == true) self.is_linking_libc = true; + if (module.link_libcpp == true) self.is_linking_libcpp = true; - .system_lib => |system_lib| { - if ((system_lib.search_strategy != prev_search_strategy or - system_lib.preferred_link_mode != prev_preferred_link_mode) and - self.linkage != .static) - { - switch (system_lib.search_strategy) { - .no_fallback => switch (system_lib.preferred_link_mode) { - .Dynamic => try zig_args.append("-search_dylibs_only"), - .Static => try zig_args.append("-search_static_only"), - }, - .paths_first => switch (system_lib.preferred_link_mode) { - .Dynamic => try zig_args.append("-search_paths_first"), - .Static => try zig_args.append("-search_paths_first_static"), - }, - .mode_first => switch (system_lib.preferred_link_mode) { - .Dynamic => try zig_args.append("-search_dylibs_first"), - .Static => try zig_args.append("-search_static_first"), - }, - } - prev_search_strategy = system_lib.search_strategy; - prev_preferred_link_mode = system_lib.preferred_link_mode; + // Inherit dependencies on darwin frameworks. + if (!dyn) { + for (module.frameworks.keys(), module.frameworks.values()) |name, info| { + try frameworks.put(b.allocator, name, info); } + } - const prefix: []const u8 = prefix: { - if (system_lib.needed) break :prefix "-needed-l"; - if (system_lib.weak) break :prefix "-weak-l"; - break :prefix "-l"; - }; - switch (system_lib.use_pkg_config) { - .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), - .yes, .force => { - if (self.runPkgConfig(system_lib.name)) |args| { - try zig_args.appendSlice(args); - } else |err| switch (err) { - error.PkgConfigInvalidOutput, - error.PkgConfigCrashed, - error.PkgConfigFailed, - error.PkgConfigNotInstalled, - error.PackageNotFound, - => switch (system_lib.use_pkg_config) { - .yes => { - // pkg-config failed, so fall back to linking the library - // by name directly. - try zig_args.append(b.fmt("{s}{s}", .{ - prefix, - system_lib.name, - })); + // Inherit dependencies on system libraries and static libraries. + total_linker_objects += module.link_objects.items.len; + for (module.link_objects.items) |link_object| { + switch (link_object) { + .static_path => |static_path| try zig_args.append(static_path.getPath(b)), + .system_lib => |system_lib| { + if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null) + continue; + + if (dyn) + continue; + + if ((system_lib.search_strategy != prev_search_strategy or + system_lib.preferred_link_mode != prev_preferred_link_mode) and + self.linkage != .static) + { + switch (system_lib.search_strategy) { + .no_fallback => switch (system_lib.preferred_link_mode) { + .Dynamic => try zig_args.append("-search_dylibs_only"), + .Static => try zig_args.append("-search_static_only"), + }, + .paths_first => switch (system_lib.preferred_link_mode) { + .Dynamic => try zig_args.append("-search_paths_first"), + .Static => try zig_args.append("-search_paths_first_static"), }, - .force => { - panic("pkg-config failed for library {s}", .{system_lib.name}); + .mode_first => switch (system_lib.preferred_link_mode) { + .Dynamic => try zig_args.append("-search_dylibs_first"), + .Static => try zig_args.append("-search_static_first"), }, - .no => unreachable, + } + prev_search_strategy = system_lib.search_strategy; + prev_preferred_link_mode = system_lib.preferred_link_mode; + } + + const prefix: []const u8 = prefix: { + if (system_lib.needed) break :prefix "-needed-l"; + if (system_lib.weak) break :prefix "-weak-l"; + break :prefix "-l"; + }; + switch (system_lib.use_pkg_config) { + .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), + .yes, .force => { + if (self.runPkgConfig(system_lib.name)) |args| { + try zig_args.appendSlice(args); + } else |err| switch (err) { + error.PkgConfigInvalidOutput, + error.PkgConfigCrashed, + error.PkgConfigFailed, + error.PkgConfigNotInstalled, + error.PackageNotFound, + => switch (system_lib.use_pkg_config) { + .yes => { + // pkg-config failed, so fall back to linking the library + // by name directly. + try zig_args.append(b.fmt("{s}{s}", .{ + prefix, + system_lib.name, + })); + }, + .force => { + panic("pkg-config failed for library {s}", .{system_lib.name}); + }, + .no => unreachable, + }, + + else => |e| return e, + } + }, + } + }, + .other_step => |other| { + const included_in_lib = (compile.kind == .lib and other.kind == .obj); + if (dyn or included_in_lib) + continue; + + switch (other.kind) { + .exe => return step.fail("cannot link with an executable build artifact", .{}), + .@"test" => return step.fail("cannot link with a test", .{}), + .obj => { + try zig_args.append(other.getEmittedBin().getPath(b)); + }, + .lib => l: { + if (self.isStaticLibrary() and other.isStaticLibrary()) { + // Avoid putting a static library inside a static library. + break :l; + } + + // For DLLs, we gotta link against the implib. For + // everything else, we directly link against the library file. + const full_path_lib = if (other.producesImplib()) + other.getGeneratedFilePath("generated_implib", &self.step) + else + other.getGeneratedFilePath("generated_bin", &self.step); + try zig_args.append(full_path_lib); + + if (other.linkage == Linkage.dynamic and + self.root_module.target_info.target.os.tag != .windows) + { + if (fs.path.dirname(full_path_lib)) |dirname| { + try zig_args.append("-rpath"); + try zig_args.append(dirname); + } + } }, + } + }, + .assembly_file => |asm_file| { + if (prev_has_cflags) { + try zig_args.append("-cflags"); + try zig_args.append("--"); + prev_has_cflags = false; + } + try zig_args.append(asm_file.getPath(b)); + }, - else => |e| return e, + .c_source_file => |c_source_file| { + if (c_source_file.flags.len == 0) { + if (prev_has_cflags) { + try zig_args.append("-cflags"); + try zig_args.append("--"); + prev_has_cflags = false; + } + } else { + try zig_args.append("-cflags"); + for (c_source_file.flags) |arg| { + try zig_args.append(arg); + } + try zig_args.append("--"); + prev_has_cflags = true; } + try zig_args.append(c_source_file.file.getPath(b)); }, - } - }, - .assembly_file => |asm_file| { - if (prev_has_cflags) { - try zig_args.append("-cflags"); - try zig_args.append("--"); - prev_has_cflags = false; - } - try zig_args.append(asm_file.getPath(b)); - }, + .c_source_files => |c_source_files| { + if (c_source_files.flags.len == 0) { + if (prev_has_cflags) { + try zig_args.append("-cflags"); + try zig_args.append("--"); + prev_has_cflags = false; + } + } else { + try zig_args.append("-cflags"); + for (c_source_files.flags) |flag| { + try zig_args.append(flag); + } + try zig_args.append("--"); + prev_has_cflags = true; + } + if (c_source_files.dependency) |dep| { + for (c_source_files.files) |file| { + try zig_args.append(dep.builder.pathFromRoot(file)); + } + } else { + for (c_source_files.files) |file| { + try zig_args.append(b.pathFromRoot(file)); + } + } + }, - .c_source_file => |c_source_file| { - if (c_source_file.flags.len == 0) { - if (prev_has_cflags) { - try zig_args.append("-cflags"); - try zig_args.append("--"); - prev_has_cflags = false; - } - } else { - try zig_args.append("-cflags"); - for (c_source_file.flags) |arg| { - try zig_args.append(arg); - } - try zig_args.append("--"); - prev_has_cflags = true; + .win32_resource_file => |rc_source_file| { + if (rc_source_file.flags.len == 0) { + if (prev_has_rcflags) { + try zig_args.append("-rcflags"); + try zig_args.append("--"); + prev_has_rcflags = false; + } + } else { + try zig_args.append("-rcflags"); + for (rc_source_file.flags) |arg| { + try zig_args.append(arg); + } + try zig_args.append("--"); + prev_has_rcflags = true; + } + try zig_args.append(rc_source_file.file.getPath(b)); + }, } - try zig_args.append(c_source_file.file.getPath(b)); - }, + } + } - .c_source_files => |c_source_files| { - if (c_source_files.flags.len == 0) { - if (prev_has_cflags) { - try zig_args.append("-cflags"); - try zig_args.append("--"); - prev_has_cflags = false; - } - } else { - try zig_args.append("-cflags"); - for (c_source_files.flags) |flag| { - try zig_args.append(flag); - } - try zig_args.append("--"); - prev_has_cflags = true; - } - if (c_source_files.dependency) |dep| { - for (c_source_files.files) |file| { - try zig_args.append(dep.builder.pathFromRoot(file)); - } - } else { - for (c_source_files.files) |file| { - try zig_args.append(b.pathFromRoot(file)); - } - } - }, + if (total_linker_objects == 0) { + return step.fail("the linker needs one or more objects to link", .{}); + } - .win32_resource_file => |rc_source_file| { - if (rc_source_file.flags.len == 0) { - if (prev_has_rcflags) { - try zig_args.append("-rcflags"); - try zig_args.append("--"); - prev_has_rcflags = false; - } - } else { - try zig_args.append("-rcflags"); - for (rc_source_file.flags) |arg| { - try zig_args.append(arg); - } - try zig_args.append("--"); - prev_has_rcflags = true; - } - try zig_args.append(rc_source_file.file.getPath(b)); - }, + for (frameworks.keys(), frameworks.values()) |name, info| { + if (info.needed) { + try zig_args.append("-needed_framework"); + } else if (info.weak) { + try zig_args.append("-weak_framework"); + } else { + try zig_args.append("-framework"); + } + try zig_args.append(name); } - } - if (self.win32_manifest) |manifest_file| { - try zig_args.append(manifest_file.getPath(b)); - } + if (self.is_linking_libcpp) { + try zig_args.append("-lc++"); + } - if (transitive_deps.is_linking_libcpp) { - try zig_args.append("-lc++"); + if (self.is_linking_libc) { + try zig_args.append("-lc"); + } } - if (transitive_deps.is_linking_libc) { - try zig_args.append("-lc"); + if (self.win32_manifest) |manifest_file| { + try zig_args.append(manifest_file.getPath(b)); } if (self.image_base) |image_base| { @@ -1702,17 +1436,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.generated_llvm_ir != null) try zig_args.append("-femit-llvm-ir"); if (self.generated_h != null) try zig_args.append("-femit-h"); - try addFlag(&zig_args, "strip", self.strip); - try addFlag(&zig_args, "formatted-panics", self.formatted_panics); - try addFlag(&zig_args, "unwind-tables", self.unwind_tables); - - if (self.dwarf_format) |dwarf_format| { - try zig_args.append(switch (dwarf_format) { - .@"32" => "-gdwarf32", - .@"64" => "-gdwarf64", - }); - } - switch (self.compress_debug_sections) { .none => {}, .zlib => try zig_args.append("--compress-debug-sections=zlib"), @@ -1769,11 +1492,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(libc_file); } - switch (self.optimize) { - .Debug => {}, // Skip since it's the default. - else => try zig_args.append(b.fmt("-O{s}", .{@tagName(self.optimize)})), - } - try zig_args.append("--cache-dir"); try zig_args.append(b.cache_root.path orelse "."); @@ -1793,11 +1511,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(b.fmt("{}", .{version})); } - if (self.target.isDarwin()) { + if (self.root_module.target_info.target.isDarwin()) { const install_name = self.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{ - self.target.libPrefix(), + self.root_module.target_info.target.libPrefix(), self.name, - self.target.dynamicLibSuffix(), + self.root_module.target_info.target.dynamicLibSuffix(), }); try zig_args.append("-install_name"); try zig_args.append(install_name); @@ -1823,27 +1541,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } try addFlag(&zig_args, "compiler-rt", self.bundle_compiler_rt); - try addFlag(&zig_args, "single-threaded", self.single_threaded); - if (self.disable_stack_probing) { - try zig_args.append("-fno-stack-check"); - } - try addFlag(&zig_args, "stack-protector", self.stack_protector); - if (self.red_zone) |red_zone| { - if (red_zone) { - try zig_args.append("-mred-zone"); - } else { - try zig_args.append("-mno-red-zone"); - } - } - try addFlag(&zig_args, "omit-frame-pointer", self.omit_frame_pointer); try addFlag(&zig_args, "dll-export-fns", self.dll_export_fns); - - if (self.disable_sanitize_c) { - try zig_args.append("-fno-sanitize-c"); - } - if (self.sanitize_thread) { - try zig_args.append("-fsanitize-thread"); - } if (self.rdynamic) { try zig_args.append("-rdynamic"); } @@ -1875,29 +1573,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(b.fmt("--global-base={d}", .{global_base})); } - if (self.code_model != .default) { - try zig_args.append("-mcmodel"); - try zig_args.append(@tagName(self.code_model)); - } if (self.wasi_exec_model) |model| { try zig_args.append(b.fmt("-mexec-model={s}", .{@tagName(model)})); } - for (self.export_symbol_names) |symbol_name| { - try zig_args.append(b.fmt("--export={s}", .{symbol_name})); - } - - if (!self.target.isNative()) { - try zig_args.appendSlice(&.{ - "-target", try self.target.zigTriple(b.allocator), - "-mcpu", try std.Build.serializeCpu(b.allocator, self.target.getCpu()), - }); - - if (self.target.dynamic_linker.get()) |dynamic_linker| { - try zig_args.append("--dynamic-linker"); - try zig_args.append(dynamic_linker); - } - } - if (self.linker_script) |linker_script| { try zig_args.append("--script"); try zig_args.append(linker_script.getPath(b)); @@ -1923,97 +1601,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try self.appendModuleArgs(&zig_args); - for (self.include_dirs.items) |include_dir| { - switch (include_dir) { - .path => |include_path| { - try zig_args.append("-I"); - try zig_args.append(include_path.getPath(b)); - }, - .path_system => |include_path| { - try zig_args.append("-isystem"); - try zig_args.append(include_path.getPath(b)); - }, - .path_after => |include_path| { - try zig_args.append("-idirafter"); - try zig_args.append(include_path.getPath(b)); - }, - .framework_path => |include_path| { - try zig_args.append("-F"); - try zig_args.append(include_path.getPath2(b, step)); - }, - .framework_path_system => |include_path| { - try zig_args.append("-iframework"); - try zig_args.append(include_path.getPath2(b, step)); - }, - .other_step => |other| { - if (other.generated_h) |header| { - try zig_args.append("-isystem"); - try zig_args.append(fs.path.dirname(header.path.?).?); - } - if (other.installed_headers.items.len > 0) { - try zig_args.append("-I"); - try zig_args.append(b.pathJoin(&.{ - other.step.owner.install_prefix, "include", - })); - } - }, - .config_header_step => |config_header| { - const full_file_path = config_header.output_file.path.?; - const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len]; - try zig_args.appendSlice(&.{ "-I", header_dir_path }); - }, - } - } - - for (self.c_macros.items) |c_macro| { - try zig_args.append("-D"); - try zig_args.append(c_macro); - } - - try zig_args.ensureUnusedCapacity(2 * self.lib_paths.items.len); - for (self.lib_paths.items) |lib_path| { - zig_args.appendAssumeCapacity("-L"); - zig_args.appendAssumeCapacity(lib_path.getPath2(b, step)); - } - - try zig_args.ensureUnusedCapacity(2 * self.rpaths.items.len); - for (self.rpaths.items) |rpath| { - zig_args.appendAssumeCapacity("-rpath"); - - if (self.target_info.target.isDarwin()) switch (rpath) { - .path, .cwd_relative => |path| { - // On Darwin, we should not try to expand special runtime paths such as - // * @executable_path - // * @loader_path - if (mem.startsWith(u8, path, "@executable_path") or - mem.startsWith(u8, path, "@loader_path")) - { - zig_args.appendAssumeCapacity(path); - continue; - } - }, - .generated, .dependency => {}, - }; - - zig_args.appendAssumeCapacity(rpath.getPath2(b, step)); - } - - { - var it = self.frameworks.iterator(); - while (it.next()) |entry| { - const name = entry.key_ptr.*; - const info = entry.value_ptr.*; - if (info.needed) { - try zig_args.append("-needed_framework"); - } else if (info.weak) { - try zig_args.append("-weak_framework"); - } else { - try zig_args.append("-framework"); - } - try zig_args.append(name); - } - } - if (b.sysroot) |sysroot| { try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); } @@ -2058,7 +1645,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(@tagName(self.rc_includes)); } - try addFlag(&zig_args, "valgrind", self.valgrind_support); try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath); if (self.build_id) |build_id| { @@ -2075,12 +1661,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(dir.getPath(b)); } - if (self.main_mod_path) |dir| { - try zig_args.append("--main-mod-path"); - try zig_args.append(dir.getPath(b)); - } - - try addFlag(&zig_args, "PIC", self.force_pic); try addFlag(&zig_args, "PIE", self.pie); try addFlag(&zig_args, "lto", self.want_lto); @@ -2223,7 +1803,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and - self.version != null and self.target.wantSharedLibSymLinks()) + self.version != null and self.root_module.target.wantSharedLibSymLinks()) { try doAtomicSymLinks( step, @@ -2234,24 +1814,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } -fn isLibCLibrary(name: []const u8) bool { - const libc_libraries = [_][]const u8{ "c", "m", "dl", "rt", "pthread" }; - for (libc_libraries) |libc_lib_name| { - if (mem.eql(u8, name, libc_lib_name)) - return true; - } - return false; -} - -fn isLibCppLibrary(name: []const u8) bool { - const libcpp_libraries = [_][]const u8{ "c++", "stdc++" }; - for (libcpp_libraries) |libcpp_lib_name| { - if (mem.eql(u8, name, libcpp_lib_name)) - return true; - } - return false; -} - /// Returned slice must be freed by the caller. fn findVcpkgRoot(allocator: Allocator) !?[]const u8 { const appdata_path = try fs.getAppDataDir(allocator, "vcpkg"); @@ -2345,67 +1907,6 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) } } -const TransitiveDeps = struct { - link_objects: ArrayList(LinkObject), - seen_system_libs: StringHashMap(void), - seen_steps: std.AutoHashMap(*const Step, void), - is_linking_libcpp: bool, - is_linking_libc: bool, - frameworks: *StringHashMap(FrameworkLinkInfo), - - fn add(td: *TransitiveDeps, link_objects: []const LinkObject) !void { - try td.link_objects.ensureUnusedCapacity(link_objects.len); - - for (link_objects) |link_object| { - try td.link_objects.append(link_object); - switch (link_object) { - .other_step => |other| try addInner(td, other, other.isDynamicLibrary()), - else => {}, - } - } - } - - fn addInner(td: *TransitiveDeps, other: *Compile, dyn: bool) !void { - // Inherit dependency on libc and libc++ - td.is_linking_libcpp = td.is_linking_libcpp or other.is_linking_libcpp; - td.is_linking_libc = td.is_linking_libc or other.is_linking_libc; - - // Inherit dependencies on darwin frameworks - if (!dyn) { - var it = other.frameworks.iterator(); - while (it.next()) |framework| { - try td.frameworks.put(framework.key_ptr.*, framework.value_ptr.*); - } - } - - // Inherit dependencies on system libraries and static libraries. - for (other.link_objects.items) |other_link_object| { - switch (other_link_object) { - .system_lib => |system_lib| { - if ((try td.seen_system_libs.fetchPut(system_lib.name, {})) != null) - continue; - - if (dyn) - continue; - - try td.link_objects.append(other_link_object); - }, - .other_step => |inner_other| { - if ((try td.seen_steps.fetchPut(&inner_other.step, {})) != null) - continue; - - const included_in_lib = (other.kind == .lib and inner_other.kind == .obj); - if (!dyn and !included_in_lib) - try td.link_objects.append(other_link_object); - - try addInner(td, inner_other, dyn or inner_other.isDynamicLibrary()); - }, - else => continue, - } - } - } -}; - fn checkCompileErrors(self: *Compile) !void { // Clear this field so that it does not get printed by the build runner. const actual_eb = self.step.result_error_bundle; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 5555b03e94ef..855eabeae9ba 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -488,7 +488,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { man.hash.addBytes(file_path); }, .artifact => |artifact| { - if (artifact.target.isWindows()) { + if (artifact.root_module.target_info.target.os.tag == .windows) { // On Windows we don't have rpaths so we have to add .dll search paths to PATH self.addPathForDynLibs(artifact); } @@ -682,8 +682,9 @@ fn runCommand( else => break :interpret, } - const need_cross_glibc = exe.target.isGnuLibC() and exe.is_linking_libc; - switch (b.host.getExternalExecutor(&exe.target_info, .{ + const need_cross_glibc = exe.root_module.target_info.target.isGnuLibC() and + exe.is_linking_libc; + switch (b.host.getExternalExecutor(&exe.root_module.target_info, .{ .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -714,9 +715,9 @@ fn runCommand( // needs the directory to be called "i686" rather than // "x86" which is why we do it manually here. const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}"; - const cpu_arch = exe.target.getCpuArch(); - const os_tag = exe.target.getOsTag(); - const abi = exe.target.getAbi(); + const cpu_arch = exe.root_module.target_info.target.cpu.arch; + const os_tag = exe.root_module.target_info.target.os.tag; + const abi = exe.root_module.target_info.target.abi; const cpu_arch_name: []const u8 = if (cpu_arch == .x86) "i686" else @@ -769,7 +770,7 @@ fn runCommand( if (allow_skip) return error.MakeSkipped; const host_name = try b.host.target.zigTriple(b.allocator); - const foreign_name = try exe.target.zigTriple(b.allocator); + const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator); return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{ host_name, foreign_name, @@ -777,7 +778,7 @@ fn runCommand( }, } - if (exe.target.isWindows()) { + if (exe.root_module.target_info.target.os.tag == .windows) { // On Windows we don't have rpaths so we have to add .dll search paths to PATH self.addPathForDynLibs(exe); } @@ -1295,15 +1296,14 @@ fn evalGeneric(self: *Run, child: *std.process.Child) !StdIoResult { fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void { const b = self.step.owner; - for (artifact.link_objects.items) |link_object| { - switch (link_object) { - .other_step => |other| { - if (other.target.isWindows() and other.isDynamicLibrary()) { - addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); - addPathForDynLibs(self, other); - } - }, - else => {}, + var it = artifact.root_module.iterateDependencies(artifact); + while (it.next()) |item| { + const other = item.compile.?; + if (item.module == &other.root_module) { + if (item.module.target_info.target.os.tag == .windows and other.isDynamicLibrary()) { + addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); + addPathForDynLibs(self, other); + } } } } @@ -1321,7 +1321,7 @@ fn failForeign( const b = self.step.owner; const host_name = try b.host.target.zigTriple(b.allocator); - const foreign_name = try exe.target.zigTriple(b.allocator); + const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator); return self.step.fail( \\unable to spawn foreign binary '{s}' ({s}) on host system ({s}) From 579f572cf203eda11da7e4e919fdfc12e15f03e2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 1 Dec 2023 13:01:39 -0700 Subject: [PATCH 004/133] zig build system: remove vcpkg integration Instead of vcpkg, users are encouraged to use the Zig package manager to fulfill dependencies on Windows. --- lib/std/Build.zig | 17 ---------- lib/std/Build/Step/Compile.zig | 59 ---------------------------------- lib/std/zig/CrossTarget.zig | 37 --------------------- 3 files changed, 113 deletions(-) diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 590ac5aadf6a..8726feb7c122 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -67,7 +67,6 @@ cache_root: Cache.Directory, global_cache_root: Cache.Directory, cache: *Cache, zig_lib_dir: ?LazyPath, -vcpkg_root: VcpkgRoot = .unattempted, pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, args: ?[][]const u8 = null, debug_log_scopes: []const []const u8 = &.{}, @@ -841,10 +840,6 @@ pub fn addRunArtifact(b: *Build, exe: *Step.Compile) *Step.Run { run_step.enableTestRunnerMode(); } - if (exe.vcpkg_bin_path) |path| { - run_step.addPathDir(path); - } - return run_step; } @@ -1978,18 +1973,6 @@ pub fn constructCMacro(allocator: Allocator, name: []const u8, value: ?[]const u return macro; } -pub const VcpkgRoot = union(VcpkgRootStatus) { - unattempted: void, - not_found: void, - found: []const u8, -}; - -pub const VcpkgRootStatus = enum { - unattempted, - not_found, - found, -}; - pub const InstallDir = union(enum) { prefix: void, lib: void, diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 31d07a43596b..4cd8868752c8 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -16,7 +16,6 @@ const PkgConfigPkg = std.Build.PkgConfigPkg; const PkgConfigError = std.Build.PkgConfigError; const RunError = std.Build.RunError; const Module = std.Build.Module; -const VcpkgRoot = std.Build.VcpkgRoot; const InstallDir = std.Build.InstallDir; const GeneratedFile = std.Build.GeneratedFile; const Compile = @This(); @@ -63,7 +62,6 @@ test_server_mode: bool, wasi_exec_model: ?std.builtin.WasiExecModel = null, installed_headers: ArrayList(*Step), -vcpkg_bin_path: ?[]const u8 = null, // keep in sync with src/Compilation.zig:RcIncludes /// Behavior of automatic detection of include directories when compiling .rc files. @@ -936,44 +934,6 @@ pub fn addFrameworkPath(self: *Compile, directory_source: LazyPath) void { directory_source.addStepDependencies(&self.step); } -/// If Vcpkg was found on the system, it will be added to include and lib -/// paths for the specified target. -pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void { - const b = self.step.owner; - // Ideally in the Unattempted case we would call the function recursively - // after findVcpkgRoot and have only one switch statement, but the compiler - // cannot resolve the error set. - switch (b.vcpkg_root) { - .unattempted => { - b.vcpkg_root = if (try findVcpkgRoot(b.allocator)) |root| - VcpkgRoot{ .found = root } - else - .not_found; - }, - .not_found => return error.VcpkgNotFound, - .found => {}, - } - - switch (b.vcpkg_root) { - .unattempted => unreachable, - .not_found => return error.VcpkgNotFound, - .found => |root| { - const allocator = b.allocator; - const triplet = try self.target.vcpkgTriplet(allocator, if (linkage == .static) .Static else .Dynamic); - defer b.allocator.free(triplet); - - const include_path = b.pathJoin(&.{ root, "installed", triplet, "include" }); - errdefer allocator.free(include_path); - try self.include_dirs.append(.{ .path = .{ .path = include_path } }); - - const lib_path = b.pathJoin(&.{ root, "installed", triplet, "lib" }); - try self.lib_paths.append(.{ .path = lib_path }); - - self.vcpkg_bin_path = b.pathJoin(&.{ root, "installed", triplet, "bin" }); - }, - } -} - pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { const b = self.step.owner; assert(self.kind == .@"test"); @@ -1814,25 +1774,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } -/// Returned slice must be freed by the caller. -fn findVcpkgRoot(allocator: Allocator) !?[]const u8 { - const appdata_path = try fs.getAppDataDir(allocator, "vcpkg"); - defer allocator.free(appdata_path); - - const path_file = try fs.path.join(allocator, &[_][]const u8{ appdata_path, "vcpkg.path.txt" }); - defer allocator.free(path_file); - - const file = fs.cwd().openFile(path_file, .{}) catch return null; - defer file.close(); - - const size = @as(usize, @intCast(try file.getEndPos())); - const vcpkg_path = try allocator.alloc(u8, size); - const size_read = try file.read(vcpkg_path); - std.debug.assert(size == size_read); - - return vcpkg_path; -} - pub fn doAtomicSymLinks( step: *Step, output_path: []const u8, diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig index ea496051b4ca..c65269e4d3dc 100644 --- a/lib/std/zig/CrossTarget.zig +++ b/lib/std/zig/CrossTarget.zig @@ -636,43 +636,6 @@ pub fn wantSharedLibSymLinks(self: CrossTarget) bool { return self.getOsTag() != .windows; } -pub const VcpkgLinkage = std.builtin.LinkMode; - -/// Returned slice must be freed by the caller. -pub fn vcpkgTriplet(self: CrossTarget, allocator: mem.Allocator, linkage: VcpkgLinkage) ![]u8 { - const arch = switch (self.getCpuArch()) { - .x86 => "x86", - .x86_64 => "x64", - - .arm, - .armeb, - .thumb, - .thumbeb, - .aarch64_32, - => "arm", - - .aarch64, - .aarch64_be, - => "arm64", - - else => return error.UnsupportedVcpkgArchitecture, - }; - - const os = switch (self.getOsTag()) { - .windows => "windows", - .linux => "linux", - .macos => "macos", - else => return error.UnsupportedVcpkgOperatingSystem, - }; - - const static_suffix = switch (linkage) { - .Static => "-static", - .Dynamic => "", - }; - - return std.fmt.allocPrint(allocator, "{s}-{s}{s}", .{ arch, os, static_suffix }); -} - pub fn isGnuLibC(self: CrossTarget) bool { return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); } From 142471fcc46070326526e3976f0150fe734df0b6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 2 Dec 2023 21:51:34 -0700 Subject: [PATCH 005/133] zig build system: change target, compilation, and module APIs Introduce the concept of "target query" and "resolved target". A target query is what the user specifies, with some things left to default. A resolved target has the default things discovered and populated. In the future, std.zig.CrossTarget will be rename to std.Target.Query. Introduces `std.Build.resolveTargetQuery` to get from one to the other. The concept of `main_mod_path` is gone, no longer supported. You have to put the root source file at the module root now. * remove deprecated API * update build.zig for the breaking API changes in this branch * move std.Build.Step.Compile.BuildId to std.zig.BuildId * add more options to std.Build.ExecutableOptions, std.Build.ObjectOptions, std.Build.SharedLibraryOptions, std.Build.StaticLibraryOptions, and std.Build.TestOptions. * remove `std.Build.constructCMacro`. There is no use for this API. * deprecate `std.Build.Step.Compile.defineCMacro`. Instead, `std.Build.Module.addCMacro` is provided. - remove `std.Build.Step.Compile.defineCMacroRaw`. * deprecate `std.Build.Step.Compile.linkFrameworkNeeded` - use `std.Build.Module.linkFramework` * deprecate `std.Build.Step.Compile.linkFrameworkWeak` - use `std.Build.Module.linkFramework` * move more logic into `std.Build.Module` * allow `target` and `optimize` to be `null` when creating a Module. Along with other fields, those unspecified options will be inherited from parent `Module` when inserted into an import table. * the `target` field of `addExecutable` is now required. pass `b.host` to get the host target. --- build.zig | 92 +- deps/aro/build/GenerateDef.zig | 4 +- lib/build_runner.zig | 7 +- lib/std/Build.zig | 177 ++- lib/std/Build/Cache.zig | 2 +- lib/std/Build/Module.zig | 347 ++++-- lib/std/Build/Step/CheckObject.zig | 48 +- lib/std/Build/Step/Compile.zig | 284 ++--- lib/std/Build/Step/ConfigHeader.zig | 6 - lib/std/Build/Step/InstallArtifact.zig | 2 +- lib/std/Build/Step/Options.zig | 6 +- lib/std/Build/Step/Run.zig | 27 +- lib/std/Build/Step/TranslateC.zig | 11 +- lib/std/Build/Step/WriteFile.zig | 7 - lib/std/std.zig | 3 - lib/std/zig.zig | 77 ++ lib/std/zig/CrossTarget.zig | 4 - lib/std/zig/system/NativeTargetInfo.zig | 4 +- src/Compilation.zig | 3 +- src/link.zig | 3 +- src/main.zig | 7 +- test/behavior/eval.zig | 20 +- test/cases.zig | 10 +- test/cbe.zig | 48 +- test/compile_errors.zig | 22 +- test/link/bss/build.zig | 1 + test/link/common_symbols/build.zig | 2 +- test/link/common_symbols_alignment/build.zig | 2 +- test/link/elf.zig | 1097 ++++++++++------- test/link/glibc_compat/build.zig | 4 +- .../interdependent_static_c_libs/build.zig | 4 +- test/link/link.zig | 175 ++- test/link/macho.zig | 59 +- test/link/macho/bugs/13056/build.zig | 6 +- test/link/macho/bugs/13457/build.zig | 2 +- test/link/macho/bugs/16308/build.zig | 2 +- test/link/macho/bugs/16628/build.zig | 2 +- test/link/macho/dead_strip/build.zig | 4 +- test/link/macho/dead_strip_dylibs/build.zig | 1 + test/link/macho/dylib/build.zig | 4 +- test/link/macho/empty/build.zig | 2 +- test/link/macho/entry/build.zig | 2 +- test/link/macho/entry_in_archive/build.zig | 4 +- test/link/macho/entry_in_dylib/build.zig | 4 +- test/link/macho/headerpad/build.zig | 1 + test/link/macho/linksection/build.zig | 2 +- test/link/macho/needed_framework/build.zig | 1 + test/link/macho/needed_library/build.zig | 4 +- test/link/macho/objc/build.zig | 1 + test/link/macho/objcpp/build.zig | 1 + test/link/macho/pagezero/build.zig | 2 +- test/link/macho/reexports/build.zig | 2 +- test/link/macho/search_strategy/build.zig | 6 +- test/link/macho/stack_size/build.zig | 2 +- test/link/macho/strict_validation/build.zig | 2 +- test/link/macho/tbdv3/build.zig | 2 +- test/link/macho/tls/build.zig | 2 +- test/link/macho/unwind_info/build.zig | 6 +- test/link/macho/weak_framework/build.zig | 1 + test/link/macho/weak_library/build.zig | 4 +- .../static_libs_from_object_files/build.zig | 14 +- test/link/wasm/archive/build.zig | 2 +- test/link/wasm/basic-features/build.zig | 4 +- test/link/wasm/bss/build.zig | 8 +- test/link/wasm/export-data/build.zig | 2 +- test/link/wasm/export/build.zig | 8 +- test/link/wasm/extern-mangle/build.zig | 2 +- test/link/wasm/extern/build.zig | 2 +- test/link/wasm/function-table/build.zig | 6 +- test/link/wasm/infer-features/build.zig | 8 +- test/link/wasm/producers/build.zig | 4 +- test/link/wasm/segments/build.zig | 4 +- test/link/wasm/shared-memory/build.zig | 6 +- test/link/wasm/stack_pointer/build.zig | 4 +- test/link/wasm/type/build.zig | 4 +- test/llvm_targets.zig | 12 +- test/nvptx.zig | 27 +- test/src/Cases.zig | 109 +- test/src/CompareOutput.zig | 6 +- test/src/StackTrace.zig | 2 +- test/src/run_translated_c.zig | 4 +- test/src/translate_c.zig | 4 +- test/standalone.zig | 4 - test/standalone/c_compiler/build.zig | 4 +- test/standalone/child_process/build.zig | 2 +- test/standalone/compiler_rt_panic/build.zig | 8 +- test/standalone/dep_diamond/build.zig | 15 +- .../dep_mutually_recursive/build.zig | 11 +- test/standalone/dep_recursive/build.zig | 7 +- test/standalone/dep_shared_builtin/build.zig | 5 +- test/standalone/dep_triangle/build.zig | 11 +- .../standalone/embed_generated_file/build.zig | 8 +- test/standalone/empty_env/build.zig | 1 + test/standalone/extern/build.zig | 2 +- test/standalone/global_linkage/build.zig | 2 +- test/standalone/install_raw_hex/build.zig | 4 +- test/standalone/ios/build.zig | 8 +- test/standalone/issue_11595/build.zig | 2 +- test/standalone/issue_12588/build.zig | 3 +- test/standalone/issue_12706/build.zig | 3 +- test/standalone/issue_339/build.zig | 2 +- test/standalone/issue_8550/build.zig | 4 +- .../standalone/load_dynamic_library/build.zig | 2 +- test/standalone/main_pkg_path/a/test.zig | 5 - test/standalone/main_pkg_path/b.zig | 1 - test/standalone/main_pkg_path/build.zig | 13 - test/standalone/mix_c_files/build.zig | 1 + test/standalone/mix_o_files/build.zig | 2 +- test/standalone/options/build.zig | 2 +- test/standalone/pie/build.zig | 4 +- test/standalone/pkg_import/build.zig | 3 +- test/standalone/self_exe_symlink/build.zig | 4 +- test/standalone/shared_library/build.zig | 2 +- test/standalone/stack_iterator/build.zig | 19 +- test/standalone/static_c_lib/build.zig | 2 +- test/standalone/strip_empty_loop/build.zig | 4 +- test/standalone/strip_struct_init/build.zig | 2 +- .../test_runner_module_imports/build.zig | 8 +- test/standalone/windows_resources/build.zig | 16 +- test/standalone/windows_spawn/build.zig | 2 +- test/standalone/zerolength_check/build.zig | 4 +- test/tests.zig | 69 +- 122 files changed, 1812 insertions(+), 1338 deletions(-) delete mode 100644 test/standalone/main_pkg_path/a/test.zig delete mode 100644 test/standalone/main_pkg_path/b.zig delete mode 100644 test/standalone/main_pkg_path/build.zig diff --git a/build.zig b/build.zig index 11b3006039b7..bc4c32035c67 100644 --- a/build.zig +++ b/build.zig @@ -39,10 +39,10 @@ pub fn build(b: *std.Build) !void { const docgen_exe = b.addExecutable(.{ .name = "docgen", .root_source_file = .{ .path = "tools/docgen.zig" }, - .target = .{}, + .target = b.host, .optimize = .Debug, + .single_threaded = single_threaded, }); - docgen_exe.single_threaded = single_threaded; const docgen_cmd = b.addRunArtifact(docgen_exe); docgen_cmd.addArgs(&.{ "--zig", b.zig_exe }); @@ -89,11 +89,11 @@ pub fn build(b: *std.Build) !void { const check_case_exe = b.addExecutable(.{ .name = "check-case", .root_source_file = .{ .path = "test/src/Cases.zig" }, + .target = b.host, .optimize = optimize, - .main_mod_path = .{ .path = "." }, + .single_threaded = single_threaded, }); check_case_exe.stack_size = stack_size; - check_case_exe.single_threaded = single_threaded; const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false; const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; @@ -194,14 +194,18 @@ pub fn build(b: *std.Build) !void { break :blk 4; }; - const exe = addCompilerStep(b, optimize, target); - exe.strip = strip; + const exe = addCompilerStep(b, .{ + .optimize = optimize, + .target = target, + .strip = strip, + .sanitize_thread = sanitize_thread, + .single_threaded = single_threaded, + }); exe.pie = pie; - exe.sanitize_thread = sanitize_thread; exe.entitlements = entitlements; exe.build_id = b.option( - std.Build.Step.Compile.BuildId, + std.zig.BuildId, "build-id", "Request creation of '.note.gnu.build-id' section", ); @@ -217,9 +221,7 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(&exe.step); - exe.single_threaded = single_threaded; - - if (target.isWindows() and target.getAbi() == .gnu) { + if (target.target.os.tag == .windows and target.target.abi == .gnu) { // LTO is currently broken on mingw, this can be removed when it's fixed. exe.want_lto = false; check_case_exe.want_lto = false; @@ -230,7 +232,7 @@ pub fn build(b: *std.Build) !void { exe.use_lld = use_llvm; const exe_options = b.addOptions(); - exe.addOptions("build_options", exe_options); + exe.root_module.addOptions("build_options", exe_options); exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames); exe_options.addOption(bool, "skip_non_native", skip_non_native); @@ -345,7 +347,7 @@ pub fn build(b: *std.Build) !void { try addStaticLlvmOptionsToExe(exe); try addStaticLlvmOptionsToExe(check_case_exe); } - if (target.isWindows()) { + if (target.target.os.tag == .windows) { inline for (.{ exe, check_case_exe }) |artifact| { artifact.linkSystemLibrary("version"); artifact.linkSystemLibrary("uuid"); @@ -369,7 +371,7 @@ pub fn build(b: *std.Build) !void { ); // On mingw, we need to opt into windows 7+ to get some features required by tracy. - const tracy_c_flags: []const []const u8 = if (target.isWindows() and target.getAbi() == .gnu) + const tracy_c_flags: []const []const u8 = if (target.target.os.tag == .windows and target.target.abi == .gnu) &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined", "-D_WIN32_WINNT=0x601" } else &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" }; @@ -377,11 +379,11 @@ pub fn build(b: *std.Build) !void { exe.addIncludePath(.{ .cwd_relative = tracy_path }); exe.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags }); if (!enable_llvm) { - exe.linkSystemLibraryName("c++"); + exe.root_module.linkSystemLibrary("c++", .{ .use_pkg_config = .no }); } exe.linkLibC(); - if (target.isWindows()) { + if (target.target.os.tag == .windows) { exe.linkSystemLibrary("dbghelp"); exe.linkSystemLibrary("ws2_32"); } @@ -390,7 +392,7 @@ pub fn build(b: *std.Build) !void { const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); const test_cases_options = b.addOptions(); - check_case_exe.addOptions("build_options", test_cases_options); + check_case_exe.root_module.addOptions("build_options", test_cases_options); test_cases_options.addOption(bool, "enable_tracy", false); test_cases_options.addOption(bool, "enable_logging", enable_logging); @@ -540,16 +542,19 @@ pub fn build(b: *std.Build) !void { fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { const semver = try std.SemanticVersion.parse(version); - var target: std.zig.CrossTarget = .{ + var target_query: std.zig.CrossTarget = .{ .cpu_arch = .wasm32, .os_tag = .wasi, }; - target.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory)); + target_query.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory)); - const exe = addCompilerStep(b, .ReleaseSmall, target); + const exe = addCompilerStep(b, .{ + .optimize = .ReleaseSmall, + .target = b.resolveTargetQuery(target_query), + }); const exe_options = b.addOptions(); - exe.addOptions("build_options", exe_options); + exe.root_module.addOptions("build_options", exe_options); exe_options.addOption(u32, "mem_leak_frames", 0); exe_options.addOption(bool, "have_llvm", false); @@ -584,17 +589,24 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { update_zig1_step.dependOn(©_zig_h.step); } -fn addCompilerStep( - b: *std.Build, +const AddCompilerStepOptions = struct { optimize: std.builtin.OptimizeMode, - target: std.zig.CrossTarget, -) *std.Build.Step.Compile { + target: std.Build.ResolvedTarget, + strip: ?bool = null, + sanitize_thread: ?bool = null, + single_threaded: ?bool = null, +}; + +fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile { const exe = b.addExecutable(.{ .name = "zig", .root_source_file = .{ .path = "src/main.zig" }, - .target = target, - .optimize = optimize, + .target = options.target, + .optimize = options.optimize, .max_rss = 7_000_000_000, + .strip = options.strip, + .sanitize_thread = options.sanitize_thread, + .single_threaded = options.single_threaded, }); exe.stack_size = stack_size; @@ -602,15 +614,15 @@ fn addCompilerStep( aro_options.addOption([]const u8, "version_str", "aro-zig"); const aro_options_module = aro_options.createModule(); const aro_backend = b.createModule(.{ - .source_file = .{ .path = "deps/aro/backend.zig" }, - .dependencies = &.{.{ + .root_source_file = .{ .path = "deps/aro/backend.zig" }, + .imports = &.{.{ .name = "build_options", .module = aro_options_module, }}, }); const aro_module = b.createModule(.{ - .source_file = .{ .path = "deps/aro/aro.zig" }, - .dependencies = &.{ + .root_source_file = .{ .path = "deps/aro/aro.zig" }, + .imports = &.{ .{ .name = "build_options", .module = aro_options_module, @@ -625,7 +637,7 @@ fn addCompilerStep( }, }); - exe.addModule("aro", aro_module); + exe.root_module.addImport("aro", aro_module); return exe; } @@ -649,7 +661,7 @@ fn addCmakeCfgOptionsToExe( exe: *std.Build.Step.Compile, use_zig_libcxx: bool, ) !void { - if (exe.target.isDarwin()) { + if (exe.rootModuleTarget().isDarwin()) { // useful for package maintainers exe.headerpad_max_install_names = true; } @@ -677,8 +689,8 @@ fn addCmakeCfgOptionsToExe( // against system-provided LLVM, Clang, LLD. const need_cpp_includes = true; const static = cfg.llvm_linkage == .static; - const lib_suffix = if (static) exe.target.staticLibSuffix()[1..] else exe.target.dynamicLibSuffix()[1..]; - switch (exe.target.getOsTag()) { + const lib_suffix = if (static) exe.rootModuleTarget().staticLibSuffix()[1..] else exe.rootModuleTarget().dynamicLibSuffix()[1..]; + switch (exe.rootModuleTarget().os.tag) { .linux => { // First we try to link against the detected libcxx name. If that doesn't work, we fall // back to -lc++ and cross our fingers. @@ -694,7 +706,7 @@ fn addCmakeCfgOptionsToExe( exe.linkLibCpp(); }, .windows => { - if (exe.target.getAbi() != .msvc) exe.linkLibCpp(); + if (exe.rootModuleTarget().abi != .msvc) exe.linkLibCpp(); }, .freebsd => { if (static) { @@ -756,12 +768,12 @@ fn addStaticLlvmOptionsToExe(exe: *std.Build.Step.Compile) !void { exe.linkSystemLibrary("z"); exe.linkSystemLibrary("zstd"); - if (exe.target.getOs().tag != .windows or exe.target.getAbi() != .msvc) { + if (exe.rootModuleTarget().os.tag != .windows or exe.rootModuleTarget().abi != .msvc) { // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. exe.linkSystemLibrary("c++"); } - if (exe.target.getOs().tag == .windows) { + if (exe.rootModuleTarget().os.tag == .windows) { exe.linkSystemLibrary("version"); exe.linkSystemLibrary("uuid"); exe.linkSystemLibrary("ole32"); @@ -810,7 +822,9 @@ fn addCMakeLibraryList(exe: *std.Build.Step.Compile, list: []const u8) void { while (it.next()) |lib| { if (mem.startsWith(u8, lib, "-l")) { exe.linkSystemLibrary(lib["-l".len..]); - } else if (exe.target.isWindows() and mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) { + } else if (exe.rootModuleTarget().os.tag == .windows and + mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) + { exe.linkSystemLibrary(lib[0 .. lib.len - ".lib".len]); } else { exe.addObjectFile(.{ .cwd_relative = lib }); diff --git a/deps/aro/build/GenerateDef.zig b/deps/aro/build/GenerateDef.zig index 129d65ebdf2a..5c0f8d4b18bd 100644 --- a/deps/aro/build/GenerateDef.zig +++ b/deps/aro/build/GenerateDef.zig @@ -21,7 +21,7 @@ pub const Options = struct { pub const Kind = enum { dafsa, named }; }; -pub fn create(owner: *std.Build, options: Options) std.Build.ModuleDependency { +pub fn create(owner: *std.Build, options: Options) std.Build.Module.Import { const self = owner.allocator.create(GenerateDef) catch @panic("OOM"); const path = owner.pathJoin(&.{ options.src_prefix, options.name }); @@ -39,7 +39,7 @@ pub fn create(owner: *std.Build, options: Options) std.Build.ModuleDependency { .generated_file = .{ .step = &self.step }, }; const module = self.step.owner.createModule(.{ - .source_file = .{ .generated = &self.generated_file }, + .root_source_file = .{ .generated = &self.generated_file }, }); return .{ .module = module, diff --git a/lib/build_runner.zig b/lib/build_runner.zig index a5e537c43c4c..fba1c90d71a7 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -46,7 +46,12 @@ pub fn main() !void { return error.InvalidArgs; }; - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const detected = try std.zig.system.NativeTargetInfo.detect(.{}); + const host: std.Build.ResolvedTarget = .{ + .query = .{}, + .target = detected.target, + .dynamic_linker = detected.dynamic_linker, + }; const build_root_directory: std.Build.Cache.Directory = .{ .path = build_root, diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 8726feb7c122..666a1ec15b23 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -14,20 +14,11 @@ const process = std.process; const EnvMap = std.process.EnvMap; const fmt_lib = std.fmt; const File = std.fs.File; -const CrossTarget = std.zig.CrossTarget; -const NativeTargetInfo = std.zig.system.NativeTargetInfo; +const TargetQuery = std.zig.CrossTarget; const Sha256 = std.crypto.hash.sha2.Sha256; const Build = @This(); pub const Cache = @import("Build/Cache.zig"); - -/// deprecated: use `Step.Compile`. -pub const LibExeObjStep = Step.Compile; -/// deprecated: use `Build`. -pub const Builder = Build; -/// deprecated: use `Step.InstallDir.Options` -pub const InstallDirectoryOptions = Step.InstallDir.Options; - pub const Step = @import("Build/Step.zig"); pub const Module = @import("Build/Module.zig"); @@ -94,7 +85,7 @@ enable_wine: bool = false, glibc_runtimes_dir: ?[]const u8 = null, /// Information about the native target. Computed before build() is invoked. -host: NativeTargetInfo, +host: ResolvedTarget, dep_prefix: []const u8 = "", @@ -220,7 +211,7 @@ pub fn create( build_root: Cache.Directory, cache_root: Cache.Directory, global_cache_root: Cache.Directory, - host: NativeTargetInfo, + host: ResolvedTarget, cache: *Cache, available_deps: AvailableDeps, ) !*Build { @@ -384,7 +375,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption const v = @field(args, field.name); const T = @TypeOf(v); switch (T) { - CrossTarget => { + TargetQuery => { user_input_options.put(field.name, .{ .name = field.name, .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, @@ -593,14 +584,22 @@ pub fn addOptions(self: *Build) *Step.Options { pub const ExecutableOptions = struct { name: []const u8, + /// If you want the executable to run on the same computer as the one + /// building the package, pass the `host` field of the package's `Build` + /// instance. + target: ResolvedTarget, root_source_file: ?LazyPath = null, version: ?std.SemanticVersion = null, - target: CrossTarget = .{}, optimize: std.builtin.OptimizeMode = .Debug, linkage: ?Step.Compile.Linkage = null, max_rss: usize = 0, link_libc: ?bool = null, single_threaded: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + omit_frame_pointer: ?bool = null, + sanitize_thread: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -621,6 +620,11 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { .optimize = options.optimize, .link_libc = options.link_libc, .single_threaded = options.single_threaded, + .pic = options.pic, + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .omit_frame_pointer = options.omit_frame_pointer, + .sanitize_thread = options.sanitize_thread, }, .version = options.version, .kind = .exe, @@ -636,11 +640,18 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { pub const ObjectOptions = struct { name: []const u8, root_source_file: ?LazyPath = null, - target: CrossTarget, + /// To choose the same computer as the one building the package, pass the + /// `host` field of the package's `Build` instance. + target: ResolvedTarget, optimize: std.builtin.OptimizeMode, max_rss: usize = 0, link_libc: ?bool = null, single_threaded: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + omit_frame_pointer: ?bool = null, + sanitize_thread: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -655,6 +666,11 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { .optimize = options.optimize, .link_libc = options.link_libc, .single_threaded = options.single_threaded, + .pic = options.pic, + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .omit_frame_pointer = options.omit_frame_pointer, + .sanitize_thread = options.sanitize_thread, }, .kind = .obj, .max_rss = options.max_rss, @@ -666,13 +682,20 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { pub const SharedLibraryOptions = struct { name: []const u8, + /// To choose the same computer as the one building the package, pass the + /// `host` field of the package's `Build` instance. + target: ResolvedTarget, + optimize: std.builtin.OptimizeMode, root_source_file: ?LazyPath = null, version: ?std.SemanticVersion = null, - target: CrossTarget, - optimize: std.builtin.OptimizeMode, max_rss: usize = 0, link_libc: ?bool = null, single_threaded: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + omit_frame_pointer: ?bool = null, + sanitize_thread: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -693,6 +716,11 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile .root_source_file = options.root_source_file, .link_libc = options.link_libc, .single_threaded = options.single_threaded, + .pic = options.pic, + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .omit_frame_pointer = options.omit_frame_pointer, + .sanitize_thread = options.sanitize_thread, }, .kind = .lib, .linkage = .dynamic, @@ -708,12 +736,19 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile pub const StaticLibraryOptions = struct { name: []const u8, root_source_file: ?LazyPath = null, - target: CrossTarget, + /// To choose the same computer as the one building the package, pass the + /// `host` field of the package's `Build` instance. + target: ResolvedTarget, optimize: std.builtin.OptimizeMode, version: ?std.SemanticVersion = null, max_rss: usize = 0, link_libc: ?bool = null, single_threaded: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + omit_frame_pointer: ?bool = null, + sanitize_thread: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -728,6 +763,11 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile .root_source_file = options.root_source_file, .link_libc = options.link_libc, .single_threaded = options.single_threaded, + .pic = options.pic, + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .omit_frame_pointer = options.omit_frame_pointer, + .sanitize_thread = options.sanitize_thread, }, .kind = .lib, .linkage = .static, @@ -742,7 +782,7 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile pub const TestOptions = struct { name: []const u8 = "test", root_source_file: LazyPath, - target: CrossTarget = .{}, + target: ?ResolvedTarget = null, optimize: std.builtin.OptimizeMode = .Debug, version: ?std.SemanticVersion = null, max_rss: usize = 0, @@ -750,6 +790,11 @@ pub const TestOptions = struct { test_runner: ?[]const u8 = null, link_libc: ?bool = null, single_threaded: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + unwind_tables: ?bool = null, + omit_frame_pointer: ?bool = null, + sanitize_thread: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -761,10 +806,15 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { .kind = .@"test", .root_module = .{ .root_source_file = options.root_source_file, - .target = options.target, + .target = options.target orelse b.host, .optimize = options.optimize, .link_libc = options.link_libc, .single_threaded = options.single_threaded, + .pic = options.pic, + .strip = options.strip, + .unwind_tables = options.unwind_tables, + .omit_frame_pointer = options.omit_frame_pointer, + .sanitize_thread = options.sanitize_thread, }, .max_rss = options.max_rss, .filter = options.filter, @@ -778,7 +828,9 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { pub const AssemblyOptions = struct { name: []const u8, source_file: LazyPath, - target: CrossTarget, + /// To choose the same computer as the one building the package, pass the + /// `host` field of the package's `Build` instance. + target: ResolvedTarget, optimize: std.builtin.OptimizeMode, max_rss: usize = 0, zig_lib_dir: ?LazyPath = null, @@ -1061,7 +1113,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ return null; }, .scalar => |s| { - if (Step.Compile.BuildId.parse(s)) |build_id| { + if (std.zig.BuildId.parse(s)) |build_id| { return build_id; } else |err| { log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) }); @@ -1126,13 +1178,20 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio } pub const StandardTargetOptionsArgs = struct { - whitelist: ?[]const CrossTarget = null, + whitelist: ?[]const TargetQuery = null, - default_target: CrossTarget = CrossTarget{}, + default_target: TargetQuery = .{}, }; +/// Exposes standard `zig build` options for choosing a target and additionally +/// resolves the target query. +pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) ResolvedTarget { + const query = b.standardTargetOptionsQueryOnly(args); + return b.resolveTargetQuery(query); +} + /// Exposes standard `zig build` options for choosing a target. -pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) CrossTarget { +pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) TargetQuery { const maybe_triple = self.option( []const u8, "target", @@ -1146,8 +1205,8 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros const triple = maybe_triple orelse "native"; - var diags: CrossTarget.ParseOptions.Diagnostics = .{}; - const selected_target = CrossTarget.parse(.{ + var diags: TargetQuery.ParseOptions.Diagnostics = .{}; + const selected_target = TargetQuery.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, @@ -1203,7 +1262,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros // Make sure it's a match of one of the list. var mismatch_triple = true; var mismatch_cpu_features = true; - var whitelist_item = CrossTarget{}; + var whitelist_item: TargetQuery = .{}; for (list) |t| { mismatch_cpu_features = true; mismatch_triple = true; @@ -1340,7 +1399,7 @@ pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool { fn typeToEnum(comptime T: type) TypeId { return switch (T) { - Step.Compile.BuildId => .build_id, + std.zig.BuildId => .build_id, else => return switch (@typeInfo(T)) { .Int => .int, .Float => .float, @@ -1408,7 +1467,7 @@ pub fn installFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8 self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .prefix, dest_rel_path).step); } -pub fn installDirectory(self: *Build, options: InstallDirectoryOptions) void { +pub fn installDirectory(self: *Build, options: Step.InstallDir.Options) void { self.getInstallStep().dependOn(&self.addInstallDirectory(options).step); } @@ -1454,7 +1513,7 @@ pub fn addInstallFileWithDir( return Step.InstallFile.create(self, source.dupe(self), install_dir, dest_rel_path); } -pub fn addInstallDirectory(self: *Build, options: InstallDirectoryOptions) *Step.InstallDir { +pub fn addInstallDirectory(self: *Build, options: Step.InstallDir.Options) *Step.InstallDir { return Step.InstallDir.create(self, options); } @@ -1511,7 +1570,7 @@ pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 { pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { // TODO report error for ambiguous situations - const exe_extension = @as(CrossTarget, .{}).exeFileExt(); + const exe_extension = @as(TargetQuery, .{}).exeFileExt(); for (self.search_prefixes.items) |search_prefix| { for (names) |name| { if (fs.path.isAbsolute(name)) { @@ -1957,22 +2016,6 @@ pub fn dumpBadGetPathHelp( tty_config.setColor(w, .reset) catch {}; } -/// Allocates a new string for assigning a value to a named macro. -/// If the value is omitted, it is set to 1. -/// `name` and `value` need not live longer than the function call. -pub fn constructCMacro(allocator: Allocator, name: []const u8, value: ?[]const u8) []const u8 { - var macro = allocator.alloc( - u8, - name.len + if (value) |value_slice| value_slice.len + 1 else 0, - ) catch |err| if (err == error.OutOfMemory) @panic("Out of memory") else unreachable; - @memcpy(macro[0..name.len], name); - if (value) |value_slice| { - macro[name.len] = '='; - @memcpy(macro[name.len + 1 ..][0..value_slice.len], value_slice); - } - return macro; -} - pub const InstallDir = union(enum) { prefix: void, lib: void, @@ -2062,6 +2105,44 @@ pub fn hex64(x: u64) [16]u8 { return result; } +/// A pair of target query and fully resolved target. +/// This type is generally required by build system API that need to be given a +/// target. The query is kept because the Zig toolchain needs to know which parts +/// of the target are "native". This can apply to the CPU, the OS, or even the ABI. +pub const ResolvedTarget = struct { + query: TargetQuery, + target: std.Target, + dynamic_linker: std.Target.DynamicLinker, + + pub fn toNativeTargetInfo(self: ResolvedTarget) std.zig.system.NativeTargetInfo { + return .{ + .target = self.target, + .dynamic_linker = self.dynamic_linker, + }; + } +}; + +/// Converts a target query into a fully resolved target that can be passed to +/// various parts of the API. +pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget { + // This context will likely be required in the future when the target is + // resolved via a WASI API or via the build protocol. + _ = b; + + const result = std.zig.system.NativeTargetInfo.detect(query) catch + @panic("unable to resolve target query"); + + return .{ + .query = query, + .target = result.target, + .dynamic_linker = result.dynamic_linker, + }; +} + +pub fn wantSharedLibSymLinks(target: std.Target) bool { + return target.os.tag != .windows; +} + test { _ = Cache; _ = Step; diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index 283a3d1f5f72..b7865e730b5e 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -270,7 +270,7 @@ pub const HashHelper = struct { .none => {}, } }, - std.Build.Step.Compile.BuildId => switch (x) { + std.zig.BuildId => switch (x) { .none, .fast, .uuid, .sha1, .md5 => hh.add(std.meta.activeTag(x)), .hexstring => |hex_string| hh.addBytes(hex_string.toSlice()), }, diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 31db0ad6894b..c672ae6c2e7c 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -3,27 +3,24 @@ owner: *std.Build, /// Tracks the set of steps that depend on this `Module`. This ensures that /// when making this `Module` depend on other `Module` objects and `Step` /// objects, respective `Step` dependencies can be added. -depending_steps: std.AutoArrayHashMapUnmanaged(*std.Build.Step.Compile, void), -/// This could either be a generated file, in which case the module -/// contains exactly one file, or it could be a path to the root source -/// file of directory of files which constitute the module. -/// If `null`, it means this module is made up of only `link_objects`. +depending_steps: std.AutoArrayHashMapUnmanaged(*Step.Compile, void), root_source_file: ?LazyPath, /// The modules that are mapped into this module's import table. -import_table: std.StringArrayHashMap(*Module), +/// Use `addImport` rather than modifying this field directly in order to +/// maintain step dependency edges. +import_table: std.StringArrayHashMapUnmanaged(*Module), -target: std.zig.CrossTarget, -target_info: NativeTargetInfo, -optimize: std.builtin.OptimizeMode, +target: ?std.Build.ResolvedTarget = null, +optimize: ?std.builtin.OptimizeMode = null, dwarf_format: ?std.dwarf.Format, -c_macros: std.ArrayList([]const u8), -include_dirs: std.ArrayList(IncludeDir), -lib_paths: std.ArrayList(LazyPath), -rpaths: std.ArrayList(LazyPath), -frameworks: std.StringArrayHashMapUnmanaged(FrameworkLinkInfo), +c_macros: std.ArrayListUnmanaged([]const u8), +include_dirs: std.ArrayListUnmanaged(IncludeDir), +lib_paths: std.ArrayListUnmanaged(LazyPath), +rpaths: std.ArrayListUnmanaged(RPath), +frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions), c_std: std.Build.CStd, -link_objects: std.ArrayList(LinkObject), +link_objects: std.ArrayListUnmanaged(LinkObject), strip: ?bool, unwind_tables: ?bool, @@ -53,9 +50,14 @@ link_libcpp: ?bool, /// Symbols to be exported when compiling to WebAssembly. export_symbol_names: []const []const u8 = &.{}, +pub const RPath = union(enum) { + lazy_path: LazyPath, + special: []const u8, +}; + pub const LinkObject = union(enum) { static_path: LazyPath, - other_step: *std.Build.Step.Compile, + other_step: *Step.Compile, system_lib: SystemLib, assembly_file: LazyPath, c_source_file: *CSourceFile, @@ -133,21 +135,32 @@ pub const IncludeDir = union(enum) { path_after: LazyPath, framework_path: LazyPath, framework_path_system: LazyPath, - other_step: *std.Build.Step.Compile, - config_header_step: *std.Build.Step.ConfigHeader, + other_step: *Step.Compile, + config_header_step: *Step.ConfigHeader, }; -pub const FrameworkLinkInfo = struct { +pub const LinkFrameworkOptions = struct { needed: bool = false, weak: bool = false, }; +/// Unspecified options here will be inherited from parent `Module` when +/// inserted into an import table. pub const CreateOptions = struct { - target: std.zig.CrossTarget, - target_info: ?NativeTargetInfo = null, - optimize: std.builtin.OptimizeMode, + /// This could either be a generated file, in which case the module + /// contains exactly one file, or it could be a path to the root source + /// file of directory of files which constitute the module. + /// If `null`, it means this module is made up of only `link_objects`. root_source_file: ?LazyPath = null, - import_table: []const Import = &.{}, + + /// The table of other modules that this module can access via `@import`. + /// Imports are allowed to be cyclical, so this table can be added to after + /// the `Module` is created via `addImport`. + imports: []const Import = &.{}, + + target: ?std.Build.ResolvedTarget = null, + optimize: ?std.builtin.OptimizeMode = null, + link_libc: ?bool = null, link_libcpp: ?bool = null, single_threaded: ?bool = null, @@ -173,26 +186,26 @@ pub const Import = struct { module: *Module, }; -pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step.Compile) Module { - var m: Module = .{ +pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*Step.Compile) void { + const allocator = owner.allocator; + + m.* = .{ .owner = owner, .depending_steps = .{}, .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, - .import_table = std.StringArrayHashMap(*Module).init(owner.allocator), + .import_table = .{}, .target = options.target, - .target_info = options.target_info orelse - NativeTargetInfo.detect(options.target) catch @panic("unhandled error"), .optimize = options.optimize, .link_libc = options.link_libc, .link_libcpp = options.link_libcpp, .dwarf_format = options.dwarf_format, - .c_macros = std.ArrayList([]const u8).init(owner.allocator), - .include_dirs = std.ArrayList(IncludeDir).init(owner.allocator), - .lib_paths = std.ArrayList(LazyPath).init(owner.allocator), - .rpaths = std.ArrayList(LazyPath).init(owner.allocator), + .c_macros = .{}, + .include_dirs = .{}, + .lib_paths = .{}, + .rpaths = .{}, .frameworks = .{}, .c_std = options.c_std, - .link_objects = std.ArrayList(LinkObject).init(owner.allocator), + .link_objects = .{}, .strip = options.strip, .unwind_tables = options.unwind_tables, .single_threaded = options.single_threaded, @@ -208,31 +221,30 @@ pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step .export_symbol_names = &.{}, }; - if (compile) |c| { - m.depending_steps.put(owner.allocator, c, {}) catch @panic("OOM"); + m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM"); + for (options.imports) |dep| { + m.import_table.putAssumeCapacity(dep.name, dep.module); } - m.import_table.ensureUnusedCapacity(options.import_table.len) catch @panic("OOM"); - for (options.import_table) |dep| { - m.import_table.putAssumeCapacity(dep.name, dep.module); + if (compile) |c| { + m.depending_steps.put(allocator, c, {}) catch @panic("OOM"); } + // This logic accesses `depending_steps` which was just modified above. var it = m.iterateDependencies(null); - while (it.next()) |item| addShallowDependencies(&m, item.module); - - return m; + while (it.next()) |item| addShallowDependencies(m, item.module); } pub fn create(owner: *std.Build, options: CreateOptions) *Module { const m = owner.allocator.create(Module) catch @panic("OOM"); - m.* = init(owner, options, null); + m.init(owner, options, null); return m; } /// Adds an existing module to be used with `@import`. pub fn addImport(m: *Module, name: []const u8, module: *Module) void { const b = m.owner; - m.import_table.put(b.dupe(name), module) catch @panic("OOM"); + m.import_table.put(b.allocator, b.dupe(name), module) catch @panic("OOM"); var it = module.iterateDependencies(null); while (it.next()) |item| addShallowDependencies(m, item.module); @@ -244,7 +256,10 @@ pub fn addImport(m: *Module, name: []const u8, module: *Module) void { fn addShallowDependencies(m: *Module, dependee: *Module) void { if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path); for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path); - for (dependee.rpaths.items) |rpath| addLazyPathDependencies(m, dependee, rpath); + for (dependee.rpaths.items) |rpath| switch (rpath) { + .lazy_path => |lp| addLazyPathDependencies(m, dependee, lp), + .special => {}, + }; for (dependee.link_objects.items) |link_object| switch (link_object) { .other_step => |compile| addStepDependencies(m, dependee, &compile.step), @@ -277,7 +292,7 @@ fn addLazyPathDependenciesOnly(m: *Module, lazy_path: LazyPath) void { } } -fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) void { +fn addStepDependencies(m: *Module, module: *Module, dependee: *Step) void { addStepDependenciesOnly(m, dependee); if (m != module) { for (m.depending_steps.keys()) |compile| { @@ -286,20 +301,19 @@ fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) v } } -fn addStepDependenciesOnly(m: *Module, dependee: *std.Build.Step) void { +fn addStepDependenciesOnly(m: *Module, dependee: *Step) void { for (m.depending_steps.keys()) |compile| { compile.step.dependOn(dependee); } } /// Creates a new module and adds it to be used with `@import`. -pub fn addAnonymousImport(m: *Module, name: []const u8, options: std.Build.CreateModuleOptions) void { - const b = m.step.owner; - const module = b.createModule(options); +pub fn addAnonymousImport(m: *Module, name: []const u8, options: CreateOptions) void { + const module = create(m.owner, options); return addImport(m, name, module); } -pub fn addOptions(m: *Module, module_name: []const u8, options: *std.Build.Step.Options) void { +pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) void { addImport(m, module_name, options.createModule()); } @@ -311,14 +325,14 @@ pub const DependencyIterator = struct { pub const Key = struct { /// The compilation that contains the `Module`. Note that a `Module` might be /// used by more than one compilation. - compile: ?*std.Build.Step.Compile, + compile: ?*Step.Compile, module: *Module, }; pub const Item = struct { /// The compilation that contains the `Module`. Note that a `Module` might be /// used by more than one compilation. - compile: ?*std.Build.Step.Compile, + compile: ?*Step.Compile, module: *Module, name: []const u8, }; @@ -368,7 +382,7 @@ pub const DependencyIterator = struct { pub fn iterateDependencies( m: *Module, - chase_steps: ?*std.Build.Step.Compile, + chase_steps: ?*Step.Compile, ) DependencyIterator { var it: DependencyIterator = .{ .allocator = m.owner.allocator, @@ -397,16 +411,18 @@ pub fn linkSystemLibrary( options: LinkSystemLibraryOptions, ) void { const b = m.owner; - if (m.target_info.target.is_libc_lib_name(name)) { + + const target = m.requireKnownTarget(); + if (target.is_libc_lib_name(name)) { m.link_libc = true; return; } - if (m.target_info.target.is_libcpp_lib_name(name)) { + if (target.is_libcpp_lib_name(name)) { m.link_libcpp = true; return; } - m.link_objects.append(.{ + m.link_objects.append(b.allocator, .{ .system_lib = .{ .name = b.dupe(name), .needed = options.needed, @@ -418,6 +434,11 @@ pub fn linkSystemLibrary( }) catch @panic("OOM"); } +pub fn linkFramework(m: *Module, name: []const u8, options: LinkFrameworkOptions) void { + const b = m.owner; + m.frameworks.put(b.allocator, b.dupe(name), options) catch @panic("OOM"); +} + pub const AddCSourceFilesOptions = struct { /// When provided, `files` are relative to `dependency` rather than the /// package that owns the `Compile` step. @@ -428,19 +449,23 @@ pub const AddCSourceFilesOptions = struct { /// Handy when you have many C/C++ source files and want them all to have the same flags. pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void { - const c_source_files = m.owner.allocator.create(CSourceFiles) catch @panic("OOM"); + const b = m.owner; + const allocator = b.allocator; + const c_source_files = allocator.create(CSourceFiles) catch @panic("OOM"); c_source_files.* = .{ .dependency = options.dependency, - .files = m.owner.dupeStrings(options.files), - .flags = m.owner.dupeStrings(options.flags), + .files = b.dupeStrings(options.files), + .flags = b.dupeStrings(options.flags), }; - m.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM"); + m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM"); } pub fn addCSourceFile(m: *Module, source: CSourceFile) void { - const c_source_file = m.owner.allocator.create(CSourceFile) catch @panic("OOM"); - c_source_file.* = source.dupe(m.owner); - m.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM"); + const b = m.owner; + const allocator = b.allocator; + const c_source_file = allocator.create(CSourceFile) catch @panic("OOM"); + c_source_file.* = source.dupe(b); + m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source.file); } @@ -448,30 +473,122 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void { /// Can be called regardless of target. The .rc file will be ignored /// if the target object format does not support embedded resources. pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void { + const b = m.owner; + const allocator = b.allocator; + const target = m.requireKnownTarget(); // Only the PE/COFF format has a Resource Table, so for any other target // the resource file is ignored. - if (m.target_info.target.ofmt != .coff) return; + if (target.ofmt != .coff) return; - const rc_source_file = m.owner.allocator.create(RcSourceFile) catch @panic("OOM"); - rc_source_file.* = source.dupe(m.owner); - m.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); + const rc_source_file = allocator.create(RcSourceFile) catch @panic("OOM"); + rc_source_file.* = source.dupe(b); + m.link_objects.append(allocator, .{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source.file); } pub fn addAssemblyFile(m: *Module, source: LazyPath) void { - m.link_objects.append(.{ .assembly_file = source.dupe(m.owner) }) catch @panic("OOM"); + const b = m.owner; + m.link_objects.append(b.allocator, .{ .assembly_file = source.dupe(b) }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source); } -pub fn addObjectFile(m: *Module, source: LazyPath) void { - m.link_objects.append(.{ .static_path = source.dupe(m.owner) }) catch @panic("OOM"); - addLazyPathDependencies(m, source); +pub fn addObjectFile(m: *Module, object: LazyPath) void { + const b = m.owner; + m.link_objects.append(b.allocator, .{ .static_path = object.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, object); +} + +pub fn addObject(m: *Module, object: *Step.Compile) void { + assert(object.kind == .obj); + m.linkLibraryOrObject(object); +} + +pub fn linkLibrary(m: *Module, library: *Step.Compile) void { + assert(library.kind == .lib); + m.linkLibraryOrObject(library); +} + +pub fn addAfterIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path_after = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addSystemIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path_system = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addConfigHeader(m: *Module, config_header: *Step.ConfigHeader) void { + const allocator = m.owner.allocator; + m.include_dirs.append(allocator, .{ .config_header_step = config_header }) catch @panic("OOM"); + addStepDependenciesOnly(m, &config_header.step); +} + +pub fn addSystemFrameworkPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .framework_path_system = directory_path.dupe(b) }) catch + @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addFrameworkPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .framework_path = directory_path.dupe(b) }) catch + @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.lib_paths.append(b.allocator, directory_path.dupe(b)) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addRPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + switch (directory_path) { + .path, .cwd_relative => |path| { + // TODO: remove this check after people upgrade and stop expecting it to work + if (std.mem.startsWith(u8, path, "@executable_path") or + std.mem.startsWith(u8, path, "@loader_path")) + { + @panic("this function is for adding directory paths. It does not support special rpaths. use addRPathSpecial for that."); + } + }, + else => {}, + } + m.rpaths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addRPathSpecial(m: *Module, bytes: []const u8) void { + const b = m.owner; + m.rpaths.append(b.allocator, .{ .special = b.dupe(bytes) }) catch @panic("OOM"); +} + +/// Equvialent to the following C code, applied to all C source files owned by +/// this `Module`: +/// ```c +/// #define name value +/// ``` +/// `name` and `value` need not live longer than the function call. +pub fn addCMacro(m: *Module, name: []const u8, value: []const u8) void { + const b = m.owner; + m.c_macros.append(b.allocator, b.fmt("-D{s}={s}", .{ name, value })) catch @panic("OOM"); } pub fn appendZigProcessFlags( m: *Module, zig_args: *std.ArrayList([]const u8), - asking_step: ?*std.Build.Step, + asking_step: ?*Step, ) !void { const b = m.owner; @@ -495,27 +612,30 @@ pub fn appendZigProcessFlags( } try zig_args.ensureUnusedCapacity(1); - switch (m.optimize) { - .Debug => {}, // Skip since it's the default. + if (m.optimize) |optimize| switch (optimize) { + .Debug => zig_args.appendAssumeCapacity("-ODebug"), .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"), .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"), .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"), - } + }; if (m.code_model != .default) { try zig_args.append("-mcmodel"); try zig_args.append(@tagName(m.code_model)); } - if (!m.target.isNative()) { - try zig_args.appendSlice(&.{ - "-target", try m.target.zigTriple(b.allocator), - "-mcpu", try std.Build.serializeCpu(b.allocator, m.target.getCpu()), - }); - - if (m.target.dynamic_linker.get()) |dynamic_linker| { - try zig_args.append("--dynamic-linker"); - try zig_args.append(dynamic_linker); + if (m.target) |target| { + // Communicate the query via CLI since it's more compact. + if (!target.query.isNative()) { + try zig_args.appendSlice(&.{ + "-target", try target.query.zigTriple(b.allocator), + "-mcpu", try std.Build.serializeCpu(b.allocator, target.query.getCpu()), + }); + + if (target.query.dynamic_linker.get()) |dynamic_linker| { + try zig_args.append("--dynamic-linker"); + try zig_args.append(dynamic_linker); + } } } @@ -565,10 +685,7 @@ pub fn appendZigProcessFlags( } } - for (m.c_macros.items) |c_macro| { - try zig_args.append("-D"); - try zig_args.append(c_macro); - } + try zig_args.appendSlice(m.c_macros.items); try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len); for (m.lib_paths.items) |lib_path| { @@ -577,26 +694,16 @@ pub fn appendZigProcessFlags( } try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len); - for (m.rpaths.items) |rpath| { - zig_args.appendAssumeCapacity("-rpath"); - - if (m.target_info.target.isDarwin()) switch (rpath) { - .path, .cwd_relative => |path| { - // On Darwin, we should not try to expand special runtime paths such as - // * @executable_path - // * @loader_path - if (std.mem.startsWith(u8, path, "@executable_path") or - std.mem.startsWith(u8, path, "@loader_path")) - { - zig_args.appendAssumeCapacity(path); - continue; - } - }, - .generated, .dependency => {}, - }; - - zig_args.appendAssumeCapacity(rpath.getPath2(b, asking_step)); - } + for (m.rpaths.items) |rpath| switch (rpath) { + .lazy_path => |lp| { + zig_args.appendAssumeCapacity("-rpath"); + zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step)); + }, + .special => |bytes| { + zig_args.appendAssumeCapacity("-rpath"); + zig_args.appendAssumeCapacity(bytes); + }, + }; } fn addFlag( @@ -609,8 +716,32 @@ fn addFlag( return args.append(if (cond) then_name else else_name); } +fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void { + const allocator = m.owner.allocator; + _ = other.getEmittedBin(); // Indicate there is a dependency on the outputted binary. + addStepDependenciesOnly(m, &other.step); + + if (other.rootModuleTarget().os.tag == .windows and other.isDynamicLibrary()) { + _ = other.getEmittedImplib(); // Indicate dependency on the outputted implib. + } + + m.link_objects.append(allocator, .{ .other_step = other }) catch @panic("OOM"); + m.include_dirs.append(allocator, .{ .other_step = other }) catch @panic("OOM"); + + for (other.installed_headers.items) |install_step| { + addStepDependenciesOnly(m, install_step); + } +} + +fn requireKnownTarget(m: *Module) std.Target { + const resolved_target = m.target orelse + @panic("this API requires the Module to be created with a known 'target' field"); + return resolved_target.target; +} + const Module = @This(); const std = @import("std"); const assert = std.debug.assert; const LazyPath = std.Build.LazyPath; const NativeTargetInfo = std.zig.system.NativeTargetInfo; +const Step = std.Build.Step; diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index 3be9cdc83cdb..c5eb1f776bbd 100644 --- a/lib/std/Build/Step/CheckObject.zig +++ b/lib/std/Build/Step/CheckObject.zig @@ -44,11 +44,11 @@ pub fn create( const SearchPhrase = struct { string: []const u8, - file_source: ?std.Build.LazyPath = null, + lazy_path: ?std.Build.LazyPath = null, fn resolve(phrase: SearchPhrase, b: *std.Build, step: *Step) []const u8 { - const file_source = phrase.file_source orelse return phrase.string; - return b.fmt("{s} {s}", .{ phrase.string, file_source.getPath2(b, step) }); + const lazy_path = phrase.lazy_path orelse return phrase.string; + return b.fmt("{s} {s}", .{ phrase.string, lazy_path.getPath2(b, step) }); } }; @@ -321,14 +321,14 @@ pub fn checkExact(self: *CheckObject, phrase: []const u8) void { /// Like `checkExact()` but takes an additional argument `LazyPath` which will be /// resolved to a full search query in `make()`. -pub fn checkExactPath(self: *CheckObject, phrase: []const u8, file_source: std.Build.LazyPath) void { - self.checkExactInner(phrase, file_source); +pub fn checkExactPath(self: *CheckObject, phrase: []const u8, lazy_path: std.Build.LazyPath) void { + self.checkExactInner(phrase, lazy_path); } -fn checkExactInner(self: *CheckObject, phrase: []const u8, file_source: ?std.Build.LazyPath) void { +fn checkExactInner(self: *CheckObject, phrase: []const u8, lazy_path: ?std.Build.LazyPath) void { assert(self.checks.items.len > 0); const last = &self.checks.items[self.checks.items.len - 1]; - last.exact(.{ .string = self.step.owner.dupe(phrase), .file_source = file_source }); + last.exact(.{ .string = self.step.owner.dupe(phrase), .lazy_path = lazy_path }); } /// Adds a fuzzy match phrase to the latest created Check. @@ -336,16 +336,20 @@ pub fn checkContains(self: *CheckObject, phrase: []const u8) void { self.checkContainsInner(phrase, null); } -/// Like `checkContains()` but takes an additional argument `FileSource` which will be +/// Like `checkContains()` but takes an additional argument `lazy_path` which will be /// resolved to a full search query in `make()`. -pub fn checkContainsPath(self: *CheckObject, phrase: []const u8, file_source: std.Build.LazyPath) void { - self.checkContainsInner(phrase, file_source); +pub fn checkContainsPath( + self: *CheckObject, + phrase: []const u8, + lazy_path: std.Build.LazyPath, +) void { + self.checkContainsInner(phrase, lazy_path); } -fn checkContainsInner(self: *CheckObject, phrase: []const u8, file_source: ?std.Build.FileSource) void { +fn checkContainsInner(self: *CheckObject, phrase: []const u8, lazy_path: ?std.Build.LazyPath) void { assert(self.checks.items.len > 0); const last = &self.checks.items[self.checks.items.len - 1]; - last.contains(.{ .string = self.step.owner.dupe(phrase), .file_source = file_source }); + last.contains(.{ .string = self.step.owner.dupe(phrase), .lazy_path = lazy_path }); } /// Adds an exact match phrase with variable extractor to the latest created Check. @@ -353,16 +357,16 @@ pub fn checkExtract(self: *CheckObject, phrase: []const u8) void { self.checkExtractInner(phrase, null); } -/// Like `checkExtract()` but takes an additional argument `FileSource` which will be +/// Like `checkExtract()` but takes an additional argument `LazyPath` which will be /// resolved to a full search query in `make()`. -pub fn checkExtractFileSource(self: *CheckObject, phrase: []const u8, file_source: std.Build.FileSource) void { - self.checkExtractInner(phrase, file_source); +pub fn checkExtractLazyPath(self: *CheckObject, phrase: []const u8, lazy_path: std.Build.LazyPath) void { + self.checkExtractInner(phrase, lazy_path); } -fn checkExtractInner(self: *CheckObject, phrase: []const u8, file_source: ?std.Build.FileSource) void { +fn checkExtractInner(self: *CheckObject, phrase: []const u8, lazy_path: ?std.Build.LazyPath) void { assert(self.checks.items.len > 0); const last = &self.checks.items[self.checks.items.len - 1]; - last.extract(.{ .string = self.step.owner.dupe(phrase), .file_source = file_source }); + last.extract(.{ .string = self.step.owner.dupe(phrase), .lazy_path = lazy_path }); } /// Adds another searched phrase to the latest created Check @@ -371,16 +375,16 @@ pub fn checkNotPresent(self: *CheckObject, phrase: []const u8) void { self.checkNotPresentInner(phrase, null); } -/// Like `checkExtract()` but takes an additional argument `FileSource` which will be +/// Like `checkExtract()` but takes an additional argument `LazyPath` which will be /// resolved to a full search query in `make()`. -pub fn checkNotPresentFileSource(self: *CheckObject, phrase: []const u8, file_source: std.Build.FileSource) void { - self.checkNotPresentInner(phrase, file_source); +pub fn checkNotPresentLazyPath(self: *CheckObject, phrase: []const u8, lazy_path: std.Build.LazyPath) void { + self.checkNotPresentInner(phrase, lazy_path); } -fn checkNotPresentInner(self: *CheckObject, phrase: []const u8, file_source: ?std.Build.FileSource) void { +fn checkNotPresentInner(self: *CheckObject, phrase: []const u8, lazy_path: ?std.Build.LazyPath) void { assert(self.checks.items.len > 0); const last = &self.checks.items[self.checks.items.len - 1]; - last.notPresent(.{ .string = self.step.owner.dupe(phrase), .file_source = file_source }); + last.notPresent(.{ .string = self.step.owner.dupe(phrase), .lazy_path = lazy_path }); } /// Creates a new check checking in the file headers (section, program headers, etc.). diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 4cd8868752c8..52c9703db0bc 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -88,7 +88,7 @@ each_lib_rpath: ?bool = null, /// As an example, the bloaty project refuses to work unless its inputs have /// build ids, in order to prevent accidental mismatches. /// The default is to not include this section because it slows down linking. -build_id: ?BuildId = null, +build_id: ?std.zig.BuildId = null, /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF /// file. @@ -200,7 +200,7 @@ pub const ExpectedCompileErrors = union(enum) { exact: []const []const u8, }; -const Entry = union(enum) { +pub const Entry = union(enum) { /// Let the compiler decide whether to make an entry point and what to name /// it. default, @@ -232,82 +232,6 @@ pub const Options = struct { win32_manifest: ?LazyPath = null, }; -pub const BuildId = union(enum) { - none, - fast, - uuid, - sha1, - md5, - hexstring: HexString, - - pub fn eql(a: BuildId, b: BuildId) bool { - const a_tag = std.meta.activeTag(a); - const b_tag = std.meta.activeTag(b); - if (a_tag != b_tag) return false; - return switch (a) { - .none, .fast, .uuid, .sha1, .md5 => true, - .hexstring => |a_hexstring| mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()), - }; - } - - pub const HexString = struct { - bytes: [32]u8, - len: u8, - - /// Result is byte values, *not* hex-encoded. - pub fn toSlice(hs: *const HexString) []const u8 { - return hs.bytes[0..hs.len]; - } - }; - - /// Input is byte values, *not* hex-encoded. - /// Asserts `bytes` fits inside `HexString` - pub fn initHexString(bytes: []const u8) BuildId { - var result: BuildId = .{ .hexstring = .{ - .bytes = undefined, - .len = @as(u8, @intCast(bytes.len)), - } }; - @memcpy(result.hexstring.bytes[0..bytes.len], bytes); - return result; - } - - /// Converts UTF-8 text to a `BuildId`. - pub fn parse(text: []const u8) !BuildId { - if (mem.eql(u8, text, "none")) { - return .none; - } else if (mem.eql(u8, text, "fast")) { - return .fast; - } else if (mem.eql(u8, text, "uuid")) { - return .uuid; - } else if (mem.eql(u8, text, "sha1") or mem.eql(u8, text, "tree")) { - return .sha1; - } else if (mem.eql(u8, text, "md5")) { - return .md5; - } else if (mem.startsWith(u8, text, "0x")) { - var result: BuildId = .{ .hexstring = undefined }; - const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]); - result.hexstring.len = @as(u8, @intCast(slice.len)); - return result; - } - return error.InvalidBuildIdStyle; - } - - test parse { - try std.testing.expectEqual(BuildId.md5, try parse("md5")); - try std.testing.expectEqual(BuildId.none, try parse("none")); - try std.testing.expectEqual(BuildId.fast, try parse("fast")); - try std.testing.expectEqual(BuildId.uuid, try parse("uuid")); - try std.testing.expectEqual(BuildId.sha1, try parse("sha1")); - try std.testing.expectEqual(BuildId.sha1, try parse("tree")); - - try std.testing.expect(BuildId.initHexString("").eql(try parse("0x"))); - try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456"))); - try std.testing.expectError(error.InvalidLength, parse("0x12-34")); - try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); - try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); - } -}; - pub const Kind = enum { exe, lib, @@ -329,6 +253,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile { else owner.fmt("{s} ", .{name}); + const target = options.root_module.target.?.target; + const step_name = owner.fmt("{s} {s}{s} {s}", .{ switch (options.kind) { .exe => "zig build-exe", @@ -337,16 +263,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .@"test" => "zig test", }, name_adjusted, - @tagName(options.root_module.optimize), - options.root_module.target.zigTriple(owner.allocator) catch @panic("OOM"), + @tagName(options.root_module.optimize orelse .Debug), + target.zigTriple(owner.allocator) catch @panic("OOM"), }); - const target_info = NativeTargetInfo.detect(options.root_module.target) catch - @panic("unhandled error"); - const out_filename = std.zig.binNameAlloc(owner.allocator, .{ .root_name = name, - .target = target_info.target, + .target = target, .output_mode = switch (options.kind) { .lib => .Lib, .obj => .Obj, @@ -361,7 +284,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { const self = owner.allocator.create(Compile) catch @panic("OOM"); self.* = .{ - .root_module = Module.init(owner, options.root_module, self), + .root_module = undefined, .verbose_link = false, .verbose_cc = false, .linkage = options.linkage, @@ -403,6 +326,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .use_lld = options.use_lld, }; + self.root_module.init(owner, options.root_module, self); + if (options.zig_lib_dir) |lp| { self.zig_lib_dir = lp.dupe(self.step.owner); lp.addStepDependencies(&self.step); @@ -410,7 +335,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { // Only the PE/COFF format has a Resource Table which is where the manifest // gets embedded, so for any other target the manifest file is just ignored. - if (target_info.target.ofmt == .coff) { + if (target.ofmt == .coff) { if (options.win32_manifest) |lp| { self.win32_manifest = lp.dupe(self.step.owner); lp.addStepDependencies(&self.step); @@ -421,14 +346,14 @@ pub fn create(owner: *std.Build, options: Options) *Compile { if (self.linkage != null and self.linkage.? == .static) { self.out_lib_filename = self.out_filename; } else if (self.version) |version| { - if (target_info.target.isDarwin()) { + if (target.isDarwin()) { self.major_only_filename = owner.fmt("lib{s}.{d}.dylib", .{ self.name, version.major, }); self.name_only_filename = owner.fmt("lib{s}.dylib", .{self.name}); self.out_lib_filename = self.out_filename; - } else if (target_info.target.os.tag == .windows) { + } else if (target.os.tag == .windows) { self.out_lib_filename = owner.fmt("{s}.lib", .{self.name}); } else { self.major_only_filename = owner.fmt("lib{s}.so.{d}", .{ self.name, version.major }); @@ -436,9 +361,9 @@ pub fn create(owner: *std.Build, options: Options) *Compile { self.out_lib_filename = self.out_filename; } } else { - if (target_info.target.isDarwin()) { + if (target.isDarwin()) { self.out_lib_filename = self.out_filename; - } else if (target_info.target.os.tag == .windows) { + } else if (target.os.tag == .windows) { self.out_lib_filename = owner.fmt("{s}.lib", .{self.name}); } else { self.out_lib_filename = self.out_filename; @@ -545,7 +470,7 @@ pub const run = @compileError("deprecated; use std.Build.addRunArtifact"); pub const install = @compileError("deprecated; use std.Build.installArtifact"); pub fn checkObject(self: *Compile) *Step.CheckObject { - return Step.CheckObject.create(self.step.owner, self.getEmittedBin(), self.target_info.target.ofmt); + return Step.CheckObject.create(self.step.owner, self.getEmittedBin(), self.rootModuleTarget().ofmt); } /// deprecated: use `setLinkerScript` @@ -562,25 +487,6 @@ pub fn forceUndefinedSymbol(self: *Compile, symbol_name: []const u8) void { self.force_undefined_symbols.put(b.dupe(symbol_name), {}) catch @panic("OOM"); } -pub fn linkFramework(self: *Compile, framework_name: []const u8) void { - const b = self.step.owner; - self.frameworks.put(b.dupe(framework_name), .{}) catch @panic("OOM"); -} - -pub fn linkFrameworkNeeded(self: *Compile, framework_name: []const u8) void { - const b = self.step.owner; - self.frameworks.put(b.dupe(framework_name), .{ - .needed = true, - }) catch @panic("OOM"); -} - -pub fn linkFrameworkWeak(self: *Compile, framework_name: []const u8) void { - const b = self.step.owner; - self.frameworks.put(b.dupe(framework_name), .{ - .weak = true, - }) catch @panic("OOM"); -} - /// Returns whether the library, executable, or object depends on a particular system library. pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { var is_linking_libc = false; @@ -598,22 +504,17 @@ pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { is_linking_libcpp = is_linking_libcpp or module.link_libcpp == true; } - if (self.root_module.target_info.target.is_libc_lib_name(name)) { + if (self.rootModuleTarget().is_libc_lib_name(name)) { return is_linking_libc; } - if (self.root_module.target_info.target.is_libcpp_lib_name(name)) { + if (self.rootModuleTarget().is_libcpp_lib_name(name)) { return is_linking_libcpp; } return false; } -pub fn linkLibrary(self: *Compile, lib: *Compile) void { - assert(lib.kind == .lib); - self.linkLibraryOrObject(lib); -} - pub fn isDynamicLibrary(self: *const Compile) bool { return self.kind == .lib and self.linkage == Linkage.dynamic; } @@ -623,16 +524,24 @@ pub fn isStaticLibrary(self: *const Compile) bool { } pub fn producesPdbFile(self: *Compile) bool { + const target = self.rootModuleTarget(); // TODO: Is this right? Isn't PDB for *any* PE/COFF file? // TODO: just share this logic with the compiler, silly! - if (!self.target.isWindows() and !self.target.isUefi()) return false; - if (self.target.getObjectFormat() == .c) return false; - if (self.strip == true or (self.strip == null and self.optimize == .ReleaseSmall)) return false; + switch (target.os.tag) { + .windows, .uefi => {}, + else => return false, + } + if (target.ofmt == .c) return false; + if (self.root_module.strip == true or + (self.root_module.strip == null and self.root_module.optimize == .ReleaseSmall)) + { + return false; + } return self.isDynamicLibrary() or self.kind == .exe or self.kind == .@"test"; } pub fn producesImplib(self: *Compile) bool { - return self.isDynamicLibrary() and self.root_module.target_info.target.os.tag == .windows; + return self.isDynamicLibrary() and self.rootModuleTarget().os.tag == .windows; } pub fn linkLibC(self: *Compile) void { @@ -643,18 +552,9 @@ pub fn linkLibCpp(self: *Compile) void { self.root_module.link_libcpp = true; } -/// If the value is omitted, it is set to 1. -/// `name` and `value` need not live longer than the function call. -pub fn defineCMacro(self: *Compile, name: []const u8, value: ?[]const u8) void { - const b = self.step.owner; - const macro = std.Build.constructCMacro(b.allocator, name, value); - self.c_macros.append(macro) catch @panic("OOM"); -} - -/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1. -pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void { - const b = self.step.owner; - self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM"); +/// Deprecated. Use `c.root_module.addCMacro`. +pub fn defineCMacro(c: *Compile, name: []const u8, value: ?[]const u8) void { + c.root_module.addCMacro(name, value orelse "1"); } /// Run pkg-config for the given library name and parse the output, returning the arguments @@ -765,6 +665,20 @@ pub fn linkSystemLibrary2( return self.root_module.linkSystemLibrary(name, options); } +pub fn linkFramework(c: *Compile, name: []const u8) void { + c.root_module.linkFramework(name, .{}); +} + +/// Deprecated. Use `c.root_module.linkFramework`. +pub fn linkFrameworkNeeded(c: *Compile, name: []const u8) void { + c.root_module.linkFramework(name, .{ .needed = true }); +} + +/// Deprecated. Use `c.root_module.linkFramework`. +pub fn linkFrameworkWeak(c: *Compile, name: []const u8) void { + c.root_module.linkFramework(name, .{ .weak = true }); +} + /// Handy when you have many C/C++ source files and want them all to have the same flags. pub fn addCSourceFiles(self: *Compile, options: Module.AddCSourceFilesOptions) void { self.root_module.addCSourceFiles(options); @@ -805,27 +719,18 @@ fn getEmittedFileGeneric(self: *Compile, output_file: *?*GeneratedFile) LazyPath return .{ .generated = generated_file }; } -/// deprecated: use `getEmittedBinDirectory` -pub const getOutputDirectorySource = getEmittedBinDirectory; - /// Returns the path to the directory that contains the emitted binary file. pub fn getEmittedBinDirectory(self: *Compile) LazyPath { _ = self.getEmittedBin(); return self.getEmittedFileGeneric(&self.emit_directory); } -/// deprecated: use `getEmittedBin` -pub const getOutputSource = getEmittedBin; - /// Returns the path to the generated executable, library or object file. /// To run an executable built with zig build, use `run`, or create an install step and invoke it. pub fn getEmittedBin(self: *Compile) LazyPath { return self.getEmittedFileGeneric(&self.generated_bin); } -/// deprecated: use `getEmittedImplib` -pub const getOutputLibSource = getEmittedImplib; - /// Returns the path to the generated import library. /// This function can only be called for libraries. pub fn getEmittedImplib(self: *Compile) LazyPath { @@ -833,9 +738,6 @@ pub fn getEmittedImplib(self: *Compile) LazyPath { return self.getEmittedFileGeneric(&self.generated_implib); } -/// deprecated: use `getEmittedH` -pub const getOutputHSource = getEmittedH; - /// Returns the path to the generated header file. /// This function can only be called for libraries or objects. pub fn getEmittedH(self: *Compile) LazyPath { @@ -843,9 +745,6 @@ pub fn getEmittedH(self: *Compile) LazyPath { return self.getEmittedFileGeneric(&self.generated_h); } -/// deprecated: use `getEmittedPdb`. -pub const getOutputPdbSource = getEmittedPdb; - /// Returns the generated PDB file. /// If the compilation does not produce a PDB file, this causes a FileNotFound error /// at build time. @@ -882,56 +781,44 @@ pub fn addObjectFile(self: *Compile, source: LazyPath) void { self.root_module.addObjectFile(source); } -pub fn addObject(self: *Compile, obj: *Compile) void { - assert(obj.kind == .obj); - self.linkLibraryOrObject(obj); +pub fn addObject(self: *Compile, object: *Compile) void { + self.root_module.addObject(object); } -pub fn addAfterIncludePath(self: *Compile, path: LazyPath) void { - const b = self.step.owner; - self.include_dirs.append(.{ .path_after = path.dupe(b) }) catch @panic("OOM"); - path.addStepDependencies(&self.step); +pub fn linkLibrary(self: *Compile, library: *Compile) void { + self.root_module.linkLibrary(library); } -pub fn addSystemIncludePath(self: *Compile, path: LazyPath) void { - const b = self.step.owner; - self.include_dirs.append(.{ .path_system = path.dupe(b) }) catch @panic("OOM"); - path.addStepDependencies(&self.step); +pub fn addAfterIncludePath(self: *Compile, lazy_path: LazyPath) void { + self.root_module.addAfterIncludePath(lazy_path); } -pub fn addIncludePath(self: *Compile, path: LazyPath) void { - const b = self.step.owner; - self.include_dirs.append(.{ .path = path.dupe(b) }) catch @panic("OOM"); - path.addStepDependencies(&self.step); +pub fn addSystemIncludePath(self: *Compile, lazy_path: LazyPath) void { + self.root_module.addSystemIncludePath(lazy_path); +} + +pub fn addIncludePath(self: *Compile, lazy_path: LazyPath) void { + self.root_module.addIncludePath(lazy_path); } pub fn addConfigHeader(self: *Compile, config_header: *Step.ConfigHeader) void { - self.step.dependOn(&config_header.step); - self.include_dirs.append(.{ .config_header_step = config_header }) catch @panic("OOM"); + self.root_module.addConfigHeader(config_header); } -pub fn addLibraryPath(self: *Compile, directory_source: LazyPath) void { - const b = self.step.owner; - self.lib_paths.append(directory_source.dupe(b)) catch @panic("OOM"); - directory_source.addStepDependencies(&self.step); +pub fn addLibraryPath(self: *Compile, directory_path: LazyPath) void { + self.root_module.addLibraryPath(directory_path); } -pub fn addRPath(self: *Compile, directory_source: LazyPath) void { - const b = self.step.owner; - self.rpaths.append(directory_source.dupe(b)) catch @panic("OOM"); - directory_source.addStepDependencies(&self.step); +pub fn addRPath(self: *Compile, directory_path: LazyPath) void { + self.root_module.addRPath(directory_path); } -pub fn addSystemFrameworkPath(self: *Compile, directory_source: LazyPath) void { - const b = self.step.owner; - self.include_dirs.append(.{ .framework_path_system = directory_source.dupe(b) }) catch @panic("OOM"); - directory_source.addStepDependencies(&self.step); +pub fn addSystemFrameworkPath(self: *Compile, directory_path: LazyPath) void { + self.root_module.addSystemFrameworkPath(directory_path); } -pub fn addFrameworkPath(self: *Compile, directory_source: LazyPath) void { - const b = self.step.owner; - self.include_dirs.append(.{ .framework_path = directory_source.dupe(b) }) catch @panic("OOM"); - directory_source.addStepDependencies(&self.step); +pub fn addFrameworkPath(self: *Compile, directory_path: LazyPath) void { + self.root_module.addFrameworkPath(directory_path); } pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { @@ -944,20 +831,6 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { self.exec_cmd_args = duped_args; } -fn linkLibraryOrObject(self: *Compile, other: *Compile) void { - other.getEmittedBin().addStepDependencies(&self.step); - if (other.target.isWindows() and other.isDynamicLibrary()) { - other.getEmittedImplib().addStepDependencies(&self.step); - } - - self.link_objects.append(.{ .other_step = other }) catch @panic("OOM"); - self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM"); - - for (other.installed_headers.items) |install_step| { - self.step.dependOn(install_step); - } -} - fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { const b = cs.step.owner; // First, traverse the whole dependency graph and give every module a @@ -1014,7 +887,7 @@ fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { fn constructDepString( allocator: std.mem.Allocator, mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8), - deps: std.StringArrayHashMap(*Module), + deps: std.StringArrayHashMapUnmanaged(*Module), ) ![]const u8 { var deps_str = std.ArrayList(u8).init(allocator); var it = deps.iterator(); @@ -1082,7 +955,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try addFlag(&zig_args, "llvm", self.use_llvm); try addFlag(&zig_args, "lld", self.use_lld); - if (self.root_module.target.ofmt) |ofmt| { + if (self.root_module.target.?.query.ofmt) |ofmt| { try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); } @@ -1110,7 +983,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { { var seen_system_libs: std.StringHashMapUnmanaged(void) = .{}; - var frameworks: std.StringArrayHashMapUnmanaged(Module.FrameworkLinkInfo) = .{}; + var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .{}; var prev_has_cflags = false; var prev_has_rcflags = false; @@ -1240,7 +1113,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(full_path_lib); if (other.linkage == Linkage.dynamic and - self.root_module.target_info.target.os.tag != .windows) + self.rootModuleTarget().os.tag != .windows) { if (fs.path.dirname(full_path_lib)) |dirname| { try zig_args.append("-rpath"); @@ -1471,11 +1344,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(b.fmt("{}", .{version})); } - if (self.root_module.target_info.target.isDarwin()) { + if (self.rootModuleTarget().isDarwin()) { const install_name = self.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{ - self.root_module.target_info.target.libPrefix(), + self.rootModuleTarget().libPrefix(), self.name, - self.root_module.target_info.target.dynamicLibSuffix(), + self.rootModuleTarget().dynamicLibSuffix(), }); try zig_args.append("-install_name"); try zig_args.append(install_name); @@ -1763,7 +1636,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and - self.version != null and self.root_module.target.wantSharedLibSymLinks()) + self.version != null and std.Build.wantSharedLibSymLinks(self.rootModuleTarget())) { try doAtomicSymLinks( step, @@ -1932,3 +1805,8 @@ fn matchCompileError(actual: []const u8, expected: []const u8) bool { } return false; } + +pub fn rootModuleTarget(c: *Compile) std.Target { + // The root module is always given a target, so we know this to be non-null. + return c.root_module.target.?.target; +} diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 9f040349c677..c352b2460c01 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -15,9 +15,6 @@ pub const Style = union(enum) { /// Start with nothing, like blank, and output a nasm .asm file. nasm, - /// deprecated: use `getPath` - pub const getFileSource = getPath; - pub fn getPath(style: Style) ?std.Build.LazyPath { switch (style) { .autoconf, .cmake => |s| return s, @@ -107,9 +104,6 @@ pub fn addValues(self: *ConfigHeader, values: anytype) void { return addValuesInner(self, values) catch @panic("OOM"); } -/// deprecated: use `getOutput` -pub const getFileSource = getOutput; - pub fn getOutput(self: *ConfigHeader) std.Build.LazyPath { return .{ .generated = &self.output_file }; } diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig index f3c9ca3bef0e..b9c3acfbc912 100644 --- a/lib/std/Build/Step/InstallArtifact.zig +++ b/lib/std/Build/Step/InstallArtifact.zig @@ -94,7 +94,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins .dylib_symlinks = if (options.dylib_symlinks orelse (dest_dir != null and artifact.isDynamicLibrary() and artifact.version != null and - artifact.target.wantSharedLibSymLinks())) .{ + std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget()))) .{ .major_only_filename = artifact.major_only_filename.?, .name_only_filename = artifact.name_only_filename.?, } else null, diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 8255be5cf410..362e030e5a9b 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -165,9 +165,6 @@ fn printLiteral(out: anytype, val: anytype, indent: u8) !void { } } -/// deprecated: use `addOptionPath` -pub const addOptionFileSource = addOptionPath; - /// The value is the path in the cache dir. /// Adds a dependency automatically. pub fn addOptionPath( @@ -189,8 +186,7 @@ pub fn addOptionArtifact(self: *Options, name: []const u8, artifact: *Step.Compi pub fn createModule(self: *Options) *std.Build.Module { return self.step.owner.createModule(.{ - .source_file = self.getOutput(), - .dependencies = &.{}, + .root_source_file = self.getOutput(), }); } diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 855eabeae9ba..40b72c7bca9e 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -197,16 +197,10 @@ pub fn addPrefixedOutputFileArg( return .{ .generated = &output.generated_file }; } -/// deprecated: use `addFileArg` -pub const addFileSourceArg = addFileArg; - pub fn addFileArg(self: *Run, lp: std.Build.LazyPath) void { self.addPrefixedFileArg("", lp); } -// deprecated: use `addPrefixedFileArg` -pub const addPrefixedFileSourceArg = addPrefixedFileArg; - pub fn addPrefixedFileArg(self: *Run, prefix: []const u8, lp: std.Build.LazyPath) void { const b = self.step.owner; @@ -488,7 +482,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { man.hash.addBytes(file_path); }, .artifact => |artifact| { - if (artifact.root_module.target_info.target.os.tag == .windows) { + if (artifact.rootModuleTarget().os.tag == .windows) { // On Windows we don't have rpaths so we have to add .dll search paths to PATH self.addPathForDynLibs(artifact); } @@ -682,9 +676,10 @@ fn runCommand( else => break :interpret, } - const need_cross_glibc = exe.root_module.target_info.target.isGnuLibC() and + const need_cross_glibc = exe.rootModuleTarget().isGnuLibC() and exe.is_linking_libc; - switch (b.host.getExternalExecutor(&exe.root_module.target_info, .{ + const other_target_info = exe.root_module.target.?.toNativeTargetInfo(); + switch (b.host.toNativeTargetInfo().getExternalExecutor(&other_target_info, .{ .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -715,9 +710,9 @@ fn runCommand( // needs the directory to be called "i686" rather than // "x86" which is why we do it manually here. const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}"; - const cpu_arch = exe.root_module.target_info.target.cpu.arch; - const os_tag = exe.root_module.target_info.target.os.tag; - const abi = exe.root_module.target_info.target.abi; + const cpu_arch = exe.rootModuleTarget().cpu.arch; + const os_tag = exe.rootModuleTarget().os.tag; + const abi = exe.rootModuleTarget().abi; const cpu_arch_name: []const u8 = if (cpu_arch == .x86) "i686" else @@ -770,7 +765,7 @@ fn runCommand( if (allow_skip) return error.MakeSkipped; const host_name = try b.host.target.zigTriple(b.allocator); - const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator); + const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator); return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{ host_name, foreign_name, @@ -778,7 +773,7 @@ fn runCommand( }, } - if (exe.root_module.target_info.target.os.tag == .windows) { + if (exe.rootModuleTarget().os.tag == .windows) { // On Windows we don't have rpaths so we have to add .dll search paths to PATH self.addPathForDynLibs(exe); } @@ -1300,7 +1295,7 @@ fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void { while (it.next()) |item| { const other = item.compile.?; if (item.module == &other.root_module) { - if (item.module.target_info.target.os.tag == .windows and other.isDynamicLibrary()) { + if (item.module.target.?.target.os.tag == .windows and other.isDynamicLibrary()) { addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); addPathForDynLibs(self, other); } @@ -1321,7 +1316,7 @@ fn failForeign( const b = self.step.owner; const host_name = try b.host.target.zigTriple(b.allocator); - const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator); + const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator); return self.step.fail( \\unable to spawn foreign binary '{s}' ({s}) on host system ({s}) diff --git a/lib/std/Build/Step/TranslateC.zig b/lib/std/Build/Step/TranslateC.zig index 26e59dad9074..31919ba11a5a 100644 --- a/lib/std/Build/Step/TranslateC.zig +++ b/lib/std/Build/Step/TranslateC.zig @@ -2,7 +2,6 @@ const std = @import("std"); const Step = std.Build.Step; const fs = std.fs; const mem = std.mem; -const CrossTarget = std.zig.CrossTarget; const TranslateC = @This(); @@ -13,7 +12,7 @@ source: std.Build.LazyPath, include_dirs: std.ArrayList([]const u8), c_macros: std.ArrayList([]const u8), out_basename: []const u8, -target: CrossTarget, +target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, output_file: std.Build.GeneratedFile, link_libc: bool, @@ -21,7 +20,7 @@ use_clang: bool, pub const Options = struct { source_file: std.Build.LazyPath, - target: CrossTarget, + target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, link_libc: bool = true, use_clang: bool = true, @@ -54,7 +53,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { pub const AddExecutableOptions = struct { name: ?[]const u8 = null, version: ?std.SemanticVersion = null, - target: ?CrossTarget = null, + target: ?std.Build.ResolvedTarget = null, optimize: ?std.builtin.OptimizeMode = null, linkage: ?Step.Compile.Linkage = null, }; @@ -139,9 +138,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try argv_list.append("--listen=-"); - if (!self.target.isNative()) { + if (!self.target.query.isNative()) { try argv_list.append("-target"); - try argv_list.append(try self.target.zigTriple(b.allocator)); + try argv_list.append(try self.target.query.zigTriple(b.allocator)); } switch (self.optimize) { diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 01019274fd91..7fcf06249f38 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -28,9 +28,6 @@ pub const File = struct { sub_path: []const u8, contents: Contents, - /// deprecated: use `getPath` - pub const getFileSource = getPath; - pub fn getPath(self: *File) std.Build.LazyPath { return .{ .generated = &self.generated_file }; } @@ -126,10 +123,6 @@ pub fn addBytesToSource(wf: *WriteFile, bytes: []const u8, sub_path: []const u8) }) catch @panic("OOM"); } -pub const getFileSource = @compileError("Deprecated; use the return value from add()/addCopyFile(), or use files[i].getPath()"); - -pub const getDirectorySource = getDirectory; - /// Returns a `LazyPath` representing the base directory that contains all the /// files from this `WriteFile`. pub fn getDirectory(wf: *WriteFile) std.Build.LazyPath { diff --git a/lib/std/std.zig b/lib/std/std.zig index 7342cadbefdb..8db22c3c6cc1 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -194,9 +194,6 @@ pub const zig = @import("zig.zig"); pub const start = @import("start.zig"); -/// deprecated: use `Build`. -pub const build = Build; - const root = @import("root"); const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {}; diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 2d2aaf17ba40..89e014190c2b 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -203,6 +203,83 @@ pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error } } +pub const BuildId = union(enum) { + none, + fast, + uuid, + sha1, + md5, + hexstring: HexString, + + pub fn eql(a: BuildId, b: BuildId) bool { + const Tag = @TypeOf(BuildId).Union.tag_type.?; + const a_tag: Tag = a; + const b_tag: Tag = b; + if (a_tag != b_tag) return false; + return switch (a) { + .none, .fast, .uuid, .sha1, .md5 => true, + .hexstring => |a_hexstring| std.mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()), + }; + } + + pub const HexString = struct { + bytes: [32]u8, + len: u8, + + /// Result is byte values, *not* hex-encoded. + pub fn toSlice(hs: *const HexString) []const u8 { + return hs.bytes[0..hs.len]; + } + }; + + /// Input is byte values, *not* hex-encoded. + /// Asserts `bytes` fits inside `HexString` + pub fn initHexString(bytes: []const u8) BuildId { + var result: BuildId = .{ .hexstring = .{ + .bytes = undefined, + .len = @intCast(bytes.len), + } }; + @memcpy(result.hexstring.bytes[0..bytes.len], bytes); + return result; + } + + /// Converts UTF-8 text to a `BuildId`. + pub fn parse(text: []const u8) !BuildId { + if (std.mem.eql(u8, text, "none")) { + return .none; + } else if (std.mem.eql(u8, text, "fast")) { + return .fast; + } else if (std.mem.eql(u8, text, "uuid")) { + return .uuid; + } else if (std.mem.eql(u8, text, "sha1") or std.mem.eql(u8, text, "tree")) { + return .sha1; + } else if (std.mem.eql(u8, text, "md5")) { + return .md5; + } else if (std.mem.startsWith(u8, text, "0x")) { + var result: BuildId = .{ .hexstring = undefined }; + const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]); + result.hexstring.len = @as(u8, @intCast(slice.len)); + return result; + } + return error.InvalidBuildIdStyle; + } + + test parse { + try std.testing.expectEqual(BuildId.md5, try parse("md5")); + try std.testing.expectEqual(BuildId.none, try parse("none")); + try std.testing.expectEqual(BuildId.fast, try parse("fast")); + try std.testing.expectEqual(BuildId.uuid, try parse("uuid")); + try std.testing.expectEqual(BuildId.sha1, try parse("sha1")); + try std.testing.expectEqual(BuildId.sha1, try parse("tree")); + + try std.testing.expect(BuildId.initHexString("").eql(try parse("0x"))); + try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456"))); + try std.testing.expectError(error.InvalidLength, parse("0x12-34")); + try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); + try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); + } +}; + test { @import("std").testing.refAllDecls(@This()); } diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig index c65269e4d3dc..dc6de46af522 100644 --- a/lib/std/zig/CrossTarget.zig +++ b/lib/std/zig/CrossTarget.zig @@ -632,10 +632,6 @@ pub fn linuxTriple(self: CrossTarget, allocator: mem.Allocator) ![]u8 { return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); } -pub fn wantSharedLibSymLinks(self: CrossTarget) bool { - return self.getOsTag() != .windows; -} - pub fn isGnuLibC(self: CrossTarget) bool { return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); } diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig index 080f18bf0a21..d44e396fb53a 100644 --- a/lib/std/zig/system/NativeTargetInfo.zig +++ b/lib/std/zig/system/NativeTargetInfo.zig @@ -1008,8 +1008,8 @@ pub const GetExternalExecutorOptions = struct { link_libc: bool = false, }; -/// Return whether or not the given host target is capable of executing natively executables -/// of the other target. +/// Return whether or not the given host is capable of running executables of +/// the other target. pub fn getExternalExecutor( host: NativeTargetInfo, candidate: *const NativeTargetInfo, diff --git a/src/Compilation.zig b/src/Compilation.zig index 296b300f8d8c..7831a5884008 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -30,7 +30,6 @@ const fatal = @import("main.zig").fatal; const clangMain = @import("main.zig").clangMain; const Module = @import("Module.zig"); const InternPool = @import("InternPool.zig"); -const BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; const c_codegen = @import("codegen/c.zig"); const libtsan = @import("libtsan.zig"); @@ -910,7 +909,7 @@ pub const InitOptions = struct { linker_print_map: bool = false, linker_opt_bisect_limit: i32 = -1, each_lib_rpath: ?bool = null, - build_id: ?BuildId = null, + build_id: ?std.zig.BuildId = null, disable_c_depfile: bool = false, linker_z_nodelete: bool = false, linker_z_notext: bool = false, diff --git a/src/link.zig b/src/link.zig index 12b9c58d9bb1..09669f4dbedc 100644 --- a/src/link.zig +++ b/src/link.zig @@ -10,7 +10,6 @@ const wasi_libc = @import("wasi_libc.zig"); const Air = @import("Air.zig"); const Allocator = std.mem.Allocator; -const BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; const Compilation = @import("Compilation.zig"); const LibCInstallation = @import("libc_installation.zig").LibCInstallation; @@ -185,7 +184,7 @@ pub const Options = struct { error_return_tracing: bool, skip_linker_dependencies: bool, each_lib_rpath: bool, - build_id: BuildId, + build_id: std.zig.BuildId, disable_lld_caching: bool, is_test: bool, hash_style: HashStyle, diff --git a/src/main.zig b/src/main.zig index 73316c6e653b..0e6ce947aa47 100644 --- a/src/main.zig +++ b/src/main.zig @@ -21,7 +21,6 @@ const introspect = @import("introspect.zig"); const EnvVar = introspect.EnvVar; const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const wasi_libc = @import("wasi_libc.zig"); -const BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; const target_util = @import("target.zig"); const crash_report = @import("crash_report.zig"); @@ -882,7 +881,7 @@ fn buildOutputType( var link_eh_frame_hdr = false; var link_emit_relocs = false; var each_lib_rpath: ?bool = null; - var build_id: ?BuildId = null; + var build_id: ?std.zig.BuildId = null; var sysroot: ?[]const u8 = null; var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena); var machine_code_model: std.builtin.CodeModel = .default; @@ -1551,7 +1550,7 @@ fn buildOutputType( build_id = .fast; } else if (mem.startsWith(u8, arg, "--build-id=")) { const style = arg["--build-id=".len..]; - build_id = BuildId.parse(style) catch |err| { + build_id = std.zig.BuildId.parse(style) catch |err| { fatal("unable to parse --build-id style '{s}': {s}", .{ style, @errorName(err), }); @@ -1847,7 +1846,7 @@ fn buildOutputType( const key = linker_arg[0..equals_pos]; const value = linker_arg[equals_pos + 1 ..]; if (mem.eql(u8, key, "--build-id")) { - build_id = BuildId.parse(value) catch |err| { + build_id = std.zig.BuildId.parse(value) catch |err| { fatal("unable to parse --build-id style '{s}': {s}", .{ value, @errorName(err), }); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index ac09066552f5..e99925f22886 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -876,27 +876,27 @@ test "two comptime calls with array default initialized to undefined" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { - const CrossTarget = struct { - dynamic_linker: DynamicLinker = DynamicLinker{}, + const A = struct { + c: B = B{}, - pub fn parse() void { - var result: CrossTarget = .{}; - result.getCpuArch(); + pub fn d() void { + var f: A = .{}; + f.e(); } - pub fn getCpuArch(self: CrossTarget) void { - _ = self; + pub fn e(g: A) void { + _ = g; } }; - const DynamicLinker = struct { + const B = struct { buffer: [255]u8 = undefined, }; }; comptime { - S.CrossTarget.parse(); - S.CrossTarget.parse(); + S.A.d(); + S.A.d(); } } diff --git a/test/cases.zig b/test/cases.zig index 2f390413321b..9bbdde4777a3 100644 --- a/test/cases.zig +++ b/test/cases.zig @@ -9,9 +9,9 @@ pub const BuildOptions = struct { llvm_has_xtensa: bool, }; -pub fn addCases(cases: *Cases, build_options: BuildOptions) !void { - try @import("compile_errors.zig").addCases(cases); - try @import("cbe.zig").addCases(cases); - try @import("llvm_targets.zig").addCases(cases, build_options); - try @import("nvptx.zig").addCases(cases); +pub fn addCases(cases: *Cases, build_options: BuildOptions, b: *std.Build) !void { + try @import("compile_errors.zig").addCases(cases, b); + try @import("cbe.zig").addCases(cases, b); + try @import("llvm_targets.zig").addCases(cases, build_options, b); + try @import("nvptx.zig").addCases(cases, b); } diff --git a/test/cbe.zig b/test/cbe.zig index bee713843846..b45a4e5f7284 100644 --- a/test/cbe.zig +++ b/test/cbe.zig @@ -2,16 +2,16 @@ const std = @import("std"); const Cases = @import("src/Cases.zig"); const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; -// These tests should work with all platforms, but we're using linux_x64 for -// now for consistency. Will be expanded eventually. -const linux_x64 = std.zig.CrossTarget{ - .cpu_arch = .x86_64, - .os_tag = .linux, -}; - -pub fn addCases(ctx: *Cases) !void { +pub fn addCases(ctx: *Cases, b: *std.Build) !void { + // These tests should work with all platforms, but we're using linux_x64 for + // now for consistency. Will be expanded eventually. + const linux_x64: std.zig.CrossTarget = .{ + .cpu_arch = .x86_64, + .os_tag = .linux, + }; + { - var case = ctx.exeFromCompiledC("hello world with updates", .{}); + var case = ctx.exeFromCompiledC("hello world with updates", .{}, b); // Regular old hello world case.addCompareOutput( @@ -59,7 +59,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("var args", .{}); + var case = ctx.exeFromCompiledC("var args", .{}, b); case.addCompareOutput( \\extern fn printf(format: [*:0]const u8, ...) c_int; @@ -72,7 +72,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("errorFromInt", .{}); + var case = ctx.exeFromCompiledC("errorFromInt", .{}, b); case.addCompareOutput( \\pub export fn main() c_int { @@ -108,7 +108,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64); + var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64, b); // Exit with 0 case.addCompareOutput( @@ -202,7 +202,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("alloc and retptr", .{}); + var case = ctx.exeFromCompiledC("alloc and retptr", .{}, b); case.addCompareOutput( \\fn add(a: i32, b: i32) i32 { @@ -220,7 +220,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("inferred local const and var", .{}); + var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b); case.addCompareOutput( \\fn add(a: i32, b: i32) i32 { @@ -236,7 +236,7 @@ pub fn addCases(ctx: *Cases) !void { , ""); } { - var case = ctx.exeFromCompiledC("control flow", .{}); + var case = ctx.exeFromCompiledC("control flow", .{}, b); // Simple while loop case.addCompareOutput( @@ -423,7 +423,7 @@ pub fn addCases(ctx: *Cases) !void { }); } //{ - // var case = ctx.exeFromCompiledC("optionals", .{}); + // var case = ctx.exeFromCompiledC("optionals", .{}, b); // // Simple while loop // case.addCompareOutput( @@ -451,7 +451,7 @@ pub fn addCases(ctx: *Cases) !void { //} { - var case = ctx.exeFromCompiledC("errors", .{}); + var case = ctx.exeFromCompiledC("errors", .{}, b); case.addCompareOutput( \\pub export fn main() c_int { \\ var e1 = error.Foo; @@ -495,7 +495,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("structs", .{}); + var case = ctx.exeFromCompiledC("structs", .{}, b); case.addError( \\const Point = struct { x: i32, y: i32 }; \\pub export fn main() c_int { @@ -562,7 +562,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("unions", .{}); + var case = ctx.exeFromCompiledC("unions", .{}, b); case.addError( \\const U = union { @@ -596,7 +596,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("enums", .{}); + var case = ctx.exeFromCompiledC("enums", .{}, b); case.addError( \\const E1 = packed enum { a, b, c }; @@ -838,7 +838,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("shift right and left", .{}); + var case = ctx.exeFromCompiledC("shift right and left", .{}, b); case.addCompareOutput( \\pub export fn main() c_int { \\ var i: u32 = 16; @@ -863,7 +863,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("inferred error sets", .{}); + var case = ctx.exeFromCompiledC("inferred error sets", .{}, b); case.addCompareOutput( \\pub export fn main() c_int { @@ -884,7 +884,7 @@ pub fn addCases(ctx: *Cases) !void { { // TODO: add u64 tests, ran into issues with the literal generated for std.math.maxInt(u64) - var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}); + var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}, b); case.addCompareOutput( \\pub export fn main() c_int { \\ // Addition @@ -933,7 +933,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = ctx.exeFromCompiledC("rem", linux_x64); + var case = ctx.exeFromCompiledC("rem", linux_x64, b); case.addCompareOutput( \\fn assert(ok: bool) void { \\ if (!ok) unreachable; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a3bdf5b8f141..ec3726e94d06 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,9 +2,9 @@ const std = @import("std"); const builtin = @import("builtin"); const Cases = @import("src/Cases.zig"); -pub fn addCases(ctx: *Cases) !void { +pub fn addCases(ctx: *Cases, b: *std.Build) !void { { - const case = ctx.obj("multiline error messages", .{}); + const case = ctx.obj("multiline error messages", b.host); case.addError( \\comptime { @@ -39,7 +39,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("isolated carriage return in multiline string literal", .{}); + const case = ctx.obj("isolated carriage return in multiline string literal", b.host); case.addError("const foo = \\\\\test\r\r rogue carriage return\n;", &[_][]const u8{ ":1:19: error: expected ';' after declaration", @@ -48,7 +48,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("missing semicolon at EOF", .{}); + const case = ctx.obj("missing semicolon at EOF", b.host); case.addError( \\const foo = 1 , &[_][]const u8{ @@ -57,7 +57,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("argument causes error", .{}); + const case = ctx.obj("argument causes error", b.host); case.addError( \\pub export fn entry() void { @@ -80,7 +80,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("astgen failure in file struct", .{}); + const case = ctx.obj("astgen failure in file struct", b.host); case.addError( \\pub export fn entry() void { @@ -95,7 +95,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("invalid store to comptime field", .{}); + const case = ctx.obj("invalid store to comptime field", b.host); case.addError( \\const a = @import("a.zig"); @@ -119,7 +119,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("file in multiple modules", .{}); + const case = ctx.obj("file in multiple modules", b.host); case.addDepModule("foo", "foo.zig"); case.addError( @@ -138,7 +138,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("wrong same named struct", .{}); + const case = ctx.obj("wrong same named struct", b.host); case.addError( \\const a = @import("a.zig"); @@ -172,7 +172,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("non-printable invalid character", .{}); + const case = ctx.obj("non-printable invalid character", b.host); case.addError("\xff\xfe" ++ \\export fn foo() bool { @@ -185,7 +185,7 @@ pub fn addCases(ctx: *Cases) !void { } { - const case = ctx.obj("imported generic method call with invalid param", .{}); + const case = ctx.obj("imported generic method call with invalid param", b.host); case.addError( \\pub const import = @import("import.zig"); diff --git a/test/link/bss/build.zig b/test/link/bss/build.zig index 3c7964fae1ef..865af0a4889f 100644 --- a/test/link/bss/build.zig +++ b/test/link/bss/build.zig @@ -7,6 +7,7 @@ pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = "bss", .root_source_file = .{ .path = "main.zig" }, + .target = b.host, .optimize = .Debug, }); diff --git a/test/link/common_symbols/build.zig b/test/link/common_symbols/build.zig index bb44073e386f..9b5c9da66292 100644 --- a/test/link/common_symbols/build.zig +++ b/test/link/common_symbols/build.zig @@ -14,7 +14,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib_a = b.addStaticLibrary(.{ .name = "a", .optimize = optimize, - .target = .{}, + .target = b.host, }); lib_a.addCSourceFiles(.{ .files = &.{ "c.c", "a.c", "b.c" }, diff --git a/test/link/common_symbols_alignment/build.zig b/test/link/common_symbols_alignment/build.zig index 049a8f5a8ffb..63aff339a976 100644 --- a/test/link/common_symbols_alignment/build.zig +++ b/test/link/common_symbols_alignment/build.zig @@ -14,7 +14,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib_a = b.addStaticLibrary(.{ .name = "a", .optimize = optimize, - .target = .{}, + .target = b.host, }); lib_a.addCSourceFiles(.{ .files = &.{"a.c"}, diff --git a/test/link/elf.zig b/test/link/elf.zig index 4055ec9219eb..d395344edd7c 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -5,20 +5,20 @@ pub fn testAll(b: *Build) *Step { const elf_step = b.step("test-elf", "Run ELF tests"); - const default_target = CrossTarget{ + const default_target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, // TODO relax this once ELF linker is able to handle other archs .os_tag = .linux, - }; - const musl_target = CrossTarget{ + }); + const musl_target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl, - }; - const glibc_target = CrossTarget{ + }); + const glibc_target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .gnu, - }; + }); // Exercise linker in -r mode elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = musl_target })); @@ -132,14 +132,18 @@ pub fn testAll(b: *Build) *Step { fn testAbsSymbols(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "abs-symbols", opts); - const obj = addObject(b, "obj", opts); - addAsmSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .asm_source_bytes = \\.globl foo \\foo = 0x800008 - ); + \\ + , + }); - const exe = addExecutable(b, "test", opts); - addCSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test", + .c_source_bytes = \\#include \\#include \\#include @@ -159,7 +163,8 @@ fn testAbsSymbols(b: *Build, opts: Options) *Step { \\ foo = 5; \\ return 0; \\} - , &.{}); + , + }); exe.addObject(obj); exe.linkLibC(); @@ -173,31 +178,36 @@ fn testAbsSymbols(b: *Build, opts: Options) *Step { fn testAsNeeded(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "as-needed", opts); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\int baz(); \\int main() { \\ printf("%d\n", baz()); \\ return 0; \\} - , &.{}); + \\ + , + }); main_o.linkLibC(); - const libfoo = addSharedLibrary(b, "foo", opts); + const libfoo = addSharedLibrary(b, opts, .{ .name = "foo" }); addCSourceBytes(libfoo, "int foo() { return 42; }", &.{}); - const libbar = addSharedLibrary(b, "bar", opts); + const libbar = addSharedLibrary(b, opts, .{ .name = "bar" }); addCSourceBytes(libbar, "int bar() { return 42; }", &.{}); - const libbaz = addSharedLibrary(b, "baz", opts); + const libbaz = addSharedLibrary(b, opts, .{ .name = "baz" }); addCSourceBytes(libbaz, \\int foo(); \\int baz() { return foo(); } , &.{}); { - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ + .name = "test", + }); exe.addObject(main_o); exe.linkSystemLibrary2("foo", .{ .needed = true }); exe.addLibraryPath(libfoo.getEmittedBinDirectory()); @@ -225,7 +235,9 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ + .name = "test", + }); exe.addObject(main_o); exe.linkSystemLibrary2("foo", .{ .needed = false }); exe.addLibraryPath(libfoo.getEmittedBinDirectory()); @@ -259,7 +271,7 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { fn testCanonicalPlt(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "canonical-plt", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\void *foo() { \\ return foo; @@ -269,17 +281,21 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { \\} , &.{}); - const b_o = addObject(b, "obj", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\void *bar(); \\void *baz() { \\ return bar; \\} - , &.{}); - b_o.force_pic = true; + \\ + , + .pic = true, + }); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\void *foo(); \\void *bar(); @@ -290,11 +306,15 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { \\ assert(bar == baz()); \\ return 0; \\} - , &.{}); + \\ + , + .pic = false, + }); main_o.linkLibC(); - main_o.force_pic = false; - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ + .name = "main", + }); exe.addObject(main_o); exe.addObject(b_o); exe.linkLibrary(dso); @@ -311,7 +331,9 @@ fn testCanonicalPlt(b: *Build, opts: Options) *Step { fn testCommonSymbols(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "common-symbols", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ + .name = "test", + }); addCSourceBytes(exe, \\int foo; \\int bar; @@ -338,8 +360,9 @@ fn testCommonSymbols(b: *Build, opts: Options) *Step { fn testCommonSymbolsInArchive(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "common-symbols-in-archive", opts); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\int foo; \\int bar; @@ -348,28 +371,43 @@ fn testCommonSymbolsInArchive(b: *Build, opts: Options) *Step { \\int main() { \\ printf("%d %d %d %d\n", foo, bar, baz, two ? two() : -1); \\} - , &.{"-fcommon"}); + \\ + , + .c_source_flags = &.{"-fcommon"}, + }); a_o.linkLibC(); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, "int foo = 5;", &.{"-fcommon"}); + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = "int foo = 5;", + .c_source_flags = &.{"-fcommon"}, + }); { - const c_o = addObject(b, "c", opts); - addCSourceBytes(c_o, + const c_o = addObject(b, opts, .{ + .name = "c", + .c_source_bytes = \\int bar; \\int two() { return 2; } - , &.{"-fcommon"}); - - const d_o = addObject(b, "d", opts); - addCSourceBytes(d_o, "int baz;", &.{"-fcommon"}); - - const lib = addStaticLibrary(b, "lib", opts); + \\ + , + .c_source_flags = &.{"-fcommon"}, + }); + + const d_o = addObject(b, opts, .{ + .name = "d", + .c_source_bytes = "int baz;", + .c_source_flags = &.{"-fcommon"}, + }); + + const lib = addStaticLibrary(b, opts, .{ .name = "lib" }); lib.addObject(b_o); lib.addObject(c_o); lib.addObject(d_o); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ + .name = "test", + }); exe.addObject(a_o); exe.linkLibrary(lib); exe.linkLibC(); @@ -380,18 +418,23 @@ fn testCommonSymbolsInArchive(b: *Build, opts: Options) *Step { } { - const e_o = addObject(b, "e", opts); - addCSourceBytes(e_o, + const e_o = addObject(b, opts, .{ + .name = "e", + .c_source_bytes = \\int bar = 0; \\int baz = 7; \\int two() { return 2; } - , &.{"-fcommon"}); + , + .c_source_flags = &.{"-fcommon"}, + }); - const lib = addStaticLibrary(b, "lib", opts); + const lib = addStaticLibrary(b, opts, .{ .name = "lib" }); lib.addObject(b_o); lib.addObject(e_o); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ + .name = "test", + }); exe.addObject(a_o); exe.linkLibrary(lib); exe.linkLibC(); @@ -407,21 +450,23 @@ fn testCommonSymbolsInArchive(b: *Build, opts: Options) *Step { fn testCopyrel(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "copyrel", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\int foo = 3; \\int bar = 5; , &.{}); - const exe = addExecutable(b, "main", opts); - addCSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\extern int foo, bar; \\int main() { \\ printf("%d %d\n", foo, bar); \\ return 0; \\} - , &.{}); + , + }); exe.linkLibrary(dso); exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 @@ -437,7 +482,7 @@ fn testCopyrel(b: *Build, opts: Options) *Step { fn testCopyrelAlias(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "copyrel-alias", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\int bruh = 31; \\int foo = 42; @@ -445,7 +490,10 @@ fn testCopyrelAlias(b: *Build, opts: Options) *Step { \\extern int baz __attribute__((alias("foo"))); , &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ + .name = "main", + .pic = false, + }); addCSourceBytes(exe, \\#include \\extern int foo; @@ -461,7 +509,6 @@ fn testCopyrelAlias(b: *Build, opts: Options) *Step { , &.{}); exe.linkLibrary(dso); exe.linkLibC(); - exe.force_pic = false; exe.pie = false; const run = addRunArtifact(exe); @@ -474,28 +521,31 @@ fn testCopyrelAlias(b: *Build, opts: Options) *Step { fn testCopyrelAlignment(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "copyrel-alignment", opts); - const a_so = addSharedLibrary(b, "a", opts); + const a_so = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(a_so, "__attribute__((aligned(32))) int foo = 5;", &.{}); - const b_so = addSharedLibrary(b, "b", opts); + const b_so = addSharedLibrary(b, opts, .{ .name = "b" }); addCSourceBytes(b_so, "__attribute__((aligned(8))) int foo = 5;", &.{}); - const c_so = addSharedLibrary(b, "c", opts); + const c_so = addSharedLibrary(b, opts, .{ .name = "c" }); addCSourceBytes(c_so, "__attribute__((aligned(256))) int foo = 5;", &.{}); - const obj = addObject(b, "main", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\extern int foo; \\int main() { printf("%d\n", foo); } - , &.{}); + \\ + , + .pic = false, + }); obj.linkLibC(); - obj.force_pic = false; const exp_stdout = "5\n"; { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(obj); exe.linkLibrary(a_so); exe.linkLibC(); @@ -514,7 +564,7 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(obj); exe.linkLibrary(b_so); exe.linkLibC(); @@ -533,7 +583,7 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(obj); exe.linkLibrary(c_so); exe.linkLibC(); @@ -557,7 +607,7 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { fn testDsoPlt(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "dso-plt", opts); - const dso = addSharedLibrary(b, "dso", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "dso" }); addCSourceBytes(dso, \\#include \\void world() { @@ -573,7 +623,7 @@ fn testDsoPlt(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, \\#include \\void world() { @@ -599,7 +649,7 @@ fn testDsoPlt(b: *Build, opts: Options) *Step { fn testDsoUndef(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "dso-undef", opts); - const dso = addSharedLibrary(b, "dso", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "dso" }); addCSourceBytes(dso, \\extern int foo; \\int bar = 5; @@ -607,13 +657,15 @@ fn testDsoUndef(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, "int foo = 3;", &.{}); + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = "int foo = 3;", + }); - const lib = addStaticLibrary(b, "lib", opts); + const lib = addStaticLibrary(b, opts, .{ .name = "lib" }); lib.addObject(obj); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); exe.linkLibrary(dso); exe.linkLibrary(lib); addCSourceBytes(exe, @@ -641,8 +693,9 @@ fn testDsoUndef(b: *Build, opts: Options) *Step { fn testEmitRelocatable(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "emit-relocatable", opts); - const obj1 = addObject(b, "obj1", opts); - addZigSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .zig_source_bytes = \\const std = @import("std"); \\extern var bar: i32; \\export fn foo() i32 { @@ -651,18 +704,20 @@ fn testEmitRelocatable(b: *Build, opts: Options) *Step { \\export fn printFoo() void { \\ std.debug.print("foo={d}\n", .{foo()}); \\} - ); - addCSourceBytes(obj1, + , + .c_source_bytes = \\#include \\int bar = 42; \\void printBar() { \\ fprintf(stderr, "bar=%d\n", bar); \\} - , &.{}); + , + }); obj1.linkLibC(); - const exe = addExecutable(b, "test", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test", + .zig_source_bytes = \\const std = @import("std"); \\extern fn printFoo() void; \\extern fn printBar() void; @@ -670,7 +725,8 @@ fn testEmitRelocatable(b: *Build, opts: Options) *Step { \\ printFoo(); \\ printBar(); \\} - ); + , + }); exe.addObject(obj1); exe.linkLibC(); @@ -688,20 +744,26 @@ fn testEmitRelocatable(b: *Build, opts: Options) *Step { fn testEmitStaticLib(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "emit-static-lib", opts); - const obj1 = addObject(b, "obj1", opts); - addCSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .c_source_bytes = \\int foo = 0; \\int bar = 2; \\int fooBar() { \\ return foo + bar; \\} - , &.{}); + , + }); - const obj2 = addObject(b, "obj2", opts); - addCSourceBytes(obj2, "int tentative;", &.{"-fcommon"}); + const obj2 = addObject(b, opts, .{ + .name = "obj2", + .c_source_bytes = "int tentative;", + .c_source_flags = &.{"-fcommon"}, + }); - const obj3 = addObject(b, "a_very_long_file_name_so_that_it_ends_up_in_strtab", opts); - addZigSourceBytes(obj3, + const obj3 = addObject(b, opts, .{ + .name = "a_very_long_file_name_so_that_it_ends_up_in_strtab", + .zig_source_bytes = \\fn weakFoo() callconv(.C) usize { \\ return 42; \\} @@ -710,9 +772,10 @@ fn testEmitStaticLib(b: *Build, opts: Options) *Step { \\ @export(weakFoo, .{ .name = "weakFoo", .linkage = .Weak }); \\ @export(strongBar, .{ .name = "strongBarAlias", .linkage = .Strong }); \\} - ); + , + }); - const lib = addStaticLibrary(b, "lib", opts); + const lib = addStaticLibrary(b, opts, .{ .name = "lib" }); lib.addObject(obj1); lib.addObject(obj2); lib.addObject(obj3); @@ -747,30 +810,36 @@ fn testEmitStaticLib(b: *Build, opts: Options) *Step { fn testEmitStaticLibZig(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "emit-static-lib-zig", opts); - const obj1 = addObject(b, "obj1", opts); - addZigSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .zig_source_bytes = \\export var foo: i32 = 42; \\export var bar: i32 = 2; - ); + , + }); - const lib = addStaticLibrary(b, "lib", opts); - addZigSourceBytes(lib, + const lib = addStaticLibrary(b, opts, .{ + .name = "lib", + .zig_source_bytes = \\extern var foo: i32; \\extern var bar: i32; \\export fn fooBar() i32 { \\ return foo + bar; \\} - ); + , + }); lib.addObject(obj1); - const exe = addExecutable(b, "test", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test", + .zig_source_bytes = \\const std = @import("std"); \\extern fn fooBar() i32; \\pub fn main() void { \\ std.debug.print("{d}", .{fooBar()}); \\} - ); + , + }); exe.linkLibrary(lib); const run = addRunArtifact(exe); @@ -783,7 +852,7 @@ fn testEmitStaticLibZig(b: *Build, opts: Options) *Step { fn testEmptyObject(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "empty-object", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, "int main() { return 0; }", &.{}); addCSourceBytes(exe, "", &.{}); exe.linkLibC(); @@ -798,18 +867,23 @@ fn testEmptyObject(b: *Build, opts: Options) *Step { fn testEntryPoint(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "entry-point", opts); - const a_o = addObject(b, "a", opts); - addAsmSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .asm_source_bytes = \\.globl foo, bar \\foo = 0x1000 \\bar = 0x2000 - ); + \\ + , + }); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, "int main() { return 0; }", &.{}); + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = "int main() { return 0; }", + }); { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(a_o); exe.addObject(b_o); exe.entry = .{ .symbol_name = "foo" }; @@ -825,7 +899,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step { // TODO looks like not assigning a unique name to this executable will // cause an artifact collision taking the cached executable from the above // step instead of generating a new one. - const exe = addExecutable(b, "other", opts); + const exe = addExecutable(b, opts, .{ .name = "other" }); exe.addObject(a_o); exe.addObject(b_o); exe.entry = .{ .symbol_name = "bar" }; @@ -843,8 +917,9 @@ fn testEntryPoint(b: *Build, opts: Options) *Step { fn testExportDynamic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "export-dynamic", opts); - const obj = addObject(b, "obj", opts); - addAsmSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .asm_source_bytes = \\.text \\ .globl foo \\ .hidden foo @@ -856,12 +931,14 @@ fn testExportDynamic(b: *Build, opts: Options) *Step { \\ .globl _start \\_start: \\ nop - ); + \\ + , + }); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, "int baz = 10;", &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\extern int baz; \\int callBaz() { @@ -885,7 +962,7 @@ fn testExportDynamic(b: *Build, opts: Options) *Step { fn testExportSymbolsFromExe(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "export-symbols-from-exe", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\void expfn1(); \\void expfn2() {} @@ -895,7 +972,7 @@ fn testExportSymbolsFromExe(b: *Build, opts: Options) *Step { \\} , &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\void expfn1() {} \\void expfn2() {} @@ -923,10 +1000,10 @@ fn testExportSymbolsFromExe(b: *Build, opts: Options) *Step { fn testFuncAddress(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "func-address", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, "void fn() {}", &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\typedef void Func(); @@ -937,7 +1014,7 @@ fn testFuncAddress(b: *Build, opts: Options) *Step { \\} , &.{}); exe.linkLibrary(dso); - exe.force_pic = false; + exe.root_module.pic = false; exe.pie = false; const run = addRunArtifact(exe); @@ -950,8 +1027,9 @@ fn testFuncAddress(b: *Build, opts: Options) *Step { fn testGcSections(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "gc-sections", opts); - const obj = addObject(b, "obj", opts); - addCppSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .cpp_source_bytes = \\#include \\int two() { return 2; } \\int live_var1 = 1; @@ -966,14 +1044,15 @@ fn testGcSections(b: *Build, opts: Options) *Step { \\ printf("%d %d\n", live_var1, live_var2); \\ live_fn2(); \\} - , &.{}); + , + }); obj.link_function_sections = true; obj.link_data_sections = true; obj.linkLibC(); obj.linkLibCpp(); { - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); exe.addObject(obj); exe.link_gc_sections = false; exe.linkLibC(); @@ -1004,7 +1083,7 @@ fn testGcSections(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); exe.addObject(obj); exe.link_gc_sections = true; exe.linkLibC(); @@ -1040,11 +1119,12 @@ fn testGcSections(b: *Build, opts: Options) *Step { fn testGcSectionsZig(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "gc-sections-zig", opts); - const obj = addObject(b, "obj", .{ + const obj = addObject(b, .{ .target = opts.target, .use_llvm = true, - }); - addCSourceBytes(obj, + }, .{ + .name = "obj", + .c_source_bytes = \\int live_var1 = 1; \\int live_var2 = 2; \\int dead_var1 = 3; @@ -1053,13 +1133,15 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { \\void live_fn2() { live_fn1(); } \\void dead_fn1() {} \\void dead_fn2() { dead_fn1(); } - , &.{}); + , + }); obj.link_function_sections = true; obj.link_data_sections = true; { - const exe = addExecutable(b, "test1", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test1", + .zig_source_bytes = \\const std = @import("std"); \\extern var live_var1: i32; \\extern var live_var2: i32; @@ -1069,7 +1151,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable; \\ live_fn2(); \\} - ); + , + }); exe.addObject(obj); exe.link_gc_sections = false; @@ -1098,8 +1181,9 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "test2", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test2", + .zig_source_bytes = \\const std = @import("std"); \\extern var live_var1: i32; \\extern var live_var2: i32; @@ -1109,7 +1193,8 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { \\ stdout.writer().print("{d} {d}\n", .{ live_var1, live_var2 }) catch unreachable; \\ live_fn2(); \\} - ); + , + }); exe.addObject(obj); exe.link_gc_sections = true; @@ -1143,7 +1228,7 @@ fn testGcSectionsZig(b: *Build, opts: Options) *Step { fn testHiddenWeakUndef(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "hidden-weak-undef", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\__attribute__((weak, visibility("hidden"))) void foo(); \\void bar() { foo(); } @@ -1162,7 +1247,7 @@ fn testHiddenWeakUndef(b: *Build, opts: Options) *Step { fn testIFuncAlias(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-alias", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\void foo() {} @@ -1173,7 +1258,7 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step { \\ assert(bar == bar2); \\} , &.{}); - exe.force_pic = true; + exe.root_module.pic = true; exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -1188,7 +1273,7 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step { fn testIFuncDlopen(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-dlopen", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\__attribute__((ifunc("resolve_foo"))) \\void foo(void); @@ -1200,7 +1285,7 @@ fn testIFuncDlopen(b: *Build, opts: Options) *Step { \\} , &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\#include @@ -1219,7 +1304,7 @@ fn testIFuncDlopen(b: *Build, opts: Options) *Step { exe.linkLibrary(dso); exe.linkLibC(); exe.linkSystemLibrary2("dl", .{}); - exe.force_pic = false; + exe.root_module.pic = false; exe.pie = false; const run = addRunArtifact(exe); @@ -1232,7 +1317,7 @@ fn testIFuncDlopen(b: *Build, opts: Options) *Step { fn testIFuncDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-dso", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\#include \\__attribute__((ifunc("resolve_foobar"))) @@ -1247,7 +1332,7 @@ fn testIFuncDso(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\void foobar(void); \\int main() { @@ -1283,7 +1368,7 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step { ; { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, main_c, &.{}); exe.linkLibC(); exe.link_z_lazy = true; @@ -1295,7 +1380,7 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step { test_step.dependOn(&run.step); } { - const exe = addExecutable(b, "other", opts); + const exe = addExecutable(b, opts, .{ .name = "other" }); addCSourceBytes(exe, main_c, &.{}); exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 @@ -1312,7 +1397,7 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step { fn testIFuncExport(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-export", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\#include \\__attribute__((ifunc("resolve_foobar"))) @@ -1338,7 +1423,7 @@ fn testIFuncExport(b: *Build, opts: Options) *Step { fn testIFuncFuncPtr(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-func-ptr", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\typedef int Fn(); \\int foo() __attribute__((ifunc("resolve_foo"))); @@ -1361,7 +1446,7 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step { \\ printf("%d\n", f()); \\} , &.{}); - exe.force_pic = true; + exe.root_module.pic = true; exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -1376,7 +1461,7 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step { fn testIFuncNoPlt(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-noplt", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\__attribute__((ifunc("resolve_foo"))) @@ -1392,7 +1477,7 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step { \\ foo(); \\} , &.{"-fno-plt"}); - exe.force_pic = true; + exe.root_module.pic = true; exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -1407,7 +1492,7 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step { fn testIFuncStatic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-static", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\void foo() __attribute__((ifunc("resolve_foo"))); @@ -1435,7 +1520,7 @@ fn testIFuncStatic(b: *Build, opts: Options) *Step { fn testIFuncStaticPie(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-static-pie", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\void foo() __attribute__((ifunc("resolve_foo"))); @@ -1451,7 +1536,7 @@ fn testIFuncStaticPie(b: *Build, opts: Options) *Step { \\} , &.{}); exe.linkage = .static; - exe.force_pic = true; + exe.root_module.pic = true; exe.pie = true; exe.linkLibC(); @@ -1478,7 +1563,7 @@ fn testImageBase(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "image-base", opts); { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); addCSourceBytes(exe, \\#include \\int main() { @@ -1502,7 +1587,7 @@ fn testImageBase(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); addCSourceBytes(exe, "void _start() {}", &.{}); exe.image_base = 0xffffffff8000000; @@ -1520,22 +1605,26 @@ fn testImageBase(b: *Build, opts: Options) *Step { fn testImportingDataDynamic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "importing-data-dynamic", opts); - const dso = addSharedLibrary(b, "a", .{ + const dso = addSharedLibrary(b, .{ .target = opts.target, .optimize = opts.optimize, .use_llvm = true, + }, .{ + .name = "a", + .c_source_bytes = "int foo = 42;", }); - addCSourceBytes(dso, "int foo = 42;", &.{}); - const main = addExecutable(b, "main", opts); - addZigSourceBytes(main, + const main = addExecutable(b, opts, .{ + .name = "main", + .zig_source_bytes = \\extern var foo: i32; \\pub fn main() void { \\ @import("std").debug.print("{d}\n", .{foo}); \\} - ); + , + .strip = true, // TODO temp hack + }); main.pie = true; - main.strip = true; // TODO temp hack main.linkLibrary(dso); main.linkLibC(); @@ -1549,28 +1638,34 @@ fn testImportingDataDynamic(b: *Build, opts: Options) *Step { fn testImportingDataStatic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "importing-data-static", opts); - const obj = addObject(b, "a", .{ + const obj = addObject(b, .{ .target = opts.target, .optimize = opts.optimize, .use_llvm = true, + }, .{ + .name = "a", + .c_source_bytes = "int foo = 42;", }); - addCSourceBytes(obj, "int foo = 42;", &.{}); - const lib = addStaticLibrary(b, "a", .{ + const lib = addStaticLibrary(b, .{ .target = opts.target, .optimize = opts.optimize, .use_llvm = true, + }, .{ + .name = "a", }); lib.addObject(obj); - const main = addExecutable(b, "main", opts); - addZigSourceBytes(main, + const main = addExecutable(b, opts, .{ + .name = "main", + .zig_source_bytes = \\extern var foo: i32; \\pub fn main() void { \\ @import("std").debug.print("{d}\n", .{foo}); \\} - ); - main.strip = true; // TODO temp hack + , + .strip = true, // TODO temp hack + }); main.linkLibrary(lib); main.linkLibC(); @@ -1584,63 +1679,76 @@ fn testImportingDataStatic(b: *Build, opts: Options) *Step { fn testInitArrayOrder(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "init-array-order", opts); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\__attribute__((constructor(10000))) void init4() { printf("1"); } - , &.{}); + , + }); a_o.linkLibC(); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\#include \\__attribute__((constructor(1000))) void init3() { printf("2"); } - , &.{}); + , + }); b_o.linkLibC(); - const c_o = addObject(b, "c", opts); - addCSourceBytes(c_o, + const c_o = addObject(b, opts, .{ + .name = "c", + .c_source_bytes = \\#include \\__attribute__((constructor)) void init1() { printf("3"); } - , &.{}); + , + }); c_o.linkLibC(); - const d_o = addObject(b, "d", opts); - addCSourceBytes(d_o, + const d_o = addObject(b, opts, .{ + .name = "d", + .c_source_bytes = \\#include \\__attribute__((constructor)) void init2() { printf("4"); } - , &.{}); + , + }); d_o.linkLibC(); - const e_o = addObject(b, "e", opts); - addCSourceBytes(e_o, + const e_o = addObject(b, opts, .{ + .name = "e", + .c_source_bytes = \\#include \\__attribute__((destructor(10000))) void fini4() { printf("5"); } - , &.{}); + , + }); e_o.linkLibC(); - const f_o = addObject(b, "f", opts); - addCSourceBytes(f_o, + const f_o = addObject(b, opts, .{ + .name = "f", + .c_source_bytes = \\#include \\__attribute__((destructor(1000))) void fini3() { printf("6"); } - , &.{}); + , + }); f_o.linkLibC(); - const g_o = addObject(b, "g", opts); - addCSourceBytes(g_o, + const g_o = addObject(b, opts, .{ + .name = "g", + .c_source_bytes = \\#include \\__attribute__((destructor)) void fini1() { printf("7"); } - , &.{}); + , + }); g_o.linkLibC(); - const h_o = addObject(b, "h", opts); - addCSourceBytes(h_o, - \\#include - \\__attribute__((destructor)) void fini2() { printf("8"); } - , &.{}); + const h_o = addObject(b, opts, .{ .name = "h", .c_source_bytes = + \\#include + \\__attribute__((destructor)) void fini2() { printf("8"); } + }); h_o.linkLibC(); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, "int main() { return 0; }", &.{}); exe.addObject(a_o); exe.addObject(b_o); @@ -1651,7 +1759,7 @@ fn testInitArrayOrder(b: *Build, opts: Options) *Step { exe.addObject(g_o); exe.addObject(h_o); - if (opts.target.isGnuLibC()) { + if (opts.target.target.isGnuLibC()) { // TODO I think we need to clarify our use of `-fPIC -fPIE` flags for different targets exe.pie = true; } @@ -1666,7 +1774,7 @@ fn testInitArrayOrder(b: *Build, opts: Options) *Step { fn testLargeAlignmentDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "large-alignment-dso", opts); - const dso = addSharedLibrary(b, "dso", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "dso" }); addCSourceBytes(dso, \\#include \\#include @@ -1695,7 +1803,7 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step { check.checkComputeCompare("addr2 16 %", .{ .op = .eq, .value = .{ .literal = 0 } }); test_step.dependOn(&check.step); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, \\void greet(); \\int main() { greet(); } @@ -1715,7 +1823,7 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step { fn testLargeAlignmentExe(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "large-alignment-exe", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, \\#include \\#include @@ -1760,7 +1868,7 @@ fn testLargeAlignmentExe(b: *Build, opts: Options) *Step { fn testLargeBss(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "large-bss", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\char arr[0x100000000]; \\int main() { @@ -1781,27 +1889,31 @@ fn testLargeBss(b: *Build, opts: Options) *Step { fn testLinkOrder(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "link-order", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, "void foo() {}", &.{}); - obj.force_pic = true; + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = "void foo() {}", + .pic = true, + }); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(obj); - const lib = addStaticLibrary(b, "b", opts); + const lib = addStaticLibrary(b, opts, .{ .name = "b" }); lib.addObject(obj); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\void foo(); \\int main() { \\ foo(); \\} - , &.{}); + , + }); // https://github.com/ziglang/zig/issues/17450 // { - // const exe = addExecutable(b, "main1", opts); + // const exe = addExecutable(b, opts, .{ .name = "main1"}); // exe.addObject(main_o); // exe.linkSystemLibrary2("a", .{}); // exe.addLibraryPath(dso.getEmittedBinDirectory()); @@ -1818,7 +1930,7 @@ fn testLinkOrder(b: *Build, opts: Options) *Step { // } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(main_o); exe.linkSystemLibrary2("b", .{}); exe.addLibraryPath(lib.getEmittedBinDirectory()); @@ -1840,14 +1952,14 @@ fn testLinkOrder(b: *Build, opts: Options) *Step { fn testLdScript(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ld-script", opts); - const dso = addSharedLibrary(b, "bar", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "bar" }); addCSourceBytes(dso, "int foo() { return 42; }", &.{}); const scripts = WriteFile.create(b); _ = scripts.add("liba.so", "INPUT(libfoo.so)"); _ = scripts.add("libfoo.so", "GROUP(AS_NEEDED(-lbar))"); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\int foo(); \\int main() { @@ -1875,7 +1987,7 @@ fn testLdScriptPathError(b: *Build, opts: Options) *Step { const scripts = WriteFile.create(b); _ = scripts.add("liba.so", "INPUT(libfoo.so)"); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, "int main() { return 0; }", &.{}); exe.linkSystemLibrary2("a", .{}); exe.addLibraryPath(scripts.getDirectory()); @@ -1895,13 +2007,15 @@ fn testLdScriptPathError(b: *Build, opts: Options) *Step { fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "mismatched-cpu-architecture-error", opts); - const obj = addObject(b, "a", .{ - .target = .{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .gnu }, + const obj = addObject(b, .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .gnu }), + }, .{ + .name = "a", + .c_source_bytes = "int foo;", + .strip = true, }); - addCSourceBytes(obj, "int foo;", &.{}); - obj.strip = true; - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\extern int foo; \\int main() { @@ -1922,7 +2036,7 @@ fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step { fn testLinkingC(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "linking-c", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, \\#include \\int main() { @@ -1951,7 +2065,7 @@ fn testLinkingC(b: *Build, opts: Options) *Step { fn testLinkingCpp(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "linking-cpp", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCppSourceBytes(exe, \\#include \\int main() { @@ -1981,24 +2095,28 @@ fn testLinkingCpp(b: *Build, opts: Options) *Step { fn testLinkingObj(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "linking-obj", opts); - const obj = addObject(b, "aobj", opts); - addZigSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "aobj", + .zig_source_bytes = \\extern var mod: usize; \\export fn callMe() usize { \\ return me * mod; \\} \\var me: usize = 42; - ); + , + }); - const exe = addExecutable(b, "testobj", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "testobj", + .zig_source_bytes = \\const std = @import("std"); \\extern fn callMe() usize; \\export var mod: usize = 2; \\pub fn main() void { \\ std.debug.print("{d}\n", .{callMe()}); \\} - ); + , + }); exe.addObject(obj); const run = addRunArtifact(exe); @@ -2011,26 +2129,32 @@ fn testLinkingObj(b: *Build, opts: Options) *Step { fn testLinkingStaticLib(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "linking-static-lib", opts); - const obj = addObject(b, "bobj", opts); - addZigSourceBytes(obj, "export var bar: i32 = -42;"); + const obj = addObject(b, opts, .{ + .name = "bobj", + .zig_source_bytes = "export var bar: i32 = -42;", + }); - const lib = addStaticLibrary(b, "alib", opts); - addZigSourceBytes(lib, + const lib = addStaticLibrary(b, opts, .{ + .name = "alib", + .zig_source_bytes = \\export fn foo() i32 { \\ return 42; \\} - ); + , + }); lib.addObject(obj); - const exe = addExecutable(b, "testlib", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "testlib", + .zig_source_bytes = \\const std = @import("std"); \\extern fn foo() i32; \\extern var bar: i32; \\pub fn main() void { \\ std.debug.print("{d}\n", .{foo() + bar}); \\} - ); + , + }); exe.linkLibrary(lib); const run = addRunArtifact(exe); @@ -2043,12 +2167,14 @@ fn testLinkingStaticLib(b: *Build, opts: Options) *Step { fn testLinkingZig(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "linking-zig-static", opts); - const exe = addExecutable(b, "test", opts); - addZigSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "test", + .zig_source_bytes = \\pub fn main() void { \\ @import("std").debug.print("Hello World!\n", .{}); \\} - ); + , + }); const run = addRunArtifact(exe); run.expectStdErrEqual("Hello World!\n"); @@ -2069,7 +2195,7 @@ fn testLinkingZig(b: *Build, opts: Options) *Step { fn testNoEhFrameHdr(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "no-eh-frame-hdr", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, "int main() { return 0; }", &.{}); exe.link_eh_frame_hdr = false; exe.linkLibC(); @@ -2086,7 +2212,7 @@ fn testNoEhFrameHdr(b: *Build, opts: Options) *Step { fn testPie(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "hello-pie", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\int main() { @@ -2095,7 +2221,7 @@ fn testPie(b: *Build, opts: Options) *Step { \\} , &.{}); exe.linkLibC(); - exe.force_pic = true; + exe.root_module.pic = true; exe.pie = true; const run = addRunArtifact(exe); @@ -2117,7 +2243,7 @@ fn testPie(b: *Build, opts: Options) *Step { fn testPltGot(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "plt-got", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\#include \\void ignore(void *foo) {} @@ -2127,7 +2253,7 @@ fn testPltGot(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\void ignore(void *); \\int hello(); @@ -2135,7 +2261,7 @@ fn testPltGot(b: *Build, opts: Options) *Step { \\int main() { hello(); } , &.{}); exe.linkLibrary(dso); - exe.force_pic = true; + exe.root_module.pic = true; exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -2151,10 +2277,12 @@ fn testPreinitArray(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "preinit-array", opts); { - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, "void _start() {}", &.{}); + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = "void _start() {}", + }); - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(obj); const check = exe.checkObject(); @@ -2163,7 +2291,7 @@ fn testPreinitArray(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); addCSourceBytes(exe, \\void preinit_fn() {} \\int main() {} @@ -2183,38 +2311,48 @@ fn testPreinitArray(b: *Build, opts: Options) *Step { fn testRelocatableArchive(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "relocatable-archive", opts); - const obj1 = addObject(b, "obj1", opts); - addCSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .c_source_bytes = \\void bar(); \\void foo() { \\ bar(); \\} - , &.{}); + , + }); - const obj2 = addObject(b, "obj2", opts); - addCSourceBytes(obj2, + const obj2 = addObject(b, opts, .{ + .name = "obj2", + .c_source_bytes = \\void bar() {} - , &.{}); + , + }); - const obj3 = addObject(b, "obj3", opts); - addCSourceBytes(obj3, + const obj3 = addObject(b, opts, .{ + .name = "obj3", + .c_source_bytes = \\void baz(); - , &.{}); + , + }); - const obj4 = addObject(b, "obj4", opts); - addCSourceBytes(obj4, + const obj4 = addObject(b, opts, .{ + .name = "obj4", + .c_source_bytes = \\void foo(); \\int main() { \\ foo(); \\} - , &.{}); + , + }); - const lib = addStaticLibrary(b, "lib", opts); + const lib = addStaticLibrary(b, opts, .{ .name = "lib" }); lib.addObject(obj1); lib.addObject(obj2); lib.addObject(obj3); - const obj5 = addObject(b, "obj5", opts); + const obj5 = addObject(b, opts, .{ + .name = "obj5", + }); obj5.addObject(obj4); obj5.linkLibrary(lib); @@ -2234,13 +2372,15 @@ fn testRelocatableEhFrame(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "relocatable-eh-frame", opts); { - const obj = addObject(b, "obj1", opts); - addCppSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj1", + .cpp_source_bytes = \\#include \\int try_me() { \\ throw std::runtime_error("Oh no!"); \\} - , &.{}); + , + }); addCppSourceBytes(obj, \\extern int try_me(); \\int try_again() { @@ -2249,7 +2389,7 @@ fn testRelocatableEhFrame(b: *Build, opts: Options) *Step { , &.{}); obj.linkLibCpp(); - const exe = addExecutable(b, "test1", opts); + const exe = addExecutable(b, opts, .{ .name = "test1" }); addCppSourceBytes(exe, \\#include \\#include @@ -2273,13 +2413,15 @@ fn testRelocatableEhFrame(b: *Build, opts: Options) *Step { { // Let's make the object file COMDAT group heavy! - const obj = addObject(b, "obj2", opts); - addCppSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj2", + .cpp_source_bytes = \\#include \\int try_me() { \\ throw std::runtime_error("Oh no!"); \\} - , &.{}); + , + }); addCppSourceBytes(obj, \\extern int try_me(); \\int try_again() { @@ -2301,7 +2443,7 @@ fn testRelocatableEhFrame(b: *Build, opts: Options) *Step { , &.{}); obj.linkLibCpp(); - const exe = addExecutable(b, "test2", opts); + const exe = addExecutable(b, opts, .{ .name = "test2" }); exe.addObject(obj); exe.linkLibCpp(); @@ -2316,13 +2458,18 @@ fn testRelocatableEhFrame(b: *Build, opts: Options) *Step { fn testRelocatableNoEhFrame(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "relocatable-no-eh-frame", opts); - const obj1 = addObject(b, "obj1", opts); - addCSourceBytes(obj1, "int bar() { return 42; }", &.{ - "-fno-unwind-tables", - "-fno-asynchronous-unwind-tables", + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .c_source_bytes = "int bar() { return 42; }", + .c_source_flags = &.{ + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + }, }); - const obj2 = addObject(b, "obj2", opts); + const obj2 = addObject(b, opts, .{ + .name = "obj2", + }); obj2.addObject(obj1); const check1 = obj1.checkObject(); @@ -2343,23 +2490,25 @@ fn testRelocatableNoEhFrame(b: *Build, opts: Options) *Step { fn testSharedAbsSymbol(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "shared-abs-symbol", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addAsmSourceBytes(dso, \\.globl foo \\foo = 3; ); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\#include \\extern char foo; \\int main() { printf("foo=%p\n", &foo); } - , &.{}); - obj.force_pic = true; + , + .pic = true, + }); obj.linkLibC(); { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(obj); exe.linkLibrary(dso); exe.pie = true; @@ -2380,7 +2529,7 @@ fn testSharedAbsSymbol(b: *Build, opts: Options) *Step { // https://github.com/ziglang/zig/issues/17430 // { - // const exe = addExecutable(b, "main2", opts); + // const exe = addExecutable(b, opts, .{ .name = "main2"}); // exe.addObject(obj); // exe.linkLibrary(dso); // exe.pie = false; @@ -2405,20 +2554,22 @@ fn testSharedAbsSymbol(b: *Build, opts: Options) *Step { fn testStrip(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "strip", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\#include \\int main() { \\ printf("Hello!\n"); \\ return 0; \\} - , &.{}); + , + }); obj.linkLibC(); { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(obj); - exe.strip = false; + exe.root_module.strip = false; exe.linkLibC(); const check = exe.checkObject(); @@ -2429,9 +2580,9 @@ fn testStrip(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(obj); - exe.strip = true; + exe.root_module.strip = true; exe.linkLibC(); const check = exe.checkObject(); @@ -2447,16 +2598,19 @@ fn testStrip(b: *Build, opts: Options) *Step { fn testTlsDfStaticTls(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-df-static-tls", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\static _Thread_local int foo = 5; \\void mutate() { ++foo; } \\int bar() { return foo; } - , &.{"-ftls-model=initial-exec"}); - obj.force_pic = true; + , + .c_source_flags = &.{"-ftls-model=initial-exec"}, + .pic = true, + }); { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(obj); // dso.link_relax = true; @@ -2468,7 +2622,7 @@ fn testTlsDfStaticTls(b: *Build, opts: Options) *Step { // TODO add -Wl,--no-relax // { - // const dso = addSharedLibrary(b, "a", opts); + // const dso = addSharedLibrary(b, opts, .{ .name = "a"}); // dso.addObject(obj); // dso.link_relax = false; @@ -2484,7 +2638,7 @@ fn testTlsDfStaticTls(b: *Build, opts: Options) *Step { fn testTlsDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-dso", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\extern _Thread_local int foo; \\_Thread_local int bar; @@ -2492,7 +2646,7 @@ fn testTlsDso(b: *Build, opts: Options) *Step { \\int get_bar1() { return bar; } , &.{}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\_Thread_local int foo; @@ -2526,8 +2680,9 @@ fn testTlsDso(b: *Build, opts: Options) *Step { fn testTlsGd(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-gd", opts); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x1 = 1; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x2; @@ -2540,37 +2695,42 @@ fn testTlsGd(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d %d %d\n", x1, x2, x3, x4, get_x5(), get_x6()); \\ return 0; \\} - , &.{}); + , + .pic = true, + }); main_o.linkLibC(); - main_o.force_pic = true; - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x3 = 3; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x5 = 5; \\int get_x5() { return x5; } - , &.{}); - a_o.force_pic = true; + , + .pic = true, + }); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x4 = 4; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x6 = 6; \\int get_x6() { return x6; } - , &.{}); - b_o.force_pic = true; + , + .pic = true, + }); const exp_stdout = "1 2 3 4 5 6\n"; - const dso1 = addSharedLibrary(b, "a", opts); + const dso1 = addSharedLibrary(b, opts, .{ .name = "a" }); dso1.addObject(a_o); - const dso2 = addSharedLibrary(b, "b", opts); + const dso2 = addSharedLibrary(b, opts, .{ .name = "b" }); dso2.addObject(b_o); // dso2.link_relax = false; // TODO { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(main_o); exe.linkLibrary(dso1); exe.linkLibrary(dso2); @@ -2581,7 +2741,7 @@ fn testTlsGd(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(main_o); // exe.link_relax = false; // TODO exe.linkLibrary(dso1); @@ -2594,7 +2754,7 @@ fn testTlsGd(b: *Build, opts: Options) *Step { // https://github.com/ziglang/zig/issues/17430 ?? // { - // const exe = addExecutable(b, "main3", opts); + // const exe = addExecutable(b, opts, .{ .name = "main3"}); // exe.addObject(main_o); // exe.linkLibrary(dso1); // exe.linkLibrary(dso2); @@ -2606,7 +2766,7 @@ fn testTlsGd(b: *Build, opts: Options) *Step { // } // { - // const exe = addExecutable(b, "main4", opts); + // const exe = addExecutable(b, opts, .{ .name = "main4"}); // exe.addObject(main_o); // // exe.link_relax = false; // TODO // exe.linkLibrary(dso1); @@ -2624,8 +2784,9 @@ fn testTlsGd(b: *Build, opts: Options) *Step { fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-gd-no-plt", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\#include \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x1 = 1; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x2; @@ -2639,18 +2800,20 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d %d %d\n", x1, x2, x3, x4, get_x5(), get_x6()); \\ return 0; \\} - , &.{"-fno-plt"}); - obj.force_pic = true; + , + .c_source_flags = &.{"-fno-plt"}, + .pic = true, + }); obj.linkLibC(); - const a_so = addSharedLibrary(b, "a", opts); + const a_so = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(a_so, \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x3 = 3; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x5 = 5; \\int get_x5() { return x5; } , &.{"-fno-plt"}); - const b_so = addSharedLibrary(b, "b", opts); + const b_so = addSharedLibrary(b, opts, .{ .name = "b" }); addCSourceBytes(b_so, \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x4 = 4; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x6 = 6; @@ -2659,7 +2822,7 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { // b_so.link_relax = false; // TODO { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(obj); exe.linkLibrary(a_so); exe.linkLibrary(b_so); @@ -2673,7 +2836,7 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(obj); exe.linkLibrary(a_so); exe.linkLibrary(b_so); @@ -2693,8 +2856,9 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { fn testTlsGdToIe(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-gd-to-ie", opts); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x1 = 1; \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x2 = 2; @@ -2705,22 +2869,25 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { \\ printf("%d %d %d\n", x1, x2, x3); \\ return 0; \\} - , &.{}); + , + .pic = true, + }); a_o.linkLibC(); - a_o.force_pic = true; - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\int foo(); \\int main() { foo(); } - , &.{}); - b_o.force_pic = true; + , + .pic = true, + }); { - const dso = addSharedLibrary(b, "a1", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a1" }); dso.addObject(a_o); - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(b_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -2733,11 +2900,11 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { } { - const dso = addSharedLibrary(b, "a2", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a2" }); dso.addObject(a_o); // dso.link_relax = false; // TODO - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(b_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -2750,11 +2917,11 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { } // { - // const dso = addSharedLibrary(b, "a", opts); + // const dso = addSharedLibrary(b, opts, .{ .name = "a"}); // dso.addObject(a_o); // dso.link_z_nodlopen = true; - // const exe = addExecutable(b, "main", opts); + // const exe = addExecutable(b, opts, .{ .name = "main"}); // exe.addObject(b_o); // exe.linkLibrary(dso); @@ -2764,12 +2931,12 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { // } // { - // const dso = addSharedLibrary(b, "a", opts); + // const dso = addSharedLibrary(b, opts, .{ .name = "a"}); // dso.addObject(a_o); // dso.link_relax = false; // dso.link_z_nodlopen = true; - // const exe = addExecutable(b, "main", opts); + // const exe = addExecutable(b, opts, .{ .name = "main"}); // exe.addObject(b_o); // exe.linkLibrary(dso); @@ -2784,7 +2951,7 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { fn testTlsIe(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-ie", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\#include \\__attribute__((tls_model("initial-exec"))) static _Thread_local int foo; @@ -2799,8 +2966,9 @@ fn testTlsIe(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\_Thread_local int baz; \\void set(); @@ -2812,13 +2980,14 @@ fn testTlsIe(b: *Build, opts: Options) *Step { \\ print(); \\ printf("%d\n", baz); \\} - , &.{}); + , + }); main_o.linkLibC(); const exp_stdout = "0 0 3 5 7\n"; { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(main_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -2831,7 +3000,7 @@ fn testTlsIe(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(main_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -2850,38 +3019,46 @@ fn testTlsIe(b: *Build, opts: Options) *Step { fn testTlsLargeAlignment(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-large-alignment", opts); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\__attribute__((section(".tdata1"))) \\_Thread_local int x = 42; - , &.{"-std=c11"}); - a_o.force_pic = true; + , + .c_source_flags = &.{"-std=c11"}, + .pic = true, + }); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\__attribute__((section(".tdata2"))) \\_Alignas(256) _Thread_local int y[] = { 1, 2, 3 }; - , &.{"-std=c11"}); - b_o.force_pic = true; + , + .c_source_flags = &.{"-std=c11"}, + .pic = true, + }); - const c_o = addObject(b, "c", opts); - addCSourceBytes(c_o, + const c_o = addObject(b, opts, .{ + .name = "c", + .c_source_bytes = \\#include \\extern _Thread_local int x; \\extern _Thread_local int y[]; \\int main() { \\ printf("%d %d %d %d\n", x, y[0], y[1], y[2]); \\} - , &.{}); - c_o.force_pic = true; + , + .pic = true, + }); c_o.linkLibC(); { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(a_o); dso.addObject(b_o); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(c_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -2894,7 +3071,7 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(a_o); exe.addObject(b_o); exe.addObject(c_o); @@ -2913,7 +3090,7 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step { fn testTlsLargeTbss(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-large-tbss", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addAsmSourceBytes(exe, \\.globl x, y \\.section .tbss,"awT",@nobits @@ -2947,7 +3124,7 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-large-static-image", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, "_Thread_local int x[] = { 1, 2, 3, [10000] = 5 };", &.{}); addCSourceBytes(exe, \\#include @@ -2956,7 +3133,7 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d %d\n", x[0], x[1], x[2], x[3], x[10000]); \\} , &.{}); - exe.force_pic = true; + exe.root_module.pic = true; exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -2971,8 +3148,9 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step { fn testTlsLd(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-ld", opts); - const main_o = addObject(b, "main", opts); - addCSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .c_source_bytes = \\#include \\extern _Thread_local int foo; \\static _Thread_local int bar; @@ -2983,18 +3161,23 @@ fn testTlsLd(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar); \\ return 0; \\} - , &.{"-ftls-model=local-dynamic"}); - main_o.force_pic = true; + , + .c_source_flags = &.{"-ftls-model=local-dynamic"}, + .pic = true, + }); main_o.linkLibC(); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, "_Thread_local int foo = 3;", &.{"-ftls-model=local-dynamic"}); - a_o.force_pic = true; + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = "_Thread_local int foo = 3;", + .c_source_flags = &.{"-ftls-model=local-dynamic"}, + .pic = true, + }); const exp_stdout = "3 5 3 5\n"; { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(main_o); exe.addObject(a_o); exe.linkLibC(); @@ -3007,7 +3190,7 @@ fn testTlsLd(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(main_o); exe.addObject(a_o); exe.linkLibC(); @@ -3026,14 +3209,14 @@ fn testTlsLd(b: *Build, opts: Options) *Step { fn testTlsLdDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-ld-dso", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\static _Thread_local int def, def1; \\int f0() { return ++def; } \\int f1() { return ++def1 + def; } , &.{"-ftls-model=local-dynamic"}); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\extern int f0(); @@ -3060,8 +3243,9 @@ fn testTlsLdDso(b: *Build, opts: Options) *Step { fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-ld-no-plt", opts); - const a_o = addObject(b, "a", opts); - addCSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\extern _Thread_local int foo; \\static _Thread_local int bar; @@ -3073,16 +3257,21 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar); \\ return 0; \\} - , &.{ "-ftls-model=local-dynamic", "-fno-plt" }); + , + .c_source_flags = &.{ "-ftls-model=local-dynamic", "-fno-plt" }, + .pic = true, + }); a_o.linkLibC(); - a_o.force_pic = true; - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, "_Thread_local int foo = 3;", &.{ "-ftls-model=local-dynamic", "-fno-plt" }); - b_o.force_pic = true; + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = "_Thread_local int foo = 3;", + .c_source_flags = &.{ "-ftls-model=local-dynamic", "-fno-plt" }, + .pic = true, + }); { - const exe = addExecutable(b, "main1", opts); + const exe = addExecutable(b, opts, .{ .name = "main1" }); exe.addObject(a_o); exe.addObject(b_o); exe.linkLibC(); @@ -3095,7 +3284,7 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main2", opts); + const exe = addExecutable(b, opts, .{ .name = "main2" }); exe.addObject(a_o); exe.addObject(b_o); exe.linkLibC(); @@ -3114,7 +3303,7 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { fn testTlsNoPic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-no-pic", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int foo; @@ -3132,7 +3321,7 @@ fn testTlsNoPic(b: *Build, opts: Options) *Step { addCSourceBytes(exe, \\__attribute__((tls_model("global-dynamic"))) _Thread_local int foo; , &.{}); - exe.force_pic = false; + exe.root_module.pic = false; exe.linkLibC(); const run = addRunArtifact(exe); @@ -3145,7 +3334,7 @@ fn testTlsNoPic(b: *Build, opts: Options) *Step { fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-offset-alignment", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\#include \\#include @@ -3163,7 +3352,7 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step { , &.{}); dso.linkLibC(); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\#include @@ -3186,7 +3375,7 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step { , &.{}); exe.addRPath(dso.getEmittedBinDirectory()); exe.linkLibC(); - exe.force_pic = true; + exe.root_module.pic = true; // https://github.com/ziglang/zig/issues/17619 exe.pie = true; @@ -3200,8 +3389,9 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step { fn testTlsPic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-pic", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\#include \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int foo; \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int bar; @@ -3213,11 +3403,12 @@ fn testTlsPic(b: *Build, opts: Options) *Step { \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar); \\ return 0; \\} - , &.{}); + , + .pic = true, + }); obj.linkLibC(); - obj.force_pic = true; - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\__attribute__((tls_model("global-dynamic"))) _Thread_local int foo = 3; , &.{}); @@ -3236,30 +3427,38 @@ fn testTlsPic(b: *Build, opts: Options) *Step { fn testTlsSmallAlignment(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-small-alignment", opts); - const a_o = addObject(b, "a", opts); - addAsmSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .asm_source_bytes = \\.text \\.byte 0 - ); - a_o.force_pic = true; + \\ + , + .pic = true, + }); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, "_Thread_local char x = 42;", &.{"-std=c11"}); - b_o.force_pic = true; + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = "_Thread_local char x = 42;", + .c_source_flags = &.{"-std=c11"}, + .pic = true, + }); - const c_o = addObject(b, "c", opts); - addCSourceBytes(c_o, + const c_o = addObject(b, opts, .{ + .name = "c", + .c_source_bytes = \\#include \\extern _Thread_local char x; \\int main() { \\ printf("%d\n", x); \\} - , &.{}); + , + .pic = true, + }); c_o.linkLibC(); - c_o.force_pic = true; { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(a_o); exe.addObject(b_o); exe.addObject(c_o); @@ -3273,11 +3472,11 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step { } { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(a_o); dso.addObject(b_o); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(c_o); exe.linkLibrary(dso); exe.linkLibC(); @@ -3295,7 +3494,7 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step { fn testTlsStatic(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "tls-static", opts); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); addCSourceBytes(exe, \\#include \\_Thread_local int a = 10; @@ -3326,12 +3525,14 @@ fn testTlsStatic(b: *Build, opts: Options) *Step { fn testUnknownFileTypeError(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "unknown-file-type-error", opts); - const dylib = addSharedLibrary(b, "a", .{ - .target = .{ .cpu_arch = .x86_64, .os_tag = .macos }, + const dylib = addSharedLibrary(b, .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .macos }), + }, .{ + .name = "a", + .zig_source_bytes = "export var foo: i32 = 0;", }); - addZigSourceBytes(dylib, "export var foo: i32 = 0;"); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\extern int foo; \\int main() { @@ -3354,28 +3555,34 @@ fn testUnknownFileTypeError(b: *Build, opts: Options) *Step { fn testUnresolvedError(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "unresolved-error", opts); - const obj1 = addObject(b, "a", opts); - addCSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\int foo(); \\int bar() { \\ return foo() + 1; \\} - , &.{"-ffunction-sections"}); + , + .c_source_flags = &.{"-ffunction-sections"}, + }); obj1.linkLibC(); - const obj2 = addObject(b, "b", opts); - addCSourceBytes(obj2, + const obj2 = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\#include \\int foo(); \\int bar(); \\int main() { \\ return foo() + bar(); \\} - , &.{"-ffunction-sections"}); + , + .c_source_flags = &.{"-ffunction-sections"}, + }); obj2.linkLibC(); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(obj1); exe.addObject(obj2); exe.linkLibC(); @@ -3392,19 +3599,21 @@ fn testUnresolvedError(b: *Build, opts: Options) *Step { fn testWeakExports(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "weak-exports", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = \\#include \\__attribute__((weak)) int foo(); \\int main() { \\ printf("%d\n", foo ? foo() : 3); \\} - , &.{}); + , + .pic = true, + }); obj.linkLibC(); - obj.force_pic = true; { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(obj); dso.linkLibC(); @@ -3415,7 +3624,7 @@ fn testWeakExports(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); exe.addObject(obj); exe.linkLibC(); // https://github.com/ziglang/zig/issues/17619 @@ -3437,14 +3646,14 @@ fn testWeakExports(b: *Build, opts: Options) *Step { fn testWeakUndefsDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "weak-undef-dso", opts); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); addCSourceBytes(dso, \\__attribute__((weak)) int foo(); \\int bar() { return foo ? foo() : -1; } , &.{}); { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\int bar(); @@ -3461,7 +3670,7 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step { } { - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\int foo() { return 5; } @@ -3484,12 +3693,14 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step { fn testZNow(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "z-now", opts); - const obj = addObject(b, "obj", opts); - addCSourceBytes(obj, "int main() { return 0; }", &.{}); - obj.force_pic = true; + const obj = addObject(b, opts, .{ + .name = "obj", + .c_source_bytes = "int main() { return 0; }", + .pic = true, + }); { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(obj); const check = dso.checkObject(); @@ -3499,7 +3710,7 @@ fn testZNow(b: *Build, opts: Options) *Step { } { - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(obj); dso.link_z_lazy = true; @@ -3515,7 +3726,7 @@ fn testZNow(b: *Build, opts: Options) *Step { fn testZStackSize(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "z-stack-size", opts); - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, "int main() { return 0; }", &.{}); exe.stack_size = 0x800000; exe.linkLibC(); @@ -3540,8 +3751,9 @@ fn testZText(b: *Build, opts: Options) *Step { // musl supports only a very limited number of text relocations and only in DSOs (and // rightly so!). - const a_o = addObject(b, "a", opts); - addAsmSourceBytes(a_o, + const a_o = addObject(b, opts, .{ + .name = "a", + .asm_source_bytes = \\.globl fn1 \\fn1: \\ sub $8, %rsp @@ -3549,10 +3761,13 @@ fn testZText(b: *Build, opts: Options) *Step { \\ call *%rax \\ add $8, %rsp \\ ret - ); + \\ + , + }); - const b_o = addObject(b, "b", opts); - addCSourceBytes(b_o, + const b_o = addObject(b, opts, .{ + .name = "b", + .c_source_bytes = \\int fn1(); \\int fn2() { \\ return 3; @@ -3561,15 +3776,16 @@ fn testZText(b: *Build, opts: Options) *Step { \\int fnn() { \\ return fn1(); \\} - , &.{}); - b_o.force_pic = true; + , + .pic = true, + }); - const dso = addSharedLibrary(b, "a", opts); + const dso = addSharedLibrary(b, opts, .{ .name = "a" }); dso.addObject(a_o); dso.addObject(b_o); dso.link_z_notext = true; - const exe = addExecutable(b, "main", opts); + const exe = addExecutable(b, opts, .{ .name = "main" }); addCSourceBytes(exe, \\#include \\int fnn(); @@ -3608,7 +3824,6 @@ const addObject = link.addObject; const addRunArtifact = link.addRunArtifact; const addSharedLibrary = link.addSharedLibrary; const addStaticLibrary = link.addStaticLibrary; -const addZigSourceBytes = link.addZigSourceBytes; const expectLinkErrors = link.expectLinkErrors; const link = @import("link.zig"); const std = @import("std"); diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index a104633fd764..85cbc48e5478 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -8,9 +8,9 @@ pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = t, .root_source_file = .{ .path = "main.c" }, - .target = std.zig.CrossTarget.parse( + .target = b.resolveTargetQuery(std.zig.CrossTarget.parse( .{ .arch_os_abi = t }, - ) catch unreachable, + ) catch unreachable), }); exe.linkLibC(); // TODO: actually test the output diff --git a/test/link/interdependent_static_c_libs/build.zig b/test/link/interdependent_static_c_libs/build.zig index 757c0d419b63..01ed218cce3f 100644 --- a/test/link/interdependent_static_c_libs/build.zig +++ b/test/link/interdependent_static_c_libs/build.zig @@ -14,7 +14,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib_a = b.addStaticLibrary(.{ .name = "a", .optimize = optimize, - .target = .{}, + .target = b.host, }); lib_a.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &[_][]const u8{} }); lib_a.addIncludePath(.{ .path = "." }); @@ -22,7 +22,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib_b = b.addStaticLibrary(.{ .name = "b", .optimize = optimize, - .target = .{}, + .target = b.host, }); lib_b.addCSourceFile(.{ .file = .{ .path = "b.c" }, .flags = &[_][]const u8{} }); lib_b.addIncludePath(.{ .path = "." }); diff --git a/test/link/link.zig b/test/link/link.zig index b08a929d8b30..d5bbbe9f4bfb 100644 --- a/test/link/link.zig +++ b/test/link/link.zig @@ -7,62 +7,160 @@ pub fn build(b: *Build) void { } pub const Options = struct { - target: CrossTarget, + target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode = .Debug, use_llvm: bool = true, use_lld: bool = false, }; -pub fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { - const target = opts.target.zigTriple(b.allocator) catch @panic("OOM"); +pub fn addTestStep(b: *Build, prefix: []const u8, opts: Options) *Step { + const target = opts.target.target.zigTriple(b.allocator) catch @panic("OOM"); const optimize = @tagName(opts.optimize); const use_llvm = if (opts.use_llvm) "llvm" else "no-llvm"; - const name = std.fmt.allocPrint(b.allocator, "test-" ++ prefix ++ "-{s}-{s}-{s}", .{ - target, - optimize, - use_llvm, + const name = std.fmt.allocPrint(b.allocator, "test-{s}-{s}-{s}-{s}", .{ + prefix, target, optimize, use_llvm, }) catch @panic("OOM"); return b.step(name, ""); } -pub fn addExecutable(b: *Build, name: []const u8, opts: Options) *Compile { - return b.addExecutable(.{ - .name = name, - .target = opts.target, - .optimize = opts.optimize, - .use_llvm = opts.use_llvm, - .use_lld = opts.use_lld, +const OverlayOptions = struct { + name: []const u8, + asm_source_bytes: ?[]const u8 = null, + c_source_bytes: ?[]const u8 = null, + c_source_flags: []const []const u8 = &.{}, + cpp_source_bytes: ?[]const u8 = null, + cpp_source_flags: []const []const u8 = &.{}, + zig_source_bytes: ?[]const u8 = null, + pic: ?bool = null, + strip: ?bool = null, +}; + +pub fn addExecutable(b: *std.Build, base: Options, overlay: OverlayOptions) *Step.Compile { + const compile_step = b.addExecutable(.{ + .name = overlay.name, + .root_source_file = rsf: { + const bytes = overlay.zig_source_bytes orelse break :rsf null; + break :rsf b.addWriteFiles().add("a.zig", bytes); + }, + .target = base.target, + .optimize = base.optimize, + .use_llvm = base.use_llvm, + .use_lld = base.use_lld, + .pic = overlay.pic, + .strip = overlay.strip, }); + if (overlay.cpp_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.cpp", bytes), + .flags = overlay.cpp_source_flags, + }); + } + if (overlay.c_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.c", bytes), + .flags = overlay.c_source_flags, + }); + } + if (overlay.asm_source_bytes) |bytes| { + compile_step.addAssemblyFile(b.addWriteFiles().add("a.s", bytes)); + } + return compile_step; } -pub fn addObject(b: *Build, name: []const u8, opts: Options) *Compile { - return b.addObject(.{ - .name = name, - .target = opts.target, - .optimize = opts.optimize, - .use_llvm = opts.use_llvm, - .use_lld = opts.use_lld, +pub fn addObject(b: *Build, base: Options, overlay: OverlayOptions) *Step.Compile { + const compile_step = b.addObject(.{ + .name = overlay.name, + .root_source_file = rsf: { + const bytes = overlay.zig_source_bytes orelse break :rsf null; + break :rsf b.addWriteFiles().add("a.zig", bytes); + }, + .target = base.target, + .optimize = base.optimize, + .use_llvm = base.use_llvm, + .use_lld = base.use_lld, + .pic = overlay.pic, + .strip = overlay.strip, }); + if (overlay.cpp_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.cpp", bytes), + .flags = overlay.cpp_source_flags, + }); + } + if (overlay.c_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.c", bytes), + .flags = overlay.c_source_flags, + }); + } + if (overlay.asm_source_bytes) |bytes| { + compile_step.addAssemblyFile(b.addWriteFiles().add("a.s", bytes)); + } + return compile_step; } -pub fn addStaticLibrary(b: *Build, name: []const u8, opts: Options) *Compile { - return b.addStaticLibrary(.{ - .name = name, - .target = opts.target, - .optimize = opts.optimize, - .use_llvm = opts.use_llvm, - .use_lld = opts.use_lld, +pub fn addStaticLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile { + const compile_step = b.addStaticLibrary(.{ + .name = overlay.name, + .root_source_file = rsf: { + const bytes = overlay.zig_source_bytes orelse break :rsf null; + break :rsf b.addWriteFiles().add("a.zig", bytes); + }, + .target = base.target, + .optimize = base.optimize, + .use_llvm = base.use_llvm, + .use_lld = base.use_lld, + .pic = overlay.pic, + .strip = overlay.strip, }); + if (overlay.cpp_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.cpp", bytes), + .flags = overlay.cpp_source_flags, + }); + } + if (overlay.c_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.c", bytes), + .flags = overlay.c_source_flags, + }); + } + if (overlay.asm_source_bytes) |bytes| { + compile_step.addAssemblyFile(b.addWriteFiles().add("a.s", bytes)); + } + return compile_step; } -pub fn addSharedLibrary(b: *Build, name: []const u8, opts: Options) *Compile { - return b.addSharedLibrary(.{ - .name = name, - .target = opts.target, - .optimize = opts.optimize, - .use_llvm = opts.use_llvm, - .use_lld = opts.use_lld, +pub fn addSharedLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile { + const compile_step = b.addSharedLibrary(.{ + .name = overlay.name, + .root_source_file = rsf: { + const bytes = overlay.zig_source_bytes orelse break :rsf null; + break :rsf b.addWriteFiles().add("a.zig", bytes); + }, + .target = base.target, + .optimize = base.optimize, + .use_llvm = base.use_llvm, + .use_lld = base.use_lld, + .pic = overlay.pic, + .strip = overlay.strip, }); + if (overlay.cpp_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.cpp", bytes), + .flags = overlay.cpp_source_flags, + }); + } + if (overlay.c_source_bytes) |bytes| { + compile_step.addCSourceFile(.{ + .file = b.addWriteFiles().add("a.c", bytes), + .flags = overlay.c_source_flags, + }); + } + if (overlay.asm_source_bytes) |bytes| { + compile_step.addAssemblyFile(b.addWriteFiles().add("a.s", bytes)); + } + return compile_step; } pub fn addRunArtifact(comp: *Compile) *Run { @@ -72,13 +170,6 @@ pub fn addRunArtifact(comp: *Compile) *Run { return run; } -pub fn addZigSourceBytes(comp: *Compile, bytes: []const u8) void { - const b = comp.step.owner; - const file = WriteFile.create(b).add("a.zig", bytes); - file.addStepDependencies(&comp.step); - comp.root_src = file; -} - pub fn addCSourceBytes(comp: *Compile, bytes: []const u8, flags: []const []const u8) void { const b = comp.step.owner; const file = WriteFile.create(b).add("a.c", bytes); diff --git a/test/link/macho.zig b/test/link/macho.zig index f172d9af17a2..230107c9b266 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -1,26 +1,29 @@ //! Here we test our MachO linker for correctness and functionality. //! TODO migrate standalone tests from test/link/macho/* to here. -pub fn testAll(b: *Build) *Step { +pub fn testAll(b: *std.Build) *Step { const macho_step = b.step("test-macho", "Run MachO tests"); - const default_target = CrossTarget{ .os_tag = .macos }; - - macho_step.dependOn(testResolvingBoundarySymbols(b, .{ .target = default_target })); + macho_step.dependOn(testResolvingBoundarySymbols(b, .{ + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), + })); return macho_step; } -fn testResolvingBoundarySymbols(b: *Build, opts: Options) *Step { +fn testResolvingBoundarySymbols(b: *std.Build, opts: Options) *Step { const test_step = addTestStep(b, "macho-resolving-boundary-symbols", opts); - const obj1 = addObject(b, "obj1", opts); - addCppSourceBytes(obj1, + const obj1 = addObject(b, opts, .{ + .name = "obj1", + .cpp_source_bytes = \\constexpr const char* MESSAGE __attribute__((used, section("__DATA_CONST,__message_ptr"))) = "codebase"; - , &.{}); + , + }); - const main_o = addObject(b, "main", opts); - addZigSourceBytes(main_o, + const main_o = addObject(b, opts, .{ + .name = "main", + .zig_source_bytes = \\const std = @import("std"); \\extern fn interop() [*:0]const u8; \\pub fn main() !void { @@ -28,23 +31,27 @@ fn testResolvingBoundarySymbols(b: *Build, opts: Options) *Step { \\ std.mem.span(interop()), \\ }); \\} - ); + , + }); { - const obj2 = addObject(b, "obj2", opts); - addCppSourceBytes(obj2, + const obj2 = addObject(b, opts, .{ + .name = "obj2", + .cpp_source_bytes = \\extern const char* message_pointer __asm("section$start$__DATA_CONST$__message_ptr"); \\extern "C" const char* interop() { \\ return message_pointer; \\} - , &.{}); + , + }); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); exe.addObject(obj1); exe.addObject(obj2); exe.addObject(main_o); - const run = addRunArtifact(exe); + const run = b.addRunArtifact(exe); + run.skip_foreign_checks = true; run.expectStdErrEqual("All your codebase are belong to us.\n"); test_step.dependOn(&run.step); @@ -55,15 +62,17 @@ fn testResolvingBoundarySymbols(b: *Build, opts: Options) *Step { } { - const obj3 = addObject(b, "obj3", opts); - addCppSourceBytes(obj3, + const obj3 = addObject(b, opts, .{ + .name = "obj3", + .cpp_source_bytes = \\extern const char* message_pointer __asm("section$start$__DATA$__message_ptr"); \\extern "C" const char* interop() { \\ return message_pointer; \\} - , &.{}); + , + }); - const exe = addExecutable(b, "test", opts); + const exe = addExecutable(b, opts, .{ .name = "test" }); exe.addObject(obj1); exe.addObject(obj3); exe.addObject(main_o); @@ -77,20 +86,16 @@ fn testResolvingBoundarySymbols(b: *Build, opts: Options) *Step { return test_step; } -fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { +fn addTestStep(b: *std.Build, comptime prefix: []const u8, opts: Options) *Step { return link.addTestStep(b, "macho-" ++ prefix, opts); } -const addCppSourceBytes = link.addCppSourceBytes; -const addExecutable = link.addExecutable; const addObject = link.addObject; -const addRunArtifact = link.addRunArtifact; -const addZigSourceBytes = link.addZigSourceBytes; +const addExecutable = link.addExecutable; const expectLinkErrors = link.expectLinkErrors; const link = @import("link.zig"); const std = @import("std"); -const Build = std.Build; const CrossTarget = std.zig.CrossTarget; const Options = link.Options; -const Step = Build.Step; +const Step = std.Build.Step; diff --git a/test/link/macho/bugs/13056/build.zig b/test/link/macho/bugs/13056/build.zig index 5b19daab3cfd..c7136bbd7ffe 100644 --- a/test/link/macho/bugs/13056/build.zig +++ b/test/link/macho/bugs/13056/build.zig @@ -14,14 +14,14 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; - const target_info = std.zig.system.NativeTargetInfo.detect(target) catch unreachable; - const sdk = std.zig.system.darwin.getSdk(b.allocator, target_info.target) orelse + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); + const sdk = std.zig.system.darwin.getSdk(b.allocator, target.target) orelse @panic("macOS SDK is required to run the test"); const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = b.host, }); exe.addSystemIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include" }) }); exe.addIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include/c++/v1" }) }); diff --git a/test/link/macho/bugs/13457/build.zig b/test/link/macho/bugs/13457/build.zig index 89096bba387d..fe835b5715a0 100644 --- a/test/link/macho/bugs/13457/build.zig +++ b/test/link/macho/bugs/13457/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const exe = b.addExecutable(.{ .name = "test", diff --git a/test/link/macho/bugs/16308/build.zig b/test/link/macho/bugs/16308/build.zig index 3d7a884bd028..f4456b111cc8 100644 --- a/test/link/macho/bugs/16308/build.zig +++ b/test/link/macho/bugs/16308/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const lib = b.addSharedLibrary(.{ .name = "a", diff --git a/test/link/macho/bugs/16628/build.zig b/test/link/macho/bugs/16628/build.zig index aa396f7a3bc5..59c666aa27ec 100644 --- a/test/link/macho/bugs/16628/build.zig +++ b/test/link/macho/bugs/16628/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const exe = b.addExecutable(.{ .name = "test", diff --git a/test/link/macho/dead_strip/build.zig b/test/link/macho/dead_strip/build.zig index 8b8449b6b214..a5bb28df9f57 100644 --- a/test/link/macho/dead_strip/build.zig +++ b/test/link/macho/dead_strip/build.zig @@ -4,7 +4,7 @@ pub const requires_symlinks = true; pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const test_step = b.step("test", "Test the program"); b.default_step = test_step; @@ -44,7 +44,7 @@ pub fn build(b: *std.Build) void { fn createScenario( b: *std.Build, optimize: std.builtin.OptimizeMode, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, name: []const u8, ) *std.Build.Step.Compile { const exe = b.addExecutable(.{ diff --git a/test/link/macho/dead_strip_dylibs/build.zig b/test/link/macho/dead_strip_dylibs/build.zig index 52d7f2eac8a3..7ab8c16dfeba 100644 --- a/test/link/macho/dead_strip_dylibs/build.zig +++ b/test/link/macho/dead_strip_dylibs/build.zig @@ -52,6 +52,7 @@ fn createScenario( const exe = b.addExecutable(.{ .name = name, .optimize = optimize, + .target = b.host, }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); diff --git a/test/link/macho/dylib/build.zig b/test/link/macho/dylib/build.zig index beebfbdd021c..abd7175eae40 100644 --- a/test/link/macho/dylib/build.zig +++ b/test/link/macho/dylib/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const dylib = b.addSharedLibrary(.{ .name = "a", @@ -55,7 +55,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize check_exe.checkInHeaders(); check_exe.checkExact("cmd RPATH"); - check_exe.checkExactPath("path", dylib.getOutputDirectorySource()); + check_exe.checkExactPath("path", dylib.getEmittedBinDirectory()); test_step.dependOn(&check_exe.step); const run = b.addRunArtifact(exe); diff --git a/test/link/macho/empty/build.zig b/test/link/macho/empty/build.zig index 6a1350770271..af38930ae88d 100644 --- a/test/link/macho/empty/build.zig +++ b/test/link/macho/empty/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const exe = b.addExecutable(.{ .name = "test", diff --git a/test/link/macho/entry/build.zig b/test/link/macho/entry/build.zig index 9675935a9c3c..0ef717f2927e 100644 --- a/test/link/macho/entry/build.zig +++ b/test/link/macho/entry/build.zig @@ -16,7 +16,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, - .target = .{ .os_tag = .macos }, + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkLibC(); diff --git a/test/link/macho/entry_in_archive/build.zig b/test/link/macho/entry_in_archive/build.zig index f48e612d95d4..72f340b204bf 100644 --- a/test/link/macho/entry_in_archive/build.zig +++ b/test/link/macho/entry_in_archive/build.zig @@ -16,7 +16,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addStaticLibrary(.{ .name = "main", .optimize = optimize, - .target = .{ .os_tag = .macos }, + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), }); lib.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); lib.linkLibC(); @@ -24,7 +24,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, - .target = .{ .os_tag = .macos }, + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), }); exe.linkLibrary(lib); exe.linkLibC(); diff --git a/test/link/macho/entry_in_dylib/build.zig b/test/link/macho/entry_in_dylib/build.zig index 5b93541a5a0b..7827552bcfdc 100644 --- a/test/link/macho/entry_in_dylib/build.zig +++ b/test/link/macho/entry_in_dylib/build.zig @@ -16,7 +16,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addSharedLibrary(.{ .name = "bootstrap", .optimize = optimize, - .target = .{ .os_tag = .macos }, + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), }); lib.addCSourceFile(.{ .file = .{ .path = "bootstrap.c" }, .flags = &.{} }); lib.linkLibC(); @@ -25,7 +25,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, - .target = .{ .os_tag = .macos }, + .target = b.resolveTargetQuery(.{ .os_tag = .macos }), }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkLibrary(lib); diff --git a/test/link/macho/headerpad/build.zig b/test/link/macho/headerpad/build.zig index 3c0bb7c5725c..b982224e8566 100644 --- a/test/link/macho/headerpad/build.zig +++ b/test/link/macho/headerpad/build.zig @@ -112,6 +112,7 @@ fn simpleExe( const exe = b.addExecutable(.{ .name = name, .optimize = optimize, + .target = b.host, }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkLibC(); diff --git a/test/link/macho/linksection/build.zig b/test/link/macho/linksection/build.zig index 113034f96f9f..91ddfe530c5a 100644 --- a/test/link/macho/linksection/build.zig +++ b/test/link/macho/linksection/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target = std.zig.CrossTarget{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const obj = b.addObject(.{ .name = "test", diff --git a/test/link/macho/needed_framework/build.zig b/test/link/macho/needed_framework/build.zig index 45c046fe0bf5..83a3e75e2db4 100644 --- a/test/link/macho/needed_framework/build.zig +++ b/test/link/macho/needed_framework/build.zig @@ -19,6 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = b.host, }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); diff --git a/test/link/macho/needed_library/build.zig b/test/link/macho/needed_library/build.zig index cc9d2bd6465f..a07493a8b155 100644 --- a/test/link/macho/needed_library/build.zig +++ b/test/link/macho/needed_library/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const dylib = b.addSharedLibrary(.{ .name = "a", @@ -33,7 +33,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); - exe.linkSystemLibraryNeeded("a"); + exe.root_module.linkSystemLibrary("a", .{ .needed = true }); exe.addLibraryPath(dylib.getEmittedBinDirectory()); exe.addRPath(dylib.getEmittedBinDirectory()); exe.dead_strip_dylibs = true; diff --git a/test/link/macho/objc/build.zig b/test/link/macho/objc/build.zig index 979c0aa94327..26bbdc267364 100644 --- a/test/link/macho/objc/build.zig +++ b/test/link/macho/objc/build.zig @@ -17,6 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = b.host, }); exe.addIncludePath(.{ .path = "." }); exe.addCSourceFile(.{ .file = .{ .path = "Foo.m" }, .flags = &[0][]const u8{} }); diff --git a/test/link/macho/objcpp/build.zig b/test/link/macho/objcpp/build.zig index 183d3cb9d3ef..53743fafdfd5 100644 --- a/test/link/macho/objcpp/build.zig +++ b/test/link/macho/objcpp/build.zig @@ -17,6 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = b.host, }); b.default_step.dependOn(&exe.step); exe.addIncludePath(.{ .path = "." }); diff --git a/test/link/macho/pagezero/build.zig b/test/link/macho/pagezero/build.zig index 1ca7f28f1108..cee2aa9fd506 100644 --- a/test/link/macho/pagezero/build.zig +++ b/test/link/macho/pagezero/build.zig @@ -7,7 +7,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); { const exe = b.addExecutable(.{ diff --git a/test/link/macho/reexports/build.zig b/test/link/macho/reexports/build.zig index d9a9481fa0be..44c96ecf7eba 100644 --- a/test/link/macho/reexports/build.zig +++ b/test/link/macho/reexports/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const lib = b.addStaticLibrary(.{ .name = "a", diff --git a/test/link/macho/search_strategy/build.zig b/test/link/macho/search_strategy/build.zig index b76de65b0eac..181d2df91ab4 100644 --- a/test/link/macho/search_strategy/build.zig +++ b/test/link/macho/search_strategy/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); { // -search_dylibs_first @@ -45,9 +45,9 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize fn createScenario( b: *std.Build, optimize: std.builtin.OptimizeMode, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, name: []const u8, - search_strategy: std.Build.Step.Compile.SystemLib.SearchStrategy, + search_strategy: std.Build.Module.SystemLib.SearchStrategy, ) *std.Build.Step.Compile { const static = b.addStaticLibrary(.{ .name = name, diff --git a/test/link/macho/stack_size/build.zig b/test/link/macho/stack_size/build.zig index 48496bd9d51e..28a2602ea5e3 100644 --- a/test/link/macho/stack_size/build.zig +++ b/test/link/macho/stack_size/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const exe = b.addExecutable(.{ .name = "main", diff --git a/test/link/macho/strict_validation/build.zig b/test/link/macho/strict_validation/build.zig index 1cfaac49103f..f35438369c90 100644 --- a/test/link/macho/strict_validation/build.zig +++ b/test/link/macho/strict_validation/build.zig @@ -14,7 +14,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const exe = b.addExecutable(.{ .name = "main", diff --git a/test/link/macho/tbdv3/build.zig b/test/link/macho/tbdv3/build.zig index ba11004f29b9..547f72c25fc3 100644 --- a/test/link/macho/tbdv3/build.zig +++ b/test/link/macho/tbdv3/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const lib = b.addSharedLibrary(.{ .name = "a", diff --git a/test/link/macho/tls/build.zig b/test/link/macho/tls/build.zig index 443f698ea6be..af2ac8a9c630 100644 --- a/test/link/macho/tls/build.zig +++ b/test/link/macho/tls/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const lib = b.addSharedLibrary(.{ .name = "a", diff --git a/test/link/macho/unwind_info/build.zig b/test/link/macho/unwind_info/build.zig index 96c4a67568bf..534cc4e51a1d 100644 --- a/test/link/macho/unwind_info/build.zig +++ b/test/link/macho/unwind_info/build.zig @@ -14,7 +14,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); testUnwindInfo(b, test_step, optimize, target, false, "no-dead-strip"); testUnwindInfo(b, test_step, optimize, target, true, "yes-dead-strip"); @@ -24,7 +24,7 @@ fn testUnwindInfo( b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, dead_strip: bool, name: []const u8, ) void { @@ -66,7 +66,7 @@ fn testUnwindInfo( fn createScenario( b: *std.Build, optimize: std.builtin.OptimizeMode, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, name: []const u8, ) *std.Build.Step.Compile { const exe = b.addExecutable(.{ diff --git a/test/link/macho/weak_framework/build.zig b/test/link/macho/weak_framework/build.zig index dfb41b7457e7..2a430443d455 100644 --- a/test/link/macho/weak_framework/build.zig +++ b/test/link/macho/weak_framework/build.zig @@ -17,6 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, + .target = b.host, }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); diff --git a/test/link/macho/weak_library/build.zig b/test/link/macho/weak_library/build.zig index 7ae7c7c2d652..0d73b9f4eaa4 100644 --- a/test/link/macho/weak_library/build.zig +++ b/test/link/macho/weak_library/build.zig @@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + const target = b.resolveTargetQuery(.{ .os_tag = .macos }); const dylib = b.addSharedLibrary(.{ .name = "a", @@ -32,7 +32,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); - exe.linkSystemLibraryWeak("a"); + exe.root_module.linkSystemLibrary("a", .{ .weak = true }); exe.addLibraryPath(dylib.getEmittedBinDirectory()); exe.addRPath(dylib.getEmittedBinDirectory()); diff --git a/test/link/static_libs_from_object_files/build.zig b/test/link/static_libs_from_object_files/build.zig index e5a4b79acd8f..d0ea78bbd66c 100644 --- a/test/link/static_libs_from_object_files/build.zig +++ b/test/link/static_libs_from_object_files/build.zig @@ -59,7 +59,7 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built .name = "test1", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = .{}, + .target = b.host, }); for (files) |file| { @@ -77,12 +77,12 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built { const lib_a = b.addStaticLibrary(.{ .name = "test2_a", - .target = .{}, + .target = b.host, .optimize = optimize, }); const lib_b = b.addStaticLibrary(.{ .name = "test2_b", - .target = .{}, + .target = b.host, .optimize = optimize, }); @@ -94,6 +94,7 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built const exe = b.addExecutable(.{ .name = "test2", .root_source_file = .{ .path = "main.zig" }, + .target = b.host, .optimize = optimize, }); exe.linkLibrary(lib_a); @@ -110,19 +111,19 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built { const lib_a = b.addStaticLibrary(.{ .name = "test3_a", - .target = .{}, + .target = b.host, .optimize = optimize, }); const lib_b = b.addStaticLibrary(.{ .name = "test3_b", - .target = .{}, + .target = b.host, .optimize = optimize, }); for (files, 1..) |file, i| { const obj = b.addObject(.{ .name = b.fmt("obj_{}", .{i}), - .target = .{}, + .target = b.host, .optimize = optimize, }); obj.addCSourceFile(.{ .file = file, .flags = &flags }); @@ -134,6 +135,7 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built const exe = b.addExecutable(.{ .name = "test3", .root_source_file = .{ .path = "main.zig" }, + .target = b.host, .optimize = optimize, }); exe.linkLibrary(lib_a); diff --git a/test/link/wasm/archive/build.zig b/test/link/wasm/archive/build.zig index 95aea2913e9f..1d5e031848b9 100644 --- a/test/link/wasm/archive/build.zig +++ b/test/link/wasm/archive/build.zig @@ -20,11 +20,11 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; const check = lib.checkObject(); check.checkInHeaders(); diff --git a/test/link/wasm/basic-features/build.zig b/test/link/wasm/basic-features/build.zig index 9cf28ea31ef8..6f9e82d09df3 100644 --- a/test/link/wasm/basic-features/build.zig +++ b/test/link/wasm/basic-features/build.zig @@ -8,12 +8,12 @@ pub fn build(b: *std.Build) void { .name = "lib", .root_source_file = .{ .path = "main.zig" }, .optimize = .Debug, - .target = .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, .cpu_features_add = std.Target.wasm.featureSet(&.{.atomics}), .os_tag = .freestanding, - }, + }), }); lib.entry = .disabled; lib.use_llvm = false; diff --git a/test/link/wasm/bss/build.zig b/test/link/wasm/bss/build.zig index c569225f8b25..3a1592f394d5 100644 --- a/test/link/wasm/bss/build.zig +++ b/test/link/wasm/bss/build.zig @@ -17,13 +17,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize_mode, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; // to make sure the bss segment is emitted, we must import memory lib.import_memory = true; lib.link_gc_sections = false; @@ -65,13 +65,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib2.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize_mode, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; // to make sure the bss segment is emitted, we must import memory lib.import_memory = true; lib.link_gc_sections = false; diff --git a/test/link/wasm/export-data/build.zig b/test/link/wasm/export-data/build.zig index f1bba98d5f4b..bba00d5c1281 100644 --- a/test/link/wasm/export-data/build.zig +++ b/test/link/wasm/export-data/build.zig @@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void { }); lib.entry = .disabled; lib.use_lld = false; - lib.export_symbol_names = &.{ "foo", "bar" }; + lib.root_module.export_symbol_names = &.{ "foo", "bar" }; lib.global_base = 0; // put data section at address 0 to make data symbols easier to parse const check_lib = lib.checkObject(); diff --git a/test/link/wasm/export/build.zig b/test/link/wasm/export/build.zig index 2183ccd5855a..ab2893ce3c6a 100644 --- a/test/link/wasm/export/build.zig +++ b/test/link/wasm/export/build.zig @@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .name = "no-export", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), }); no_export.entry = .disabled; no_export.use_llvm = false; @@ -27,7 +27,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .name = "dynamic", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), }); dynamic_export.entry = .disabled; dynamic_export.rdynamic = true; @@ -38,10 +38,10 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .name = "force", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), }); force_export.entry = .disabled; - force_export.export_symbol_names = &.{"foo"}; + force_export.root_module.export_symbol_names = &.{"foo"}; force_export.use_llvm = false; force_export.use_lld = false; diff --git a/test/link/wasm/extern-mangle/build.zig b/test/link/wasm/extern-mangle/build.zig index d361dc140e96..41a00eefc97d 100644 --- a/test/link/wasm/extern-mangle/build.zig +++ b/test/link/wasm/extern-mangle/build.zig @@ -14,7 +14,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, }); lib.entry = .disabled; diff --git a/test/link/wasm/extern/build.zig b/test/link/wasm/extern/build.zig index a50589952042..baa2b6d61e81 100644 --- a/test/link/wasm/extern/build.zig +++ b/test/link/wasm/extern/build.zig @@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .name = "extern", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = .{ .cpu_arch = .wasm32, .os_tag = .wasi }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi }), }); exe.addCSourceFile(.{ .file = .{ .path = "foo.c" }, .flags = &.{} }); exe.use_llvm = false; diff --git a/test/link/wasm/function-table/build.zig b/test/link/wasm/function-table/build.zig index 5a139acb3e6b..aca66e4f7157 100644 --- a/test/link/wasm/function-table/build.zig +++ b/test/link/wasm/function-table/build.zig @@ -16,7 +16,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const import_table = b.addExecutable(.{ .name = "import_table", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, }); import_table.entry = .disabled; @@ -28,7 +28,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const export_table = b.addExecutable(.{ .name = "export_table", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, }); export_table.entry = .disabled; @@ -40,7 +40,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const regular_table = b.addExecutable(.{ .name = "regular_table", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, }); regular_table.entry = .disabled; diff --git a/test/link/wasm/infer-features/build.zig b/test/link/wasm/infer-features/build.zig index c883063dc514..e3fe860f5406 100644 --- a/test/link/wasm/infer-features/build.zig +++ b/test/link/wasm/infer-features/build.zig @@ -7,11 +7,11 @@ pub fn build(b: *std.Build) void { const c_obj = b.addObject(.{ .name = "c_obj", .optimize = .Debug, - .target = .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .cpu_model = .{ .explicit = &std.Target.wasm.cpu.bleeding_edge }, .os_tag = .freestanding, - }, + }), }); c_obj.addCSourceFile(.{ .file = .{ .path = "foo.c" }, .flags = &.{} }); @@ -21,11 +21,11 @@ pub fn build(b: *std.Build) void { .name = "lib", .root_source_file = .{ .path = "main.zig" }, .optimize = .Debug, - .target = .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, .os_tag = .freestanding, - }, + }), }); lib.entry = .disabled; lib.use_llvm = false; diff --git a/test/link/wasm/producers/build.zig b/test/link/wasm/producers/build.zig index b66521a45691..4fb777e1232d 100644 --- a/test/link/wasm/producers/build.zig +++ b/test/link/wasm/producers/build.zig @@ -17,13 +17,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; b.installArtifact(lib); const version_fmt = "version " ++ builtin.zig_version_string; diff --git a/test/link/wasm/segments/build.zig b/test/link/wasm/segments/build.zig index 6ab2e4a7a320..86073ff9770d 100644 --- a/test/link/wasm/segments/build.zig +++ b/test/link/wasm/segments/build.zig @@ -16,13 +16,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; lib.link_gc_sections = false; // so data is not garbage collected and we can verify data section b.installArtifact(lib); diff --git a/test/link/wasm/shared-memory/build.zig b/test/link/wasm/shared-memory/build.zig index a1d660d13582..f8751d99c049 100644 --- a/test/link/wasm/shared-memory/build.zig +++ b/test/link/wasm/shared-memory/build.zig @@ -21,16 +21,16 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt .os_tag = .freestanding, }, .optimize = optimize_mode, + .strip = false, + .single_threaded = false, }); lib.entry = .disabled; lib.use_lld = false; - lib.strip = false; lib.import_memory = true; lib.export_memory = true; lib.shared_memory = true; lib.max_memory = 67108864; - lib.single_threaded = false; - lib.export_symbol_names = &.{"foo"}; + lib.root_module.export_symbol_names = &.{"foo"}; const check_lib = lib.checkObject(); diff --git a/test/link/wasm/stack_pointer/build.zig b/test/link/wasm/stack_pointer/build.zig index 93c0f10e1475..e95c27827ed0 100644 --- a/test/link/wasm/stack_pointer/build.zig +++ b/test/link/wasm/stack_pointer/build.zig @@ -16,13 +16,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; lib.stack_size = std.wasm.page_size * 2; // set an explicit stack size lib.link_gc_sections = false; b.installArtifact(lib); diff --git a/test/link/wasm/type/build.zig b/test/link/wasm/type/build.zig index 88ded91403a5..a318ddb1f97d 100644 --- a/test/link/wasm/type/build.zig +++ b/test/link/wasm/type/build.zig @@ -16,13 +16,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, - .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), .optimize = optimize, + .strip = false, }); lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; - lib.strip = false; b.installArtifact(lib); const check_lib = lib.checkObject(); diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig index 6f01925a9fc2..6a3139dd9f0e 100644 --- a/test/llvm_targets.zig +++ b/test/llvm_targets.zig @@ -127,17 +127,21 @@ const targets = [_]std.zig.CrossTarget{ .{ .cpu_arch = .xtensa, .os_tag = .linux, .abi = .none }, }; -pub fn addCases(ctx: *Cases, build_options: @import("cases.zig").BuildOptions) !void { +pub fn addCases( + ctx: *Cases, + build_options: @import("cases.zig").BuildOptions, + b: *std.Build, +) !void { if (!build_options.enable_llvm) return; - for (targets) |target| { - if (target.cpu_arch) |arch| switch (arch) { + for (targets) |target_query| { + if (target_query.cpu_arch) |arch| switch (arch) { .m68k => if (!build_options.llvm_has_m68k) continue, .csky => if (!build_options.llvm_has_csky) continue, .arc => if (!build_options.llvm_has_arc) continue, .xtensa => if (!build_options.llvm_has_xtensa) continue, else => {}, }; - var case = ctx.noEmitUsingLlvmBackend("llvm_targets", target); + var case = ctx.noEmitUsingLlvmBackend("llvm_targets", b.resolveTargetQuery(target_query)); case.addCompile(""); } } diff --git a/test/nvptx.zig b/test/nvptx.zig index c3748570e89c..fd4c66db8978 100644 --- a/test/nvptx.zig +++ b/test/nvptx.zig @@ -1,9 +1,14 @@ const std = @import("std"); const Cases = @import("src/Cases.zig"); -pub fn addCases(ctx: *Cases) !void { +pub fn addCases(ctx: *Cases, b: *std.Build) !void { + const target = b.resolveTargetQuery(.{ + .cpu_arch = .nvptx64, + .os_tag = .cuda, + }); + { - var case = addPtx(ctx, "simple addition and subtraction"); + var case = addPtx(ctx, target, "simple addition and subtraction"); case.addCompile( \\fn add(a: i32, b: i32) i32 { @@ -20,7 +25,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = addPtx(ctx, "read special registers"); + var case = addPtx(ctx, target, "read special registers"); case.addCompile( \\fn threadIdX() u32 { @@ -37,7 +42,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = addPtx(ctx, "address spaces"); + var case = addPtx(ctx, target, "address spaces"); case.addCompile( \\var x: i32 addrspace(.global) = 0; @@ -50,7 +55,7 @@ pub fn addCases(ctx: *Cases) !void { } { - var case = addPtx(ctx, "reduce in shared mem"); + var case = addPtx(ctx, target, "reduce in shared mem"); case.addCompile( \\fn threadIdX() u32 { \\ return asm ("mov.u32 \t%[r], %tid.x;" @@ -82,18 +87,10 @@ pub fn addCases(ctx: *Cases) !void { } } -const nvptx_target = std.zig.CrossTarget{ - .cpu_arch = .nvptx64, - .os_tag = .cuda, -}; - -pub fn addPtx( - ctx: *Cases, - name: []const u8, -) *Cases.Case { +fn addPtx(ctx: *Cases, target: std.Build.ResolvedTarget, name: []const u8) *Cases.Case { ctx.cases.append(.{ .name = name, - .target = nvptx_target, + .target = target, .updates = std.ArrayList(Cases.Update).init(ctx.cases.allocator), .output_mode = .Obj, .deps = std.ArrayList(Cases.DepModule).init(ctx.cases.allocator), diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 262f8e9ac76e..2aa92fc90872 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -76,7 +76,7 @@ pub const Case = struct { name: []const u8, /// The platform the test targets. For non-native platforms, an emulator /// such as QEMU is required for tests to complete. - target: CrossTarget, + target: std.Build.ResolvedTarget, /// In order to be able to run e.g. Execution updates, this must be set /// to Executable. output_mode: std.builtin.OutputMode, @@ -155,7 +155,7 @@ pub const Translate = struct { name: []const u8, input: [:0]const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, link_libc: bool, c_frontend: CFrontend, kind: union(enum) { @@ -171,7 +171,7 @@ pub const Translate = struct { pub fn addExe( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, ) *Case { ctx.cases.append(Case{ .name = name, @@ -184,16 +184,16 @@ pub fn addExe( } /// Adds a test case for Zig input, producing an executable -pub fn exe(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn exe(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { return ctx.addExe(name, target); } -pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { - var target_adjusted = target; - target_adjusted.ofmt = .c; +pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.zig.CrossTarget, b: *std.Build) *Case { + var adjusted_query = target_query; + adjusted_query.ofmt = .c; ctx.cases.append(Case{ .name = name, - .target = target_adjusted, + .target = b.resolveTargetQuery(adjusted_query), .updates = std.ArrayList(Update).init(ctx.cases.allocator), .output_mode = .Exe, .deps = std.ArrayList(DepModule).init(ctx.arena), @@ -202,7 +202,7 @@ pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target: CrossTarget) *Cas return &ctx.cases.items[ctx.cases.items.len - 1]; } -pub fn noEmitUsingLlvmBackend(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn noEmitUsingLlvmBackend(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { ctx.cases.append(Case{ .name = name, .target = target, @@ -217,7 +217,7 @@ pub fn noEmitUsingLlvmBackend(ctx: *Cases, name: []const u8, target: CrossTarget /// Adds a test case that uses the LLVM backend to emit an executable. /// Currently this implies linking libc, because only then we can generate a testable executable. -pub fn exeUsingLlvmBackend(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn exeUsingLlvmBackend(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { ctx.cases.append(Case{ .name = name, .target = target, @@ -233,7 +233,7 @@ pub fn exeUsingLlvmBackend(ctx: *Cases, name: []const u8, target: CrossTarget) * pub fn addObj( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, ) *Case { ctx.cases.append(Case{ .name = name, @@ -248,7 +248,7 @@ pub fn addObj( pub fn addTest( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, ) *Case { ctx.cases.append(Case{ .name = name, @@ -262,17 +262,17 @@ pub fn addTest( } /// Adds a test case for Zig input, producing an object file. -pub fn obj(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn obj(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { return ctx.addObj(name, target); } /// Adds a test case for ZIR input, producing an object file. -pub fn objZIR(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn objZIR(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { return ctx.addObj(name, target, .ZIR); } /// Adds a test case for Zig or ZIR input, producing C code. -pub fn addC(ctx: *Cases, name: []const u8, target: CrossTarget) *Case { +pub fn addC(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Case { var target_adjusted = target; target_adjusted.ofmt = std.Target.ObjectFormat.c; ctx.cases.append(Case{ @@ -308,7 +308,7 @@ pub fn compareOutput( pub fn addTransform( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, src: [:0]const u8, result: [:0]const u8, ) void { @@ -320,7 +320,7 @@ pub fn addTransform( pub fn transform( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, src: [:0]const u8, result: [:0]const u8, ) void { @@ -330,7 +330,7 @@ pub fn transform( pub fn addError( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, src: [:0]const u8, expected_errors: []const []const u8, ) void { @@ -343,7 +343,7 @@ pub fn addError( pub fn compileError( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, src: [:0]const u8, expected_errors: []const []const u8, ) void { @@ -355,7 +355,7 @@ pub fn compileError( pub fn addCompile( ctx: *Cases, name: []const u8, - target: CrossTarget, + target: std.Build.ResolvedTarget, src: [:0]const u8, ) void { ctx.addObj(name, target).addCompile(src); @@ -368,9 +368,9 @@ pub fn addCompile( /// Each file should include a test manifest as a contiguous block of comments at /// the end of the file. The first line should be the test type, followed by a set of /// key-value config values, followed by a blank line, then the expected output. -pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir) void { +pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void { var current_file: []const u8 = "none"; - ctx.addFromDirInner(dir, ¤t_file) catch |err| { + ctx.addFromDirInner(dir, ¤t_file, b) catch |err| { std.debug.panicExtra( @errorReturnTrace(), @returnAddress(), @@ -386,6 +386,7 @@ fn addFromDirInner( /// This is kept up to date with the currently being processed file so /// that if any errors occur the caller knows it happened during this file. current_file: *[]const u8, + b: *std.Build, ) !void { var it = try iterable_dir.walk(ctx.arena); var filenames = std.ArrayList([]const u8).init(ctx.arena); @@ -422,7 +423,7 @@ fn addFromDirInner( var manifest = try TestManifest.parse(ctx.arena, src); const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.zig.CrossTarget); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -430,12 +431,12 @@ fn addFromDirInner( if (manifest.type == .translate_c) { for (c_frontends) |c_frontend| { - for (targets) |target| { + for (targets) |target_query| { const output = try manifest.trailingLinesSplit(ctx.arena); try ctx.translate.append(.{ .name = std.fs.path.stem(filename), .c_frontend = c_frontend, - .target = target, + .target = b.resolveTargetQuery(target_query), .link_libc = link_libc, .input = src, .kind = .{ .translate = output }, @@ -446,12 +447,12 @@ fn addFromDirInner( } if (manifest.type == .run_translated_c) { for (c_frontends) |c_frontend| { - for (targets) |target| { + for (targets) |target_query| { const output = try manifest.trailingSplit(ctx.arena); try ctx.translate.append(.{ .name = std.fs.path.stem(filename), .c_frontend = c_frontend, - .target = target, + .target = b.resolveTargetQuery(target_query), .link_libc = link_libc, .input = src, .kind = .{ .run = output }, @@ -464,16 +465,18 @@ fn addFromDirInner( var cases = std.ArrayList(usize).init(ctx.arena); // Cross-product to get all possible test combinations - for (backends) |backend| { - for (targets) |target| { + for (targets) |target_query| { + const resolved_target = b.resolveTargetQuery(target_query); + const target = resolved_target.target; + for (backends) |backend| { if (backend == .stage2 and - target.getCpuArch() != .wasm32 and target.getCpuArch() != .x86_64) + target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64) { // Other backends don't support new liveness format continue; } - if (backend == .stage2 and target.getOsTag() == .macos and - target.getCpuArch() == .x86_64 and builtin.cpu.arch == .aarch64) + if (backend == .stage2 and target.os.tag == .macos and + target.cpu.arch == .x86_64 and builtin.cpu.arch == .aarch64) { // Rosetta has issues with ZLD continue; @@ -482,7 +485,7 @@ fn addFromDirInner( const next = ctx.cases.items.len; try ctx.cases.append(.{ .name = std.fs.path.stem(filename), - .target = target, + .target = resolved_target, .backend = backend, .updates = std.ArrayList(Cases.Update).init(ctx.cases.allocator), .is_test = is_test, @@ -622,8 +625,8 @@ pub fn lowerToBuildSteps( } for (case.deps.items) |dep| { - artifact.addAnonymousModule(dep.name, .{ - .source_file = file_sources.get(dep.path).?, + artifact.root_module.addAnonymousImport(dep.name, .{ + .root_source_file = file_sources.get(dep.path).?, }); } @@ -644,9 +647,8 @@ pub fn lowerToBuildSteps( parent_step.dependOn(&artifact.step); }, .Execution => |expected_stdout| no_exec: { - const run = if (case.target.ofmt == .c) run_step: { - const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err| - std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)}); + const run = if (case.target.target.ofmt == .c) run_step: { + const target_info = case.target.toNativeTargetInfo(); if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; @@ -666,7 +668,7 @@ pub fn lowerToBuildSteps( "--", "-lc", "-target", - case.target.zigTriple(b.allocator) catch @panic("OOM"), + case.target.target.zigTriple(b.allocator) catch @panic("OOM"), }); run_c.addArtifactArg(artifact); break :run_step run_c; @@ -692,8 +694,7 @@ pub fn lowerToBuildSteps( continue; // Pass test. } - const target_info = std.zig.system.NativeTargetInfo.detect(case.target) catch |err| - std.debug.panic("unable to detect target host: {s}\n", .{@errorName(err)}); + const target_info = case.target.toNativeTargetInfo(); if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. continue; // Pass test. @@ -1159,9 +1160,9 @@ const TestManifest = struct { } fn getDefaultParser(comptime T: type) ParseFn(T) { - if (T == CrossTarget) return struct { + if (T == std.zig.CrossTarget) return struct { fn parse(str: []const u8) anyerror!T { - return CrossTarget.parse(.{ .arch_os_abi = str }); + return std.zig.CrossTarget.parse(.{ .arch_os_abi = str }); } }.parse; @@ -1198,7 +1199,6 @@ const builtin = @import("builtin"); const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const CrossTarget = std.zig.CrossTarget; const Compilation = @import("../../src/Compilation.zig"); const zig_h = @import("../../src/link.zig").File.C.zig_h; const introspect = @import("../../src/introspect.zig"); @@ -1287,7 +1287,7 @@ pub fn main() !void { if (cases.items.len == 0) { const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(arena, "target", CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.zig.CrossTarget); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -1295,12 +1295,12 @@ pub fn main() !void { if (manifest.type == .translate_c) { for (c_frontends) |c_frontend| { - for (targets) |target| { + for (targets) |target_query| { const output = try manifest.trailingLinesSplit(ctx.arena); try ctx.translate.append(.{ .name = std.fs.path.stem(filename), .c_frontend = c_frontend, - .target = target, + .target = resolveTargetQuery(target_query), .is_test = is_test, .link_libc = link_libc, .input = src, @@ -1312,12 +1312,12 @@ pub fn main() !void { } if (manifest.type == .run_translated_c) { for (c_frontends) |c_frontend| { - for (targets) |target| { + for (targets) |target_query| { const output = try manifest.trailingSplit(ctx.arena); try ctx.translate.append(.{ .name = std.fs.path.stem(filename), .c_frontend = c_frontend, - .target = target, + .target = resolveTargetQuery(target_query), .is_test = is_test, .link_libc = link_libc, .output = output, @@ -1385,6 +1385,17 @@ pub fn main() !void { return runCases(&ctx, zig_exe_path); } +fn resolveTargetQuery(query: std.zig.CrossTarget) std.Build.ResolvedTarget { + const result = std.zig.system.NativeTargetInfo.detect(query) catch + @panic("unable to resolve target query"); + + return .{ + .query = query, + .target = result.target, + .dynamic_linker = result.dynamic_linker, + }; +} + fn runCases(self: *Cases, zig_exe_path: []const u8) !void { const host = try std.zig.system.NativeTargetInfo.detect(.{}); diff --git a/test/src/CompareOutput.zig b/test/src/CompareOutput.zig index 39226f036929..b3570b6ee224 100644 --- a/test/src/CompareOutput.zig +++ b/test/src/CompareOutput.zig @@ -96,7 +96,7 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void { const exe = b.addExecutable(.{ .name = "test", - .target = .{}, + .target = b.host, .optimize = .Debug, }); exe.addAssemblyFile(write_src.files.items[0].getPath()); @@ -121,7 +121,7 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void { .name = "test", .root_source_file = write_src.files.items[0].getPath(), .optimize = optimize, - .target = .{}, + .target = b.host, }); if (case.link_libc) { exe.linkSystemLibrary("c"); @@ -146,7 +146,7 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void { const exe = b.addExecutable(.{ .name = "test", .root_source_file = write_src.files.items[0].getPath(), - .target = .{}, + .target = b.host, .optimize = .Debug, }); if (case.link_libc) { diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig index c42e9114be8c..f0dc9a8c0ce2 100644 --- a/test/src/StackTrace.zig +++ b/test/src/StackTrace.zig @@ -77,7 +77,7 @@ fn addExpect( .name = "test", .root_source_file = write_src.files.items[0].getPath(), .optimize = optimize_mode, - .target = .{}, + .target = b.host, }); const run = b.addRunArtifact(exe); diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig index cd2d0d9e3b16..544f9a53098a 100644 --- a/test/src/run_translated_c.zig +++ b/test/src/run_translated_c.zig @@ -11,7 +11,7 @@ pub const RunTranslatedCContext = struct { step: *std.Build.Step, test_index: usize, test_filter: ?[]const u8, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, const TestCase = struct { name: []const u8, @@ -86,7 +86,7 @@ pub const RunTranslatedCContext = struct { } const translate_c = b.addTranslateC(.{ .source_file = write_src.files.items[0].getPath(), - .target = .{}, + .target = b.host, .optimize = .Debug, }); diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig index a71886099f7a..71288c11da66 100644 --- a/test/src/translate_c.zig +++ b/test/src/translate_c.zig @@ -18,7 +18,7 @@ pub const TranslateCContext = struct { sources: ArrayList(SourceFile), expected_lines: ArrayList([]const u8), allow_warnings: bool, - target: CrossTarget = CrossTarget{}, + target: CrossTarget = .{}, const SourceFile = struct { filename: []const u8, @@ -109,7 +109,7 @@ pub const TranslateCContext = struct { const translate_c = b.addTranslateC(.{ .source_file = write_src.files.items[0].getPath(), - .target = case.target, + .target = b.resolveTargetQuery(case.target), .optimize = .Debug, }); diff --git a/test/standalone.zig b/test/standalone.zig index fc455a2aa71c..fdd3185cdfbc 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -89,10 +89,6 @@ pub const build_cases = [_]BuildCase{ // .build_root = "test/standalone/issue_13970", // .import = @import("standalone/issue_13970/build.zig"), //}, - .{ - .build_root = "test/standalone/main_pkg_path", - .import = @import("standalone/main_pkg_path/build.zig"), - }, .{ .build_root = "test/standalone/shared_library", .import = @import("standalone/shared_library/build.zig"), diff --git a/test/standalone/c_compiler/build.zig b/test/standalone/c_compiler/build.zig index a2191f2f2eb5..236042d487da 100644 --- a/test/standalone/c_compiler/build.zig +++ b/test/standalone/c_compiler/build.zig @@ -23,7 +23,7 @@ fn add( cpp_name: []const u8, optimize: std.builtin.OptimizeMode, ) void { - const target: std.zig.CrossTarget = .{}; + const target = b.host; const exe_c = b.addExecutable(.{ .name = c_name, @@ -42,7 +42,7 @@ fn add( exe_cpp.addCSourceFile(.{ .file = .{ .path = "test.cpp" }, .flags = &[0][]const u8{} }); exe_cpp.linkLibCpp(); - switch (target.getOsTag()) { + switch (target.target.os.tag) { .windows => { // https://github.com/ziglang/zig/issues/8531 exe_cpp.want_lto = false; diff --git a/test/standalone/child_process/build.zig b/test/standalone/child_process/build.zig index b874a7acc5e6..89558c00e609 100644 --- a/test/standalone/child_process/build.zig +++ b/test/standalone/child_process/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; if (builtin.os.tag == .wasi) return; diff --git a/test/standalone/compiler_rt_panic/build.zig b/test/standalone/compiler_rt_panic/build.zig index 3d22319bacf5..cb275e08dfec 100644 --- a/test/standalone/compiler_rt_panic/build.zig +++ b/test/standalone/compiler_rt_panic/build.zig @@ -4,16 +4,16 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const target = b.standardTargetOptions(.{}); + const resolved_target = b.standardTargetOptions(.{}); + const target = resolved_target.target; const optimize = b.standardOptimizeOption(.{}); - const abi = target.getAbi(); - if (target.getObjectFormat() != .elf or !(abi.isMusl() or abi.isGnu())) return; + if (target.ofmt != .elf or !(target.abi.isMusl() or target.abi.isGnu())) return; const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, - .target = target, + .target = resolved_target, }); exe.linkLibC(); exe.addCSourceFile(.{ diff --git a/test/standalone/dep_diamond/build.zig b/test/standalone/dep_diamond/build.zig index 6c6d9b6d1a25..9190b29594cf 100644 --- a/test/standalone/dep_diamond/build.zig +++ b/test/standalone/dep_diamond/build.zig @@ -7,21 +7,22 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; const shared = b.createModule(.{ - .source_file = .{ .path = "shared.zig" }, + .root_source_file = .{ .path = "shared.zig" }, }); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, + .target = b.host, .optimize = optimize, }); - exe.addAnonymousModule("foo", .{ - .source_file = .{ .path = "foo.zig" }, - .dependencies = &.{.{ .name = "shared", .module = shared }}, + exe.root_module.addAnonymousImport("foo", .{ + .root_source_file = .{ .path = "foo.zig" }, + .imports = &.{.{ .name = "shared", .module = shared }}, }); - exe.addAnonymousModule("bar", .{ - .source_file = .{ .path = "bar.zig" }, - .dependencies = &.{.{ .name = "shared", .module = shared }}, + exe.root_module.addAnonymousImport("bar", .{ + .root_source_file = .{ .path = "bar.zig" }, + .imports = &.{.{ .name = "shared", .module = shared }}, }); const run = b.addRunArtifact(exe); diff --git a/test/standalone/dep_mutually_recursive/build.zig b/test/standalone/dep_mutually_recursive/build.zig index e70e77540182..04589d9b5ba4 100644 --- a/test/standalone/dep_mutually_recursive/build.zig +++ b/test/standalone/dep_mutually_recursive/build.zig @@ -7,20 +7,21 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; const foo = b.createModule(.{ - .source_file = .{ .path = "foo.zig" }, + .root_source_file = .{ .path = "foo.zig" }, }); const bar = b.createModule(.{ - .source_file = .{ .path = "bar.zig" }, + .root_source_file = .{ .path = "bar.zig" }, }); - foo.dependencies.put("bar", bar) catch @panic("OOM"); - bar.dependencies.put("foo", foo) catch @panic("OOM"); + foo.addImport("bar", bar); + bar.addImport("foo", foo); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, + .target = b.host, .optimize = optimize, }); - exe.addModule("foo", foo); + exe.root_module.addImport("foo", foo); const run = b.addRunArtifact(exe); test_step.dependOn(&run.step); diff --git a/test/standalone/dep_recursive/build.zig b/test/standalone/dep_recursive/build.zig index 2e2cf4ea4d4f..a6334e6a9763 100644 --- a/test/standalone/dep_recursive/build.zig +++ b/test/standalone/dep_recursive/build.zig @@ -7,16 +7,17 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; const foo = b.createModule(.{ - .source_file = .{ .path = "foo.zig" }, + .root_source_file = .{ .path = "foo.zig" }, }); - foo.dependencies.put("foo", foo) catch @panic("OOM"); + foo.addImport("foo", foo); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, + .target = b.host, .optimize = optimize, }); - exe.addModule("foo", foo); + exe.root_module.addImport("foo", foo); const run = b.addRunArtifact(exe); test_step.dependOn(&run.step); diff --git a/test/standalone/dep_shared_builtin/build.zig b/test/standalone/dep_shared_builtin/build.zig index 175118d33192..33d53ad166ba 100644 --- a/test/standalone/dep_shared_builtin/build.zig +++ b/test/standalone/dep_shared_builtin/build.zig @@ -9,10 +9,11 @@ pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, + .target = b.host, .optimize = optimize, }); - exe.addAnonymousModule("foo", .{ - .source_file = .{ .path = "foo.zig" }, + exe.root_module.addAnonymousImport("foo", .{ + .root_source_file = .{ .path = "foo.zig" }, }); const run = b.addRunArtifact(exe); diff --git a/test/standalone/dep_triangle/build.zig b/test/standalone/dep_triangle/build.zig index 63eed997ceb6..b15555499753 100644 --- a/test/standalone/dep_triangle/build.zig +++ b/test/standalone/dep_triangle/build.zig @@ -7,19 +7,20 @@ pub fn build(b: *std.Build) void { const optimize: std.builtin.OptimizeMode = .Debug; const shared = b.createModule(.{ - .source_file = .{ .path = "shared.zig" }, + .root_source_file = .{ .path = "shared.zig" }, }); const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, + .target = b.host, .optimize = optimize, }); - exe.addAnonymousModule("foo", .{ - .source_file = .{ .path = "foo.zig" }, - .dependencies = &.{.{ .name = "shared", .module = shared }}, + exe.root_module.addAnonymousImport("foo", .{ + .root_source_file = .{ .path = "foo.zig" }, + .imports = &.{.{ .name = "shared", .module = shared }}, }); - exe.addModule("shared", shared); + exe.root_module.addImport("shared", shared); const run = b.addRunArtifact(exe); test_step.dependOn(&run.step); diff --git a/test/standalone/embed_generated_file/build.zig b/test/standalone/embed_generated_file/build.zig index ca05c33c39a6..3f67cdea5421 100644 --- a/test/standalone/embed_generated_file/build.zig +++ b/test/standalone/embed_generated_file/build.zig @@ -7,10 +7,10 @@ pub fn build(b: *std.Build) void { const bootloader = b.addExecutable(.{ .name = "bootloader", .root_source_file = .{ .path = "bootloader.zig" }, - .target = .{ + .target = b.resolveTargetQuery(.{ .cpu_arch = .x86, .os_tag = .freestanding, - }, + }), .optimize = .ReleaseSmall, }); @@ -18,8 +18,8 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "main.zig" }, .optimize = .Debug, }); - exe.addAnonymousModule("bootloader.elf", .{ - .source_file = bootloader.getEmittedBin(), + exe.root_module.addAnonymousImport("bootloader.elf", .{ + .root_source_file = bootloader.getEmittedBin(), }); // TODO: actually check the output diff --git a/test/standalone/empty_env/build.zig b/test/standalone/empty_env/build.zig index 27ec75be22df..a2fe48312827 100644 --- a/test/standalone/empty_env/build.zig +++ b/test/standalone/empty_env/build.zig @@ -15,6 +15,7 @@ pub fn build(b: *std.Build) void { const main = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, + .target = b.host, .optimize = optimize, }); diff --git a/test/standalone/extern/build.zig b/test/standalone/extern/build.zig index 153380e91ded..401deb3dc4d1 100644 --- a/test/standalone/extern/build.zig +++ b/test/standalone/extern/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { const obj = b.addObject(.{ .name = "exports", .root_source_file = .{ .path = "exports.zig" }, - .target = .{}, + .target = b.host, .optimize = optimize, }); const main = b.addTest(.{ diff --git a/test/standalone/global_linkage/build.zig b/test/standalone/global_linkage/build.zig index d560027265cb..13b7fcfa0e5f 100644 --- a/test/standalone/global_linkage/build.zig +++ b/test/standalone/global_linkage/build.zig @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; const obj1 = b.addStaticLibrary(.{ .name = "obj1", diff --git a/test/standalone/install_raw_hex/build.zig b/test/standalone/install_raw_hex/build.zig index c05490a3e5b9..d1ec55ab5349 100644 --- a/test/standalone/install_raw_hex/build.zig +++ b/test/standalone/install_raw_hex/build.zig @@ -5,12 +5,12 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const target = .{ + const target = b.resolveTargetQuery(.{ .cpu_arch = .thumb, .cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m4 }, .os_tag = .freestanding, .abi = .gnueabihf, - }; + }); const optimize: std.builtin.OptimizeMode = .Debug; diff --git a/test/standalone/ios/build.zig b/test/standalone/ios/build.zig index 18168688445d..7642f3a3e843 100644 --- a/test/standalone/ios/build.zig +++ b/test/standalone/ios/build.zig @@ -8,12 +8,12 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{ + const target = b.resolveTargetQuery(.{ .cpu_arch = .aarch64, .os_tag = .ios, - }; - const target_info = std.zig.system.NativeTargetInfo.detect(target) catch @panic("couldn't detect native target"); - const sdk = std.zig.system.darwin.getSdk(b.allocator, target_info.target) orelse @panic("no iOS SDK found"); + }); + const sdk = std.zig.system.darwin.getSdk(b.allocator, target.target) orelse + @panic("no iOS SDK found"); b.sysroot = sdk; const exe = b.addExecutable(.{ diff --git a/test/standalone/issue_11595/build.zig b/test/standalone/issue_11595/build.zig index e69b4bfdd593..c591b3058b5d 100644 --- a/test/standalone/issue_11595/build.zig +++ b/test/standalone/issue_11595/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; if (builtin.os.tag == .windows) { // https://github.com/ziglang/zig/issues/12419 diff --git a/test/standalone/issue_12588/build.zig b/test/standalone/issue_12588/build.zig index e6d01192d3cf..aaf8f6c3149b 100644 --- a/test/standalone/issue_12588/build.zig +++ b/test/standalone/issue_12588/build.zig @@ -5,13 +5,12 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; const obj = b.addObject(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, - .target = target, + .target = b.host, }); _ = obj.getEmittedLlvmIr(); _ = obj.getEmittedLlvmBc(); diff --git a/test/standalone/issue_12706/build.zig b/test/standalone/issue_12706/build.zig index fb60ac28a114..9a80dae256fe 100644 --- a/test/standalone/issue_12706/build.zig +++ b/test/standalone/issue_12706/build.zig @@ -1,13 +1,12 @@ const std = @import("std"); const builtin = @import("builtin"); -const CrossTarget = std.zig.CrossTarget; pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; const exe = b.addExecutable(.{ .name = "main", diff --git a/test/standalone/issue_339/build.zig b/test/standalone/issue_339/build.zig index d53ba992ea3e..5dc686a77924 100644 --- a/test/standalone/issue_339/build.zig +++ b/test/standalone/issue_339/build.zig @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; const obj = b.addObject(.{ .name = "test", diff --git a/test/standalone/issue_8550/build.zig b/test/standalone/issue_8550/build.zig index a7815618744b..557019cfdc04 100644 --- a/test/standalone/issue_8550/build.zig +++ b/test/standalone/issue_8550/build.zig @@ -5,13 +5,13 @@ pub fn build(b: *std.Build) !void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target = std.zig.CrossTarget{ + const target = b.resolveTargetQuery(.{ .os_tag = .freestanding, .cpu_arch = .arm, .cpu_model = .{ .explicit = &std.Target.arm.cpu.arm1176jz_s, }, - }; + }); const kernel = b.addExecutable(.{ .name = "kernel", diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig index 5dc605e71111..140f276ebe04 100644 --- a/test/standalone/load_dynamic_library/build.zig +++ b/test/standalone/load_dynamic_library/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; if (builtin.os.tag == .wasi) return; diff --git a/test/standalone/main_pkg_path/a/test.zig b/test/standalone/main_pkg_path/a/test.zig deleted file mode 100644 index 286489912b39..000000000000 --- a/test/standalone/main_pkg_path/a/test.zig +++ /dev/null @@ -1,5 +0,0 @@ -const b = @import("../b.zig"); - -test "main pkg path" { - b.foo(); -} diff --git a/test/standalone/main_pkg_path/b.zig b/test/standalone/main_pkg_path/b.zig deleted file mode 100644 index 87d61fa63e88..000000000000 --- a/test/standalone/main_pkg_path/b.zig +++ /dev/null @@ -1 +0,0 @@ -pub fn foo() void {} diff --git a/test/standalone/main_pkg_path/build.zig b/test/standalone/main_pkg_path/build.zig deleted file mode 100644 index d1b67592b5b0..000000000000 --- a/test/standalone/main_pkg_path/build.zig +++ /dev/null @@ -1,13 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) void { - const test_step = b.step("test", "Test it"); - b.default_step = test_step; - - const test_exe = b.addTest(.{ - .root_source_file = .{ .path = "a/test.zig" }, - .main_pkg_path = .{ .path = "." }, - }); - - test_step.dependOn(&b.addRunArtifact(test_exe).step); -} diff --git a/test/standalone/mix_c_files/build.zig b/test/standalone/mix_c_files/build.zig index b675be9eebe4..e91f87e13284 100644 --- a/test/standalone/mix_c_files/build.zig +++ b/test/standalone/mix_c_files/build.zig @@ -19,6 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize const exe = b.addExecutable(.{ .name = "test", .root_source_file = .{ .path = "main.zig" }, + .target = b.host, .optimize = optimize, }); exe.addCSourceFile(.{ .file = .{ .path = "test.c" }, .flags = &[_][]const u8{"-std=c11"} }); diff --git a/test/standalone/mix_o_files/build.zig b/test/standalone/mix_o_files/build.zig index 980e52ad3baa..aa648145a831 100644 --- a/test/standalone/mix_o_files/build.zig +++ b/test/standalone/mix_o_files/build.zig @@ -5,7 +5,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; const obj = b.addObject(.{ .name = "base64", diff --git a/test/standalone/options/build.zig b/test/standalone/options/build.zig index d87610ba220a..97cf91c1fbc3 100644 --- a/test/standalone/options/build.zig +++ b/test/standalone/options/build.zig @@ -3,7 +3,7 @@ const std = @import("std"); pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "src/main.zig" }, - .target = .{}, + .target = b.host, .optimize = .Debug, }); diff --git a/test/standalone/pie/build.zig b/test/standalone/pie/build.zig index 1efcd5c26e87..2e9f99ff4b67 100644 --- a/test/standalone/pie/build.zig +++ b/test/standalone/pie/build.zig @@ -5,10 +5,10 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{ + const target = b.resolveTargetQuery(.{ .os_tag = .linux, .cpu_arch = .x86_64, - }; + }); const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, diff --git a/test/standalone/pkg_import/build.zig b/test/standalone/pkg_import/build.zig index 30f4b2ede49b..207f924f9be9 100644 --- a/test/standalone/pkg_import/build.zig +++ b/test/standalone/pkg_import/build.zig @@ -10,8 +10,9 @@ pub fn build(b: *std.Build) void { .name = "test", .root_source_file = .{ .path = "test.zig" }, .optimize = optimize, + .target = b.host, }); - exe.addAnonymousModule("my_pkg", .{ .source_file = .{ .path = "pkg.zig" } }); + exe.root_module.addAnonymousImport("my_pkg", .{ .root_source_file = .{ .path = "pkg.zig" } }); const run = b.addRunArtifact(exe); test_step.dependOn(&run.step); diff --git a/test/standalone/self_exe_symlink/build.zig b/test/standalone/self_exe_symlink/build.zig index 10e0a6a5127d..c4720ce967cb 100644 --- a/test/standalone/self_exe_symlink/build.zig +++ b/test/standalone/self_exe_symlink/build.zig @@ -7,11 +7,11 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; // The test requires getFdPath in order to to get the path of the // File returned by openSelfExe - if (!std.os.isGetFdPathSupportedOnTarget(target.getOs())) return; + if (!std.os.isGetFdPathSupportedOnTarget(target.target.os)) return; const main = b.addExecutable(.{ .name = "main", diff --git a/test/standalone/shared_library/build.zig b/test/standalone/shared_library/build.zig index 4b4a154225c4..4d409295e866 100644 --- a/test/standalone/shared_library/build.zig +++ b/test/standalone/shared_library/build.zig @@ -10,7 +10,7 @@ pub fn build(b: *std.Build) void { } const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; const lib = b.addSharedLibrary(.{ .name = "mathtest", .root_source_file = .{ .path = "mathtest.zig" }, diff --git a/test/standalone/stack_iterator/build.zig b/test/standalone/stack_iterator/build.zig index 628210452c42..6a98011e411a 100644 --- a/test/standalone/stack_iterator/build.zig +++ b/test/standalone/stack_iterator/build.zig @@ -22,11 +22,10 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "unwind.zig" }, .target = target, .optimize = optimize, + .unwind_tables = target.target.isDarwin(), + .omit_frame_pointer = false, }); - if (target.isDarwin()) exe.unwind_tables = true; - exe.omit_frame_pointer = false; - const run_cmd = b.addRunArtifact(exe); test_step.dependOn(&run_cmd.step); } @@ -46,11 +45,10 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "unwind.zig" }, .target = target, .optimize = optimize, + .unwind_tables = true, + .omit_frame_pointer = true, }); - exe.omit_frame_pointer = true; - exe.unwind_tables = true; - const run_cmd = b.addRunArtifact(exe); test_step.dependOn(&run_cmd.step); } @@ -69,11 +67,12 @@ pub fn build(b: *std.Build) void { .name = "c_shared_lib", .target = target, .optimize = optimize, + .strip = false, }); - if (target.isWindows()) c_shared_lib.defineCMacro("LIB_API", "__declspec(dllexport)"); + if (target.target.os.tag == .windows) + c_shared_lib.defineCMacro("LIB_API", "__declspec(dllexport)"); - c_shared_lib.strip = false; c_shared_lib.addCSourceFile(.{ .file = .{ .path = "shared_lib.c" }, .flags = &.{"-fomit-frame-pointer"}, @@ -85,10 +84,10 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "shared_lib_unwind.zig" }, .target = target, .optimize = optimize, + .unwind_tables = target.target.isDarwin(), + .omit_frame_pointer = true, }); - if (target.isDarwin()) exe.unwind_tables = true; - exe.omit_frame_pointer = true; exe.linkLibrary(c_shared_lib); const run_cmd = b.addRunArtifact(exe); diff --git a/test/standalone/static_c_lib/build.zig b/test/standalone/static_c_lib/build.zig index 1e3e80c36323..244107b0f1e1 100644 --- a/test/standalone/static_c_lib/build.zig +++ b/test/standalone/static_c_lib/build.zig @@ -9,7 +9,7 @@ pub fn build(b: *std.Build) void { const foo = b.addStaticLibrary(.{ .name = "foo", .optimize = optimize, - .target = .{}, + .target = b.host, }); foo.addCSourceFile(.{ .file = .{ .path = "foo.c" }, .flags = &[_][]const u8{} }); foo.addIncludePath(.{ .path = "." }); diff --git a/test/standalone/strip_empty_loop/build.zig b/test/standalone/strip_empty_loop/build.zig index e64781d99142..4875bd9128c7 100644 --- a/test/standalone/strip_empty_loop/build.zig +++ b/test/standalone/strip_empty_loop/build.zig @@ -5,15 +5,15 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize = std.builtin.OptimizeMode.Debug; - const target = std.zig.CrossTarget{}; + const target = b.host; const main = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = target, + .strip = true, }); - main.strip = true; // TODO: actually check the output _ = main.getEmittedBin(); diff --git a/test/standalone/strip_struct_init/build.zig b/test/standalone/strip_struct_init/build.zig index b67da4681905..2d903f973a1f 100644 --- a/test/standalone/strip_struct_init/build.zig +++ b/test/standalone/strip_struct_init/build.zig @@ -9,8 +9,8 @@ pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, + .strip = true, }); - main.strip = true; test_step.dependOn(&b.addRunArtifact(main).step); } diff --git a/test/standalone/test_runner_module_imports/build.zig b/test/standalone/test_runner_module_imports/build.zig index f27771889827..af8e68d71789 100644 --- a/test/standalone/test_runner_module_imports/build.zig +++ b/test/standalone/test_runner_module_imports/build.zig @@ -6,13 +6,13 @@ pub fn build(b: *std.Build) void { .test_runner = "test_runner/main.zig", }); - const module1 = b.createModule(.{ .source_file = .{ .path = "module1/main.zig" } }); + const module1 = b.createModule(.{ .root_source_file = .{ .path = "module1/main.zig" } }); const module2 = b.createModule(.{ - .source_file = .{ .path = "module2/main.zig" }, - .dependencies = &.{.{ .name = "module1", .module = module1 }}, + .root_source_file = .{ .path = "module2/main.zig" }, + .imports = &.{.{ .name = "module1", .module = module1 }}, }); - t.addModule("module2", module2); + t.root_module.addImport("module2", module2); const test_step = b.step("test", "Run unit tests"); test_step.dependOn(&b.addRunArtifact(t).step); diff --git a/test/standalone/windows_resources/build.zig b/test/standalone/windows_resources/build.zig index 9476fa7839db..e927a03fc40f 100644 --- a/test/standalone/windows_resources/build.zig +++ b/test/standalone/windows_resources/build.zig @@ -4,21 +4,25 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const native_target: std.zig.CrossTarget = .{}; - const cross_target = .{ + const cross_target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu, - }; + }); - add(b, native_target, .any, test_step); + add(b, b.host, .any, test_step); add(b, cross_target, .any, test_step); - add(b, native_target, .gnu, test_step); + add(b, b.host, .gnu, test_step); add(b, cross_target, .gnu, test_step); } -fn add(b: *std.Build, target: std.zig.CrossTarget, rc_includes: enum { any, gnu }, test_step: *std.Build.Step) void { +fn add( + b: *std.Build, + target: std.Build.ResolvedTarget, + rc_includes: enum { any, gnu }, + test_step: *std.Build.Step, +) void { const exe = b.addExecutable(.{ .name = "zig_resource_test", .root_source_file = .{ .path = "main.zig" }, diff --git a/test/standalone/windows_spawn/build.zig b/test/standalone/windows_spawn/build.zig index 6c865f0a9fc1..a52cbd7202a3 100644 --- a/test/standalone/windows_spawn/build.zig +++ b/test/standalone/windows_spawn/build.zig @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const optimize: std.builtin.OptimizeMode = .Debug; - const target: std.zig.CrossTarget = .{}; + const target = b.host; if (builtin.os.tag != .windows) return; diff --git a/test/standalone/zerolength_check/build.zig b/test/standalone/zerolength_check/build.zig index 4e5c1937f733..dacfc841c1a7 100644 --- a/test/standalone/zerolength_check/build.zig +++ b/test/standalone/zerolength_check/build.zig @@ -13,11 +13,11 @@ pub fn build(b: *std.Build) void { fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { const unit_tests = b.addTest(.{ .root_source_file = .{ .path = "src/main.zig" }, - .target = .{ + .target = b.resolveTargetQuery(.{ .os_tag = .wasi, .cpu_arch = .wasm32, .cpu_features_add = std.Target.wasm.featureSet(&.{.bulk_memory}), - }, + }), .optimize = optimize, }); diff --git a/test/tests.zig b/test/tests.zig index 808ffad6ee17..a8f9b6281021 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; -const CrossTarget = std.zig.CrossTarget; const mem = std.mem; const OptimizeMode = std.builtin.OptimizeMode; const Step = std.Build.Step; @@ -22,13 +21,13 @@ pub const CompareOutputContext = @import("src/CompareOutput.zig"); pub const StackTracesContext = @import("src/StackTrace.zig"); const TestTarget = struct { - target: CrossTarget = .{}, + target: std.zig.CrossTarget = .{}, optimize_mode: std.builtin.OptimizeMode = .Debug, link_libc: ?bool = null, single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, - force_pic: ?bool = null, + pic: ?bool = null, strip: ?bool = null, }; @@ -105,7 +104,7 @@ const test_targets = blk: { }, .use_llvm = false, .use_lld = false, - .force_pic = true, + .pic = true, }, .{ .target = .{ @@ -146,7 +145,7 @@ const test_targets = blk: { //}, // https://github.com/ziglang/zig/issues/13623 //.{ - // .target = CrossTarget.parse(.{ + // .target = std.zig.CrossTarget.parse(.{ // .arch_os_abi = "arm-linux-none", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -287,13 +286,13 @@ const test_targets = blk: { }, .{ - .target = CrossTarget.parse(.{ + .target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8a", }) catch unreachable, }, .{ - .target = CrossTarget.parse(.{ + .target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }) catch unreachable, @@ -301,7 +300,7 @@ const test_targets = blk: { }, // https://github.com/ziglang/zig/issues/3287 //.{ - // .target = CrossTarget.parse(.{ + // .target = std.zig.CrossTarget.parse(.{ // .arch_os_abi = "arm-linux-gnueabihf", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -495,10 +494,10 @@ const test_targets = blk: { }; const CAbiTarget = struct { - target: CrossTarget = .{}, + target: std.zig.CrossTarget = .{}, use_llvm: ?bool = null, use_lld: ?bool = null, - force_pic: ?bool = null, + pic: ?bool = null, strip: ?bool = null, c_defines: []const []const u8 = &.{}, }; @@ -543,7 +542,7 @@ const c_abi_targets = [_]CAbiTarget{ }, .use_llvm = false, .use_lld = false, - .force_pic = true, + .pic = true, .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, }, .{ @@ -645,7 +644,7 @@ pub fn addStackTraceTests( const check_exe = b.addExecutable(.{ .name = "check-stack-trace", .root_source_file = .{ .path = "test/src/check-stack-trace.zig" }, - .target = .{}, + .target = b.host, .optimize = .Debug, }); @@ -682,12 +681,14 @@ pub fn addStandaloneTests( if (os_tag != builtin.os.tag) continue; } + const resolved_target = b.resolveTargetQuery(case.target); + if (case.is_exe) { const exe = b.addExecutable(.{ .name = std.fs.path.stem(case.src_path), .root_source_file = .{ .path = case.src_path }, .optimize = optimize, - .target = case.target, + .target = resolved_target, }); if (case.link_libc) exe.linkLibC(); @@ -701,7 +702,7 @@ pub fn addStandaloneTests( .name = std.fs.path.stem(case.src_path), .root_source_file = .{ .path = case.src_path }, .optimize = optimize, - .target = case.target, + .target = resolved_target, }); if (case.link_libc) exe.linkLibC(); @@ -1001,7 +1002,7 @@ pub fn addTranslateCTests(b: *std.Build, test_filter: ?[]const u8) *Step { pub fn addRunTranslatedCTests( b: *std.Build, test_filter: ?[]const u8, - target: std.zig.CrossTarget, + target: std.Build.ResolvedTarget, ) *Step { const cases = b.allocator.create(RunTranslatedCContext) catch @panic("OOM"); cases.* = .{ @@ -1105,7 +1106,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const these_tests = b.addTest(.{ .root_source_file = .{ .path = options.root_src }, .optimize = test_target.optimize_mode, - .target = test_target.target, + .target = b.resolveTargetQuery(test_target.target), .max_rss = max_rss, .filter = options.test_filter, .link_libc = test_target.link_libc, @@ -1113,9 +1114,9 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { .use_llvm = test_target.use_llvm, .use_lld = test_target.use_lld, .zig_lib_dir = .{ .path = "lib" }, + .pic = test_target.pic, + .strip = test_target.strip, }); - these_tests.force_pic = test_target.force_pic; - these_tests.strip = test_target.strip; const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else ""; const backend_suffix = if (test_target.use_llvm == true) "-llvm" @@ -1126,7 +1127,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { else ""; const use_lld = if (test_target.use_lld == false) "-no-lld" else ""; - const use_pic = if (test_target.force_pic == true) "-pic" else ""; + const use_pic = if (test_target.pic == true) "-pic" else ""; these_tests.addIncludePath(.{ .path = "test" }); @@ -1154,7 +1155,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const compile_c = b.addExecutable(.{ .name = qualified_name, .link_libc = test_target.link_libc, - .target = altered_target, + .target = b.resolveTargetQuery(altered_target), .zig_lib_dir = .{ .path = "lib" }, }); compile_c.addCSourceFile(.{ @@ -1229,41 +1230,39 @@ pub fn addCAbiTests(b: *std.Build, skip_non_native: bool, skip_release: bool) *S for (c_abi_targets) |c_abi_target| { if (skip_non_native and !c_abi_target.target.isNative()) continue; - if (c_abi_target.target.isWindows() and c_abi_target.target.getCpuArch() == .aarch64) { + const resolved_target = b.resolveTargetQuery(c_abi_target.target); + const target = resolved_target.target; + + if (target.os.tag == .windows and target.cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/14908 continue; } const test_step = b.addTest(.{ .name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{ - c_abi_target.target.zigTriple(b.allocator) catch @panic("OOM"), - c_abi_target.target.getCpuModel().name, + target.zigTriple(b.allocator) catch @panic("OOM"), + target.cpu.model.name, @tagName(optimize_mode), if (c_abi_target.use_llvm == true) "-llvm" - else if (c_abi_target.target.ofmt == std.Target.ObjectFormat.c) + else if (target.ofmt == .c) "-cbe" else if (c_abi_target.use_llvm == false) "-selfhosted" else "", if (c_abi_target.use_lld == false) "-no-lld" else "", - if (c_abi_target.force_pic == true) "-pic" else "", + if (c_abi_target.pic == true) "-pic" else "", }), .root_source_file = .{ .path = "test/c_abi/main.zig" }, - .target = c_abi_target.target, + .target = resolved_target, .optimize = optimize_mode, .link_libc = true, .use_llvm = c_abi_target.use_llvm, .use_lld = c_abi_target.use_lld, + .pic = c_abi_target.pic, + .strip = c_abi_target.strip, }); - test_step.force_pic = c_abi_target.force_pic; - test_step.strip = c_abi_target.strip; - if (c_abi_target.target.abi != null and c_abi_target.target.abi.?.isMusl()) { - // TODO NativeTargetInfo insists on dynamically linking musl - // for some reason? - test_step.target_info.dynamic_linker.max_byte = null; - } test_step.addCSourceFile(.{ .file = .{ .path = "test/c_abi/cfuncs.c" }, .flags = &.{"-std=c99"}, @@ -1297,8 +1296,8 @@ pub fn addCases( var dir = try b.build_root.handle.openDir("test/cases", .{ .iterate = true }); defer dir.close(); - cases.addFromDir(dir); - try @import("cases.zig").addCases(&cases, build_options); + cases.addFromDir(dir, b); + try @import("cases.zig").addCases(&cases, build_options, b); const cases_dir_path = try b.build_root.join(b.allocator, &.{ "test", "cases" }); cases.lowerToBuildSteps( From dd45095ba13217021551f4988953f7e337f9a694 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 2 Dec 2023 22:13:45 -0700 Subject: [PATCH 006/133] spelling fixes --- lib/std/Build/Module.zig | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index c672ae6c2e7c..3428581333e1 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -30,21 +30,11 @@ stack_check: ?bool, sanitize_c: ?bool, sanitize_thread: ?bool, code_model: std.builtin.CodeModel, -/// Whether to emit machine code that integrates with Valgrind. valgrind: ?bool, -/// Position Independent Code pic: ?bool, red_zone: ?bool, -/// Whether to omit the stack frame pointer. Frees up a register and makes it -/// more more difficiult to obtain stack traces. Has target-dependent effects. omit_frame_pointer: ?bool, -/// `true` requires a compilation that includes this Module to link libc. -/// `false` causes a build failure if a compilation that includes this Module would link libc. -/// `null` neither requires nor prevents libc from being linked. link_libc: ?bool, -/// `true` requires a compilation that includes this Module to link libc++. -/// `false` causes a build failure if a compilation that includes this Module would link libc++. -/// `null` neither requires nor prevents libc++ from being linked. link_libcpp: ?bool, /// Symbols to be exported when compiling to WebAssembly. @@ -161,7 +151,13 @@ pub const CreateOptions = struct { target: ?std.Build.ResolvedTarget = null, optimize: ?std.builtin.OptimizeMode = null, + /// `true` requires a compilation that includes this Module to link libc. + /// `false` causes a build failure if a compilation that includes this Module would link libc. + /// `null` neither requires nor prevents libc from being linked. link_libc: ?bool = null, + /// `true` requires a compilation that includes this Module to link libc++. + /// `false` causes a build failure if a compilation that includes this Module would link libc++. + /// `null` neither requires nor prevents libc++ from being linked. link_libcpp: ?bool = null, single_threaded: ?bool = null, strip: ?bool = null, @@ -173,11 +169,13 @@ pub const CreateOptions = struct { stack_check: ?bool = null, sanitize_c: ?bool = null, sanitize_thread: ?bool = null, + /// Whether to emit machine code that integrates with Valgrind. valgrind: ?bool = null, + /// Position Independent Code pic: ?bool = null, red_zone: ?bool = null, /// Whether to omit the stack frame pointer. Frees up a register and makes it - /// more more difficiult to obtain stack traces. Has target-dependent effects. + /// more difficult to obtain stack traces. Has target-dependent effects. omit_frame_pointer: ?bool = null, }; From ad385649b985c53ddec530c627dccbe30c0ce0a6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 12:32:58 -0700 Subject: [PATCH 007/133] fix std lib tests --- lib/std/Build/Step/Options.zig | 7 ++++++- lib/std/zig.zig | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 362e030e5a9b..9ed936fe7e69 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -294,7 +294,12 @@ test Options { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const detected = try std.zig.system.NativeTargetInfo.detect(.{}); + const host: std.Build.ResolvedTarget = .{ + .query = .{}, + .target = detected.target, + .dynamic_linker = detected.dynamic_linker, + }; var cache: std.Build.Cache = .{ .gpa = arena.allocator(), diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 89e014190c2b..9af804fa0a61 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -212,7 +212,7 @@ pub const BuildId = union(enum) { hexstring: HexString, pub fn eql(a: BuildId, b: BuildId) bool { - const Tag = @TypeOf(BuildId).Union.tag_type.?; + const Tag = @typeInfo(BuildId).Union.tag_type.?; const a_tag: Tag = a; const b_tag: Tag = b; if (a_tag != b_tag) return false; From 0ee8fbb15dd32a2bb91696e4765926e9170d2a23 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 14:12:17 -0700 Subject: [PATCH 008/133] build runner: print subtree of failed nodes context Previously when an error message is printed, it is sometimes not possible to know which build step it corresponds to. With the subtree printed in this commit, the context is always clear. --- lib/build_runner.zig | 322 +++++++++++++++++++++++++------------------ 1 file changed, 185 insertions(+), 137 deletions(-) diff --git a/lib/build_runner.zig b/lib/build_runner.zig index fba1c90d71a7..8be6b61425b1 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -363,7 +363,7 @@ const Run = struct { claimed_rss: usize, summary: ?Summary, ttyconf: std.io.tty.Config, - stderr: std.fs.File, + stderr: File, }; fn runStepNames( @@ -584,7 +584,7 @@ const PrintNode = struct { last: bool = false, }; -fn printPrefix(node: *PrintNode, stderr: std.fs.File, ttyconf: std.io.tty.Config) !void { +fn printPrefix(node: *PrintNode, stderr: File, ttyconf: std.io.tty.Config) !void { const parent = node.parent orelse return; if (parent.parent == null) return; try printPrefix(parent, stderr, ttyconf); @@ -598,11 +598,145 @@ fn printPrefix(node: *PrintNode, stderr: std.fs.File, ttyconf: std.io.tty.Config } } +fn printChildNodePrefix(stderr: File, ttyconf: std.io.tty.Config) !void { + try stderr.writeAll(switch (ttyconf) { + .no_color, .windows_api => "+- ", + .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ + }); +} + +fn printStepStatus( + s: *Step, + stderr: File, + ttyconf: std.io.tty.Config, + run: *const Run, +) !void { + switch (s.state) { + .precheck_unstarted => unreachable, + .precheck_started => unreachable, + .precheck_done => unreachable, + .running => unreachable, + + .dependency_failure => { + try ttyconf.setColor(stderr, .dim); + try stderr.writeAll(" transitive failure\n"); + try ttyconf.setColor(stderr, .reset); + }, + + .success => { + try ttyconf.setColor(stderr, .green); + if (s.result_cached) { + try stderr.writeAll(" cached"); + } else if (s.test_results.test_count > 0) { + const pass_count = s.test_results.passCount(); + try stderr.writer().print(" {d} passed", .{pass_count}); + if (s.test_results.skip_count > 0) { + try ttyconf.setColor(stderr, .yellow); + try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count}); + } + } else { + try stderr.writeAll(" success"); + } + try ttyconf.setColor(stderr, .reset); + if (s.result_duration_ns) |ns| { + try ttyconf.setColor(stderr, .dim); + if (ns >= std.time.ns_per_min) { + try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min}); + } else if (ns >= std.time.ns_per_s) { + try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s}); + } else if (ns >= std.time.ns_per_ms) { + try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms}); + } else if (ns >= std.time.ns_per_us) { + try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us}); + } else { + try stderr.writer().print(" {d}ns", .{ns}); + } + try ttyconf.setColor(stderr, .reset); + } + if (s.result_peak_rss != 0) { + const rss = s.result_peak_rss; + try ttyconf.setColor(stderr, .dim); + if (rss >= 1000_000_000) { + try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000}); + } else if (rss >= 1000_000) { + try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000}); + } else if (rss >= 1000) { + try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000}); + } else { + try stderr.writer().print(" MaxRSS:{d}B", .{rss}); + } + try ttyconf.setColor(stderr, .reset); + } + try stderr.writeAll("\n"); + }, + .skipped, .skipped_oom => |skip| { + try ttyconf.setColor(stderr, .yellow); + try stderr.writeAll(" skipped"); + if (skip == .skipped_oom) { + try stderr.writeAll(" (not enough memory)"); + try ttyconf.setColor(stderr, .dim); + try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); + try ttyconf.setColor(stderr, .yellow); + } + try stderr.writeAll("\n"); + try ttyconf.setColor(stderr, .reset); + }, + .failure => try printStepFailure(s, stderr, ttyconf), + } +} + +fn printStepFailure( + s: *Step, + stderr: File, + ttyconf: std.io.tty.Config, +) !void { + if (s.result_error_bundle.errorMessageCount() > 0) { + try ttyconf.setColor(stderr, .red); + try stderr.writer().print(" {d} errors\n", .{ + s.result_error_bundle.errorMessageCount(), + }); + try ttyconf.setColor(stderr, .reset); + } else if (!s.test_results.isSuccess()) { + try stderr.writer().print(" {d}/{d} passed", .{ + s.test_results.passCount(), s.test_results.test_count, + }); + if (s.test_results.fail_count > 0) { + try stderr.writeAll(", "); + try ttyconf.setColor(stderr, .red); + try stderr.writer().print("{d} failed", .{ + s.test_results.fail_count, + }); + try ttyconf.setColor(stderr, .reset); + } + if (s.test_results.skip_count > 0) { + try stderr.writeAll(", "); + try ttyconf.setColor(stderr, .yellow); + try stderr.writer().print("{d} skipped", .{ + s.test_results.skip_count, + }); + try ttyconf.setColor(stderr, .reset); + } + if (s.test_results.leak_count > 0) { + try stderr.writeAll(", "); + try ttyconf.setColor(stderr, .red); + try stderr.writer().print("{d} leaked", .{ + s.test_results.leak_count, + }); + try ttyconf.setColor(stderr, .reset); + } + try stderr.writeAll("\n"); + } else { + try ttyconf.setColor(stderr, .red); + try stderr.writeAll(" failure\n"); + try ttyconf.setColor(stderr, .reset); + } +} + fn printTreeStep( b: *std.Build, s: *Step, run: *const Run, - stderr: std.fs.File, + stderr: File, ttyconf: std.io.tty.Config, parent_node: *PrintNode, step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), @@ -615,10 +749,7 @@ fn printTreeStep( if (!first) try ttyconf.setColor(stderr, .dim); if (parent_node.parent != null) { if (parent_node.last) { - try stderr.writeAll(switch (ttyconf) { - .no_color, .windows_api => "+- ", - .escape_codes => "\x1B\x28\x30\x6d\x71\x1B\x28\x42 ", // └─ - }); + try printChildNodePrefix(stderr, ttyconf); } else { try stderr.writeAll(switch (ttyconf) { .no_color, .windows_api => "+- ", @@ -631,119 +762,7 @@ fn printTreeStep( try stderr.writeAll(s.name); if (first) { - switch (s.state) { - .precheck_unstarted => unreachable, - .precheck_started => unreachable, - .precheck_done => unreachable, - .running => unreachable, - - .dependency_failure => { - try ttyconf.setColor(stderr, .dim); - try stderr.writeAll(" transitive failure\n"); - try ttyconf.setColor(stderr, .reset); - }, - - .success => { - try ttyconf.setColor(stderr, .green); - if (s.result_cached) { - try stderr.writeAll(" cached"); - } else if (s.test_results.test_count > 0) { - const pass_count = s.test_results.passCount(); - try stderr.writer().print(" {d} passed", .{pass_count}); - if (s.test_results.skip_count > 0) { - try ttyconf.setColor(stderr, .yellow); - try stderr.writer().print(" {d} skipped", .{s.test_results.skip_count}); - } - } else { - try stderr.writeAll(" success"); - } - try ttyconf.setColor(stderr, .reset); - if (s.result_duration_ns) |ns| { - try ttyconf.setColor(stderr, .dim); - if (ns >= std.time.ns_per_min) { - try stderr.writer().print(" {d}m", .{ns / std.time.ns_per_min}); - } else if (ns >= std.time.ns_per_s) { - try stderr.writer().print(" {d}s", .{ns / std.time.ns_per_s}); - } else if (ns >= std.time.ns_per_ms) { - try stderr.writer().print(" {d}ms", .{ns / std.time.ns_per_ms}); - } else if (ns >= std.time.ns_per_us) { - try stderr.writer().print(" {d}us", .{ns / std.time.ns_per_us}); - } else { - try stderr.writer().print(" {d}ns", .{ns}); - } - try ttyconf.setColor(stderr, .reset); - } - if (s.result_peak_rss != 0) { - const rss = s.result_peak_rss; - try ttyconf.setColor(stderr, .dim); - if (rss >= 1000_000_000) { - try stderr.writer().print(" MaxRSS:{d}G", .{rss / 1000_000_000}); - } else if (rss >= 1000_000) { - try stderr.writer().print(" MaxRSS:{d}M", .{rss / 1000_000}); - } else if (rss >= 1000) { - try stderr.writer().print(" MaxRSS:{d}K", .{rss / 1000}); - } else { - try stderr.writer().print(" MaxRSS:{d}B", .{rss}); - } - try ttyconf.setColor(stderr, .reset); - } - try stderr.writeAll("\n"); - }, - .skipped, .skipped_oom => |skip| { - try ttyconf.setColor(stderr, .yellow); - try stderr.writeAll(" skipped"); - if (skip == .skipped_oom) { - try stderr.writeAll(" (not enough memory)"); - try ttyconf.setColor(stderr, .dim); - try stderr.writer().print(" upper bound of {d} exceeded runner limit ({d})", .{ s.max_rss, run.max_rss }); - try ttyconf.setColor(stderr, .yellow); - } - try stderr.writeAll("\n"); - try ttyconf.setColor(stderr, .reset); - }, - .failure => { - if (s.result_error_bundle.errorMessageCount() > 0) { - try ttyconf.setColor(stderr, .red); - try stderr.writer().print(" {d} errors\n", .{ - s.result_error_bundle.errorMessageCount(), - }); - try ttyconf.setColor(stderr, .reset); - } else if (!s.test_results.isSuccess()) { - try stderr.writer().print(" {d}/{d} passed", .{ - s.test_results.passCount(), s.test_results.test_count, - }); - if (s.test_results.fail_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); - try stderr.writer().print("{d} failed", .{ - s.test_results.fail_count, - }); - try ttyconf.setColor(stderr, .reset); - } - if (s.test_results.skip_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .yellow); - try stderr.writer().print("{d} skipped", .{ - s.test_results.skip_count, - }); - try ttyconf.setColor(stderr, .reset); - } - if (s.test_results.leak_count > 0) { - try stderr.writeAll(", "); - try ttyconf.setColor(stderr, .red); - try stderr.writer().print("{d} leaked", .{ - s.test_results.leak_count, - }); - try ttyconf.setColor(stderr, .reset); - } - try stderr.writeAll("\n"); - } else { - try ttyconf.setColor(stderr, .red); - try stderr.writeAll(" failure\n"); - try ttyconf.setColor(stderr, .reset); - } - }, - } + try printStepStatus(s, stderr, ttyconf, run); const last_index = if (!failures_only) s.dependencies.items.len -| 1 else blk: { var i: usize = s.dependencies.items.len; @@ -897,22 +916,7 @@ fn workerMakeOneStep( sub_prog_node.context.lock_stderr(); defer sub_prog_node.context.unlock_stderr(); - const stderr = run.stderr; - const ttyconf = run.ttyconf; - - for (s.result_error_msgs.items) |msg| { - // Sometimes it feels like you just can't catch a break. Finally, - // with Zig, you can. - ttyconf.setColor(stderr, .bold) catch break; - stderr.writeAll(s.owner.dep_prefix) catch break; - stderr.writeAll(s.name) catch break; - stderr.writeAll(": ") catch break; - ttyconf.setColor(stderr, .red) catch break; - stderr.writeAll("error: ") catch break; - ttyconf.setColor(stderr, .reset) catch break; - stderr.writeAll(msg) catch break; - stderr.writeAll("\n") catch break; - } + printErrorMessages(b, s, run) catch {}; } handle_result: { @@ -967,6 +971,50 @@ fn workerMakeOneStep( } } +fn printErrorMessages(b: *std.Build, failing_step: *Step, run: *const Run) !void { + const gpa = b.allocator; + const stderr = run.stderr; + const ttyconf = run.ttyconf; + + // Provide context for where these error messages are coming from by + // printing the corresponding Step subtree. + + var step_stack: std.ArrayListUnmanaged(*Step) = .{}; + defer step_stack.deinit(gpa); + try step_stack.append(gpa, failing_step); + while (step_stack.items[step_stack.items.len - 1].dependants.items.len != 0) { + try step_stack.append(gpa, step_stack.items[step_stack.items.len - 1].dependants.items[0]); + } + + // Now, `step_stack` has the subtree that we want to print, in reverse order. + try ttyconf.setColor(stderr, .dim); + var indent: usize = 0; + while (step_stack.popOrNull()) |s| : (indent += 1) { + if (indent > 0) { + try stderr.writer().writeByteNTimes(' ', (indent - 1) * 3); + try printChildNodePrefix(stderr, ttyconf); + } + + try stderr.writeAll(s.name); + + if (s == failing_step) { + try printStepFailure(s, stderr, ttyconf); + } else { + try stderr.writeAll("\n"); + } + } + try ttyconf.setColor(stderr, .reset); + + // Finally, the actual error messages. + for (failing_step.result_error_msgs.items) |msg| { + try ttyconf.setColor(stderr, .red); + try stderr.writeAll("error: "); + try ttyconf.setColor(stderr, .reset); + try stderr.writeAll(msg); + try stderr.writeAll("\n"); + } +} + fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void { // run the build script to collect the options if (!already_ran_build) { @@ -1116,7 +1164,7 @@ fn cleanExit() void { const Color = enum { auto, off, on }; const Summary = enum { all, failures, none }; -fn get_tty_conf(color: Color, stderr: std.fs.File) std.io.tty.Config { +fn get_tty_conf(color: Color, stderr: File) std.io.tty.Config { return switch (color) { .auto => std.io.tty.detectConfig(stderr), .on => .escape_codes, From 04480f72d8993196052375c0f0aca9d33f475fe7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 16:15:27 -0700 Subject: [PATCH 009/133] fix linker test regressions Caused by problems with transitive dependencies --- lib/std/Build/Module.zig | 9 +++- lib/std/Build/Step/Compile.zig | 87 ++++++++++++++++++++++++---------- lib/std/Build/Step/Run.zig | 2 +- test/link/elf.zig | 16 ++++--- 4 files changed, 81 insertions(+), 33 deletions(-) diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 3428581333e1..f17f296e64b6 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -229,7 +229,7 @@ pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*St } // This logic accesses `depending_steps` which was just modified above. - var it = m.iterateDependencies(null); + var it = m.iterateDependencies(null, false); while (it.next()) |item| addShallowDependencies(m, item.module); } @@ -244,7 +244,7 @@ pub fn addImport(m: *Module, name: []const u8, module: *Module) void { const b = m.owner; m.import_table.put(b.allocator, b.dupe(name), module) catch @panic("OOM"); - var it = module.iterateDependencies(null); + var it = module.iterateDependencies(null, false); while (it.next()) |item| addShallowDependencies(m, item.module); } @@ -319,6 +319,7 @@ pub const DependencyIterator = struct { allocator: std.mem.Allocator, index: usize, set: std.AutoArrayHashMapUnmanaged(Key, []const u8), + chase_dyn_libs: bool, pub const Key = struct { /// The compilation that contains the `Module`. Note that a `Module` might be @@ -361,6 +362,8 @@ pub const DependencyIterator = struct { if (key.compile != null) { for (module.link_objects.items) |link_object| switch (link_object) { .other_step => |compile| { + if (!it.chase_dyn_libs and compile.isDynamicLibrary()) continue; + it.set.put(it.allocator, .{ .module = &compile.root_module, .compile = compile, @@ -381,11 +384,13 @@ pub const DependencyIterator = struct { pub fn iterateDependencies( m: *Module, chase_steps: ?*Step.Compile, + chase_dyn_libs: bool, ) DependencyIterator { var it: DependencyIterator = .{ .allocator = m.owner.allocator, .index = 0, .set = .{}, + .chase_dyn_libs = chase_dyn_libs, }; it.set.ensureUnusedCapacity(m.owner.allocator, m.import_table.count() + 1) catch @panic("OOM"); it.set.putAssumeCapacity(.{ diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 52c9703db0bc..93027003f352 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -488,11 +488,12 @@ pub fn forceUndefinedSymbol(self: *Compile, symbol_name: []const u8) void { } /// Returns whether the library, executable, or object depends on a particular system library. +/// Includes transitive dependencies. pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { var is_linking_libc = false; var is_linking_libcpp = false; - var it = self.root_module.iterateDependencies(self); + var it = self.root_module.iterateDependencies(self, true); while (it.next()) |module| { for (module.link_objects.items) |link_object| { switch (link_object) { @@ -841,7 +842,7 @@ fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { var names = std.StringHashMap(void).init(b.allocator); { - var it = cs.root_module.iterateDependencies(null); + var it = cs.root_module.iterateDependencies(null, false); _ = it.next(); // Skip over the root module. while (it.next()) |item| { // While we're traversing the root dependencies, let's make sure that no module names @@ -1000,33 +1001,51 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try self.root_module.appendZigProcessFlags(&zig_args, step); - var it = self.root_module.iterateDependencies(self); + { + // Fully recursive iteration including dynamic libraries to detect + // libc and libc++ linkage. + var it = self.root_module.iterateDependencies(self, true); + while (it.next()) |key| { + if (key.module.link_libc == true) self.is_linking_libc = true; + if (key.module.link_libcpp == true) self.is_linking_libcpp = true; + } + } + + // For this loop, don't chase dynamic libraries because their link + // objects are already linked. + var it = self.root_module.iterateDependencies(self, false); + while (it.next()) |key| { const module = key.module; const compile = key.compile.?; - const dyn = compile.isDynamicLibrary(); - // Inherit dependency on libc and libc++. - if (module.link_libc == true) self.is_linking_libc = true; - if (module.link_libcpp == true) self.is_linking_libcpp = true; + // While walking transitive dependencies, if a given link object is + // already included in a library, it should not redundantly be + // placed on the linker line of the dependee. + const my_responsibility = compile == self; + const already_linked = !my_responsibility and compile.isDynamicLibrary(); // Inherit dependencies on darwin frameworks. - if (!dyn) { + if (!already_linked) { for (module.frameworks.keys(), module.frameworks.values()) |name, info| { try frameworks.put(b.allocator, name, info); } } // Inherit dependencies on system libraries and static libraries. - total_linker_objects += module.link_objects.items.len; for (module.link_objects.items) |link_object| { switch (link_object) { - .static_path => |static_path| try zig_args.append(static_path.getPath(b)), + .static_path => |static_path| { + if (my_responsibility) { + try zig_args.append(static_path.getPath(b)); + total_linker_objects += 1; + } + }, .system_lib => |system_lib| { if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null) continue; - if (dyn) + if (already_linked) continue; if ((system_lib.search_strategy != prev_search_strategy or @@ -1088,29 +1107,36 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } }, .other_step => |other| { - const included_in_lib = (compile.kind == .lib and other.kind == .obj); - if (dyn or included_in_lib) - continue; - switch (other.kind) { .exe => return step.fail("cannot link with an executable build artifact", .{}), .@"test" => return step.fail("cannot link with a test", .{}), .obj => { - try zig_args.append(other.getEmittedBin().getPath(b)); + const included_in_lib = !my_responsibility and + compile.kind == .lib and other.kind == .obj; + if (!already_linked and !included_in_lib) { + try zig_args.append(other.getEmittedBin().getPath(b)); + total_linker_objects += 1; + } }, .lib => l: { - if (self.isStaticLibrary() and other.isStaticLibrary()) { + const other_produces_implib = other.producesImplib(); + const other_is_static = other_produces_implib or other.isStaticLibrary(); + + if (self.isStaticLibrary() and other_is_static) { // Avoid putting a static library inside a static library. break :l; } - // For DLLs, we gotta link against the implib. For - // everything else, we directly link against the library file. - const full_path_lib = if (other.producesImplib()) + // For DLLs, we must link against the implib. + // For everything else, we directly link + // against the library file. + const full_path_lib = if (other_produces_implib) other.getGeneratedFilePath("generated_implib", &self.step) else other.getGeneratedFilePath("generated_bin", &self.step); + try zig_args.append(full_path_lib); + total_linker_objects += 1; if (other.linkage == Linkage.dynamic and self.rootModuleTarget().os.tag != .windows) @@ -1123,16 +1149,21 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }, } }, - .assembly_file => |asm_file| { + .assembly_file => |asm_file| l: { + if (!my_responsibility) break :l; + if (prev_has_cflags) { try zig_args.append("-cflags"); try zig_args.append("--"); prev_has_cflags = false; } try zig_args.append(asm_file.getPath(b)); + total_linker_objects += 1; }, - .c_source_file => |c_source_file| { + .c_source_file => |c_source_file| l: { + if (!my_responsibility) break :l; + if (c_source_file.flags.len == 0) { if (prev_has_cflags) { try zig_args.append("-cflags"); @@ -1148,9 +1179,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { prev_has_cflags = true; } try zig_args.append(c_source_file.file.getPath(b)); + total_linker_objects += 1; }, - .c_source_files => |c_source_files| { + .c_source_files => |c_source_files| l: { + if (!my_responsibility) break :l; + if (c_source_files.flags.len == 0) { if (prev_has_cflags) { try zig_args.append("-cflags"); @@ -1165,6 +1199,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append("--"); prev_has_cflags = true; } + if (c_source_files.dependency) |dep| { for (c_source_files.files) |file| { try zig_args.append(dep.builder.pathFromRoot(file)); @@ -1174,9 +1209,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(b.pathFromRoot(file)); } } + total_linker_objects += c_source_files.files.len; }, - .win32_resource_file => |rc_source_file| { + .win32_resource_file => |rc_source_file| l: { + if (!my_responsibility) break :l; + if (rc_source_file.flags.len == 0) { if (prev_has_rcflags) { try zig_args.append("-rcflags"); @@ -1192,6 +1230,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { prev_has_rcflags = true; } try zig_args.append(rc_source_file.file.getPath(b)); + total_linker_objects += 1; }, } } diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 40b72c7bca9e..92a40dcd1f17 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1291,7 +1291,7 @@ fn evalGeneric(self: *Run, child: *std.process.Child) !StdIoResult { fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void { const b = self.step.owner; - var it = artifact.root_module.iterateDependencies(artifact); + var it = artifact.root_module.iterateDependencies(artifact, true); while (it.next()) |item| { const other = item.compile.?; if (item.module == &other.root_module) { diff --git a/test/link/elf.zig b/test/link/elf.zig index d395344edd7c..95bb929dc019 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -1317,8 +1317,9 @@ fn testIFuncDlopen(b: *Build, opts: Options) *Step { fn testIFuncDso(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "ifunc-dso", opts); - const dso = addSharedLibrary(b, opts, .{ .name = "a" }); - addCSourceBytes(dso, + const dso = addSharedLibrary(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\__attribute__((ifunc("resolve_foobar"))) \\void foobar(void); @@ -1329,16 +1330,19 @@ fn testIFuncDso(b: *Build, opts: Options) *Step { \\static Func *resolve_foobar(void) { \\ return real_foobar; \\} - , &.{}); + , + }); dso.linkLibC(); - const exe = addExecutable(b, opts, .{ .name = "main" }); - addCSourceBytes(exe, + const exe = addExecutable(b, opts, .{ + .name = "main", + .c_source_bytes = \\void foobar(void); \\int main() { \\ foobar(); \\} - , &.{}); + , + }); exe.linkLibrary(dso); const run = addRunArtifact(exe); From 3963be03ec76c080811c9599eff03825c0a83ea8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 16:31:29 -0700 Subject: [PATCH 010/133] std.Build: handle ResolvedTarget in userInputOptionsFromArgs --- lib/std/Build.zig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 666a1ec15b23..24e245b02828 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -392,6 +392,23 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption .used = false, }) catch @panic("OOM"); }, + ResolvedTarget => { + user_input_options.put(field.name, .{ + .name = field.name, + .value = .{ .scalar = v.target.zigTriple(allocator) catch @panic("OOM") }, + .used = false, + }) catch @panic("OOM"); + user_input_options.put("cpu", .{ + .name = "cpu", + .value = .{ + .scalar = if (v.query.isNativeCpu()) + "native" + else + serializeCpu(allocator, v.target.cpu) catch unreachable, + }, + .used = false, + }) catch @panic("OOM"); + }, []const u8 => { user_input_options.put(field.name, .{ .name = field.name, From f10b5268e80d3f77198a55161427ad8ba6edce05 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 17:52:13 -0700 Subject: [PATCH 011/133] fix windows-only test case not upgraded to new build API --- test/standalone/issue_5825/build.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/standalone/issue_5825/build.zig b/test/standalone/issue_5825/build.zig index a6573175399b..078a9415701b 100644 --- a/test/standalone/issue_5825/build.zig +++ b/test/standalone/issue_5825/build.zig @@ -8,11 +8,11 @@ pub fn build(b: *std.Build) void { // Building for the msvc abi requires a native MSVC installation if (builtin.os.tag != .windows or builtin.cpu.arch != .x86_64) return; - const target = .{ + const target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .msvc, - }; + }); const optimize: std.builtin.OptimizeMode = .Debug; const obj = b.addObject(.{ .name = "issue_5825", From 767eb5da7793d83a7b5b666e5367727fc4f0160b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 3 Dec 2023 17:52:26 -0700 Subject: [PATCH 012/133] fix infinite loop in Run step Previously this relied on recursion; now it relies on the recursive iteration which is better, but means the recursive call needs to be deleted. --- lib/std/Build/Step/Run.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 92a40dcd1f17..36b2eb82eba9 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1297,7 +1297,6 @@ fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void { if (item.module == &other.root_module) { if (item.module.target.?.target.os.tag == .windows and other.isDynamicLibrary()) { addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); - addPathForDynLibs(self, other); } } } From 67d48b94d601521e15dd44c8789b1f528d09f10c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 12:14:58 -0700 Subject: [PATCH 013/133] std.Target: flatten --- CMakeLists.txt | 32 +- lib/std/Target.zig | 2696 +++++++++++++++++++++ lib/std/{target => Target}/aarch64.zig | 0 lib/std/{target => Target}/amdgpu.zig | 0 lib/std/{target => Target}/arc.zig | 0 lib/std/{target => Target}/arm.zig | 0 lib/std/{target => Target}/avr.zig | 0 lib/std/{target => Target}/bpf.zig | 0 lib/std/{target => Target}/csky.zig | 0 lib/std/{target => Target}/hexagon.zig | 0 lib/std/{target => Target}/loongarch.zig | 0 lib/std/{target => Target}/m68k.zig | 0 lib/std/{target => Target}/mips.zig | 0 lib/std/{target => Target}/msp430.zig | 0 lib/std/{target => Target}/nvptx.zig | 0 lib/std/{target => Target}/powerpc.zig | 0 lib/std/{target => Target}/riscv.zig | 0 lib/std/{target => Target}/s390x.zig | 0 lib/std/{target => Target}/sparc.zig | 0 lib/std/{target => Target}/spirv.zig | 0 lib/std/{target => Target}/ve.zig | 0 lib/std/{target => Target}/wasm.zig | 0 lib/std/{target => Target}/x86.zig | 0 lib/std/{target => Target}/xtensa.zig | 0 lib/std/std.zig | 2 +- lib/std/target.zig | 2698 ---------------------- 26 files changed, 2713 insertions(+), 2715 deletions(-) create mode 100644 lib/std/Target.zig rename lib/std/{target => Target}/aarch64.zig (100%) rename lib/std/{target => Target}/amdgpu.zig (100%) rename lib/std/{target => Target}/arc.zig (100%) rename lib/std/{target => Target}/arm.zig (100%) rename lib/std/{target => Target}/avr.zig (100%) rename lib/std/{target => Target}/bpf.zig (100%) rename lib/std/{target => Target}/csky.zig (100%) rename lib/std/{target => Target}/hexagon.zig (100%) rename lib/std/{target => Target}/loongarch.zig (100%) rename lib/std/{target => Target}/m68k.zig (100%) rename lib/std/{target => Target}/mips.zig (100%) rename lib/std/{target => Target}/msp430.zig (100%) rename lib/std/{target => Target}/nvptx.zig (100%) rename lib/std/{target => Target}/powerpc.zig (100%) rename lib/std/{target => Target}/riscv.zig (100%) rename lib/std/{target => Target}/s390x.zig (100%) rename lib/std/{target => Target}/sparc.zig (100%) rename lib/std/{target => Target}/spirv.zig (100%) rename lib/std/{target => Target}/ve.zig (100%) rename lib/std/{target => Target}/wasm.zig (100%) rename lib/std/{target => Target}/x86.zig (100%) rename lib/std/{target => Target}/xtensa.zig (100%) delete mode 100644 lib/std/target.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index b5f9c023778e..831243557f43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,22 +480,22 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordtf2.zig" "${CMAKE_SOURCE_DIR}/lib/std/start.zig" "${CMAKE_SOURCE_DIR}/lib/std/std.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/aarch64.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/amdgpu.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/arm.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/avr.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/bpf.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/hexagon.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/mips.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/msp430.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/nvptx.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/powerpc.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/riscv.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/sparc.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/s390x.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/wasm.zig" - "${CMAKE_SOURCE_DIR}/lib/std/target/x86.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/aarch64.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/amdgpu.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/arm.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/avr.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/bpf.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/hexagon.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/mips.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/msp430.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/nvptx.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/powerpc.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/riscv.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/sparc.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/s390x.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/wasm.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/x86.zig" "${CMAKE_SOURCE_DIR}/lib/std/Thread.zig" "${CMAKE_SOURCE_DIR}/lib/std/Thread/Futex.zig" "${CMAKE_SOURCE_DIR}/lib/std/Thread/Mutex.zig" diff --git a/lib/std/Target.zig b/lib/std/Target.zig new file mode 100644 index 000000000000..9e7414365c9b --- /dev/null +++ b/lib/std/Target.zig @@ -0,0 +1,2696 @@ +cpu: Cpu, +os: Os, +abi: Abi, +ofmt: ObjectFormat, + +pub const Os = struct { + tag: Tag, + version_range: VersionRange, + + pub const Tag = enum { + freestanding, + ananas, + cloudabi, + dragonfly, + freebsd, + fuchsia, + ios, + kfreebsd, + linux, + lv2, + macos, + netbsd, + openbsd, + solaris, + uefi, + windows, + zos, + haiku, + minix, + rtems, + nacl, + aix, + cuda, + nvcl, + amdhsa, + ps4, + ps5, + elfiamcu, + tvos, + watchos, + driverkit, + mesa3d, + contiki, + amdpal, + hermit, + hurd, + wasi, + emscripten, + shadermodel, + liteos, + opencl, + glsl450, + vulkan, + plan9, + illumos, + other, + + pub inline fn isDarwin(tag: Tag) bool { + return switch (tag) { + .ios, .macos, .watchos, .tvos => true, + else => false, + }; + } + + pub inline fn isBSD(tag: Tag) bool { + return tag.isDarwin() or switch (tag) { + .kfreebsd, .freebsd, .openbsd, .netbsd, .dragonfly => true, + else => false, + }; + } + + pub inline fn isSolarish(tag: Tag) bool { + return tag == .solaris or tag == .illumos; + } + + pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 { + if (tag.isDarwin()) { + return ".dylib"; + } + switch (tag) { + .windows => return ".dll", + else => return ".so", + } + } + + pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os { + return .{ + .tag = tag, + .version_range = VersionRange.default(tag, arch), + }; + } + }; + + /// Based on NTDDI version constants from + /// https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt + pub const WindowsVersion = enum(u32) { + nt4 = 0x04000000, + win2k = 0x05000000, + xp = 0x05010000, + ws2003 = 0x05020000, + vista = 0x06000000, + win7 = 0x06010000, + win8 = 0x06020000, + win8_1 = 0x06030000, + win10 = 0x0A000000, //aka win10_th1 + win10_th2 = 0x0A000001, + win10_rs1 = 0x0A000002, + win10_rs2 = 0x0A000003, + win10_rs3 = 0x0A000004, + win10_rs4 = 0x0A000005, + win10_rs5 = 0x0A000006, + win10_19h1 = 0x0A000007, + win10_vb = 0x0A000008, //aka win10_19h2 + win10_mn = 0x0A000009, //aka win10_20h1 + win10_fe = 0x0A00000A, //aka win10_20h2 + _, + + /// Latest Windows version that the Zig Standard Library is aware of + pub const latest = WindowsVersion.win10_fe; + + /// Compared against build numbers reported by the runtime to distinguish win10 versions, + /// where 0x0A000000 + index corresponds to the WindowsVersion u32 value. + pub const known_win10_build_numbers = [_]u32{ + 10240, //win10 aka win10_th1 + 10586, //win10_th2 + 14393, //win10_rs1 + 15063, //win10_rs2 + 16299, //win10_rs3 + 17134, //win10_rs4 + 17763, //win10_rs5 + 18362, //win10_19h1 + 18363, //win10_vb aka win10_19h2 + 19041, //win10_mn aka win10_20h1 + 19042, //win10_fe aka win10_20h2 + }; + + /// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`. + pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool { + return @intFromEnum(self) >= @intFromEnum(ver); + } + + pub const Range = struct { + min: WindowsVersion, + max: WindowsVersion, + + pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool { + return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max); + } + + /// Checks if system is guaranteed to be at least `version` or older than `version`. + /// Returns `null` if a runtime check is required. + pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool { + if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true; + if (@intFromEnum(self.max) < @intFromEnum(ver)) return false; + return null; + } + }; + + /// This function is defined to serialize a Zig source code representation of this + /// type, that, when parsed, will deserialize into the same data. + pub fn format( + self: WindowsVersion, + comptime fmt: []const u8, + _: std.fmt.FormatOptions, + out_stream: anytype, + ) !void { + if (comptime std.mem.eql(u8, fmt, "s")) { + if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) { + try std.fmt.format(out_stream, ".{s}", .{@tagName(self)}); + } else { + // TODO this code path breaks zig triples, but it is used in `builtin` + try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)}); + } + } else if (fmt.len == 0) { + if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) { + try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)}); + } else { + try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)}); + } + } else { + std.fmt.invalidFmtError(fmt, self); + } + } + }; + + pub const LinuxVersionRange = struct { + range: std.SemanticVersion.Range, + glibc: std.SemanticVersion, + + pub inline fn includesVersion(self: LinuxVersionRange, ver: std.SemanticVersion) bool { + return self.range.includesVersion(ver); + } + + /// Checks if system is guaranteed to be at least `version` or older than `version`. + /// Returns `null` if a runtime check is required. + pub inline fn isAtLeast(self: LinuxVersionRange, ver: std.SemanticVersion) ?bool { + return self.range.isAtLeast(ver); + } + }; + + /// The version ranges here represent the minimum OS version to be supported + /// and the maximum OS version to be supported. The default values represent + /// the range that the Zig Standard Library bases its abstractions on. + /// + /// The minimum version of the range is the main setting to tweak for a target. + /// Usually, the maximum target OS version will remain the default, which is + /// the latest released version of the OS. + /// + /// To test at compile time if the target is guaranteed to support a given OS feature, + /// one should check that the minimum version of the range is greater than or equal to + /// the version the feature was introduced in. + /// + /// To test at compile time if the target certainly will not support a given OS feature, + /// one should check that the maximum version of the range is less than the version the + /// feature was introduced in. + /// + /// If neither of these cases apply, a runtime check should be used to determine if the + /// target supports a given OS feature. + /// + /// Binaries built with a given maximum version will continue to function on newer + /// operating system versions. However, such a binary may not take full advantage of the + /// newer operating system APIs. + /// + /// See `Os.isAtLeast`. + pub const VersionRange = union { + none: void, + semver: std.SemanticVersion.Range, + linux: LinuxVersionRange, + windows: WindowsVersion.Range, + + /// The default `VersionRange` represents the range that the Zig Standard Library + /// bases its abstractions on. + pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange { + switch (tag) { + .freestanding, + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .zos, + .haiku, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .wasi, + .emscripten, + .driverkit, + .shadermodel, + .liteos, + .uefi, + .opencl, // TODO: OpenCL versions + .glsl450, // TODO: GLSL versions + .vulkan, + .plan9, + .illumos, + .other, + => return .{ .none = {} }, + + .freebsd => return .{ + .semver = std.SemanticVersion.Range{ + .min = .{ .major = 12, .minor = 0, .patch = 0 }, + .max = .{ .major = 14, .minor = 0, .patch = 0 }, + }, + }, + .macos => return switch (arch) { + .aarch64 => VersionRange{ + .semver = .{ + .min = .{ .major = 11, .minor = 7, .patch = 1 }, + .max = .{ .major = 14, .minor = 1, .patch = 0 }, + }, + }, + .x86_64 => VersionRange{ + .semver = .{ + .min = .{ .major = 11, .minor = 7, .patch = 1 }, + .max = .{ .major = 14, .minor = 1, .patch = 0 }, + }, + }, + else => unreachable, + }, + .ios => return .{ + .semver = .{ + .min = .{ .major = 12, .minor = 0, .patch = 0 }, + .max = .{ .major = 17, .minor = 1, .patch = 0 }, + }, + }, + .watchos => return .{ + .semver = .{ + .min = .{ .major = 6, .minor = 0, .patch = 0 }, + .max = .{ .major = 10, .minor = 1, .patch = 0 }, + }, + }, + .tvos => return .{ + .semver = .{ + .min = .{ .major = 13, .minor = 0, .patch = 0 }, + .max = .{ .major = 17, .minor = 1, .patch = 0 }, + }, + }, + .netbsd => return .{ + .semver = .{ + .min = .{ .major = 8, .minor = 0, .patch = 0 }, + .max = .{ .major = 10, .minor = 0, .patch = 0 }, + }, + }, + .openbsd => return .{ + .semver = .{ + .min = .{ .major = 6, .minor = 8, .patch = 0 }, + .max = .{ .major = 7, .minor = 4, .patch = 0 }, + }, + }, + .dragonfly => return .{ + .semver = .{ + .min = .{ .major = 5, .minor = 8, .patch = 0 }, + .max = .{ .major = 6, .minor = 4, .patch = 0 }, + }, + }, + .solaris => return .{ + .semver = .{ + .min = .{ .major = 5, .minor = 11, .patch = 0 }, + .max = .{ .major = 5, .minor = 11, .patch = 0 }, + }, + }, + + .linux => return .{ + .linux = .{ + .range = .{ + .min = .{ .major = 4, .minor = 19, .patch = 0 }, + .max = .{ .major = 6, .minor = 5, .patch = 7 }, + }, + .glibc = .{ .major = 2, .minor = 28, .patch = 0 }, + }, + }, + + .windows => return .{ + .windows = .{ + .min = .win8_1, + .max = WindowsVersion.latest, + }, + }, + } + } + }; + + pub const TaggedVersionRange = union(enum) { + none: void, + semver: std.SemanticVersion.Range, + linux: LinuxVersionRange, + windows: WindowsVersion.Range, + }; + + /// Provides a tagged union. `Target` does not store the tag because it is + /// redundant with the OS tag; this function abstracts that part away. + pub inline fn getVersionRange(self: Os) TaggedVersionRange { + switch (self.tag) { + .linux => return TaggedVersionRange{ .linux = self.version_range.linux }, + .windows => return TaggedVersionRange{ .windows = self.version_range.windows }, + + .freebsd, + .macos, + .ios, + .tvos, + .watchos, + .netbsd, + .openbsd, + .dragonfly, + .solaris, + => return TaggedVersionRange{ .semver = self.version_range.semver }, + + else => return .none, + } + } + + /// Checks if system is guaranteed to be at least `version` or older than `version`. + /// Returns `null` if a runtime check is required. + pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: anytype) ?bool { + if (self.tag != tag) return false; + + return switch (tag) { + .linux => self.version_range.linux.isAtLeast(version), + .windows => self.version_range.windows.isAtLeast(version), + else => self.version_range.semver.isAtLeast(version), + }; + } + + /// On Darwin, we always link libSystem which contains libc. + /// Similarly on FreeBSD and NetBSD we always link system libc + /// since this is the stable syscall interface. + pub fn requiresLibC(os: Os) bool { + return switch (os.tag) { + .freebsd, + .netbsd, + .macos, + .ios, + .tvos, + .watchos, + .dragonfly, + .openbsd, + .haiku, + .solaris, + .illumos, + => true, + + .linux, + .windows, + .freestanding, + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .zos, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .wasi, + .emscripten, + .driverkit, + .shadermodel, + .liteos, + .uefi, + .opencl, + .glsl450, + .vulkan, + .plan9, + .other, + => false, + }; + } +}; + +pub const aarch64 = @import("Target/aarch64.zig"); +pub const arc = @import("Target/arc.zig"); +pub const amdgpu = @import("Target/amdgpu.zig"); +pub const arm = @import("Target/arm.zig"); +pub const avr = @import("Target/avr.zig"); +pub const bpf = @import("Target/bpf.zig"); +pub const csky = @import("Target/csky.zig"); +pub const hexagon = @import("Target/hexagon.zig"); +pub const loongarch = @import("Target/loongarch.zig"); +pub const m68k = @import("Target/m68k.zig"); +pub const mips = @import("Target/mips.zig"); +pub const msp430 = @import("Target/msp430.zig"); +pub const nvptx = @import("Target/nvptx.zig"); +pub const powerpc = @import("Target/powerpc.zig"); +pub const riscv = @import("Target/riscv.zig"); +pub const sparc = @import("Target/sparc.zig"); +pub const spirv = @import("Target/spirv.zig"); +pub const s390x = @import("Target/s390x.zig"); +pub const ve = @import("Target/ve.zig"); +pub const wasm = @import("Target/wasm.zig"); +pub const x86 = @import("Target/x86.zig"); +pub const xtensa = @import("Target/xtensa.zig"); + +pub const Abi = enum { + none, + gnu, + gnuabin32, + gnuabi64, + gnueabi, + gnueabihf, + gnuf32, + gnuf64, + gnusf, + gnux32, + gnuilp32, + code16, + eabi, + eabihf, + android, + musl, + musleabi, + musleabihf, + muslx32, + msvc, + itanium, + cygnus, + coreclr, + simulator, + macabi, + pixel, + vertex, + geometry, + hull, + domain, + compute, + library, + raygeneration, + intersection, + anyhit, + closesthit, + miss, + callable, + mesh, + amplification, + + pub fn default(arch: Cpu.Arch, target_os: Os) Abi { + if (arch.isWasm()) { + return .musl; + } + switch (target_os.tag) { + .freestanding, + .ananas, + .cloudabi, + .dragonfly, + .lv2, + .zos, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .other, + => return .eabi, + .openbsd, + .freebsd, + .fuchsia, + .kfreebsd, + .netbsd, + .hurd, + .haiku, + .windows, + => return .gnu, + .uefi => return .msvc, + .linux, + .wasi, + .emscripten, + => return .musl, + .opencl, // TODO: SPIR-V ABIs with Linkage capability + .glsl450, + .vulkan, + .plan9, // TODO specify abi + .macos, + .ios, + .tvos, + .watchos, + .driverkit, + .shadermodel, + .liteos, // TODO: audit this + .solaris, + .illumos, + => return .none, + } + } + + pub inline fn isGnu(abi: Abi) bool { + return switch (abi) { + .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true, + else => false, + }; + } + + pub inline fn isMusl(abi: Abi) bool { + return switch (abi) { + .musl, .musleabi, .musleabihf => true, + else => false, + }; + } + + pub inline fn floatAbi(abi: Abi) FloatAbi { + return switch (abi) { + .gnueabihf, + .eabihf, + .musleabihf, + => .hard, + else => .soft, + }; + } +}; + +pub const ObjectFormat = enum { + /// Common Object File Format (Windows) + coff, + /// DirectX Container + dxcontainer, + /// Executable and Linking Format + elf, + /// macOS relocatables + macho, + /// Standard, Portable Intermediate Representation V + spirv, + /// WebAssembly + wasm, + /// C source code + c, + /// Intel IHEX + hex, + /// Machine code with no metadata. + raw, + /// Plan 9 from Bell Labs + plan9, + /// Nvidia PTX format + nvptx, + + pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 { + return switch (of) { + .coff => ".obj", + .elf, .macho, .wasm => ".o", + .c => ".c", + .spirv => ".spv", + .hex => ".ihex", + .raw => ".bin", + .plan9 => plan9Ext(cpu_arch), + .nvptx => ".ptx", + .dxcontainer => ".dxil", + }; + } + + pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat { + return switch (os_tag) { + .windows, .uefi => .coff, + .ios, .macos, .watchos, .tvos => .macho, + .plan9 => .plan9, + else => return switch (cpu_arch) { + .wasm32, .wasm64 => .wasm, + .spirv32, .spirv64 => .spirv, + .nvptx, .nvptx64 => .nvptx, + else => .elf, + }, + }; + } +}; + +pub const SubSystem = enum { + Console, + Windows, + Posix, + Native, + EfiApplication, + EfiBootServiceDriver, + EfiRom, + EfiRuntimeDriver, +}; + +pub const Cpu = struct { + /// Architecture + arch: Arch, + + /// The CPU model to target. It has a set of features + /// which are overridden with the `features` field. + model: *const Model, + + /// An explicit list of the entire CPU feature set. It may differ from the specific CPU model's features. + features: Feature.Set, + + pub const Feature = struct { + /// The bit index into `Set`. Has a default value of `undefined` because the canonical + /// structures are populated via comptime logic. + index: Set.Index = undefined, + + /// Has a default value of `undefined` because the canonical + /// structures are populated via comptime logic. + name: []const u8 = undefined, + + /// If this corresponds to an LLVM-recognized feature, this will be populated; + /// otherwise null. + llvm_name: ?[:0]const u8, + + /// Human-friendly UTF-8 text. + description: []const u8, + + /// Sparse `Set` of features this depends on. + dependencies: Set, + + /// A bit set of all the features. + pub const Set = struct { + ints: [usize_count]usize, + + pub const needed_bit_count = 288; + pub const byte_count = (needed_bit_count + 7) / 8; + pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); + pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); + pub const ShiftInt = std.math.Log2Int(usize); + + pub const empty = Set{ .ints = [1]usize{0} ** usize_count }; + + pub fn isEmpty(set: Set) bool { + return for (set.ints) |x| { + if (x != 0) break false; + } else true; + } + + pub fn isEnabled(set: Set, arch_feature_index: Index) bool { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); + return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0; + } + + /// Adds the specified feature but not its dependencies. + pub fn addFeature(set: *Set, arch_feature_index: Index) void { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); + set.ints[usize_index] |= @as(usize, 1) << bit_index; + } + + /// Adds the specified feature set but not its dependencies. + pub fn addFeatureSet(set: *Set, other_set: Set) void { + switch (builtin.zig_backend) { + .stage2_x86_64 => { + for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int; + }, + else => { + set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints); + }, + } + } + + /// Removes the specified feature but not its dependents. + pub fn removeFeature(set: *Set, arch_feature_index: Index) void { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); + set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); + } + + /// Removes the specified feature but not its dependents. + pub fn removeFeatureSet(set: *Set, other_set: Set) void { + switch (builtin.zig_backend) { + .stage2_x86_64 => { + for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int; + }, + else => { + set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints); + }, + } + } + + pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { + @setEvalBranchQuota(1000000); + + var old = set.ints; + while (true) { + for (all_features_list, 0..) |feature, index_usize| { + const index = @as(Index, @intCast(index_usize)); + if (set.isEnabled(index)) { + set.addFeatureSet(feature.dependencies); + } + } + const nothing_changed = std.mem.eql(usize, &old, &set.ints); + if (nothing_changed) return; + old = set.ints; + } + } + + pub fn asBytes(set: *const Set) *const [byte_count]u8 { + return @as(*const [byte_count]u8, @ptrCast(&set.ints)); + } + + pub fn eql(set: Set, other_set: Set) bool { + return std.mem.eql(usize, &set.ints, &other_set.ints); + } + + pub fn isSuperSetOf(set: Set, other_set: Set) bool { + switch (builtin.zig_backend) { + .stage2_x86_64 => { + var result = true; + for (&set.ints, other_set.ints) |*set_int, other_set_int| + result = result and (set_int.* & other_set_int) == other_set_int; + return result; + }, + else => { + const V = @Vector(usize_count, usize); + const set_v: V = set.ints; + const other_v: V = other_set.ints; + return @reduce(.And, (set_v & other_v) == other_v); + }, + } + } + }; + + pub fn feature_set_fns(comptime F: type) type { + return struct { + /// Populates only the feature bits specified. + pub fn featureSet(features: []const F) Set { + var x = Set.empty; + for (features) |feature| { + x.addFeature(@intFromEnum(feature)); + } + return x; + } + + /// Returns true if the specified feature is enabled. + pub fn featureSetHas(set: Set, feature: F) bool { + return set.isEnabled(@intFromEnum(feature)); + } + + /// Returns true if any specified feature is enabled. + pub fn featureSetHasAny(set: Set, features: anytype) bool { + inline for (features) |feature| { + if (set.isEnabled(@intFromEnum(@as(F, feature)))) return true; + } + return false; + } + + /// Returns true if every specified feature is enabled. + pub fn featureSetHasAll(set: Set, features: anytype) bool { + inline for (features) |feature| { + if (!set.isEnabled(@intFromEnum(@as(F, feature)))) return false; + } + return true; + } + }; + } + }; + + pub const Arch = enum { + arm, + armeb, + aarch64, + aarch64_be, + aarch64_32, + arc, + avr, + bpfel, + bpfeb, + csky, + dxil, + hexagon, + loongarch32, + loongarch64, + m68k, + mips, + mipsel, + mips64, + mips64el, + msp430, + powerpc, + powerpcle, + powerpc64, + powerpc64le, + r600, + amdgcn, + riscv32, + riscv64, + sparc, + sparc64, + sparcel, + s390x, + tce, + tcele, + thumb, + thumbeb, + x86, + x86_64, + xcore, + xtensa, + nvptx, + nvptx64, + le32, + le64, + amdil, + amdil64, + hsail, + hsail64, + spir, + spir64, + spirv32, + spirv64, + kalimba, + shave, + lanai, + wasm32, + wasm64, + renderscript32, + renderscript64, + ve, + // Stage1 currently assumes that architectures above this comment + // map one-to-one with the ZigLLVM_ArchType enum. + spu_2, + + pub inline fn isX86(arch: Arch) bool { + return switch (arch) { + .x86, .x86_64 => true, + else => false, + }; + } + + pub inline fn isARM(arch: Arch) bool { + return switch (arch) { + .arm, .armeb => true, + else => false, + }; + } + + pub inline fn isAARCH64(arch: Arch) bool { + return switch (arch) { + .aarch64, .aarch64_be, .aarch64_32 => true, + else => false, + }; + } + + pub inline fn isThumb(arch: Arch) bool { + return switch (arch) { + .thumb, .thumbeb => true, + else => false, + }; + } + + pub inline fn isArmOrThumb(arch: Arch) bool { + return arch.isARM() or arch.isThumb(); + } + + pub inline fn isWasm(arch: Arch) bool { + return switch (arch) { + .wasm32, .wasm64 => true, + else => false, + }; + } + + pub inline fn isRISCV(arch: Arch) bool { + return switch (arch) { + .riscv32, .riscv64 => true, + else => false, + }; + } + + pub inline fn isMIPS(arch: Arch) bool { + return switch (arch) { + .mips, .mipsel, .mips64, .mips64el => true, + else => false, + }; + } + + pub inline fn isPPC(arch: Arch) bool { + return switch (arch) { + .powerpc, .powerpcle => true, + else => false, + }; + } + + pub inline fn isPPC64(arch: Arch) bool { + return switch (arch) { + .powerpc64, .powerpc64le => true, + else => false, + }; + } + + pub inline fn isSPARC(arch: Arch) bool { + return switch (arch) { + .sparc, .sparcel, .sparc64 => true, + else => false, + }; + } + + pub inline fn isSpirV(arch: Arch) bool { + return switch (arch) { + .spirv32, .spirv64 => true, + else => false, + }; + } + + pub inline fn isBpf(arch: Arch) bool { + return switch (arch) { + .bpfel, .bpfeb => true, + else => false, + }; + } + + pub inline fn isNvptx(arch: Arch) bool { + return switch (arch) { + .nvptx, .nvptx64 => true, + else => false, + }; + } + + pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { + for (arch.allCpuModels()) |cpu| { + if (std.mem.eql(u8, cpu_name, cpu.name)) { + return cpu; + } + } + return error.UnknownCpuModel; + } + + pub fn toElfMachine(arch: Arch) std.elf.EM { + return switch (arch) { + .avr => .AVR, + .msp430 => .MSP430, + .arc => .ARC, + .arm => .ARM, + .armeb => .ARM, + .hexagon => .HEXAGON, + .dxil => .NONE, + .m68k => .@"68K", + .le32 => .NONE, + .mips => .MIPS, + .mipsel => .MIPS_RS3_LE, + .powerpc, .powerpcle => .PPC, + .r600 => .NONE, + .riscv32 => .RISCV, + .sparc => .SPARC, + .sparcel => .SPARC, + .tce => .NONE, + .tcele => .NONE, + .thumb => .ARM, + .thumbeb => .ARM, + .x86 => .@"386", + .xcore => .XCORE, + .xtensa => .XTENSA, + .nvptx => .NONE, + .amdil => .NONE, + .hsail => .NONE, + .spir => .NONE, + .kalimba => .CSR_KALIMBA, + .shave => .NONE, + .lanai => .LANAI, + .wasm32 => .NONE, + .renderscript32 => .NONE, + .aarch64_32 => .AARCH64, + .aarch64 => .AARCH64, + .aarch64_be => .AARCH64, + .mips64 => .MIPS, + .mips64el => .MIPS_RS3_LE, + .powerpc64 => .PPC64, + .powerpc64le => .PPC64, + .riscv64 => .RISCV, + .x86_64 => .X86_64, + .nvptx64 => .NONE, + .le64 => .NONE, + .amdil64 => .NONE, + .hsail64 => .NONE, + .spir64 => .NONE, + .wasm64 => .NONE, + .renderscript64 => .NONE, + .amdgcn => .AMDGPU, + .bpfel => .BPF, + .bpfeb => .BPF, + .csky => .CSKY, + .sparc64 => .SPARCV9, + .s390x => .S390, + .ve => .NONE, + .spu_2 => .SPU_2, + .spirv32 => .NONE, + .spirv64 => .NONE, + .loongarch32 => .NONE, + .loongarch64 => .NONE, + }; + } + + pub fn toCoffMachine(arch: Arch) std.coff.MachineType { + return switch (arch) { + .avr => .Unknown, + .msp430 => .Unknown, + .arc => .Unknown, + .arm => .ARM, + .armeb => .Unknown, + .dxil => .Unknown, + .hexagon => .Unknown, + .m68k => .Unknown, + .le32 => .Unknown, + .mips => .Unknown, + .mipsel => .Unknown, + .powerpc, .powerpcle => .POWERPC, + .r600 => .Unknown, + .riscv32 => .RISCV32, + .sparc => .Unknown, + .sparcel => .Unknown, + .tce => .Unknown, + .tcele => .Unknown, + .thumb => .Thumb, + .thumbeb => .Thumb, + .x86 => .I386, + .xcore => .Unknown, + .xtensa => .Unknown, + .nvptx => .Unknown, + .amdil => .Unknown, + .hsail => .Unknown, + .spir => .Unknown, + .kalimba => .Unknown, + .shave => .Unknown, + .lanai => .Unknown, + .wasm32 => .Unknown, + .renderscript32 => .Unknown, + .aarch64_32 => .ARM64, + .aarch64 => .ARM64, + .aarch64_be => .ARM64, + .mips64 => .Unknown, + .mips64el => .Unknown, + .powerpc64 => .Unknown, + .powerpc64le => .Unknown, + .riscv64 => .RISCV64, + .x86_64 => .X64, + .nvptx64 => .Unknown, + .le64 => .Unknown, + .amdil64 => .Unknown, + .hsail64 => .Unknown, + .spir64 => .Unknown, + .wasm64 => .Unknown, + .renderscript64 => .Unknown, + .amdgcn => .Unknown, + .bpfel => .Unknown, + .bpfeb => .Unknown, + .csky => .Unknown, + .sparc64 => .Unknown, + .s390x => .Unknown, + .ve => .Unknown, + .spu_2 => .Unknown, + .spirv32 => .Unknown, + .spirv64 => .Unknown, + .loongarch32 => .Unknown, + .loongarch64 => .Unknown, + }; + } + + pub fn endian(arch: Arch) std.builtin.Endian { + return switch (arch) { + .avr, + .arm, + .aarch64_32, + .aarch64, + .amdgcn, + .amdil, + .amdil64, + .bpfel, + .csky, + .xtensa, + .hexagon, + .hsail, + .hsail64, + .kalimba, + .le32, + .le64, + .mipsel, + .mips64el, + .msp430, + .nvptx, + .nvptx64, + .sparcel, + .tcele, + .powerpcle, + .powerpc64le, + .r600, + .riscv32, + .riscv64, + .x86, + .x86_64, + .wasm32, + .wasm64, + .xcore, + .thumb, + .spir, + .spir64, + .renderscript32, + .renderscript64, + .shave, + .ve, + .spu_2, + // GPU bitness is opaque. For now, assume little endian. + .spirv32, + .spirv64, + .dxil, + .loongarch32, + .loongarch64, + .arc, + => .little, + + .armeb, + .aarch64_be, + .bpfeb, + .m68k, + .mips, + .mips64, + .powerpc, + .powerpc64, + .thumbeb, + .sparc, + .sparc64, + .tce, + .lanai, + .s390x, + => .big, + }; + } + + /// Returns whether this architecture supports the address space + pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool { + const is_nvptx = arch == .nvptx or arch == .nvptx64; + const is_spirv = arch == .spirv32 or arch == .spirv64; + const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; + return switch (address_space) { + .generic => true, + .fs, .gs, .ss => arch == .x86_64 or arch == .x86, + .global, .constant, .local, .shared => is_gpu, + .param => is_nvptx, + // TODO this should also check how many flash banks the cpu has + .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, + }; + } + + /// Returns a name that matches the lib/std/target/* source file name. + pub fn genericName(arch: Arch) []const u8 { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => "arm", + .aarch64, .aarch64_be, .aarch64_32 => "aarch64", + .bpfel, .bpfeb => "bpf", + .loongarch32, .loongarch64 => "loongarch", + .mips, .mipsel, .mips64, .mips64el => "mips", + .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc", + .amdgcn => "amdgpu", + .riscv32, .riscv64 => "riscv", + .sparc, .sparc64, .sparcel => "sparc", + .s390x => "s390x", + .x86, .x86_64 => "x86", + .nvptx, .nvptx64 => "nvptx", + .wasm32, .wasm64 => "wasm", + .spirv32, .spirv64 => "spirv", + else => @tagName(arch), + }; + } + + /// All CPU features Zig is aware of, sorted lexicographically by name. + pub fn allFeaturesList(arch: Arch) []const Cpu.Feature { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.all_features, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features, + .arc => &arc.all_features, + .avr => &avr.all_features, + .bpfel, .bpfeb => &bpf.all_features, + .csky => &csky.all_features, + .hexagon => &hexagon.all_features, + .loongarch32, .loongarch64 => &loongarch.all_features, + .m68k => &m68k.all_features, + .mips, .mipsel, .mips64, .mips64el => &mips.all_features, + .msp430 => &msp430.all_features, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => &powerpc.all_features, + .amdgcn => &amdgpu.all_features, + .riscv32, .riscv64 => &riscv.all_features, + .sparc, .sparc64, .sparcel => &sparc.all_features, + .spirv32, .spirv64 => &spirv.all_features, + .s390x => &s390x.all_features, + .x86, .x86_64 => &x86.all_features, + .xtensa => &xtensa.all_features, + .nvptx, .nvptx64 => &nvptx.all_features, + .ve => &ve.all_features, + .wasm32, .wasm64 => &wasm.all_features, + + else => &[0]Cpu.Feature{}, + }; + } + + /// All processors Zig is aware of, sorted lexicographically by name. + pub fn allCpuModels(arch: Arch) []const *const Cpu.Model { + return switch (arch) { + .arc => comptime allCpusFromDecls(arc.cpu), + .arm, .armeb, .thumb, .thumbeb => comptime allCpusFromDecls(arm.cpu), + .aarch64, .aarch64_be, .aarch64_32 => comptime allCpusFromDecls(aarch64.cpu), + .avr => comptime allCpusFromDecls(avr.cpu), + .bpfel, .bpfeb => comptime allCpusFromDecls(bpf.cpu), + .csky => comptime allCpusFromDecls(csky.cpu), + .hexagon => comptime allCpusFromDecls(hexagon.cpu), + .loongarch32, .loongarch64 => comptime allCpusFromDecls(loongarch.cpu), + .m68k => comptime allCpusFromDecls(m68k.cpu), + .mips, .mipsel, .mips64, .mips64el => comptime allCpusFromDecls(mips.cpu), + .msp430 => comptime allCpusFromDecls(msp430.cpu), + .powerpc, .powerpcle, .powerpc64, .powerpc64le => comptime allCpusFromDecls(powerpc.cpu), + .amdgcn => comptime allCpusFromDecls(amdgpu.cpu), + .riscv32, .riscv64 => comptime allCpusFromDecls(riscv.cpu), + .sparc, .sparc64, .sparcel => comptime allCpusFromDecls(sparc.cpu), + .spirv32, .spirv64 => comptime allCpusFromDecls(spirv.cpu), + .s390x => comptime allCpusFromDecls(s390x.cpu), + .x86, .x86_64 => comptime allCpusFromDecls(x86.cpu), + .xtensa => comptime allCpusFromDecls(xtensa.cpu), + .nvptx, .nvptx64 => comptime allCpusFromDecls(nvptx.cpu), + .ve => comptime allCpusFromDecls(ve.cpu), + .wasm32, .wasm64 => comptime allCpusFromDecls(wasm.cpu), + + else => &[0]*const Model{}, + }; + } + + fn allCpusFromDecls(comptime cpus: type) []const *const Cpu.Model { + const decls = @typeInfo(cpus).Struct.decls; + var array: [decls.len]*const Cpu.Model = undefined; + for (decls, 0..) |decl, i| { + array[i] = &@field(cpus, decl.name); + } + return &array; + } + }; + + pub const Model = struct { + name: []const u8, + llvm_name: ?[:0]const u8, + features: Feature.Set, + + pub fn toCpu(model: *const Model, arch: Arch) Cpu { + var features = model.features; + features.populateDependencies(arch.allFeaturesList()); + return .{ + .arch = arch, + .model = model, + .features = features, + }; + } + + pub fn generic(arch: Arch) *const Model { + const S = struct { + const generic_model = Model{ + .name = "generic", + .llvm_name = null, + .features = Cpu.Feature.Set.empty, + }; + }; + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, + .avr => &avr.cpu.avr2, + .bpfel, .bpfeb => &bpf.cpu.generic, + .hexagon => &hexagon.cpu.generic, + .loongarch32 => &loongarch.cpu.generic_la32, + .loongarch64 => &loongarch.cpu.generic_la64, + .m68k => &m68k.cpu.generic, + .mips, .mipsel => &mips.cpu.mips32, + .mips64, .mips64el => &mips.cpu.mips64, + .msp430 => &msp430.cpu.generic, + .powerpc => &powerpc.cpu.ppc, + .powerpcle => &powerpc.cpu.ppc, + .powerpc64 => &powerpc.cpu.ppc64, + .powerpc64le => &powerpc.cpu.ppc64le, + .amdgcn => &amdgpu.cpu.generic, + .riscv32 => &riscv.cpu.generic_rv32, + .riscv64 => &riscv.cpu.generic_rv64, + .spirv32, .spirv64 => &spirv.cpu.generic, + .sparc, .sparcel => &sparc.cpu.generic, + .sparc64 => &sparc.cpu.v9, // 64-bit SPARC needs v9 as the baseline + .s390x => &s390x.cpu.generic, + .x86 => &x86.cpu.i386, + .x86_64 => &x86.cpu.x86_64, + .nvptx, .nvptx64 => &nvptx.cpu.sm_20, + .ve => &ve.cpu.generic, + .wasm32, .wasm64 => &wasm.cpu.generic, + + else => &S.generic_model, + }; + } + + pub fn baseline(arch: Arch) *const Model { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline, + .riscv32 => &riscv.cpu.baseline_rv32, + .riscv64 => &riscv.cpu.baseline_rv64, + .x86 => &x86.cpu.pentium4, + .nvptx, .nvptx64 => &nvptx.cpu.sm_20, + .sparc, .sparcel => &sparc.cpu.v8, + + else => generic(arch), + }; + } + }; + + /// The "default" set of CPU features for cross-compiling. A conservative set + /// of features that is expected to be supported on most available hardware. + pub fn baseline(arch: Arch) Cpu { + return Model.baseline(arch).toCpu(arch); + } +}; + +pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 { + return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); +} + +pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 { + return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); +} + +pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 { + return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi); +} + +pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 { + return switch (os_tag) { + .windows => ".exe", + .uefi => ".efi", + .plan9 => plan9Ext(cpu_arch), + else => switch (cpu_arch) { + .wasm32, .wasm64 => ".wasm", + else => "", + }, + }; +} + +pub fn exeFileExt(self: Target) [:0]const u8 { + return exeFileExtSimple(self.cpu.arch, self.os.tag); +} + +pub fn staticLibSuffix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 { + if (abi == .msvc) { + return ".lib"; + } + switch (os_tag) { + .windows, .uefi => return ".lib", + else => return ".a", + } +} + +pub fn staticLibSuffix(self: Target) [:0]const u8 { + return staticLibSuffix_os_abi(self.os.tag, self.abi); +} + +pub fn dynamicLibSuffix(self: Target) [:0]const u8 { + return self.os.tag.dynamicLibSuffix(); +} + +pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 { + if (abi == .msvc) { + return ""; + } + switch (os_tag) { + .windows, .uefi => return "", + else => return "lib", + } +} + +pub fn libPrefix(self: Target) [:0]const u8 { + return libPrefix_os_abi(self.os.tag, self.abi); +} + +pub inline fn isMinGW(self: Target) bool { + return self.os.tag == .windows and self.isGnu(); +} + +pub inline fn isGnu(self: Target) bool { + return self.abi.isGnu(); +} + +pub inline fn isMusl(self: Target) bool { + return self.abi.isMusl(); +} + +pub inline fn isAndroid(self: Target) bool { + return self.abi == .android; +} + +pub inline fn isWasm(self: Target) bool { + return self.cpu.arch.isWasm(); +} + +pub inline fn isDarwin(self: Target) bool { + return self.os.tag.isDarwin(); +} + +pub inline fn isBSD(self: Target) bool { + return self.os.tag.isBSD(); +} + +pub inline fn isBpfFreestanding(self: Target) bool { + return self.cpu.arch.isBpf() and self.os.tag == .freestanding; +} + +pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool { + return os_tag == .linux and abi.isGnu(); +} + +pub inline fn isGnuLibC(self: Target) bool { + return isGnuLibC_os_tag_abi(self.os.tag, self.abi); +} + +pub inline fn supportsNewStackCall(self: Target) bool { + return !self.cpu.arch.isWasm(); +} + +pub inline fn isSpirV(self: Target) bool { + return self.cpu.arch.isSpirV(); +} + +pub const FloatAbi = enum { + hard, + soft, +}; + +pub inline fn getFloatAbi(self: Target) FloatAbi { + return self.abi.floatAbi(); +} + +pub inline fn hasDynamicLinker(self: Target) bool { + if (self.cpu.arch.isWasm()) { + return false; + } + switch (self.os.tag) { + .freestanding, + .ios, + .tvos, + .watchos, + .macos, + .uefi, + .windows, + .emscripten, + .opencl, + .glsl450, + .vulkan, + .plan9, + .other, + => return false, + else => return true, + } +} + +pub const DynamicLinker = struct { + /// Contains the memory used to store the dynamic linker path. This field should + /// not be used directly. See `get` and `set`. This field exists so that this API requires no allocator. + buffer: [255]u8 = undefined, + + /// Used to construct the dynamic linker path. This field should not be used + /// directly. See `get` and `set`. + max_byte: ?u8 = null, + + /// Asserts that the length is less than or equal to 255 bytes. + pub fn init(dl_or_null: ?[]const u8) DynamicLinker { + var result: DynamicLinker = undefined; + result.set(dl_or_null); + return result; + } + + /// The returned memory has the same lifetime as the `DynamicLinker`. + pub fn get(self: *const DynamicLinker) ?[]const u8 { + const m: usize = self.max_byte orelse return null; + return self.buffer[0 .. m + 1]; + } + + /// Asserts that the length is less than or equal to 255 bytes. + pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void { + if (dl_or_null) |dl| { + @memcpy(self.buffer[0..dl.len], dl); + self.max_byte = @as(u8, @intCast(dl.len - 1)); + } else { + self.max_byte = null; + } + } +}; + +pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { + var result: DynamicLinker = .{}; + const S = struct { + fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker { + r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1)); + return r.*; + } + fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker { + @memcpy(r.buffer[0..s.len], s); + r.max_byte = @as(u8, @intCast(s.len - 1)); + return r.*; + } + }; + const print = S.print; + const copy = S.copy; + + if (self.abi == .android) { + const suffix = if (self.ptrBitWidth() == 64) "64" else ""; + return print(&result, "/system/bin/linker{s}", .{suffix}); + } + + if (self.abi.isMusl()) { + const is_arm = switch (self.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => true, + else => false, + }; + const arch_part = switch (self.cpu.arch) { + .arm, .thumb => "arm", + .armeb, .thumbeb => "armeb", + else => |arch| @tagName(arch), + }; + const arch_suffix = if (is_arm and self.abi.floatAbi() == .hard) "hf" else ""; + return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix }); + } + + switch (self.os.tag) { + .freebsd => return copy(&result, "/libexec/ld-elf.so.1"), + .netbsd => return copy(&result, "/libexec/ld.elf_so"), + .openbsd => return copy(&result, "/usr/libexec/ld.so"), + .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"), + .solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"), + .linux => switch (self.cpu.arch) { + .x86, + .sparc, + .sparcel, + => return copy(&result, "/lib/ld-linux.so.2"), + + .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"), + .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"), + .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"), + + .arm, + .armeb, + .thumb, + .thumbeb, + => return copy(&result, switch (self.abi.floatAbi()) { + .hard => "/lib/ld-linux-armhf.so.3", + else => "/lib/ld-linux.so.3", + }), + + .mips, + .mipsel, + .mips64, + .mips64el, + => { + const lib_suffix = switch (self.abi) { + .gnuabin32, .gnux32 => "32", + .gnuabi64 => "64", + else => "", + }; + const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008); + const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1"; + return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader }); + }, + + .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"), + .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"), + .s390x => return copy(&result, "/lib64/ld64.so.1"), + .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"), + .x86_64 => return copy(&result, switch (self.abi) { + .gnux32 => "/libx32/ld-linux-x32.so.2", + else => "/lib64/ld-linux-x86-64.so.2", + }), + + .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"), + .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"), + + // Architectures in this list have been verified as not having a standard + // dynamic linker path. + .wasm32, + .wasm64, + .bpfel, + .bpfeb, + .nvptx, + .nvptx64, + .spu_2, + .avr, + .spirv32, + .spirv64, + => return result, + + // TODO go over each item in this list and either move it to the above list, or + // implement the standard dynamic linker path code for it. + .arc, + .csky, + .hexagon, + .m68k, + .msp430, + .r600, + .amdgcn, + .tce, + .tcele, + .xcore, + .le32, + .le64, + .amdil, + .amdil64, + .hsail, + .hsail64, + .spir, + .spir64, + .kalimba, + .shave, + .lanai, + .renderscript32, + .renderscript64, + .ve, + .dxil, + .loongarch32, + .loongarch64, + .xtensa, + => return result, + }, + + .ios, + .tvos, + .watchos, + .macos, + => return copy(&result, "/usr/lib/dyld"), + + // Operating systems in this list have been verified as not having a standard + // dynamic linker path. + .freestanding, + .uefi, + .windows, + .emscripten, + .wasi, + .opencl, + .glsl450, + .vulkan, + .other, + .plan9, + => return result, + + // TODO revisit when multi-arch for Haiku is available + .haiku => return copy(&result, "/system/runtime_loader"), + + // TODO go over each item in this list and either move it to the above list, or + // implement the standard dynamic linker path code for it. + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .zos, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .driverkit, + .shadermodel, + .liteos, + => return result, + } +} + +/// 0c spim little-endian MIPS 3000 family +/// 1c 68000 Motorola MC68000 +/// 2c 68020 Motorola MC68020 +/// 5c arm little-endian ARM +/// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T) +/// 7c arm64 ARM64 (ARMv8) +/// 8c 386 Intel x86, i486, Pentium, etc. +/// kc sparc Sun SPARC +/// qc power Power PC +/// vc mips big-endian MIPS 3000 family +pub fn plan9Ext(cpu_arch: Cpu.Arch) [:0]const u8 { + return switch (cpu_arch) { + .arm => ".5", + .x86_64 => ".6", + .aarch64 => ".7", + .x86 => ".8", + .sparc => ".k", + .powerpc, .powerpcle => ".q", + .mips, .mipsel => ".v", + // ISAs without designated characters get 'X' for lack of a better option. + else => ".X", + }; +} + +pub fn maxIntAlignment(target: Target) u16 { + return switch (target.cpu.arch) { + .avr => 1, + .msp430 => 2, + .xcore => 4, + + .arm, + .armeb, + .thumb, + .thumbeb, + .hexagon, + .mips, + .mipsel, + .powerpc, + .powerpcle, + .r600, + .amdgcn, + .riscv32, + .sparc, + .sparcel, + .s390x, + .lanai, + .wasm32, + .wasm64, + => 8, + + .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) { + .windows, .uefi => 8, + else => 4, + }, + + // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16 + // is a relevant number in three cases: + // 1. Different machine code instruction when loading into SIMD register. + // 2. The C ABI wants 16 for extern structs. + // 3. 16-byte cmpxchg needs 16-byte alignment. + // Same logic for powerpc64, mips64, sparc64. + .x86_64, + .powerpc64, + .powerpc64le, + .mips64, + .mips64el, + .sparc64, + => return switch (target.ofmt) { + .c => 16, + else => 8, + }, + + // Even LLVMABIAlignmentOfType(i128) agrees on these targets. + .aarch64, + .aarch64_be, + .aarch64_32, + .riscv64, + .bpfel, + .bpfeb, + .nvptx, + .nvptx64, + => 16, + + // Below this comment are unverified but based on the fact that C requires + // int128_t to be 16 bytes aligned, it's a safe default. + .spu_2, + .csky, + .arc, + .m68k, + .tce, + .tcele, + .le32, + .amdil, + .hsail, + .spir, + .kalimba, + .renderscript32, + .spirv32, + .shave, + .le64, + .amdil64, + .hsail64, + .spir64, + .renderscript64, + .ve, + .spirv64, + .dxil, + .loongarch32, + .loongarch64, + .xtensa, + => 16, + }; +} + +pub fn ptrBitWidth(target: Target) u16 { + switch (target.abi) { + .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32, + .gnuabi64 => return 64, + else => {}, + } + switch (target.cpu.arch) { + .avr, + .msp430, + .spu_2, + => return 16, + + .arc, + .arm, + .armeb, + .csky, + .hexagon, + .m68k, + .le32, + .mips, + .mipsel, + .powerpc, + .powerpcle, + .r600, + .riscv32, + .sparcel, + .tce, + .tcele, + .thumb, + .thumbeb, + .x86, + .xcore, + .nvptx, + .amdil, + .hsail, + .spir, + .kalimba, + .shave, + .lanai, + .wasm32, + .renderscript32, + .aarch64_32, + .spirv32, + .loongarch32, + .dxil, + .xtensa, + => return 32, + + .aarch64, + .aarch64_be, + .mips64, + .mips64el, + .powerpc64, + .powerpc64le, + .riscv64, + .x86_64, + .nvptx64, + .le64, + .amdil64, + .hsail64, + .spir64, + .wasm64, + .renderscript64, + .amdgcn, + .bpfel, + .bpfeb, + .sparc64, + .s390x, + .ve, + .spirv64, + .loongarch64, + => return 64, + + .sparc => return if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) 64 else 32, + } +} + +pub fn stackAlignment(target: Target) u16 { + return switch (target.cpu.arch) { + .m68k => 2, + .amdgcn => 4, + .x86 => switch (target.os.tag) { + .windows, .uefi => 4, + else => 16, + }, + .arm, + .armeb, + .thumb, + .thumbeb, + .mips, + .mipsel, + .sparc, + .sparcel, + => 8, + .aarch64, + .aarch64_be, + .aarch64_32, + .bpfeb, + .bpfel, + .mips64, + .mips64el, + .riscv32, + .riscv64, + .sparc64, + .x86_64, + .ve, + .wasm32, + .wasm64, + => 16, + .powerpc64, + .powerpc64le, + => switch (target.os.tag) { + else => 8, + .linux => 16, + }, + else => @divExact(target.ptrBitWidth(), 8), + }; +} + +/// Default signedness of `char` for the native C compiler for this target +/// Note that char signedness is implementation-defined and many compilers provide +/// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char +pub fn charSignedness(target: Target) std.builtin.Signedness { + switch (target.cpu.arch) { + .aarch64, + .aarch64_32, + .aarch64_be, + .arm, + .armeb, + .thumb, + .thumbeb, + => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned, + .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned, + .powerpcle, + .powerpc64le, + .s390x, + .xcore, + .arc, + .msp430, + .riscv32, + .riscv64, + => return .unsigned, + else => return .signed, + } +} + +pub const CType = enum { + char, + short, + ushort, + int, + uint, + long, + ulong, + longlong, + ulonglong, + float, + double, + longdouble, +}; + +pub fn c_type_byte_size(t: Target, c_type: CType) u16 { + return switch (c_type) { + .char, + .short, + .ushort, + .int, + .uint, + .long, + .ulong, + .longlong, + .ulonglong, + .float, + .double, + => @divExact(c_type_bit_size(t, c_type), 8), + + .longdouble => switch (c_type_bit_size(t, c_type)) { + 16 => 2, + 32 => 4, + 64 => 8, + 80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))), + 128 => 16, + else => unreachable, + }, + }; +} + +pub fn c_type_bit_size(target: Target, c_type: CType) u16 { + switch (target.os.tag) { + .freestanding, .other => switch (target.cpu.arch) { + .msp430 => switch (c_type) { + .char => return 8, + .short, .ushort, .int, .uint => return 16, + .float, .long, .ulong => return 32, + .longlong, .ulonglong, .double, .longdouble => return 64, + }, + .avr => switch (c_type) { + .char => return 8, + .short, .ushort, .int, .uint => return 16, + .long, .ulong, .float, .double, .longdouble => return 32, + .longlong, .ulonglong => return 64, + }, + .tce, .tcele => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .long, .ulong, .longlong, .ulonglong => return 32, + .float, .double, .longdouble => return 32, + }, + .mips64, .mips64el => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return if (target.abi != .gnuabin32) 64 else 32, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 128, + }, + .x86_64 => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => switch (target.abi) { + .gnux32, .muslx32 => return 32, + else => return 64, + }, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 80, + }, + else => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return target.ptrBitWidth(), + .longlong, .ulonglong, .double => return 64, + .longdouble => switch (target.cpu.arch) { + .x86 => switch (target.abi) { + .android => return 64, + else => return 80, + }, + + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + => switch (target.abi) { + .musl, + .musleabi, + .musleabihf, + .muslx32, + => return 64, + else => return 128, + }, + + .riscv32, + .riscv64, + .aarch64, + .aarch64_be, + .aarch64_32, + .s390x, + .sparc, + .sparc64, + .sparcel, + .wasm32, + .wasm64, + => return 128, + + else => return 64, + }, + }, + }, + + .linux, + .freebsd, + .netbsd, + .dragonfly, + .openbsd, + .wasi, + .emscripten, + .plan9, + .solaris, + .illumos, + .haiku, + .ananas, + .fuchsia, + .minix, + => switch (target.cpu.arch) { + .msp430 => switch (c_type) { + .char => return 8, + .short, .ushort, .int, .uint => return 16, + .long, .ulong, .float => return 32, + .longlong, .ulonglong, .double, .longdouble => return 64, + }, + .avr => switch (c_type) { + .char => return 8, + .short, .ushort, .int, .uint => return 16, + .long, .ulong, .float, .double, .longdouble => return 32, + .longlong, .ulonglong => return 64, + }, + .tce, .tcele => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .long, .ulong, .longlong, .ulonglong => return 32, + .float, .double, .longdouble => return 32, + }, + .mips64, .mips64el => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return if (target.abi != .gnuabin32) 64 else 32, + .longlong, .ulonglong, .double => return 64, + .longdouble => if (target.os.tag == .freebsd) return 64 else return 128, + }, + .x86_64 => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => switch (target.abi) { + .gnux32, .muslx32 => return 32, + else => return 64, + }, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 80, + }, + else => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return target.ptrBitWidth(), + .longlong, .ulonglong, .double => return 64, + .longdouble => switch (target.cpu.arch) { + .x86 => switch (target.abi) { + .android => return 64, + else => return 80, + }, + + .powerpc, + .powerpcle, + => switch (target.abi) { + .musl, + .musleabi, + .musleabihf, + .muslx32, + => return 64, + else => switch (target.os.tag) { + .freebsd, .netbsd, .openbsd => return 64, + else => return 128, + }, + }, + + .powerpc64, + .powerpc64le, + => switch (target.abi) { + .musl, + .musleabi, + .musleabihf, + .muslx32, + => return 64, + else => switch (target.os.tag) { + .freebsd, .openbsd => return 64, + else => return 128, + }, + }, + + .riscv32, + .riscv64, + .aarch64, + .aarch64_be, + .aarch64_32, + .s390x, + .mips64, + .mips64el, + .sparc, + .sparc64, + .sparcel, + .wasm32, + .wasm64, + => return 128, + + else => return 64, + }, + }, + }, + + .windows, .uefi => switch (target.cpu.arch) { + .x86 => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return 32, + .longlong, .ulonglong, .double => return 64, + .longdouble => switch (target.abi) { + .gnu, .gnuilp32, .cygnus => return 80, + else => return 64, + }, + }, + .x86_64 => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => switch (target.abi) { + .cygnus => return 64, + else => return 32, + }, + .longlong, .ulonglong, .double => return 64, + .longdouble => switch (target.abi) { + .gnu, .gnuilp32, .cygnus => return 80, + else => return 64, + }, + }, + else => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return 32, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 64, + }, + }, + + .macos, .ios, .tvos, .watchos => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => switch (target.cpu.arch) { + .x86, .arm, .aarch64_32 => return 32, + .x86_64 => switch (target.abi) { + .gnux32, .muslx32 => return 32, + else => return 64, + }, + else => return 64, + }, + .longlong, .ulonglong, .double => return 64, + .longdouble => switch (target.cpu.arch) { + .x86 => switch (target.abi) { + .android => return 64, + else => return 80, + }, + .x86_64 => return 80, + else => return 64, + }, + }, + + .nvcl, .cuda => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => switch (target.cpu.arch) { + .nvptx => return 32, + .nvptx64 => return 64, + else => return 64, + }, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 64, + }, + + .amdhsa, .amdpal => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong, .longlong, .ulonglong, .double => return 64, + .longdouble => return 128, + }, + + .opencl => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong, .double => return 64, + .longlong, .ulonglong => return 128, + // Note: The OpenCL specification does not guarantee a particular size for long double, + // but clang uses 128 bits. + .longdouble => return 128, + }, + + .ps4, .ps5 => switch (c_type) { + .char => return 8, + .short, .ushort => return 16, + .int, .uint, .float => return 32, + .long, .ulong => return 64, + .longlong, .ulonglong, .double => return 64, + .longdouble => return 80, + }, + + .cloudabi, + .kfreebsd, + .lv2, + .zos, + .rtems, + .nacl, + .aix, + .elfiamcu, + .mesa3d, + .contiki, + .hermit, + .hurd, + .glsl450, + .vulkan, + .driverkit, + .shadermodel, + .liteos, + => @panic("TODO specify the C integer and float type sizes for this OS"), + } +} + +pub fn c_type_alignment(target: Target, c_type: CType) u16 { + // Overrides for unusual alignments + switch (target.cpu.arch) { + .avr => return 1, + .x86 => switch (target.os.tag) { + .windows, .uefi => switch (c_type) { + .longlong, .ulonglong, .double => return 8, + .longdouble => switch (target.abi) { + .gnu, .gnuilp32, .cygnus => return 4, + else => return 8, + }, + else => {}, + }, + else => {}, + }, + else => {}, + } + + // Next-power-of-two-aligned, up to a maximum. + return @min( + std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8), + switch (target.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) { + .netbsd => switch (target.abi) { + .gnueabi, + .gnueabihf, + .eabi, + .eabihf, + .android, + .musleabi, + .musleabihf, + => 8, + + else => @as(u16, 4), + }, + .ios, .tvos, .watchos => 4, + else => 8, + }, + + .msp430, + .avr, + => 2, + + .arc, + .csky, + .x86, + .xcore, + .dxil, + .loongarch32, + .tce, + .tcele, + .le32, + .amdil, + .hsail, + .spir, + .spirv32, + .kalimba, + .shave, + .renderscript32, + .ve, + .spu_2, + .xtensa, + => 4, + + .aarch64_32, + .amdgcn, + .amdil64, + .bpfel, + .bpfeb, + .hexagon, + .hsail64, + .loongarch64, + .m68k, + .mips, + .mipsel, + .sparc, + .sparcel, + .sparc64, + .lanai, + .le64, + .nvptx, + .nvptx64, + .r600, + .s390x, + .spir64, + .spirv64, + .renderscript64, + => 8, + + .aarch64, + .aarch64_be, + .mips64, + .mips64el, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + .riscv32, + .riscv64, + .x86_64, + .wasm32, + .wasm64, + => 16, + }, + ); +} + +pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 { + // Overrides for unusual alignments + switch (target.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) { + .netbsd => switch (target.abi) { + .gnueabi, + .gnueabihf, + .eabi, + .eabihf, + .android, + .musleabi, + .musleabihf, + => {}, + + else => switch (c_type) { + .longdouble => return 4, + else => {}, + }, + }, + .ios, .tvos, .watchos => switch (c_type) { + .longdouble => return 4, + else => {}, + }, + else => {}, + }, + .arc => switch (c_type) { + .longdouble => return 4, + else => {}, + }, + .avr => switch (c_type) { + .char, .int, .uint, .long, .ulong, .float, .longdouble => return 1, + .short, .ushort => return 2, + .double => return 4, + .longlong, .ulonglong => return 8, + }, + .x86 => switch (target.os.tag) { + .windows, .uefi => switch (c_type) { + .longdouble => switch (target.abi) { + .gnu, .gnuilp32, .cygnus => return 4, + else => return 8, + }, + else => {}, + }, + else => switch (c_type) { + .longdouble => return 4, + else => {}, + }, + }, + else => {}, + } + + // Next-power-of-two-aligned, up to a maximum. + return @min( + std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8), + switch (target.cpu.arch) { + .msp430 => @as(u16, 2), + + .csky, + .xcore, + .dxil, + .loongarch32, + .tce, + .tcele, + .le32, + .amdil, + .hsail, + .spir, + .spirv32, + .kalimba, + .shave, + .renderscript32, + .ve, + .spu_2, + .xtensa, + => 4, + + .arc, + .arm, + .armeb, + .avr, + .thumb, + .thumbeb, + .aarch64_32, + .amdgcn, + .amdil64, + .bpfel, + .bpfeb, + .hexagon, + .hsail64, + .x86, + .loongarch64, + .m68k, + .mips, + .mipsel, + .sparc, + .sparcel, + .sparc64, + .lanai, + .le64, + .nvptx, + .nvptx64, + .r600, + .s390x, + .spir64, + .spirv64, + .renderscript64, + => 8, + + .aarch64, + .aarch64_be, + .mips64, + .mips64el, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + .riscv32, + .riscv64, + .x86_64, + .wasm32, + .wasm64, + => 16, + }, + ); +} + +pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { + const ignore_case = target.os.tag == .macos or target.os.tag == .windows; + + if (eqlIgnoreCase(ignore_case, name, "c")) + return true; + + if (target.isMinGW()) { + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "uuid")) + return true; + if (eqlIgnoreCase(ignore_case, name, "mingw32")) + return true; + if (eqlIgnoreCase(ignore_case, name, "msvcrt-os")) + return true; + if (eqlIgnoreCase(ignore_case, name, "mingwex")) + return true; + + return false; + } + + if (target.abi.isGnu() or target.abi.isMusl()) { + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "rt")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "util")) + return true; + if (eqlIgnoreCase(ignore_case, name, "xnet")) + return true; + if (eqlIgnoreCase(ignore_case, name, "resolv")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dl")) + return true; + } + + if (target.abi.isMusl()) { + if (eqlIgnoreCase(ignore_case, name, "crypt")) + return true; + } + + if (target.os.tag.isDarwin()) { + if (eqlIgnoreCase(ignore_case, name, "System")) + return true; + if (eqlIgnoreCase(ignore_case, name, "c")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dbm")) + return true; + if (eqlIgnoreCase(ignore_case, name, "dl")) + return true; + if (eqlIgnoreCase(ignore_case, name, "info")) + return true; + if (eqlIgnoreCase(ignore_case, name, "m")) + return true; + if (eqlIgnoreCase(ignore_case, name, "poll")) + return true; + if (eqlIgnoreCase(ignore_case, name, "proc")) + return true; + if (eqlIgnoreCase(ignore_case, name, "pthread")) + return true; + if (eqlIgnoreCase(ignore_case, name, "rpcsvc")) + return true; + } + + if (target.os.isAtLeast(.macos, .{ .major = 10, .minor = 8, .patch = 0 }) orelse false) { + if (eqlIgnoreCase(ignore_case, name, "mx")) + return true; + } + + return false; +} + +pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { + const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; + + return eqlIgnoreCase(ignore_case, name, "c++") or + eqlIgnoreCase(ignore_case, name, "stdc++") or + eqlIgnoreCase(ignore_case, name, "c++abi"); +} + +fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { + if (ignore_case) { + return std.ascii.eqlIgnoreCase(a, b); + } else { + return std.mem.eql(u8, a, b); + } +} + +const Target = @This(); +const std = @import("std.zig"); +const builtin = @import("builtin"); +const Allocator = std.mem.Allocator; + +test { + std.testing.refAllDecls(Cpu.Arch); +} diff --git a/lib/std/target/aarch64.zig b/lib/std/Target/aarch64.zig similarity index 100% rename from lib/std/target/aarch64.zig rename to lib/std/Target/aarch64.zig diff --git a/lib/std/target/amdgpu.zig b/lib/std/Target/amdgpu.zig similarity index 100% rename from lib/std/target/amdgpu.zig rename to lib/std/Target/amdgpu.zig diff --git a/lib/std/target/arc.zig b/lib/std/Target/arc.zig similarity index 100% rename from lib/std/target/arc.zig rename to lib/std/Target/arc.zig diff --git a/lib/std/target/arm.zig b/lib/std/Target/arm.zig similarity index 100% rename from lib/std/target/arm.zig rename to lib/std/Target/arm.zig diff --git a/lib/std/target/avr.zig b/lib/std/Target/avr.zig similarity index 100% rename from lib/std/target/avr.zig rename to lib/std/Target/avr.zig diff --git a/lib/std/target/bpf.zig b/lib/std/Target/bpf.zig similarity index 100% rename from lib/std/target/bpf.zig rename to lib/std/Target/bpf.zig diff --git a/lib/std/target/csky.zig b/lib/std/Target/csky.zig similarity index 100% rename from lib/std/target/csky.zig rename to lib/std/Target/csky.zig diff --git a/lib/std/target/hexagon.zig b/lib/std/Target/hexagon.zig similarity index 100% rename from lib/std/target/hexagon.zig rename to lib/std/Target/hexagon.zig diff --git a/lib/std/target/loongarch.zig b/lib/std/Target/loongarch.zig similarity index 100% rename from lib/std/target/loongarch.zig rename to lib/std/Target/loongarch.zig diff --git a/lib/std/target/m68k.zig b/lib/std/Target/m68k.zig similarity index 100% rename from lib/std/target/m68k.zig rename to lib/std/Target/m68k.zig diff --git a/lib/std/target/mips.zig b/lib/std/Target/mips.zig similarity index 100% rename from lib/std/target/mips.zig rename to lib/std/Target/mips.zig diff --git a/lib/std/target/msp430.zig b/lib/std/Target/msp430.zig similarity index 100% rename from lib/std/target/msp430.zig rename to lib/std/Target/msp430.zig diff --git a/lib/std/target/nvptx.zig b/lib/std/Target/nvptx.zig similarity index 100% rename from lib/std/target/nvptx.zig rename to lib/std/Target/nvptx.zig diff --git a/lib/std/target/powerpc.zig b/lib/std/Target/powerpc.zig similarity index 100% rename from lib/std/target/powerpc.zig rename to lib/std/Target/powerpc.zig diff --git a/lib/std/target/riscv.zig b/lib/std/Target/riscv.zig similarity index 100% rename from lib/std/target/riscv.zig rename to lib/std/Target/riscv.zig diff --git a/lib/std/target/s390x.zig b/lib/std/Target/s390x.zig similarity index 100% rename from lib/std/target/s390x.zig rename to lib/std/Target/s390x.zig diff --git a/lib/std/target/sparc.zig b/lib/std/Target/sparc.zig similarity index 100% rename from lib/std/target/sparc.zig rename to lib/std/Target/sparc.zig diff --git a/lib/std/target/spirv.zig b/lib/std/Target/spirv.zig similarity index 100% rename from lib/std/target/spirv.zig rename to lib/std/Target/spirv.zig diff --git a/lib/std/target/ve.zig b/lib/std/Target/ve.zig similarity index 100% rename from lib/std/target/ve.zig rename to lib/std/Target/ve.zig diff --git a/lib/std/target/wasm.zig b/lib/std/Target/wasm.zig similarity index 100% rename from lib/std/target/wasm.zig rename to lib/std/Target/wasm.zig diff --git a/lib/std/target/x86.zig b/lib/std/Target/x86.zig similarity index 100% rename from lib/std/target/x86.zig rename to lib/std/Target/x86.zig diff --git a/lib/std/target/xtensa.zig b/lib/std/Target/xtensa.zig similarity index 100% rename from lib/std/target/xtensa.zig rename to lib/std/Target/xtensa.zig diff --git a/lib/std/std.zig b/lib/std/std.zig index 8db22c3c6cc1..66e30c4b4ee1 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -47,7 +47,7 @@ pub const StringArrayHashMap = array_hash_map.StringArrayHashMap; pub const StringArrayHashMapUnmanaged = array_hash_map.StringArrayHashMapUnmanaged; /// deprecated: use `DoublyLinkedList`. pub const TailQueue = DoublyLinkedList; -pub const Target = @import("target.zig").Target; +pub const Target = @import("Target.zig"); pub const Thread = @import("Thread.zig"); pub const Treap = @import("treap.zig").Treap; pub const Tz = tz.Tz; diff --git a/lib/std/target.zig b/lib/std/target.zig deleted file mode 100644 index dc2ea3d740c4..000000000000 --- a/lib/std/target.zig +++ /dev/null @@ -1,2698 +0,0 @@ -const std = @import("std.zig"); -const builtin = @import("builtin"); -const mem = std.mem; -const Version = std.SemanticVersion; - -pub const Target = struct { - cpu: Cpu, - os: Os, - abi: Abi, - ofmt: ObjectFormat, - - pub const Os = struct { - tag: Tag, - version_range: VersionRange, - - pub const Tag = enum { - freestanding, - ananas, - cloudabi, - dragonfly, - freebsd, - fuchsia, - ios, - kfreebsd, - linux, - lv2, - macos, - netbsd, - openbsd, - solaris, - uefi, - windows, - zos, - haiku, - minix, - rtems, - nacl, - aix, - cuda, - nvcl, - amdhsa, - ps4, - ps5, - elfiamcu, - tvos, - watchos, - driverkit, - mesa3d, - contiki, - amdpal, - hermit, - hurd, - wasi, - emscripten, - shadermodel, - liteos, - opencl, - glsl450, - vulkan, - plan9, - illumos, - other, - - pub inline fn isDarwin(tag: Tag) bool { - return switch (tag) { - .ios, .macos, .watchos, .tvos => true, - else => false, - }; - } - - pub inline fn isBSD(tag: Tag) bool { - return tag.isDarwin() or switch (tag) { - .kfreebsd, .freebsd, .openbsd, .netbsd, .dragonfly => true, - else => false, - }; - } - - pub inline fn isSolarish(tag: Tag) bool { - return tag == .solaris or tag == .illumos; - } - - pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 { - if (tag.isDarwin()) { - return ".dylib"; - } - switch (tag) { - .windows => return ".dll", - else => return ".so", - } - } - - pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os { - return .{ - .tag = tag, - .version_range = VersionRange.default(tag, arch), - }; - } - }; - - /// Based on NTDDI version constants from - /// https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt - pub const WindowsVersion = enum(u32) { - nt4 = 0x04000000, - win2k = 0x05000000, - xp = 0x05010000, - ws2003 = 0x05020000, - vista = 0x06000000, - win7 = 0x06010000, - win8 = 0x06020000, - win8_1 = 0x06030000, - win10 = 0x0A000000, //aka win10_th1 - win10_th2 = 0x0A000001, - win10_rs1 = 0x0A000002, - win10_rs2 = 0x0A000003, - win10_rs3 = 0x0A000004, - win10_rs4 = 0x0A000005, - win10_rs5 = 0x0A000006, - win10_19h1 = 0x0A000007, - win10_vb = 0x0A000008, //aka win10_19h2 - win10_mn = 0x0A000009, //aka win10_20h1 - win10_fe = 0x0A00000A, //aka win10_20h2 - _, - - /// Latest Windows version that the Zig Standard Library is aware of - pub const latest = WindowsVersion.win10_fe; - - /// Compared against build numbers reported by the runtime to distinguish win10 versions, - /// where 0x0A000000 + index corresponds to the WindowsVersion u32 value. - pub const known_win10_build_numbers = [_]u32{ - 10240, //win10 aka win10_th1 - 10586, //win10_th2 - 14393, //win10_rs1 - 15063, //win10_rs2 - 16299, //win10_rs3 - 17134, //win10_rs4 - 17763, //win10_rs5 - 18362, //win10_19h1 - 18363, //win10_vb aka win10_19h2 - 19041, //win10_mn aka win10_20h1 - 19042, //win10_fe aka win10_20h2 - }; - - /// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`. - pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool { - return @intFromEnum(self) >= @intFromEnum(ver); - } - - pub const Range = struct { - min: WindowsVersion, - max: WindowsVersion, - - pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool { - return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max); - } - - /// Checks if system is guaranteed to be at least `version` or older than `version`. - /// Returns `null` if a runtime check is required. - pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool { - if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true; - if (@intFromEnum(self.max) < @intFromEnum(ver)) return false; - return null; - } - }; - - /// This function is defined to serialize a Zig source code representation of this - /// type, that, when parsed, will deserialize into the same data. - pub fn format( - self: WindowsVersion, - comptime fmt: []const u8, - _: std.fmt.FormatOptions, - out_stream: anytype, - ) !void { - if (comptime std.mem.eql(u8, fmt, "s")) { - if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) { - try std.fmt.format(out_stream, ".{s}", .{@tagName(self)}); - } else { - // TODO this code path breaks zig triples, but it is used in `builtin` - try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)}); - } - } else if (fmt.len == 0) { - if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) { - try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)}); - } else { - try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)}); - } - } else { - std.fmt.invalidFmtError(fmt, self); - } - } - }; - - pub const LinuxVersionRange = struct { - range: Version.Range, - glibc: Version, - - pub inline fn includesVersion(self: LinuxVersionRange, ver: Version) bool { - return self.range.includesVersion(ver); - } - - /// Checks if system is guaranteed to be at least `version` or older than `version`. - /// Returns `null` if a runtime check is required. - pub inline fn isAtLeast(self: LinuxVersionRange, ver: Version) ?bool { - return self.range.isAtLeast(ver); - } - }; - - /// The version ranges here represent the minimum OS version to be supported - /// and the maximum OS version to be supported. The default values represent - /// the range that the Zig Standard Library bases its abstractions on. - /// - /// The minimum version of the range is the main setting to tweak for a target. - /// Usually, the maximum target OS version will remain the default, which is - /// the latest released version of the OS. - /// - /// To test at compile time if the target is guaranteed to support a given OS feature, - /// one should check that the minimum version of the range is greater than or equal to - /// the version the feature was introduced in. - /// - /// To test at compile time if the target certainly will not support a given OS feature, - /// one should check that the maximum version of the range is less than the version the - /// feature was introduced in. - /// - /// If neither of these cases apply, a runtime check should be used to determine if the - /// target supports a given OS feature. - /// - /// Binaries built with a given maximum version will continue to function on newer - /// operating system versions. However, such a binary may not take full advantage of the - /// newer operating system APIs. - /// - /// See `Os.isAtLeast`. - pub const VersionRange = union { - none: void, - semver: Version.Range, - linux: LinuxVersionRange, - windows: WindowsVersion.Range, - - /// The default `VersionRange` represents the range that the Zig Standard Library - /// bases its abstractions on. - pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange { - switch (tag) { - .freestanding, - .ananas, - .cloudabi, - .fuchsia, - .kfreebsd, - .lv2, - .zos, - .haiku, - .minix, - .rtems, - .nacl, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .wasi, - .emscripten, - .driverkit, - .shadermodel, - .liteos, - .uefi, - .opencl, // TODO: OpenCL versions - .glsl450, // TODO: GLSL versions - .vulkan, - .plan9, - .illumos, - .other, - => return .{ .none = {} }, - - .freebsd => return .{ - .semver = Version.Range{ - .min = .{ .major = 12, .minor = 0, .patch = 0 }, - .max = .{ .major = 14, .minor = 0, .patch = 0 }, - }, - }, - .macos => return switch (arch) { - .aarch64 => VersionRange{ - .semver = .{ - .min = .{ .major = 11, .minor = 7, .patch = 1 }, - .max = .{ .major = 14, .minor = 1, .patch = 0 }, - }, - }, - .x86_64 => VersionRange{ - .semver = .{ - .min = .{ .major = 11, .minor = 7, .patch = 1 }, - .max = .{ .major = 14, .minor = 1, .patch = 0 }, - }, - }, - else => unreachable, - }, - .ios => return .{ - .semver = .{ - .min = .{ .major = 12, .minor = 0, .patch = 0 }, - .max = .{ .major = 17, .minor = 1, .patch = 0 }, - }, - }, - .watchos => return .{ - .semver = .{ - .min = .{ .major = 6, .minor = 0, .patch = 0 }, - .max = .{ .major = 10, .minor = 1, .patch = 0 }, - }, - }, - .tvos => return .{ - .semver = .{ - .min = .{ .major = 13, .minor = 0, .patch = 0 }, - .max = .{ .major = 17, .minor = 1, .patch = 0 }, - }, - }, - .netbsd => return .{ - .semver = .{ - .min = .{ .major = 8, .minor = 0, .patch = 0 }, - .max = .{ .major = 10, .minor = 0, .patch = 0 }, - }, - }, - .openbsd => return .{ - .semver = .{ - .min = .{ .major = 6, .minor = 8, .patch = 0 }, - .max = .{ .major = 7, .minor = 4, .patch = 0 }, - }, - }, - .dragonfly => return .{ - .semver = .{ - .min = .{ .major = 5, .minor = 8, .patch = 0 }, - .max = .{ .major = 6, .minor = 4, .patch = 0 }, - }, - }, - .solaris => return .{ - .semver = .{ - .min = .{ .major = 5, .minor = 11, .patch = 0 }, - .max = .{ .major = 5, .minor = 11, .patch = 0 }, - }, - }, - - .linux => return .{ - .linux = .{ - .range = .{ - .min = .{ .major = 4, .minor = 19, .patch = 0 }, - .max = .{ .major = 6, .minor = 5, .patch = 7 }, - }, - .glibc = .{ .major = 2, .minor = 28, .patch = 0 }, - }, - }, - - .windows => return .{ - .windows = .{ - .min = .win8_1, - .max = WindowsVersion.latest, - }, - }, - } - } - }; - - pub const TaggedVersionRange = union(enum) { - none: void, - semver: Version.Range, - linux: LinuxVersionRange, - windows: WindowsVersion.Range, - }; - - /// Provides a tagged union. `Target` does not store the tag because it is - /// redundant with the OS tag; this function abstracts that part away. - pub inline fn getVersionRange(self: Os) TaggedVersionRange { - switch (self.tag) { - .linux => return TaggedVersionRange{ .linux = self.version_range.linux }, - .windows => return TaggedVersionRange{ .windows = self.version_range.windows }, - - .freebsd, - .macos, - .ios, - .tvos, - .watchos, - .netbsd, - .openbsd, - .dragonfly, - .solaris, - => return TaggedVersionRange{ .semver = self.version_range.semver }, - - else => return .none, - } - } - - /// Checks if system is guaranteed to be at least `version` or older than `version`. - /// Returns `null` if a runtime check is required. - pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: anytype) ?bool { - if (self.tag != tag) return false; - - return switch (tag) { - .linux => self.version_range.linux.isAtLeast(version), - .windows => self.version_range.windows.isAtLeast(version), - else => self.version_range.semver.isAtLeast(version), - }; - } - - /// On Darwin, we always link libSystem which contains libc. - /// Similarly on FreeBSD and NetBSD we always link system libc - /// since this is the stable syscall interface. - pub fn requiresLibC(os: Os) bool { - return switch (os.tag) { - .freebsd, - .netbsd, - .macos, - .ios, - .tvos, - .watchos, - .dragonfly, - .openbsd, - .haiku, - .solaris, - .illumos, - => true, - - .linux, - .windows, - .freestanding, - .ananas, - .cloudabi, - .fuchsia, - .kfreebsd, - .lv2, - .zos, - .minix, - .rtems, - .nacl, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .wasi, - .emscripten, - .driverkit, - .shadermodel, - .liteos, - .uefi, - .opencl, - .glsl450, - .vulkan, - .plan9, - .other, - => false, - }; - } - }; - - pub const aarch64 = @import("target/aarch64.zig"); - pub const arc = @import("target/arc.zig"); - pub const amdgpu = @import("target/amdgpu.zig"); - pub const arm = @import("target/arm.zig"); - pub const avr = @import("target/avr.zig"); - pub const bpf = @import("target/bpf.zig"); - pub const csky = @import("target/csky.zig"); - pub const hexagon = @import("target/hexagon.zig"); - pub const loongarch = @import("target/loongarch.zig"); - pub const m68k = @import("target/m68k.zig"); - pub const mips = @import("target/mips.zig"); - pub const msp430 = @import("target/msp430.zig"); - pub const nvptx = @import("target/nvptx.zig"); - pub const powerpc = @import("target/powerpc.zig"); - pub const riscv = @import("target/riscv.zig"); - pub const sparc = @import("target/sparc.zig"); - pub const spirv = @import("target/spirv.zig"); - pub const s390x = @import("target/s390x.zig"); - pub const ve = @import("target/ve.zig"); - pub const wasm = @import("target/wasm.zig"); - pub const x86 = @import("target/x86.zig"); - pub const xtensa = @import("target/xtensa.zig"); - - pub const Abi = enum { - none, - gnu, - gnuabin32, - gnuabi64, - gnueabi, - gnueabihf, - gnuf32, - gnuf64, - gnusf, - gnux32, - gnuilp32, - code16, - eabi, - eabihf, - android, - musl, - musleabi, - musleabihf, - muslx32, - msvc, - itanium, - cygnus, - coreclr, - simulator, - macabi, - pixel, - vertex, - geometry, - hull, - domain, - compute, - library, - raygeneration, - intersection, - anyhit, - closesthit, - miss, - callable, - mesh, - amplification, - - pub fn default(arch: Cpu.Arch, target_os: Os) Abi { - if (arch.isWasm()) { - return .musl; - } - switch (target_os.tag) { - .freestanding, - .ananas, - .cloudabi, - .dragonfly, - .lv2, - .zos, - .minix, - .rtems, - .nacl, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .other, - => return .eabi, - .openbsd, - .freebsd, - .fuchsia, - .kfreebsd, - .netbsd, - .hurd, - .haiku, - .windows, - => return .gnu, - .uefi => return .msvc, - .linux, - .wasi, - .emscripten, - => return .musl, - .opencl, // TODO: SPIR-V ABIs with Linkage capability - .glsl450, - .vulkan, - .plan9, // TODO specify abi - .macos, - .ios, - .tvos, - .watchos, - .driverkit, - .shadermodel, - .liteos, // TODO: audit this - .solaris, - .illumos, - => return .none, - } - } - - pub inline fn isGnu(abi: Abi) bool { - return switch (abi) { - .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true, - else => false, - }; - } - - pub inline fn isMusl(abi: Abi) bool { - return switch (abi) { - .musl, .musleabi, .musleabihf => true, - else => false, - }; - } - - pub inline fn floatAbi(abi: Abi) FloatAbi { - return switch (abi) { - .gnueabihf, - .eabihf, - .musleabihf, - => .hard, - else => .soft, - }; - } - }; - - pub const ObjectFormat = enum { - /// Common Object File Format (Windows) - coff, - /// DirectX Container - dxcontainer, - /// Executable and Linking Format - elf, - /// macOS relocatables - macho, - /// Standard, Portable Intermediate Representation V - spirv, - /// WebAssembly - wasm, - /// C source code - c, - /// Intel IHEX - hex, - /// Machine code with no metadata. - raw, - /// Plan 9 from Bell Labs - plan9, - /// Nvidia PTX format - nvptx, - - pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 { - return switch (of) { - .coff => ".obj", - .elf, .macho, .wasm => ".o", - .c => ".c", - .spirv => ".spv", - .hex => ".ihex", - .raw => ".bin", - .plan9 => plan9Ext(cpu_arch), - .nvptx => ".ptx", - .dxcontainer => ".dxil", - }; - } - - pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat { - return switch (os_tag) { - .windows, .uefi => .coff, - .ios, .macos, .watchos, .tvos => .macho, - .plan9 => .plan9, - else => return switch (cpu_arch) { - .wasm32, .wasm64 => .wasm, - .spirv32, .spirv64 => .spirv, - .nvptx, .nvptx64 => .nvptx, - else => .elf, - }, - }; - } - }; - - pub const SubSystem = enum { - Console, - Windows, - Posix, - Native, - EfiApplication, - EfiBootServiceDriver, - EfiRom, - EfiRuntimeDriver, - }; - - pub const Cpu = struct { - /// Architecture - arch: Arch, - - /// The CPU model to target. It has a set of features - /// which are overridden with the `features` field. - model: *const Model, - - /// An explicit list of the entire CPU feature set. It may differ from the specific CPU model's features. - features: Feature.Set, - - pub const Feature = struct { - /// The bit index into `Set`. Has a default value of `undefined` because the canonical - /// structures are populated via comptime logic. - index: Set.Index = undefined, - - /// Has a default value of `undefined` because the canonical - /// structures are populated via comptime logic. - name: []const u8 = undefined, - - /// If this corresponds to an LLVM-recognized feature, this will be populated; - /// otherwise null. - llvm_name: ?[:0]const u8, - - /// Human-friendly UTF-8 text. - description: []const u8, - - /// Sparse `Set` of features this depends on. - dependencies: Set, - - /// A bit set of all the features. - pub const Set = struct { - ints: [usize_count]usize, - - pub const needed_bit_count = 288; - pub const byte_count = (needed_bit_count + 7) / 8; - pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); - pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); - pub const ShiftInt = std.math.Log2Int(usize); - - pub const empty = Set{ .ints = [1]usize{0} ** usize_count }; - - pub fn isEmpty(set: Set) bool { - return for (set.ints) |x| { - if (x != 0) break false; - } else true; - } - - pub fn isEnabled(set: Set, arch_feature_index: Index) bool { - const usize_index = arch_feature_index / @bitSizeOf(usize); - const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); - return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0; - } - - /// Adds the specified feature but not its dependencies. - pub fn addFeature(set: *Set, arch_feature_index: Index) void { - const usize_index = arch_feature_index / @bitSizeOf(usize); - const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); - set.ints[usize_index] |= @as(usize, 1) << bit_index; - } - - /// Adds the specified feature set but not its dependencies. - pub fn addFeatureSet(set: *Set, other_set: Set) void { - switch (builtin.zig_backend) { - .stage2_x86_64 => { - for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int; - }, - else => { - set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints); - }, - } - } - - /// Removes the specified feature but not its dependents. - pub fn removeFeature(set: *Set, arch_feature_index: Index) void { - const usize_index = arch_feature_index / @bitSizeOf(usize); - const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize))); - set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); - } - - /// Removes the specified feature but not its dependents. - pub fn removeFeatureSet(set: *Set, other_set: Set) void { - switch (builtin.zig_backend) { - .stage2_x86_64 => { - for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int; - }, - else => { - set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints); - }, - } - } - - pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { - @setEvalBranchQuota(1000000); - - var old = set.ints; - while (true) { - for (all_features_list, 0..) |feature, index_usize| { - const index = @as(Index, @intCast(index_usize)); - if (set.isEnabled(index)) { - set.addFeatureSet(feature.dependencies); - } - } - const nothing_changed = mem.eql(usize, &old, &set.ints); - if (nothing_changed) return; - old = set.ints; - } - } - - pub fn asBytes(set: *const Set) *const [byte_count]u8 { - return @as(*const [byte_count]u8, @ptrCast(&set.ints)); - } - - pub fn eql(set: Set, other_set: Set) bool { - return mem.eql(usize, &set.ints, &other_set.ints); - } - - pub fn isSuperSetOf(set: Set, other_set: Set) bool { - switch (builtin.zig_backend) { - .stage2_x86_64 => { - var result = true; - for (&set.ints, other_set.ints) |*set_int, other_set_int| - result = result and (set_int.* & other_set_int) == other_set_int; - return result; - }, - else => { - const V = @Vector(usize_count, usize); - const set_v: V = set.ints; - const other_v: V = other_set.ints; - return @reduce(.And, (set_v & other_v) == other_v); - }, - } - } - }; - - pub fn feature_set_fns(comptime F: type) type { - return struct { - /// Populates only the feature bits specified. - pub fn featureSet(features: []const F) Set { - var x = Set.empty; - for (features) |feature| { - x.addFeature(@intFromEnum(feature)); - } - return x; - } - - /// Returns true if the specified feature is enabled. - pub fn featureSetHas(set: Set, feature: F) bool { - return set.isEnabled(@intFromEnum(feature)); - } - - /// Returns true if any specified feature is enabled. - pub fn featureSetHasAny(set: Set, features: anytype) bool { - inline for (features) |feature| { - if (set.isEnabled(@intFromEnum(@as(F, feature)))) return true; - } - return false; - } - - /// Returns true if every specified feature is enabled. - pub fn featureSetHasAll(set: Set, features: anytype) bool { - inline for (features) |feature| { - if (!set.isEnabled(@intFromEnum(@as(F, feature)))) return false; - } - return true; - } - }; - } - }; - - pub const Arch = enum { - arm, - armeb, - aarch64, - aarch64_be, - aarch64_32, - arc, - avr, - bpfel, - bpfeb, - csky, - dxil, - hexagon, - loongarch32, - loongarch64, - m68k, - mips, - mipsel, - mips64, - mips64el, - msp430, - powerpc, - powerpcle, - powerpc64, - powerpc64le, - r600, - amdgcn, - riscv32, - riscv64, - sparc, - sparc64, - sparcel, - s390x, - tce, - tcele, - thumb, - thumbeb, - x86, - x86_64, - xcore, - xtensa, - nvptx, - nvptx64, - le32, - le64, - amdil, - amdil64, - hsail, - hsail64, - spir, - spir64, - spirv32, - spirv64, - kalimba, - shave, - lanai, - wasm32, - wasm64, - renderscript32, - renderscript64, - ve, - // Stage1 currently assumes that architectures above this comment - // map one-to-one with the ZigLLVM_ArchType enum. - spu_2, - - pub inline fn isX86(arch: Arch) bool { - return switch (arch) { - .x86, .x86_64 => true, - else => false, - }; - } - - pub inline fn isARM(arch: Arch) bool { - return switch (arch) { - .arm, .armeb => true, - else => false, - }; - } - - pub inline fn isAARCH64(arch: Arch) bool { - return switch (arch) { - .aarch64, .aarch64_be, .aarch64_32 => true, - else => false, - }; - } - - pub inline fn isThumb(arch: Arch) bool { - return switch (arch) { - .thumb, .thumbeb => true, - else => false, - }; - } - - pub inline fn isArmOrThumb(arch: Arch) bool { - return arch.isARM() or arch.isThumb(); - } - - pub inline fn isWasm(arch: Arch) bool { - return switch (arch) { - .wasm32, .wasm64 => true, - else => false, - }; - } - - pub inline fn isRISCV(arch: Arch) bool { - return switch (arch) { - .riscv32, .riscv64 => true, - else => false, - }; - } - - pub inline fn isMIPS(arch: Arch) bool { - return switch (arch) { - .mips, .mipsel, .mips64, .mips64el => true, - else => false, - }; - } - - pub inline fn isPPC(arch: Arch) bool { - return switch (arch) { - .powerpc, .powerpcle => true, - else => false, - }; - } - - pub inline fn isPPC64(arch: Arch) bool { - return switch (arch) { - .powerpc64, .powerpc64le => true, - else => false, - }; - } - - pub inline fn isSPARC(arch: Arch) bool { - return switch (arch) { - .sparc, .sparcel, .sparc64 => true, - else => false, - }; - } - - pub inline fn isSpirV(arch: Arch) bool { - return switch (arch) { - .spirv32, .spirv64 => true, - else => false, - }; - } - - pub inline fn isBpf(arch: Arch) bool { - return switch (arch) { - .bpfel, .bpfeb => true, - else => false, - }; - } - - pub inline fn isNvptx(arch: Arch) bool { - return switch (arch) { - .nvptx, .nvptx64 => true, - else => false, - }; - } - - pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { - for (arch.allCpuModels()) |cpu| { - if (mem.eql(u8, cpu_name, cpu.name)) { - return cpu; - } - } - return error.UnknownCpuModel; - } - - pub fn toElfMachine(arch: Arch) std.elf.EM { - return switch (arch) { - .avr => .AVR, - .msp430 => .MSP430, - .arc => .ARC, - .arm => .ARM, - .armeb => .ARM, - .hexagon => .HEXAGON, - .dxil => .NONE, - .m68k => .@"68K", - .le32 => .NONE, - .mips => .MIPS, - .mipsel => .MIPS_RS3_LE, - .powerpc, .powerpcle => .PPC, - .r600 => .NONE, - .riscv32 => .RISCV, - .sparc => .SPARC, - .sparcel => .SPARC, - .tce => .NONE, - .tcele => .NONE, - .thumb => .ARM, - .thumbeb => .ARM, - .x86 => .@"386", - .xcore => .XCORE, - .xtensa => .XTENSA, - .nvptx => .NONE, - .amdil => .NONE, - .hsail => .NONE, - .spir => .NONE, - .kalimba => .CSR_KALIMBA, - .shave => .NONE, - .lanai => .LANAI, - .wasm32 => .NONE, - .renderscript32 => .NONE, - .aarch64_32 => .AARCH64, - .aarch64 => .AARCH64, - .aarch64_be => .AARCH64, - .mips64 => .MIPS, - .mips64el => .MIPS_RS3_LE, - .powerpc64 => .PPC64, - .powerpc64le => .PPC64, - .riscv64 => .RISCV, - .x86_64 => .X86_64, - .nvptx64 => .NONE, - .le64 => .NONE, - .amdil64 => .NONE, - .hsail64 => .NONE, - .spir64 => .NONE, - .wasm64 => .NONE, - .renderscript64 => .NONE, - .amdgcn => .AMDGPU, - .bpfel => .BPF, - .bpfeb => .BPF, - .csky => .CSKY, - .sparc64 => .SPARCV9, - .s390x => .S390, - .ve => .NONE, - .spu_2 => .SPU_2, - .spirv32 => .NONE, - .spirv64 => .NONE, - .loongarch32 => .NONE, - .loongarch64 => .NONE, - }; - } - - pub fn toCoffMachine(arch: Arch) std.coff.MachineType { - return switch (arch) { - .avr => .Unknown, - .msp430 => .Unknown, - .arc => .Unknown, - .arm => .ARM, - .armeb => .Unknown, - .dxil => .Unknown, - .hexagon => .Unknown, - .m68k => .Unknown, - .le32 => .Unknown, - .mips => .Unknown, - .mipsel => .Unknown, - .powerpc, .powerpcle => .POWERPC, - .r600 => .Unknown, - .riscv32 => .RISCV32, - .sparc => .Unknown, - .sparcel => .Unknown, - .tce => .Unknown, - .tcele => .Unknown, - .thumb => .Thumb, - .thumbeb => .Thumb, - .x86 => .I386, - .xcore => .Unknown, - .xtensa => .Unknown, - .nvptx => .Unknown, - .amdil => .Unknown, - .hsail => .Unknown, - .spir => .Unknown, - .kalimba => .Unknown, - .shave => .Unknown, - .lanai => .Unknown, - .wasm32 => .Unknown, - .renderscript32 => .Unknown, - .aarch64_32 => .ARM64, - .aarch64 => .ARM64, - .aarch64_be => .ARM64, - .mips64 => .Unknown, - .mips64el => .Unknown, - .powerpc64 => .Unknown, - .powerpc64le => .Unknown, - .riscv64 => .RISCV64, - .x86_64 => .X64, - .nvptx64 => .Unknown, - .le64 => .Unknown, - .amdil64 => .Unknown, - .hsail64 => .Unknown, - .spir64 => .Unknown, - .wasm64 => .Unknown, - .renderscript64 => .Unknown, - .amdgcn => .Unknown, - .bpfel => .Unknown, - .bpfeb => .Unknown, - .csky => .Unknown, - .sparc64 => .Unknown, - .s390x => .Unknown, - .ve => .Unknown, - .spu_2 => .Unknown, - .spirv32 => .Unknown, - .spirv64 => .Unknown, - .loongarch32 => .Unknown, - .loongarch64 => .Unknown, - }; - } - - pub fn endian(arch: Arch) std.builtin.Endian { - return switch (arch) { - .avr, - .arm, - .aarch64_32, - .aarch64, - .amdgcn, - .amdil, - .amdil64, - .bpfel, - .csky, - .xtensa, - .hexagon, - .hsail, - .hsail64, - .kalimba, - .le32, - .le64, - .mipsel, - .mips64el, - .msp430, - .nvptx, - .nvptx64, - .sparcel, - .tcele, - .powerpcle, - .powerpc64le, - .r600, - .riscv32, - .riscv64, - .x86, - .x86_64, - .wasm32, - .wasm64, - .xcore, - .thumb, - .spir, - .spir64, - .renderscript32, - .renderscript64, - .shave, - .ve, - .spu_2, - // GPU bitness is opaque. For now, assume little endian. - .spirv32, - .spirv64, - .dxil, - .loongarch32, - .loongarch64, - .arc, - => .little, - - .armeb, - .aarch64_be, - .bpfeb, - .m68k, - .mips, - .mips64, - .powerpc, - .powerpc64, - .thumbeb, - .sparc, - .sparc64, - .tce, - .lanai, - .s390x, - => .big, - }; - } - - /// Returns whether this architecture supports the address space - pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool { - const is_nvptx = arch == .nvptx or arch == .nvptx64; - const is_spirv = arch == .spirv32 or arch == .spirv64; - const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; - return switch (address_space) { - .generic => true, - .fs, .gs, .ss => arch == .x86_64 or arch == .x86, - .global, .constant, .local, .shared => is_gpu, - .param => is_nvptx, - // TODO this should also check how many flash banks the cpu has - .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, - }; - } - - /// Returns a name that matches the lib/std/target/* source file name. - pub fn genericName(arch: Arch) []const u8 { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => "arm", - .aarch64, .aarch64_be, .aarch64_32 => "aarch64", - .bpfel, .bpfeb => "bpf", - .loongarch32, .loongarch64 => "loongarch", - .mips, .mipsel, .mips64, .mips64el => "mips", - .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc", - .amdgcn => "amdgpu", - .riscv32, .riscv64 => "riscv", - .sparc, .sparc64, .sparcel => "sparc", - .s390x => "s390x", - .x86, .x86_64 => "x86", - .nvptx, .nvptx64 => "nvptx", - .wasm32, .wasm64 => "wasm", - .spirv32, .spirv64 => "spirv", - else => @tagName(arch), - }; - } - - /// All CPU features Zig is aware of, sorted lexicographically by name. - pub fn allFeaturesList(arch: Arch) []const Cpu.Feature { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => &arm.all_features, - .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features, - .arc => &arc.all_features, - .avr => &avr.all_features, - .bpfel, .bpfeb => &bpf.all_features, - .csky => &csky.all_features, - .hexagon => &hexagon.all_features, - .loongarch32, .loongarch64 => &loongarch.all_features, - .m68k => &m68k.all_features, - .mips, .mipsel, .mips64, .mips64el => &mips.all_features, - .msp430 => &msp430.all_features, - .powerpc, .powerpcle, .powerpc64, .powerpc64le => &powerpc.all_features, - .amdgcn => &amdgpu.all_features, - .riscv32, .riscv64 => &riscv.all_features, - .sparc, .sparc64, .sparcel => &sparc.all_features, - .spirv32, .spirv64 => &spirv.all_features, - .s390x => &s390x.all_features, - .x86, .x86_64 => &x86.all_features, - .xtensa => &xtensa.all_features, - .nvptx, .nvptx64 => &nvptx.all_features, - .ve => &ve.all_features, - .wasm32, .wasm64 => &wasm.all_features, - - else => &[0]Cpu.Feature{}, - }; - } - - /// All processors Zig is aware of, sorted lexicographically by name. - pub fn allCpuModels(arch: Arch) []const *const Cpu.Model { - return switch (arch) { - .arc => comptime allCpusFromDecls(arc.cpu), - .arm, .armeb, .thumb, .thumbeb => comptime allCpusFromDecls(arm.cpu), - .aarch64, .aarch64_be, .aarch64_32 => comptime allCpusFromDecls(aarch64.cpu), - .avr => comptime allCpusFromDecls(avr.cpu), - .bpfel, .bpfeb => comptime allCpusFromDecls(bpf.cpu), - .csky => comptime allCpusFromDecls(csky.cpu), - .hexagon => comptime allCpusFromDecls(hexagon.cpu), - .loongarch32, .loongarch64 => comptime allCpusFromDecls(loongarch.cpu), - .m68k => comptime allCpusFromDecls(m68k.cpu), - .mips, .mipsel, .mips64, .mips64el => comptime allCpusFromDecls(mips.cpu), - .msp430 => comptime allCpusFromDecls(msp430.cpu), - .powerpc, .powerpcle, .powerpc64, .powerpc64le => comptime allCpusFromDecls(powerpc.cpu), - .amdgcn => comptime allCpusFromDecls(amdgpu.cpu), - .riscv32, .riscv64 => comptime allCpusFromDecls(riscv.cpu), - .sparc, .sparc64, .sparcel => comptime allCpusFromDecls(sparc.cpu), - .spirv32, .spirv64 => comptime allCpusFromDecls(spirv.cpu), - .s390x => comptime allCpusFromDecls(s390x.cpu), - .x86, .x86_64 => comptime allCpusFromDecls(x86.cpu), - .xtensa => comptime allCpusFromDecls(xtensa.cpu), - .nvptx, .nvptx64 => comptime allCpusFromDecls(nvptx.cpu), - .ve => comptime allCpusFromDecls(ve.cpu), - .wasm32, .wasm64 => comptime allCpusFromDecls(wasm.cpu), - - else => &[0]*const Model{}, - }; - } - - fn allCpusFromDecls(comptime cpus: type) []const *const Cpu.Model { - const decls = @typeInfo(cpus).Struct.decls; - var array: [decls.len]*const Cpu.Model = undefined; - for (decls, 0..) |decl, i| { - array[i] = &@field(cpus, decl.name); - } - return &array; - } - }; - - pub const Model = struct { - name: []const u8, - llvm_name: ?[:0]const u8, - features: Feature.Set, - - pub fn toCpu(model: *const Model, arch: Arch) Cpu { - var features = model.features; - features.populateDependencies(arch.allFeaturesList()); - return .{ - .arch = arch, - .model = model, - .features = features, - }; - } - - pub fn generic(arch: Arch) *const Model { - const S = struct { - const generic_model = Model{ - .name = "generic", - .llvm_name = null, - .features = Cpu.Feature.Set.empty, - }; - }; - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic, - .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, - .avr => &avr.cpu.avr2, - .bpfel, .bpfeb => &bpf.cpu.generic, - .hexagon => &hexagon.cpu.generic, - .loongarch32 => &loongarch.cpu.generic_la32, - .loongarch64 => &loongarch.cpu.generic_la64, - .m68k => &m68k.cpu.generic, - .mips, .mipsel => &mips.cpu.mips32, - .mips64, .mips64el => &mips.cpu.mips64, - .msp430 => &msp430.cpu.generic, - .powerpc => &powerpc.cpu.ppc, - .powerpcle => &powerpc.cpu.ppc, - .powerpc64 => &powerpc.cpu.ppc64, - .powerpc64le => &powerpc.cpu.ppc64le, - .amdgcn => &amdgpu.cpu.generic, - .riscv32 => &riscv.cpu.generic_rv32, - .riscv64 => &riscv.cpu.generic_rv64, - .spirv32, .spirv64 => &spirv.cpu.generic, - .sparc, .sparcel => &sparc.cpu.generic, - .sparc64 => &sparc.cpu.v9, // 64-bit SPARC needs v9 as the baseline - .s390x => &s390x.cpu.generic, - .x86 => &x86.cpu.i386, - .x86_64 => &x86.cpu.x86_64, - .nvptx, .nvptx64 => &nvptx.cpu.sm_20, - .ve => &ve.cpu.generic, - .wasm32, .wasm64 => &wasm.cpu.generic, - - else => &S.generic_model, - }; - } - - pub fn baseline(arch: Arch) *const Model { - return switch (arch) { - .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline, - .riscv32 => &riscv.cpu.baseline_rv32, - .riscv64 => &riscv.cpu.baseline_rv64, - .x86 => &x86.cpu.pentium4, - .nvptx, .nvptx64 => &nvptx.cpu.sm_20, - .sparc, .sparcel => &sparc.cpu.v8, - - else => generic(arch), - }; - } - }; - - /// The "default" set of CPU features for cross-compiling. A conservative set - /// of features that is expected to be supported on most available hardware. - pub fn baseline(arch: Arch) Cpu { - return Model.baseline(arch).toCpu(arch); - } - }; - - pub fn zigTriple(self: Target, allocator: mem.Allocator) ![]u8 { - return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); - } - - pub fn linuxTripleSimple(allocator: mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 { - return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); - } - - pub fn linuxTriple(self: Target, allocator: mem.Allocator) ![]u8 { - return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi); - } - - pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 { - return switch (os_tag) { - .windows => ".exe", - .uefi => ".efi", - .plan9 => plan9Ext(cpu_arch), - else => switch (cpu_arch) { - .wasm32, .wasm64 => ".wasm", - else => "", - }, - }; - } - - pub fn exeFileExt(self: Target) [:0]const u8 { - return exeFileExtSimple(self.cpu.arch, self.os.tag); - } - - pub fn staticLibSuffix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 { - if (abi == .msvc) { - return ".lib"; - } - switch (os_tag) { - .windows, .uefi => return ".lib", - else => return ".a", - } - } - - pub fn staticLibSuffix(self: Target) [:0]const u8 { - return staticLibSuffix_os_abi(self.os.tag, self.abi); - } - - pub fn dynamicLibSuffix(self: Target) [:0]const u8 { - return self.os.tag.dynamicLibSuffix(); - } - - pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 { - if (abi == .msvc) { - return ""; - } - switch (os_tag) { - .windows, .uefi => return "", - else => return "lib", - } - } - - pub fn libPrefix(self: Target) [:0]const u8 { - return libPrefix_os_abi(self.os.tag, self.abi); - } - - pub inline fn isMinGW(self: Target) bool { - return self.os.tag == .windows and self.isGnu(); - } - - pub inline fn isGnu(self: Target) bool { - return self.abi.isGnu(); - } - - pub inline fn isMusl(self: Target) bool { - return self.abi.isMusl(); - } - - pub inline fn isAndroid(self: Target) bool { - return self.abi == .android; - } - - pub inline fn isWasm(self: Target) bool { - return self.cpu.arch.isWasm(); - } - - pub inline fn isDarwin(self: Target) bool { - return self.os.tag.isDarwin(); - } - - pub inline fn isBSD(self: Target) bool { - return self.os.tag.isBSD(); - } - - pub inline fn isBpfFreestanding(self: Target) bool { - return self.cpu.arch.isBpf() and self.os.tag == .freestanding; - } - - pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool { - return os_tag == .linux and abi.isGnu(); - } - - pub inline fn isGnuLibC(self: Target) bool { - return isGnuLibC_os_tag_abi(self.os.tag, self.abi); - } - - pub inline fn supportsNewStackCall(self: Target) bool { - return !self.cpu.arch.isWasm(); - } - - pub inline fn isSpirV(self: Target) bool { - return self.cpu.arch.isSpirV(); - } - - pub const FloatAbi = enum { - hard, - soft, - }; - - pub inline fn getFloatAbi(self: Target) FloatAbi { - return self.abi.floatAbi(); - } - - pub inline fn hasDynamicLinker(self: Target) bool { - if (self.cpu.arch.isWasm()) { - return false; - } - switch (self.os.tag) { - .freestanding, - .ios, - .tvos, - .watchos, - .macos, - .uefi, - .windows, - .emscripten, - .opencl, - .glsl450, - .vulkan, - .plan9, - .other, - => return false, - else => return true, - } - } - - pub const DynamicLinker = struct { - /// Contains the memory used to store the dynamic linker path. This field should - /// not be used directly. See `get` and `set`. This field exists so that this API requires no allocator. - buffer: [255]u8 = undefined, - - /// Used to construct the dynamic linker path. This field should not be used - /// directly. See `get` and `set`. - max_byte: ?u8 = null, - - /// Asserts that the length is less than or equal to 255 bytes. - pub fn init(dl_or_null: ?[]const u8) DynamicLinker { - var result: DynamicLinker = undefined; - result.set(dl_or_null); - return result; - } - - /// The returned memory has the same lifetime as the `DynamicLinker`. - pub fn get(self: *const DynamicLinker) ?[]const u8 { - const m: usize = self.max_byte orelse return null; - return self.buffer[0 .. m + 1]; - } - - /// Asserts that the length is less than or equal to 255 bytes. - pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void { - if (dl_or_null) |dl| { - @memcpy(self.buffer[0..dl.len], dl); - self.max_byte = @as(u8, @intCast(dl.len - 1)); - } else { - self.max_byte = null; - } - } - }; - - pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { - var result: DynamicLinker = .{}; - const S = struct { - fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker { - r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1)); - return r.*; - } - fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker { - @memcpy(r.buffer[0..s.len], s); - r.max_byte = @as(u8, @intCast(s.len - 1)); - return r.*; - } - }; - const print = S.print; - const copy = S.copy; - - if (self.abi == .android) { - const suffix = if (self.ptrBitWidth() == 64) "64" else ""; - return print(&result, "/system/bin/linker{s}", .{suffix}); - } - - if (self.abi.isMusl()) { - const is_arm = switch (self.cpu.arch) { - .arm, .armeb, .thumb, .thumbeb => true, - else => false, - }; - const arch_part = switch (self.cpu.arch) { - .arm, .thumb => "arm", - .armeb, .thumbeb => "armeb", - else => |arch| @tagName(arch), - }; - const arch_suffix = if (is_arm and self.abi.floatAbi() == .hard) "hf" else ""; - return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix }); - } - - switch (self.os.tag) { - .freebsd => return copy(&result, "/libexec/ld-elf.so.1"), - .netbsd => return copy(&result, "/libexec/ld.elf_so"), - .openbsd => return copy(&result, "/usr/libexec/ld.so"), - .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"), - .solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"), - .linux => switch (self.cpu.arch) { - .x86, - .sparc, - .sparcel, - => return copy(&result, "/lib/ld-linux.so.2"), - - .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"), - .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"), - .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"), - - .arm, - .armeb, - .thumb, - .thumbeb, - => return copy(&result, switch (self.abi.floatAbi()) { - .hard => "/lib/ld-linux-armhf.so.3", - else => "/lib/ld-linux.so.3", - }), - - .mips, - .mipsel, - .mips64, - .mips64el, - => { - const lib_suffix = switch (self.abi) { - .gnuabin32, .gnux32 => "32", - .gnuabi64 => "64", - else => "", - }; - const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008); - const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1"; - return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader }); - }, - - .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"), - .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"), - .s390x => return copy(&result, "/lib64/ld64.so.1"), - .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"), - .x86_64 => return copy(&result, switch (self.abi) { - .gnux32 => "/libx32/ld-linux-x32.so.2", - else => "/lib64/ld-linux-x86-64.so.2", - }), - - .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"), - .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"), - - // Architectures in this list have been verified as not having a standard - // dynamic linker path. - .wasm32, - .wasm64, - .bpfel, - .bpfeb, - .nvptx, - .nvptx64, - .spu_2, - .avr, - .spirv32, - .spirv64, - => return result, - - // TODO go over each item in this list and either move it to the above list, or - // implement the standard dynamic linker path code for it. - .arc, - .csky, - .hexagon, - .m68k, - .msp430, - .r600, - .amdgcn, - .tce, - .tcele, - .xcore, - .le32, - .le64, - .amdil, - .amdil64, - .hsail, - .hsail64, - .spir, - .spir64, - .kalimba, - .shave, - .lanai, - .renderscript32, - .renderscript64, - .ve, - .dxil, - .loongarch32, - .loongarch64, - .xtensa, - => return result, - }, - - .ios, - .tvos, - .watchos, - .macos, - => return copy(&result, "/usr/lib/dyld"), - - // Operating systems in this list have been verified as not having a standard - // dynamic linker path. - .freestanding, - .uefi, - .windows, - .emscripten, - .wasi, - .opencl, - .glsl450, - .vulkan, - .other, - .plan9, - => return result, - - // TODO revisit when multi-arch for Haiku is available - .haiku => return copy(&result, "/system/runtime_loader"), - - // TODO go over each item in this list and either move it to the above list, or - // implement the standard dynamic linker path code for it. - .ananas, - .cloudabi, - .fuchsia, - .kfreebsd, - .lv2, - .zos, - .minix, - .rtems, - .nacl, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .driverkit, - .shadermodel, - .liteos, - => return result, - } - } - - /// 0c spim little-endian MIPS 3000 family - /// 1c 68000 Motorola MC68000 - /// 2c 68020 Motorola MC68020 - /// 5c arm little-endian ARM - /// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T) - /// 7c arm64 ARM64 (ARMv8) - /// 8c 386 Intel x86, i486, Pentium, etc. - /// kc sparc Sun SPARC - /// qc power Power PC - /// vc mips big-endian MIPS 3000 family - pub fn plan9Ext(cpu_arch: Cpu.Arch) [:0]const u8 { - return switch (cpu_arch) { - .arm => ".5", - .x86_64 => ".6", - .aarch64 => ".7", - .x86 => ".8", - .sparc => ".k", - .powerpc, .powerpcle => ".q", - .mips, .mipsel => ".v", - // ISAs without designated characters get 'X' for lack of a better option. - else => ".X", - }; - } - - pub fn maxIntAlignment(target: Target) u16 { - return switch (target.cpu.arch) { - .avr => 1, - .msp430 => 2, - .xcore => 4, - - .arm, - .armeb, - .thumb, - .thumbeb, - .hexagon, - .mips, - .mipsel, - .powerpc, - .powerpcle, - .r600, - .amdgcn, - .riscv32, - .sparc, - .sparcel, - .s390x, - .lanai, - .wasm32, - .wasm64, - => 8, - - .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) { - .windows, .uefi => 8, - else => 4, - }, - - // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16 - // is a relevant number in three cases: - // 1. Different machine code instruction when loading into SIMD register. - // 2. The C ABI wants 16 for extern structs. - // 3. 16-byte cmpxchg needs 16-byte alignment. - // Same logic for powerpc64, mips64, sparc64. - .x86_64, - .powerpc64, - .powerpc64le, - .mips64, - .mips64el, - .sparc64, - => return switch (target.ofmt) { - .c => 16, - else => 8, - }, - - // Even LLVMABIAlignmentOfType(i128) agrees on these targets. - .aarch64, - .aarch64_be, - .aarch64_32, - .riscv64, - .bpfel, - .bpfeb, - .nvptx, - .nvptx64, - => 16, - - // Below this comment are unverified but based on the fact that C requires - // int128_t to be 16 bytes aligned, it's a safe default. - .spu_2, - .csky, - .arc, - .m68k, - .tce, - .tcele, - .le32, - .amdil, - .hsail, - .spir, - .kalimba, - .renderscript32, - .spirv32, - .shave, - .le64, - .amdil64, - .hsail64, - .spir64, - .renderscript64, - .ve, - .spirv64, - .dxil, - .loongarch32, - .loongarch64, - .xtensa, - => 16, - }; - } - - pub fn ptrBitWidth(target: Target) u16 { - switch (target.abi) { - .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32, - .gnuabi64 => return 64, - else => {}, - } - switch (target.cpu.arch) { - .avr, - .msp430, - .spu_2, - => return 16, - - .arc, - .arm, - .armeb, - .csky, - .hexagon, - .m68k, - .le32, - .mips, - .mipsel, - .powerpc, - .powerpcle, - .r600, - .riscv32, - .sparcel, - .tce, - .tcele, - .thumb, - .thumbeb, - .x86, - .xcore, - .nvptx, - .amdil, - .hsail, - .spir, - .kalimba, - .shave, - .lanai, - .wasm32, - .renderscript32, - .aarch64_32, - .spirv32, - .loongarch32, - .dxil, - .xtensa, - => return 32, - - .aarch64, - .aarch64_be, - .mips64, - .mips64el, - .powerpc64, - .powerpc64le, - .riscv64, - .x86_64, - .nvptx64, - .le64, - .amdil64, - .hsail64, - .spir64, - .wasm64, - .renderscript64, - .amdgcn, - .bpfel, - .bpfeb, - .sparc64, - .s390x, - .ve, - .spirv64, - .loongarch64, - => return 64, - - .sparc => return if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) 64 else 32, - } - } - - pub fn stackAlignment(target: Target) u16 { - return switch (target.cpu.arch) { - .m68k => 2, - .amdgcn => 4, - .x86 => switch (target.os.tag) { - .windows, .uefi => 4, - else => 16, - }, - .arm, - .armeb, - .thumb, - .thumbeb, - .mips, - .mipsel, - .sparc, - .sparcel, - => 8, - .aarch64, - .aarch64_be, - .aarch64_32, - .bpfeb, - .bpfel, - .mips64, - .mips64el, - .riscv32, - .riscv64, - .sparc64, - .x86_64, - .ve, - .wasm32, - .wasm64, - => 16, - .powerpc64, - .powerpc64le, - => switch (target.os.tag) { - else => 8, - .linux => 16, - }, - else => @divExact(target.ptrBitWidth(), 8), - }; - } - - /// Default signedness of `char` for the native C compiler for this target - /// Note that char signedness is implementation-defined and many compilers provide - /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char - pub fn charSignedness(target: Target) std.builtin.Signedness { - switch (target.cpu.arch) { - .aarch64, - .aarch64_32, - .aarch64_be, - .arm, - .armeb, - .thumb, - .thumbeb, - => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned, - .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned, - .powerpcle, - .powerpc64le, - .s390x, - .xcore, - .arc, - .msp430, - .riscv32, - .riscv64, - => return .unsigned, - else => return .signed, - } - } - - pub const CType = enum { - char, - short, - ushort, - int, - uint, - long, - ulong, - longlong, - ulonglong, - float, - double, - longdouble, - }; - - pub fn c_type_byte_size(t: Target, c_type: CType) u16 { - return switch (c_type) { - .char, - .short, - .ushort, - .int, - .uint, - .long, - .ulong, - .longlong, - .ulonglong, - .float, - .double, - => @divExact(c_type_bit_size(t, c_type), 8), - - .longdouble => switch (c_type_bit_size(t, c_type)) { - 16 => 2, - 32 => 4, - 64 => 8, - 80 => @as(u16, @intCast(mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))), - 128 => 16, - else => unreachable, - }, - }; - } - - pub fn c_type_bit_size(target: Target, c_type: CType) u16 { - switch (target.os.tag) { - .freestanding, .other => switch (target.cpu.arch) { - .msp430 => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .float, .long, .ulong => return 32, - .longlong, .ulonglong, .double, .longdouble => return 64, - }, - .avr => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .long, .ulong, .float, .double, .longdouble => return 32, - .longlong, .ulonglong => return 64, - }, - .tce, .tcele => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .long, .ulong, .longlong, .ulonglong => return 32, - .float, .double, .longdouble => return 32, - }, - .mips64, .mips64el => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return if (target.abi != .gnuabin32) 64 else 32, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 128, - }, - .x86_64 => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => switch (target.abi) { - .gnux32, .muslx32 => return 32, - else => return 64, - }, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 80, - }, - else => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return target.ptrBitWidth(), - .longlong, .ulonglong, .double => return 64, - .longdouble => switch (target.cpu.arch) { - .x86 => switch (target.abi) { - .android => return 64, - else => return 80, - }, - - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - => switch (target.abi) { - .musl, - .musleabi, - .musleabihf, - .muslx32, - => return 64, - else => return 128, - }, - - .riscv32, - .riscv64, - .aarch64, - .aarch64_be, - .aarch64_32, - .s390x, - .sparc, - .sparc64, - .sparcel, - .wasm32, - .wasm64, - => return 128, - - else => return 64, - }, - }, - }, - - .linux, - .freebsd, - .netbsd, - .dragonfly, - .openbsd, - .wasi, - .emscripten, - .plan9, - .solaris, - .illumos, - .haiku, - .ananas, - .fuchsia, - .minix, - => switch (target.cpu.arch) { - .msp430 => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .long, .ulong, .float => return 32, - .longlong, .ulonglong, .double, .longdouble => return 64, - }, - .avr => switch (c_type) { - .char => return 8, - .short, .ushort, .int, .uint => return 16, - .long, .ulong, .float, .double, .longdouble => return 32, - .longlong, .ulonglong => return 64, - }, - .tce, .tcele => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .long, .ulong, .longlong, .ulonglong => return 32, - .float, .double, .longdouble => return 32, - }, - .mips64, .mips64el => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return if (target.abi != .gnuabin32) 64 else 32, - .longlong, .ulonglong, .double => return 64, - .longdouble => if (target.os.tag == .freebsd) return 64 else return 128, - }, - .x86_64 => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => switch (target.abi) { - .gnux32, .muslx32 => return 32, - else => return 64, - }, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 80, - }, - else => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return target.ptrBitWidth(), - .longlong, .ulonglong, .double => return 64, - .longdouble => switch (target.cpu.arch) { - .x86 => switch (target.abi) { - .android => return 64, - else => return 80, - }, - - .powerpc, - .powerpcle, - => switch (target.abi) { - .musl, - .musleabi, - .musleabihf, - .muslx32, - => return 64, - else => switch (target.os.tag) { - .freebsd, .netbsd, .openbsd => return 64, - else => return 128, - }, - }, - - .powerpc64, - .powerpc64le, - => switch (target.abi) { - .musl, - .musleabi, - .musleabihf, - .muslx32, - => return 64, - else => switch (target.os.tag) { - .freebsd, .openbsd => return 64, - else => return 128, - }, - }, - - .riscv32, - .riscv64, - .aarch64, - .aarch64_be, - .aarch64_32, - .s390x, - .mips64, - .mips64el, - .sparc, - .sparc64, - .sparcel, - .wasm32, - .wasm64, - => return 128, - - else => return 64, - }, - }, - }, - - .windows, .uefi => switch (target.cpu.arch) { - .x86 => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return 32, - .longlong, .ulonglong, .double => return 64, - .longdouble => switch (target.abi) { - .gnu, .gnuilp32, .cygnus => return 80, - else => return 64, - }, - }, - .x86_64 => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => switch (target.abi) { - .cygnus => return 64, - else => return 32, - }, - .longlong, .ulonglong, .double => return 64, - .longdouble => switch (target.abi) { - .gnu, .gnuilp32, .cygnus => return 80, - else => return 64, - }, - }, - else => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return 32, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 64, - }, - }, - - .macos, .ios, .tvos, .watchos => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => switch (target.cpu.arch) { - .x86, .arm, .aarch64_32 => return 32, - .x86_64 => switch (target.abi) { - .gnux32, .muslx32 => return 32, - else => return 64, - }, - else => return 64, - }, - .longlong, .ulonglong, .double => return 64, - .longdouble => switch (target.cpu.arch) { - .x86 => switch (target.abi) { - .android => return 64, - else => return 80, - }, - .x86_64 => return 80, - else => return 64, - }, - }, - - .nvcl, .cuda => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => switch (target.cpu.arch) { - .nvptx => return 32, - .nvptx64 => return 64, - else => return 64, - }, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 64, - }, - - .amdhsa, .amdpal => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong, .longlong, .ulonglong, .double => return 64, - .longdouble => return 128, - }, - - .opencl => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong, .double => return 64, - .longlong, .ulonglong => return 128, - // Note: The OpenCL specification does not guarantee a particular size for long double, - // but clang uses 128 bits. - .longdouble => return 128, - }, - - .ps4, .ps5 => switch (c_type) { - .char => return 8, - .short, .ushort => return 16, - .int, .uint, .float => return 32, - .long, .ulong => return 64, - .longlong, .ulonglong, .double => return 64, - .longdouble => return 80, - }, - - .cloudabi, - .kfreebsd, - .lv2, - .zos, - .rtems, - .nacl, - .aix, - .elfiamcu, - .mesa3d, - .contiki, - .hermit, - .hurd, - .glsl450, - .vulkan, - .driverkit, - .shadermodel, - .liteos, - => @panic("TODO specify the C integer and float type sizes for this OS"), - } - } - - pub fn c_type_alignment(target: Target, c_type: CType) u16 { - // Overrides for unusual alignments - switch (target.cpu.arch) { - .avr => return 1, - .x86 => switch (target.os.tag) { - .windows, .uefi => switch (c_type) { - .longlong, .ulonglong, .double => return 8, - .longdouble => switch (target.abi) { - .gnu, .gnuilp32, .cygnus => return 4, - else => return 8, - }, - else => {}, - }, - else => {}, - }, - else => {}, - } - - // Next-power-of-two-aligned, up to a maximum. - return @min( - std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8), - switch (target.cpu.arch) { - .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) { - .netbsd => switch (target.abi) { - .gnueabi, - .gnueabihf, - .eabi, - .eabihf, - .android, - .musleabi, - .musleabihf, - => 8, - - else => @as(u16, 4), - }, - .ios, .tvos, .watchos => 4, - else => 8, - }, - - .msp430, - .avr, - => 2, - - .arc, - .csky, - .x86, - .xcore, - .dxil, - .loongarch32, - .tce, - .tcele, - .le32, - .amdil, - .hsail, - .spir, - .spirv32, - .kalimba, - .shave, - .renderscript32, - .ve, - .spu_2, - .xtensa, - => 4, - - .aarch64_32, - .amdgcn, - .amdil64, - .bpfel, - .bpfeb, - .hexagon, - .hsail64, - .loongarch64, - .m68k, - .mips, - .mipsel, - .sparc, - .sparcel, - .sparc64, - .lanai, - .le64, - .nvptx, - .nvptx64, - .r600, - .s390x, - .spir64, - .spirv64, - .renderscript64, - => 8, - - .aarch64, - .aarch64_be, - .mips64, - .mips64el, - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - .riscv32, - .riscv64, - .x86_64, - .wasm32, - .wasm64, - => 16, - }, - ); - } - - pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 { - // Overrides for unusual alignments - switch (target.cpu.arch) { - .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) { - .netbsd => switch (target.abi) { - .gnueabi, - .gnueabihf, - .eabi, - .eabihf, - .android, - .musleabi, - .musleabihf, - => {}, - - else => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - }, - .ios, .tvos, .watchos => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - else => {}, - }, - .arc => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - .avr => switch (c_type) { - .char, .int, .uint, .long, .ulong, .float, .longdouble => return 1, - .short, .ushort => return 2, - .double => return 4, - .longlong, .ulonglong => return 8, - }, - .x86 => switch (target.os.tag) { - .windows, .uefi => switch (c_type) { - .longdouble => switch (target.abi) { - .gnu, .gnuilp32, .cygnus => return 4, - else => return 8, - }, - else => {}, - }, - else => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - }, - else => {}, - } - - // Next-power-of-two-aligned, up to a maximum. - return @min( - std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8), - switch (target.cpu.arch) { - .msp430 => @as(u16, 2), - - .csky, - .xcore, - .dxil, - .loongarch32, - .tce, - .tcele, - .le32, - .amdil, - .hsail, - .spir, - .spirv32, - .kalimba, - .shave, - .renderscript32, - .ve, - .spu_2, - .xtensa, - => 4, - - .arc, - .arm, - .armeb, - .avr, - .thumb, - .thumbeb, - .aarch64_32, - .amdgcn, - .amdil64, - .bpfel, - .bpfeb, - .hexagon, - .hsail64, - .x86, - .loongarch64, - .m68k, - .mips, - .mipsel, - .sparc, - .sparcel, - .sparc64, - .lanai, - .le64, - .nvptx, - .nvptx64, - .r600, - .s390x, - .spir64, - .spirv64, - .renderscript64, - => 8, - - .aarch64, - .aarch64_be, - .mips64, - .mips64el, - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - .riscv32, - .riscv64, - .x86_64, - .wasm32, - .wasm64, - => 16, - }, - ); - } - - pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool { - const ignore_case = target.os.tag == .macos or target.os.tag == .windows; - - if (eqlIgnoreCase(ignore_case, name, "c")) - return true; - - if (target.isMinGW()) { - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "uuid")) - return true; - if (eqlIgnoreCase(ignore_case, name, "mingw32")) - return true; - if (eqlIgnoreCase(ignore_case, name, "msvcrt-os")) - return true; - if (eqlIgnoreCase(ignore_case, name, "mingwex")) - return true; - - return false; - } - - if (target.abi.isGnu() or target.abi.isMusl()) { - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "rt")) - return true; - if (eqlIgnoreCase(ignore_case, name, "pthread")) - return true; - if (eqlIgnoreCase(ignore_case, name, "util")) - return true; - if (eqlIgnoreCase(ignore_case, name, "xnet")) - return true; - if (eqlIgnoreCase(ignore_case, name, "resolv")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dl")) - return true; - } - - if (target.abi.isMusl()) { - if (eqlIgnoreCase(ignore_case, name, "crypt")) - return true; - } - - if (target.os.tag.isDarwin()) { - if (eqlIgnoreCase(ignore_case, name, "System")) - return true; - if (eqlIgnoreCase(ignore_case, name, "c")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dbm")) - return true; - if (eqlIgnoreCase(ignore_case, name, "dl")) - return true; - if (eqlIgnoreCase(ignore_case, name, "info")) - return true; - if (eqlIgnoreCase(ignore_case, name, "m")) - return true; - if (eqlIgnoreCase(ignore_case, name, "poll")) - return true; - if (eqlIgnoreCase(ignore_case, name, "proc")) - return true; - if (eqlIgnoreCase(ignore_case, name, "pthread")) - return true; - if (eqlIgnoreCase(ignore_case, name, "rpcsvc")) - return true; - } - - if (target.os.isAtLeast(.macos, .{ .major = 10, .minor = 8, .patch = 0 }) orelse false) { - if (eqlIgnoreCase(ignore_case, name, "mx")) - return true; - } - - return false; - } - - pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { - const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows; - - return eqlIgnoreCase(ignore_case, name, "c++") or - eqlIgnoreCase(ignore_case, name, "stdc++") or - eqlIgnoreCase(ignore_case, name, "c++abi"); - } -}; - -fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool { - if (ignore_case) { - return std.ascii.eqlIgnoreCase(a, b); - } else { - return std.mem.eql(u8, a, b); - } -} - -test { - std.testing.refAllDecls(Target.Cpu.Arch); -} From 3179f58c414b5e4845b9bf3acdf276fe8e2b88a0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 12:35:04 -0700 Subject: [PATCH 014/133] rename std.zig.CrossTarget to std.Target.Query --- CMakeLists.txt | 2 +- lib/std/Build.zig | 38 ++--- lib/std/Build/Step/Compile.zig | 1 - lib/std/Target.zig | 4 +- .../{zig/CrossTarget.zig => Target/Query.zig} | 145 +++++++++--------- lib/std/zig.zig | 3 +- lib/std/zig/system/NativeTargetInfo.zig | 106 ++++++------- lib/std/zig/system/darwin/macos.zig | 2 +- lib/std/zig/system/linux.zig | 3 - lib/std/zig/system/x86.zig | 5 +- src/libc_installation.zig | 2 +- src/main.zig | 74 ++++----- test/cbe.zig | 2 +- test/link/elf.zig | 1 - test/link/glibc_compat/build.zig | 2 +- test/link/link.zig | 1 - test/link/macho.zig | 2 - test/llvm_targets.zig | 2 +- test/src/Cases.zig | 12 +- test/src/translate_c.zig | 5 +- test/standalone.zig | 2 +- test/standalone/windows_resources/build.zig | 6 +- test/tests.zig | 12 +- test/translate_c.zig | 5 +- 24 files changed, 215 insertions(+), 222 deletions(-) rename lib/std/{zig/CrossTarget.zig => Target/Query.zig} (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 831243557f43..fa3a10dc4ce5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -481,6 +481,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/start.zig" "${CMAKE_SOURCE_DIR}/lib/std/std.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/Query.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/aarch64.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/amdgpu.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/arm.zig" @@ -508,7 +509,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/zig.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/AstRlAnnotate.zig" - "${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/render.zig" diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 24e245b02828..db7e3493da50 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -10,11 +10,11 @@ const log = std.log; const ArrayList = std.ArrayList; const StringHashMap = std.StringHashMap; const Allocator = mem.Allocator; +const Target = std.Target; const process = std.process; const EnvMap = std.process.EnvMap; const fmt_lib = std.fmt; const File = std.fs.File; -const TargetQuery = std.zig.CrossTarget; const Sha256 = std.crypto.hash.sha2.Sha256; const Build = @This(); @@ -375,7 +375,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption const v = @field(args, field.name); const T = @TypeOf(v); switch (T) { - TargetQuery => { + Target.Query => { user_input_options.put(field.name, .{ .name = field.name, .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, @@ -1195,9 +1195,9 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio } pub const StandardTargetOptionsArgs = struct { - whitelist: ?[]const TargetQuery = null, + whitelist: ?[]const Target.Query = null, - default_target: TargetQuery = .{}, + default_target: Target.Query = .{}, }; /// Exposes standard `zig build` options for choosing a target and additionally @@ -1208,7 +1208,7 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve } /// Exposes standard `zig build` options for choosing a target. -pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) TargetQuery { +pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) Target.Query { const maybe_triple = self.option( []const u8, "target", @@ -1222,8 +1222,8 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA const triple = maybe_triple orelse "native"; - var diags: TargetQuery.ParseOptions.Diagnostics = .{}; - const selected_target = TargetQuery.parse(.{ + var diags: Target.Query.ParseOptions.Diagnostics = .{}; + const selected_target = Target.Query.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, @@ -1260,7 +1260,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA \\Available operating systems: \\ , .{diags.os_name.?}); - inline for (std.meta.fields(std.Target.Os.Tag)) |field| { + inline for (std.meta.fields(Target.Os.Tag)) |field| { log.err(" {s}", .{field.name}); } self.markInvalidUserInput(); @@ -1279,7 +1279,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA // Make sure it's a match of one of the list. var mismatch_triple = true; var mismatch_cpu_features = true; - var whitelist_item: TargetQuery = .{}; + var whitelist_item: Target.Query = .{}; for (list) |t| { mismatch_cpu_features = true; mismatch_triple = true; @@ -1316,7 +1316,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA var populated_cpu_features = whitelist_cpu.model.features; populated_cpu_features.populateDependencies(all_features); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); if (in_cpu_set) { log.err("{s} ", .{feature.name}); @@ -1324,7 +1324,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA } log.err(" Remove: ", .{}); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = selected_cpu.features.isEnabled(i); if (in_actual_set and !in_cpu_set) { @@ -1587,7 +1587,7 @@ pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 { pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { // TODO report error for ambiguous situations - const exe_extension = @as(TargetQuery, .{}).exeFileExt(); + const exe_extension = @as(Target.Query, .{}).exeFileExt(); for (self.search_prefixes.items) |search_prefix| { for (names) |name| { if (fs.path.isAbsolute(name)) { @@ -2064,7 +2064,7 @@ pub const InstalledFile = struct { } }; -pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { +pub fn serializeCpu(allocator: Allocator, cpu: Target.Cpu) ![]const u8 { // TODO this logic can disappear if cpu model + features becomes part of the target triple const all_features = cpu.arch.allFeaturesList(); var populated_cpu_features = cpu.model.features; @@ -2078,7 +2078,7 @@ pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { try mcpu_buffer.appendSlice(cpu.model.name); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = cpu.features.isEnabled(i); if (in_cpu_set and !in_actual_set) { @@ -2127,9 +2127,9 @@ pub fn hex64(x: u64) [16]u8 { /// target. The query is kept because the Zig toolchain needs to know which parts /// of the target are "native". This can apply to the CPU, the OS, or even the ABI. pub const ResolvedTarget = struct { - query: TargetQuery, - target: std.Target, - dynamic_linker: std.Target.DynamicLinker, + query: Target.Query, + target: Target, + dynamic_linker: Target.DynamicLinker, pub fn toNativeTargetInfo(self: ResolvedTarget) std.zig.system.NativeTargetInfo { return .{ @@ -2141,7 +2141,7 @@ pub const ResolvedTarget = struct { /// Converts a target query into a fully resolved target that can be passed to /// various parts of the API. -pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget { +pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { // This context will likely be required in the future when the target is // resolved via a WASI API or via the build protocol. _ = b; @@ -2156,7 +2156,7 @@ pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget { }; } -pub fn wantSharedLibSymLinks(target: std.Target) bool { +pub fn wantSharedLibSymLinks(target: Target) bool { return target.os.tag != .windows; } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 93027003f352..cd5986617670 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -9,7 +9,6 @@ const StringHashMap = std.StringHashMap; const Sha256 = std.crypto.hash.sha2.Sha256; const Allocator = mem.Allocator; const Step = std.Build.Step; -const CrossTarget = std.zig.CrossTarget; const NativeTargetInfo = std.zig.system.NativeTargetInfo; const LazyPath = std.Build.LazyPath; const PkgConfigPkg = std.Build.PkgConfigPkg; diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 9e7414365c9b..f5a207426444 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3,6 +3,8 @@ os: Os, abi: Abi, ofmt: ObjectFormat, +pub const Query = @import("Target/Query.zig"); + pub const Os = struct { tag: Tag, version_range: VersionRange, @@ -1387,7 +1389,7 @@ pub const Cpu = struct { }; pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 { - return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); + return Query.fromTarget(self).zigTriple(allocator); } pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 { diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/Target/Query.zig similarity index 88% rename from lib/std/zig/CrossTarget.zig rename to lib/std/Target/Query.zig index dc6de46af522..617d141d3980 100644 --- a/lib/std/zig/CrossTarget.zig +++ b/lib/std/Target/Query.zig @@ -1,13 +1,7 @@ -//! Contains all the same data as `Target`, additionally introducing the concept of "the native target". -//! The purpose of this abstraction is to provide meaningful and unsurprising defaults. -//! This struct does reference any resources and it is copyable. - -const CrossTarget = @This(); -const std = @import("../std.zig"); -const builtin = @import("builtin"); -const assert = std.debug.assert; -const Target = std.Target; -const mem = std.mem; +//! Contains all the same data as `Target`, additionally introducing the +//! concept of "the native target". The purpose of this abstraction is to +//! provide meaningful and unsurprising defaults. This struct does reference +//! any resources and it is copyable. /// `null` means native. cpu_arch: ?Target.Cpu.Arch = null, @@ -69,8 +63,8 @@ pub const SemanticVersion = std.SemanticVersion; pub const DynamicLinker = Target.DynamicLinker; -pub fn fromTarget(target: Target) CrossTarget { - var result: CrossTarget = .{ +pub fn fromTarget(target: Target) Query { + var result: Query = .{ .cpu_arch = target.cpu.arch, .cpu_model = .{ .explicit = target.cpu.model }, .os_tag = target.os.tag, @@ -102,7 +96,7 @@ pub fn fromTarget(target: Target) CrossTarget { return result; } -fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void { +fn updateOsVersionRange(self: *Query, os: Target.Os) void { switch (os.tag) { .freestanding, .ananas, @@ -171,7 +165,7 @@ fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void { } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn toTarget(self: CrossTarget) Target { +pub fn toTarget(self: Query) Target { return .{ .cpu = self.getCpu(), .os = self.getOs(), @@ -233,11 +227,11 @@ pub const ParseOptions = struct { }; }; -pub fn parse(args: ParseOptions) !CrossTarget { +pub fn parse(args: ParseOptions) !Query { var dummy_diags: ParseOptions.Diagnostics = undefined; const diags = args.diagnostics orelse &dummy_diags; - var result: CrossTarget = .{ + var result: Query = .{ .dynamic_linker = DynamicLinker.init(args.dynamic_linker), }; @@ -341,7 +335,7 @@ pub fn parse(args: ParseOptions) !CrossTarget { /// Similar to `parse` except instead of fully parsing, it only determines the CPU /// architecture and returns it if it can be determined, and returns `null` otherwise. -/// This is intended to be used if the API user of CrossTarget needs to learn the +/// This is intended to be used if the API user of Query needs to learn the /// target CPU architecture in order to fully populate `ParseOptions`. pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch { var it = mem.splitScalar(u8, args.arch_os_abi, '-'); @@ -386,7 +380,7 @@ test parseVersion { } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getCpu(self: CrossTarget) Target.Cpu { +pub fn getCpu(self: Query) Target.Cpu { switch (self.cpu_model) { .native => { // This works when doing `zig build` because Zig generates a build executable using @@ -417,23 +411,23 @@ pub fn getCpu(self: CrossTarget) Target.Cpu { } } -pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch { +pub fn getCpuArch(self: Query) Target.Cpu.Arch { return self.cpu_arch orelse builtin.cpu.arch; } -pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model { +pub fn getCpuModel(self: Query) *const Target.Cpu.Model { return switch (self.cpu_model) { .explicit => |cpu_model| cpu_model, else => self.getCpu().model, }; } -pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set { +pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set { return self.getCpu().features; } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getOs(self: CrossTarget) Target.Os { +pub fn getOs(self: Query) Target.Os { // `builtin.os` works when doing `zig build` because Zig generates a build executable using // native OS version range. However this will not be accurate otherwise, and // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. @@ -465,28 +459,28 @@ pub fn getOs(self: CrossTarget) Target.Os { return adjusted_os; } -pub fn getOsTag(self: CrossTarget) Target.Os.Tag { +pub fn getOsTag(self: Query) Target.Os.Tag { return self.os_tag orelse builtin.os.tag; } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getOsVersionMin(self: CrossTarget) OsVersion { +pub fn getOsVersionMin(self: Query) OsVersion { if (self.os_version_min) |version_min| return version_min; - var tmp: CrossTarget = undefined; + var tmp: Query = undefined; tmp.updateOsVersionRange(self.getOs()); return tmp.os_version_min.?; } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getOsVersionMax(self: CrossTarget) OsVersion { +pub fn getOsVersionMax(self: Query) OsVersion { if (self.os_version_max) |version_max| return version_max; - var tmp: CrossTarget = undefined; + var tmp: Query = undefined; tmp.updateOsVersionRange(self.getOs()); return tmp.os_version_max.?; } /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getAbi(self: CrossTarget) Target.Abi { +pub fn getAbi(self: Query) Target.Abi { if (self.abi) |abi| return abi; if (self.os_tag == null) { @@ -499,70 +493,70 @@ pub fn getAbi(self: CrossTarget) Target.Abi { return Target.Abi.default(self.getCpuArch(), self.getOs()); } -pub fn isFreeBSD(self: CrossTarget) bool { +pub fn isFreeBSD(self: Query) bool { return self.getOsTag() == .freebsd; } -pub fn isDarwin(self: CrossTarget) bool { +pub fn isDarwin(self: Query) bool { return self.getOsTag().isDarwin(); } -pub fn isNetBSD(self: CrossTarget) bool { +pub fn isNetBSD(self: Query) bool { return self.getOsTag() == .netbsd; } -pub fn isOpenBSD(self: CrossTarget) bool { +pub fn isOpenBSD(self: Query) bool { return self.getOsTag() == .openbsd; } -pub fn isUefi(self: CrossTarget) bool { +pub fn isUefi(self: Query) bool { return self.getOsTag() == .uefi; } -pub fn isDragonFlyBSD(self: CrossTarget) bool { +pub fn isDragonFlyBSD(self: Query) bool { return self.getOsTag() == .dragonfly; } -pub fn isLinux(self: CrossTarget) bool { +pub fn isLinux(self: Query) bool { return self.getOsTag() == .linux; } -pub fn isWindows(self: CrossTarget) bool { +pub fn isWindows(self: Query) bool { return self.getOsTag() == .windows; } -pub fn exeFileExt(self: CrossTarget) [:0]const u8 { +pub fn exeFileExt(self: Query) [:0]const u8 { return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); } -pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 { +pub fn staticLibSuffix(self: Query) [:0]const u8 { return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi()); } -pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 { +pub fn dynamicLibSuffix(self: Query) [:0]const u8 { return self.getOsTag().dynamicLibSuffix(); } -pub fn libPrefix(self: CrossTarget) [:0]const u8 { +pub fn libPrefix(self: Query) [:0]const u8 { return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi()); } -pub fn isNativeCpu(self: CrossTarget) bool { +pub fn isNativeCpu(self: Query) bool { return self.cpu_arch == null and (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty(); } -pub fn isNativeOs(self: CrossTarget) bool { +pub fn isNativeOs(self: Query) bool { return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and self.dynamic_linker.get() == null and self.glibc_version == null; } -pub fn isNativeAbi(self: CrossTarget) bool { +pub fn isNativeAbi(self: Query) bool { return self.os_tag == null and self.abi == null; } -pub fn isNative(self: CrossTarget) bool { +pub fn isNative(self: Query) bool { return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); } @@ -576,7 +570,7 @@ fn formatVersion(version: SemanticVersion, writer: anytype) !void { } } -pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}![]u8 { +pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 { if (self.isNative()) { return allocator.dupe(u8, "native"); } @@ -622,37 +616,37 @@ pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory} return result.toOwnedSlice(); } -pub fn allocDescription(self: CrossTarget, allocator: mem.Allocator) ![]u8 { +pub fn allocDescription(self: Query, allocator: mem.Allocator) ![]u8 { // TODO is there anything else worthy of the description that is not // already captured in the triple? return self.zigTriple(allocator); } -pub fn linuxTriple(self: CrossTarget, allocator: mem.Allocator) ![]u8 { +pub fn linuxTriple(self: Query, allocator: mem.Allocator) ![]u8 { return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); } -pub fn isGnuLibC(self: CrossTarget) bool { +pub fn isGnuLibC(self: Query) bool { return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); } -pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32) void { +pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { assert(self.isGnuLibC()); self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; } -pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat { +pub fn getObjectFormat(self: Query) Target.ObjectFormat { return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); } -pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void { +pub fn updateCpuFeatures(self: Query, set: *Target.Cpu.Feature.Set) void { set.removeFeatureSet(self.cpu_features_sub); set.addFeatureSet(self.cpu_features_add); set.populateDependencies(self.getCpuArch().allFeaturesList()); set.removeFeatureSet(self.cpu_features_sub); } -fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void { +fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !void { var it = mem.splitScalar(u8, text, '.'); const os_name = it.first(); diags.os_name = os_name; @@ -749,12 +743,19 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const } } -test "CrossTarget.parse" { +const Query = @This(); +const std = @import("../std.zig"); +const builtin = @import("builtin"); +const assert = std.debug.assert; +const Target = std.Target; +const mem = std.mem; + +test parse { if (builtin.target.isGnuLibC()) { - var cross_target = try CrossTarget.parse(.{}); - cross_target.setGnuLibCVersion(2, 1, 1); + var query = try Query.parse(.{}); + query.setGnuLibCVersion(2, 1, 1); - const text = try cross_target.zigTriple(std.testing.allocator); + const text = try query.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); var buf: [256]u8 = undefined; @@ -767,30 +768,30 @@ test "CrossTarget.parse" { try std.testing.expectEqualSlices(u8, triple, text); } { - const cross_target = try CrossTarget.parse(.{ + const query = try Query.parse(.{ .arch_os_abi = "aarch64-linux", .cpu_features = "native", }); - try std.testing.expect(cross_target.cpu_arch.? == .aarch64); - try std.testing.expect(cross_target.cpu_model == .native); + try std.testing.expect(query.cpu_arch.? == .aarch64); + try std.testing.expect(query.cpu_model == .native); } { - const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "native" }); + const query = try Query.parse(.{ .arch_os_abi = "native" }); - try std.testing.expect(cross_target.cpu_arch == null); - try std.testing.expect(cross_target.isNative()); + try std.testing.expect(query.cpu_arch == null); + try std.testing.expect(query.isNative()); - const text = try cross_target.zigTriple(std.testing.allocator); + const text = try query.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "native", text); } { - const cross_target = try CrossTarget.parse(.{ + const query = try Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu", .cpu_features = "x86_64-sse-sse2-avx-cx8", }); - const target = cross_target.toTarget(); + const target = query.toTarget(); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .gnu); @@ -806,16 +807,16 @@ test "CrossTarget.parse" { try std.testing.expect(Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87 })); try std.testing.expect(!Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87, .sse })); - const text = try cross_target.zigTriple(std.testing.allocator); + const text = try query.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); } { - const cross_target = try CrossTarget.parse(.{ + const query = try Query.parse(.{ .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }); - const target = cross_target.toTarget(); + const target = query.toTarget(); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .musleabihf); @@ -823,16 +824,16 @@ test "CrossTarget.parse" { try std.testing.expect(target.cpu.model == &Target.arm.cpu.generic); try std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a)); - const text = try cross_target.zigTriple(std.testing.allocator); + const text = try query.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); } { - const cross_target = try CrossTarget.parse(.{ + const query = try Query.parse(.{ .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", .cpu_features = "generic+v8a", }); - const target = cross_target.toTarget(); + const target = query.toTarget(); try std.testing.expect(target.cpu.arch == .aarch64); try std.testing.expect(target.os.tag == .linux); @@ -847,7 +848,7 @@ test "CrossTarget.parse" { try std.testing.expect(target.os.version_range.linux.glibc.patch == 0); try std.testing.expect(target.abi == .gnu); - const text = try cross_target.zigTriple(std.testing.allocator); + const text = try query.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text); } diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 9af804fa0a61..481768bfb237 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -16,7 +16,8 @@ pub const number_literal = @import("zig/number_literal.zig"); pub const primitives = @import("zig/primitives.zig"); pub const Ast = @import("zig/Ast.zig"); pub const system = @import("zig/system.zig"); -pub const CrossTarget = @import("zig/CrossTarget.zig"); +/// Deprecated: use `std.Target.Query`. +pub const CrossTarget = std.Target.Query; pub const BuiltinFn = @import("zig/BuiltinFn.zig"); pub const AstRlAnnotate = @import("zig/AstRlAnnotate.zig"); diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig index d44e396fb53a..c4562cf7d552 100644 --- a/lib/std/zig/system/NativeTargetInfo.zig +++ b/lib/std/zig/system/NativeTargetInfo.zig @@ -9,7 +9,6 @@ const native_endian = builtin.cpu.arch.endian(); const NativeTargetInfo = @This(); const Target = std.Target; const Allocator = std.mem.Allocator; -const CrossTarget = std.zig.CrossTarget; const windows = std.zig.system.windows; const darwin = std.zig.system.darwin; const linux = std.zig.system.linux; @@ -30,13 +29,14 @@ pub const DetectError = error{ Unexpected, }; -/// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected -/// natively, which should be standard or default, and which are provided explicitly, this function -/// resolves the native components by detecting the native system, and then resolves standard/default parts -/// relative to that. -pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { - var os = cross_target.getOsTag().defaultVersionRange(cross_target.getCpuArch()); - if (cross_target.os_tag == null) { +/// Given a `Target.Query`, which specifies in detail which parts of the +/// target should be detected natively, which should be standard or default, +/// and which are provided explicitly, this function resolves the native +/// components by detecting the native system, and then resolves +/// standard/default parts relative to that. +pub fn detect(query: Target.Query) DetectError!NativeTargetInfo { + var os = query.getOsTag().defaultVersionRange(query.getCpuArch()); + if (query.os_tag == null) { switch (builtin.target.os.tag) { .linux => { const uts = std.os.uname(); @@ -162,45 +162,45 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { } } - if (cross_target.os_version_min) |min| switch (min) { + if (query.os_version_min) |min| switch (min) { .none => {}, - .semver => |semver| switch (cross_target.getOsTag()) { + .semver => |semver| switch (query.getOsTag()) { .linux => os.version_range.linux.range.min = semver, else => os.version_range.semver.min = semver, }, .windows => |win_ver| os.version_range.windows.min = win_ver, }; - if (cross_target.os_version_max) |max| switch (max) { + if (query.os_version_max) |max| switch (max) { .none => {}, - .semver => |semver| switch (cross_target.getOsTag()) { + .semver => |semver| switch (query.getOsTag()) { .linux => os.version_range.linux.range.max = semver, else => os.version_range.semver.max = semver, }, .windows => |win_ver| os.version_range.windows.max = win_ver, }; - if (cross_target.glibc_version) |glibc| { - assert(cross_target.isGnuLibC()); + if (query.glibc_version) |glibc| { + assert(query.isGnuLibC()); os.version_range.linux.glibc = glibc; } // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the // native CPU architecture as being different than the current target), we use this: - const cpu_arch = cross_target.getCpuArch(); + const cpu_arch = query.getCpuArch(); - const cpu = switch (cross_target.cpu_model) { - .native => detectNativeCpuAndFeatures(cpu_arch, os, cross_target), + const cpu = switch (query.cpu_model) { + .native => detectNativeCpuAndFeatures(cpu_arch, os, query), .baseline => Target.Cpu.baseline(cpu_arch), - .determined_by_cpu_arch => if (cross_target.cpu_arch == null) - detectNativeCpuAndFeatures(cpu_arch, os, cross_target) + .determined_by_cpu_arch => if (query.cpu_arch == null) + detectNativeCpuAndFeatures(cpu_arch, os, query) else Target.Cpu.baseline(cpu_arch), .explicit => |model| model.toCpu(cpu_arch), } orelse backup_cpu_detection: { break :backup_cpu_detection Target.Cpu.baseline(cpu_arch); }; - var result = try detectAbiAndDynamicLinker(cpu, os, cross_target); + var result = try detectAbiAndDynamicLinker(cpu, os, query); // For x86, we need to populate some CPU feature flags depending on architecture // and mode: // * 16bit_mode => if the abi is code16 @@ -209,15 +209,15 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { // sets one of them, that takes precedence. switch (cpu_arch) { .x86 => { - if (!std.Target.x86.featureSetHasAny(cross_target.cpu_features_add, .{ + if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ .@"16bit_mode", .@"32bit_mode", })) { switch (result.target.abi) { .code16 => result.target.cpu.features.addFeature( - @intFromEnum(std.Target.x86.Feature.@"16bit_mode"), + @intFromEnum(Target.x86.Feature.@"16bit_mode"), ), else => result.target.cpu.features.addFeature( - @intFromEnum(std.Target.x86.Feature.@"32bit_mode"), + @intFromEnum(Target.x86.Feature.@"32bit_mode"), ), } } @@ -228,12 +228,12 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { }, .thumb, .thumbeb => { result.target.cpu.features.addFeature( - @intFromEnum(std.Target.arm.Feature.thumb_mode), + @intFromEnum(Target.arm.Feature.thumb_mode), ); }, else => {}, } - cross_target.updateCpuFeatures(&result.target.cpu.features); + query.updateCpuFeatures(&result.target.cpu.features); return result; } @@ -253,22 +253,22 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { fn detectAbiAndDynamicLinker( cpu: Target.Cpu, os: Target.Os, - cross_target: CrossTarget, + query: Target.Query, ) DetectError!NativeTargetInfo { const native_target_has_ld = comptime builtin.target.hasDynamicLinker(); const is_linux = builtin.target.os.tag == .linux; const is_solarish = builtin.target.os.tag.isSolarish(); - const have_all_info = cross_target.dynamic_linker.get() != null and - cross_target.abi != null and (!is_linux or cross_target.abi.?.isGnu()); - const os_is_non_native = cross_target.os_tag != null; + const have_all_info = query.dynamic_linker.get() != null and + query.abi != null and (!is_linux or query.abi.?.isGnu()); + const os_is_non_native = query.os_tag != null; // The Solaris/illumos environment is always the same. if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) { - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); } - if (cross_target.abi) |abi| { + if (query.abi) |abi| { if (abi.isMusl()) { // musl implies static linking. - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); } } // The current target's ABI cannot be relied on for this. For example, we may build the zig @@ -287,7 +287,7 @@ fn detectAbiAndDynamicLinker( }; var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; var ld_info_list_len: usize = 0; - const ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); + const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); for (all_abis) |abi| { // This may be a nonsensical parameter. We detect this with @@ -345,7 +345,7 @@ fn detectAbiAndDynamicLinker( error.Unexpected, => |e| { std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); }, else => |e| return e, @@ -363,7 +363,7 @@ fn detectAbiAndDynamicLinker( const line = buffer[0..newline]; if (!mem.startsWith(u8, line, "#!")) break :blk file; var it = mem.tokenizeScalar(u8, line[2..], ' '); - file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, cross_target); + file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, query); file.close(); } }; @@ -373,7 +373,7 @@ fn detectAbiAndDynamicLinker( // trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file. // TODO: inline this function and combine the buffer we already read above to find // the possible shebang line with the buffer we use for the ELF header. - return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) { + return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, query) catch |err| switch (err) { error.FileSystem, error.SystemResources, error.SymLinkLoop, @@ -393,7 +393,7 @@ fn detectAbiAndDynamicLinker( // Finally, we fall back on the standard path. => |e| { std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); }, }; } @@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { while (it.next()) |s| { if (mem.startsWith(u8, s, "GLIBC_2.")) { const chopped = s["GLIBC_".len..]; - const ver = CrossTarget.parseVersion(chopped) catch |err| switch (err) { + const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) { error.Overflow => return error.InvalidGnuLibCVersion, error.InvalidVersion => return error.InvalidGnuLibCVersion, }; @@ -588,7 +588,7 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ Unreco } // chop off "libc-" and ".so" const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; - return CrossTarget.parseVersion(link_name_chopped) catch |err| switch (err) { + return Target.Query.parseVersion(link_name_chopped) catch |err| switch (err) { error.Overflow => return error.InvalidGnuLibCVersion, error.InvalidVersion => return error.InvalidGnuLibCVersion, }; @@ -627,7 +627,7 @@ pub fn abiAndDynamicLinkerFromFile( cpu: Target.Cpu, os: Target.Os, ld_info_list: []const LdInfo, - cross_target: CrossTarget, + query: Target.Query, ) AbiAndDynamicLinkerFromFileError!NativeTargetInfo { var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); @@ -655,13 +655,13 @@ pub fn abiAndDynamicLinkerFromFile( .target = .{ .cpu = cpu, .os = os, - .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .abi = query.abi orelse Target.Abi.default(cpu.arch, os), + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), }, - .dynamic_linker = cross_target.dynamic_linker, + .dynamic_linker = query.dynamic_linker, }; var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC - const look_for_ld = cross_target.dynamic_linker.get() == null; + const look_for_ld = query.dynamic_linker.get() == null; var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined; if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile; @@ -706,7 +706,7 @@ pub fn abiAndDynamicLinkerFromFile( }, // We only need this for detecting glibc version. elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - cross_target.glibc_version == null) + query.glibc_version == null) { var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); @@ -747,7 +747,7 @@ pub fn abiAndDynamicLinkerFromFile( } if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - cross_target.glibc_version == null) + query.glibc_version == null) { const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); @@ -927,19 +927,19 @@ fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize { return i; } -fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: CrossTarget) !NativeTargetInfo { +fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) !NativeTargetInfo { const target: Target = .{ .cpu = cpu, .os = os, - .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .abi = query.abi orelse Target.Abi.default(cpu.arch, os), + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), }; return NativeTargetInfo{ .target = target, - .dynamic_linker = if (cross_target.dynamic_linker.get() == null) + .dynamic_linker = if (query.dynamic_linker.get() == null) target.standardDynamicLinkerPath() else - cross_target.dynamic_linker, + query.dynamic_linker, }; } @@ -964,13 +964,13 @@ pub fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @ } } -fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu { +fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, // although it is a runtime value, is guaranteed to be one of the architectures in the set // of the respective switch prong. switch (builtin.cpu.arch) { .x86_64, .x86 => { - return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, cross_target); + return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query); }, else => {}, } diff --git a/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig index 2c0b22e96cba..c4feb7a35b26 100644 --- a/lib/std/zig/system/darwin/macos.zig +++ b/lib/std/zig/system/darwin/macos.zig @@ -87,7 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion { const ver = try svt.expectContent(); try svt.skipUntilTag(.end, "string"); - return try std.zig.CrossTarget.parseVersion(ver); + return try std.Target.Query.parseVersion(ver); } const SystemVersionTokenizer = struct { diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig index f2f89f8317b6..d2d31b407981 100644 --- a/lib/std/zig/system/linux.zig +++ b/lib/std/zig/system/linux.zig @@ -5,10 +5,7 @@ const io = std.io; const fs = std.fs; const fmt = std.fmt; const testing = std.testing; - const Target = std.Target; -const CrossTarget = std.zig.CrossTarget; - const assert = std.debug.assert; const SparcCpuinfoImpl = struct { diff --git a/lib/std/zig/system/x86.zig b/lib/std/zig/system/x86.zig index b99f5cf65faa..edcfcebf29d3 100644 --- a/lib/std/zig/system/x86.zig +++ b/lib/std/zig/system/x86.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const Target = std.Target; -const CrossTarget = std.zig.CrossTarget; const XCR0_XMM = 0x02; const XCR0_YMM = 0x04; @@ -23,8 +22,8 @@ inline fn hasMask(input: u32, mask: u32) bool { return (input & mask) == mask; } -pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu { - _ = cross_target; +pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) Target.Cpu { + _ = query; var cpu = Target.Cpu{ .arch = arch, .model = Target.Cpu.Model.generic(arch), diff --git a/src/libc_installation.zig b/src/libc_installation.zig index 48b505d9359b..facb16257e61 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -41,7 +41,7 @@ pub const LibCInstallation = struct { pub fn parse( allocator: Allocator, libc_file: []const u8, - target: std.zig.CrossTarget, + target: std.Target.Query, ) !LibCInstallation { var self: LibCInstallation = .{}; diff --git a/src/main.zig b/src/main.zig index 0e6ce947aa47..17603acf2c8f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2551,7 +2551,7 @@ fn buildOutputType( } }; - var target_parse_options: std.zig.CrossTarget.ParseOptions = .{ + var target_parse_options: std.Target.Query.ParseOptions = .{ .arch_os_abi = target_arch_os_abi, .cpu_features = target_mcpu, .dynamic_linker = target_dynamic_linker, @@ -2563,7 +2563,7 @@ fn buildOutputType( if (llvm_m_args.items.len != 0) { // If this returns null, we let it fall through to the case below which will // run the full parse function and do proper error handling. - if (std.zig.CrossTarget.parseCpuArch(target_parse_options)) |cpu_arch| { + if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| { var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa); defer llvm_to_zig_name.deinit(); @@ -2607,8 +2607,8 @@ fn buildOutputType( } } - const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options); - const target_info = try detectNativeTargetInfo(cross_target); + const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options); + const target_info = try detectNativeTargetInfo(target_query); if (target_info.target.os.tag != .freestanding) { if (ensure_libc_on_non_freestanding) @@ -2695,13 +2695,13 @@ fn buildOutputType( } if (use_lld) |opt| { - if (opt and cross_target.isDarwin()) { + if (opt and target_query.isDarwin()) { fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{}); } } if (want_lto) |opt| { - if (opt and cross_target.isDarwin()) { + if (opt and target_query.isDarwin()) { fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{}); } } @@ -2771,7 +2771,7 @@ fn buildOutputType( var libc_installation: ?LibCInstallation = null; if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, cross_target) catch |err| { + libc_installation = LibCInstallation.parse(arena, paths_file, target_query) catch |err| { fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); }; } @@ -2835,7 +2835,7 @@ fn buildOutputType( // After this point, external_system_libs is used instead of system_libs. // Trigger native system library path detection if necessary. - if (sysroot == null and cross_target.isNativeOs() and cross_target.isNativeAbi() and + if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and (external_system_libs.len != 0 or want_native_include_dirs)) { const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { @@ -2864,7 +2864,7 @@ fn buildOutputType( libc_installation = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, - .target = cross_target.toTarget(), + .target = target_query.toTarget(), }); try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? }); @@ -3455,8 +3455,8 @@ fn buildOutputType( .global_cache_directory = global_cache_directory, .root_name = root_name, .target = target_info.target, - .is_native_os = cross_target.isNativeOs(), - .is_native_abi = cross_target.isNativeAbi(), + .is_native_os = target_query.isNativeOs(), + .is_native_abi = target_query.isNativeAbi(), .dynamic_linker = target_info.dynamic_linker.get(), .sysroot = sysroot, .output_mode = output_mode, @@ -4013,16 +4013,16 @@ const ModuleDepIterator = struct { } }; -fn parseCrossTargetOrReportFatalError( +fn parseTargetQueryOrReportFatalError( allocator: Allocator, - opts: std.zig.CrossTarget.ParseOptions, -) !std.zig.CrossTarget { + opts: std.Target.Query.ParseOptions, +) !std.Target.Query { var opts_with_diags = opts; - var diags: std.zig.CrossTarget.ParseOptions.Diagnostics = .{}; + var diags: std.Target.Query.ParseOptions.Diagnostics = .{}; if (opts_with_diags.diagnostics == null) { opts_with_diags.diagnostics = &diags; } - return std.zig.CrossTarget.parse(opts_with_diags) catch |err| switch (err) { + return std.Target.Query.parse(opts_with_diags) catch |err| switch (err) { error.UnknownCpuModel => { help: { var help_text = std.ArrayList(u8).init(allocator); @@ -4666,9 +4666,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: while (true) { switch (cur_includes) { .any, .msvc => { - const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable; - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable; + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| { if (cur_includes == .any) { // fall back to mingw @@ -4691,9 +4691,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: }; }, .gnu => { - const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable; - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable; + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null); return .{ .include_paths = detected_libc.libc_include_dir_list, @@ -4754,7 +4754,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } } - const cross_target = try parseCrossTargetOrReportFatalError(gpa, .{ + const target_query = try parseTargetQueryOrReportFatalError(gpa, .{ .arch_os_abi = target_arch_os_abi, }); @@ -4766,7 +4766,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { const libc_installation: ?*LibCInstallation = libc: { if (input_file) |libc_file| { const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.parse(arena, libc_file, cross_target) catch |err| { + libc.* = LibCInstallation.parse(arena, libc_file, target_query) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; break :libc libc; @@ -4781,8 +4781,8 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { }; defer zig_lib_directory.handle.close(); - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const libc_dirs = Compilation.detectLibCIncludeDirs( arena, @@ -4812,15 +4812,15 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } if (input_file) |libc_file| { - var libc = LibCInstallation.parse(gpa, libc_file, cross_target) catch |err| { + var libc = LibCInstallation.parse(gpa, libc_file, target_query) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; defer libc.deinit(gpa); } else { - if (!cross_target.isNative()) { + if (!target_query.isNative()) { fatal("unable to detect libc for non-native target", .{}); } - const target_info = try detectNativeTargetInfo(cross_target); + const target_info = try detectNativeTargetInfo(target_query); var libc = LibCInstallation.findNative(.{ .allocator = gpa, @@ -5113,8 +5113,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi gimmeMoreOfThoseSweetSweetFileDescriptors(); - const cross_target: std.zig.CrossTarget = .{}; - const target_info = try detectNativeTargetInfo(cross_target); + const target_query: std.Target.Query = .{}; + const target_info = try detectNativeTargetInfo(target_query); const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", @@ -5283,8 +5283,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .global_cache_directory = global_cache_directory, .root_name = "build", .target = target_info.target, - .is_native_os = cross_target.isNativeOs(), - .is_native_abi = cross_target.isNativeAbi(), + .is_native_os = target_query.isNativeOs(), + .is_native_abi = target_query.isNativeAbi(), .dynamic_linker = target_info.dynamic_linker.get(), .output_mode = .Exe, .main_mod = &main_mod, @@ -6269,8 +6269,8 @@ test "fds" { gimmeMoreOfThoseSweetSweetFileDescriptors(); } -fn detectNativeTargetInfo(cross_target: std.zig.CrossTarget) !std.zig.system.NativeTargetInfo { - return std.zig.system.NativeTargetInfo.detect(cross_target); +fn detectNativeTargetInfo(target_query: std.Target.Query) !std.zig.system.NativeTargetInfo { + return std.zig.system.NativeTargetInfo.detect(target_query); } const usage_ast_check = @@ -6672,8 +6672,8 @@ fn warnAboutForeignBinaries( target_info: *const std.zig.system.NativeTargetInfo, link_libc: bool, ) !void { - const host_cross_target: std.zig.CrossTarget = .{}; - const host_target_info = try detectNativeTargetInfo(host_cross_target); + const host_query: std.Target.Query = .{}; + const host_target_info = try detectNativeTargetInfo(host_query); switch (host_target_info.getExternalExecutor(target_info, .{ .link_libc = link_libc })) { .native => return, diff --git a/test/cbe.zig b/test/cbe.zig index b45a4e5f7284..26724a1df000 100644 --- a/test/cbe.zig +++ b/test/cbe.zig @@ -5,7 +5,7 @@ const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; pub fn addCases(ctx: *Cases, b: *std.Build) !void { // These tests should work with all platforms, but we're using linux_x64 for // now for consistency. Will be expanded eventually. - const linux_x64: std.zig.CrossTarget = .{ + const linux_x64: std.Target.Query = .{ .cpu_arch = .x86_64, .os_tag = .linux, }; diff --git a/test/link/elf.zig b/test/link/elf.zig index 95bb929dc019..459244db29a6 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -3833,7 +3833,6 @@ const link = @import("link.zig"); const std = @import("std"); const Build = std.Build; -const CrossTarget = std.zig.CrossTarget; const Options = link.Options; const Step = Build.Step; const WriteFile = Step.WriteFile; diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index 85cbc48e5478..6bafb0715231 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -8,7 +8,7 @@ pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = t, .root_source_file = .{ .path = "main.c" }, - .target = b.resolveTargetQuery(std.zig.CrossTarget.parse( + .target = b.resolveTargetQuery(std.Target.Query.parse( .{ .arch_os_abi = t }, ) catch unreachable), }); diff --git a/test/link/link.zig b/test/link/link.zig index d5bbbe9f4bfb..4d31d2d49ac0 100644 --- a/test/link/link.zig +++ b/test/link/link.zig @@ -199,7 +199,6 @@ const std = @import("std"); const Build = std.Build; const Compile = Step.Compile; -const CrossTarget = std.zig.CrossTarget; const Run = Step.Run; const Step = Build.Step; const WriteFile = Step.WriteFile; diff --git a/test/link/macho.zig b/test/link/macho.zig index 230107c9b266..8a5016f9b7d7 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -95,7 +95,5 @@ const addExecutable = link.addExecutable; const expectLinkErrors = link.expectLinkErrors; const link = @import("link.zig"); const std = @import("std"); - -const CrossTarget = std.zig.CrossTarget; const Options = link.Options; const Step = std.Build.Step; diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig index 6a3139dd9f0e..99eb161a5892 100644 --- a/test/llvm_targets.zig +++ b/test/llvm_targets.zig @@ -1,7 +1,7 @@ const std = @import("std"); const Cases = @import("src/Cases.zig"); -const targets = [_]std.zig.CrossTarget{ +const targets = [_]std.Target.Query{ .{ .cpu_arch = .aarch64, .os_tag = .freestanding, .abi = .none }, .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .none }, .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .simulator }, diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 2aa92fc90872..de7378d10acd 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -188,7 +188,7 @@ pub fn exe(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Cas return ctx.addExe(name, target); } -pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.zig.CrossTarget, b: *std.Build) *Case { +pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.Target.Query, b: *std.Build) *Case { var adjusted_query = target_query; adjusted_query.ofmt = .c; ctx.cases.append(Case{ @@ -423,7 +423,7 @@ fn addFromDirInner( var manifest = try TestManifest.parse(ctx.arena, src); const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.zig.CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.Target.Query); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -1160,9 +1160,9 @@ const TestManifest = struct { } fn getDefaultParser(comptime T: type) ParseFn(T) { - if (T == std.zig.CrossTarget) return struct { + if (T == std.Target.Query) return struct { fn parse(str: []const u8) anyerror!T { - return std.zig.CrossTarget.parse(.{ .arch_os_abi = str }); + return std.Target.Query.parse(.{ .arch_os_abi = str }); } }.parse; @@ -1287,7 +1287,7 @@ pub fn main() !void { if (cases.items.len == 0) { const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.zig.CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.Target.Query); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -1385,7 +1385,7 @@ pub fn main() !void { return runCases(&ctx, zig_exe_path); } -fn resolveTargetQuery(query: std.zig.CrossTarget) std.Build.ResolvedTarget { +fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget { const result = std.zig.system.NativeTargetInfo.detect(query) catch @panic("unable to resolve target query"); diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig index 71288c11da66..528e370918c3 100644 --- a/test/src/translate_c.zig +++ b/test/src/translate_c.zig @@ -5,7 +5,6 @@ const ArrayList = std.ArrayList; const fmt = std.fmt; const mem = std.mem; const fs = std.fs; -const CrossTarget = std.zig.CrossTarget; pub const TranslateCContext = struct { b: *std.Build, @@ -18,7 +17,7 @@ pub const TranslateCContext = struct { sources: ArrayList(SourceFile), expected_lines: ArrayList([]const u8), allow_warnings: bool, - target: CrossTarget = .{}, + target: std.Target.Query = .{}, const SourceFile = struct { filename: []const u8, @@ -74,7 +73,7 @@ pub const TranslateCContext = struct { pub fn addWithTarget( self: *TranslateCContext, name: []const u8, - target: CrossTarget, + target: std.Target.Query, source: []const u8, expected_lines: []const []const u8, ) void { diff --git a/test/standalone.zig b/test/standalone.zig index fdd3185cdfbc..0303c49c133f 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -2,7 +2,7 @@ pub const SimpleCase = struct { src_path: []const u8, link_libc: bool = false, all_modes: bool = false, - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, is_test: bool = false, is_exe: bool = true, /// Run only on this OS. diff --git a/test/standalone/windows_resources/build.zig b/test/standalone/windows_resources/build.zig index e927a03fc40f..51117515715a 100644 --- a/test/standalone/windows_resources/build.zig +++ b/test/standalone/windows_resources/build.zig @@ -4,17 +4,17 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const cross_target = b.resolveTargetQuery(.{ + const target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu, }); add(b, b.host, .any, test_step); - add(b, cross_target, .any, test_step); + add(b, target, .any, test_step); add(b, b.host, .gnu, test_step); - add(b, cross_target, .gnu, test_step); + add(b, target, .gnu, test_step); } fn add( diff --git a/test/tests.zig b/test/tests.zig index a8f9b6281021..29d181c60522 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -21,7 +21,7 @@ pub const CompareOutputContext = @import("src/CompareOutput.zig"); pub const StackTracesContext = @import("src/StackTrace.zig"); const TestTarget = struct { - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, optimize_mode: std.builtin.OptimizeMode = .Debug, link_libc: ?bool = null, single_threaded: ?bool = null, @@ -145,7 +145,7 @@ const test_targets = blk: { //}, // https://github.com/ziglang/zig/issues/13623 //.{ - // .target = std.zig.CrossTarget.parse(.{ + // .target = std.Target.Query.parse(.{ // .arch_os_abi = "arm-linux-none", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -286,13 +286,13 @@ const test_targets = blk: { }, .{ - .target = std.zig.CrossTarget.parse(.{ + .target = std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8a", }) catch unreachable, }, .{ - .target = std.zig.CrossTarget.parse(.{ + .target = std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }) catch unreachable, @@ -300,7 +300,7 @@ const test_targets = blk: { }, // https://github.com/ziglang/zig/issues/3287 //.{ - // .target = std.zig.CrossTarget.parse(.{ + // .target = std.Target.Query.parse(.{ // .arch_os_abi = "arm-linux-gnueabihf", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -494,7 +494,7 @@ const test_targets = blk: { }; const CAbiTarget = struct { - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, use_llvm: ?bool = null, use_lld: ?bool = null, pic: ?bool = null, diff --git a/test/translate_c.zig b/test/translate_c.zig index 2b87da406755..a3908108306f 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const tests = @import("tests.zig"); -const CrossTarget = std.zig.CrossTarget; // ******************************************************** // * * @@ -1846,7 +1845,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo5(a: [*c]f32) callconv(.Thiscall) void; }); - cases.addWithTarget("Calling convention", CrossTarget.parse(.{ + cases.addWithTarget("Calling convention", std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8_5a", }) catch unreachable, @@ -1857,7 +1856,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; }); - cases.addWithTarget("Calling convention", CrossTarget.parse(.{ + cases.addWithTarget("Calling convention", std.Target.Query.parse(.{ .arch_os_abi = "aarch64-linux-none", .cpu_features = "generic+v8_5a", }) catch unreachable, From dbdb87502d6936597424fe86842c15978ba86918 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 15:26:57 -0700 Subject: [PATCH 015/133] std.Target: add DynamicLinker --- CMakeLists.txt | 1 - lib/build_runner.zig | 4 +- lib/std/Build.zig | 15 +- lib/std/Build/Module.zig | 1 - lib/std/Build/Step/Compile.zig | 1 - lib/std/Build/Step/Options.zig | 4 +- lib/std/Build/Step/Run.zig | 6 +- lib/std/Target.zig | 72 +- lib/std/Target/Query.zig | 26 +- lib/std/zig/system.zig | 1118 +++++++++++++++++++++- lib/std/zig/system/NativePaths.zig | 4 +- lib/std/zig/system/NativeTargetInfo.zig | 1130 ----------------------- src/Compilation.zig | 27 +- src/main.zig | 132 ++- src/print_env.zig | 4 +- test/src/Cases.zig | 30 +- 16 files changed, 1280 insertions(+), 1295 deletions(-) delete mode 100644 lib/std/zig/system/NativeTargetInfo.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index fa3a10dc4ce5..b3004d3254be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -516,7 +516,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/zig/string_literal.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/system.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/system/NativePaths.zig" - "${CMAKE_SOURCE_DIR}/lib/std/zig/system/NativeTargetInfo.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/system/x86.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/tokenizer.zig" "${CMAKE_SOURCE_DIR}/src/Air.zig" diff --git a/lib/build_runner.zig b/lib/build_runner.zig index 8be6b61425b1..b485469a381f 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -46,11 +46,9 @@ pub fn main() !void { return error.InvalidArgs; }; - const detected = try std.zig.system.NativeTargetInfo.detect(.{}); const host: std.Build.ResolvedTarget = .{ .query = .{}, - .target = detected.target, - .dynamic_linker = detected.dynamic_linker, + .target = try std.zig.system.resolveTargetQuery(.{}), }; const build_root_directory: std.Build.Cache.Directory = .{ diff --git a/lib/std/Build.zig b/lib/std/Build.zig index db7e3493da50..cb5a503593ad 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -2129,14 +2129,6 @@ pub fn hex64(x: u64) [16]u8 { pub const ResolvedTarget = struct { query: Target.Query, target: Target, - dynamic_linker: Target.DynamicLinker, - - pub fn toNativeTargetInfo(self: ResolvedTarget) std.zig.system.NativeTargetInfo { - return .{ - .target = self.target, - .dynamic_linker = self.dynamic_linker, - }; - } }; /// Converts a target query into a fully resolved target that can be passed to @@ -2146,13 +2138,10 @@ pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { // resolved via a WASI API or via the build protocol. _ = b; - const result = std.zig.system.NativeTargetInfo.detect(query) catch - @panic("unable to resolve target query"); - return .{ .query = query, - .target = result.target, - .dynamic_linker = result.dynamic_linker, + .target = std.zig.system.resolveTargetQuery(query) catch + @panic("unable to resolve target query"), }; } diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index f17f296e64b6..5482ca25ec12 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -746,5 +746,4 @@ const Module = @This(); const std = @import("std"); const assert = std.debug.assert; const LazyPath = std.Build.LazyPath; -const NativeTargetInfo = std.zig.system.NativeTargetInfo; const Step = std.Build.Step; diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index cd5986617670..b51304c91006 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -9,7 +9,6 @@ const StringHashMap = std.StringHashMap; const Sha256 = std.crypto.hash.sha2.Sha256; const Allocator = mem.Allocator; const Step = std.Build.Step; -const NativeTargetInfo = std.zig.system.NativeTargetInfo; const LazyPath = std.Build.LazyPath; const PkgConfigPkg = std.Build.PkgConfigPkg; const PkgConfigError = std.Build.PkgConfigError; diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 9ed936fe7e69..938649d83ff8 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -294,11 +294,9 @@ test Options { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); - const detected = try std.zig.system.NativeTargetInfo.detect(.{}); const host: std.Build.ResolvedTarget = .{ .query = .{}, - .target = detected.target, - .dynamic_linker = detected.dynamic_linker, + .target = try std.zig.system.resolveTargetQuery(.{}), }; var cache: std.Build.Cache = .{ diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 36b2eb82eba9..ad68dce648c8 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -678,8 +678,8 @@ fn runCommand( const need_cross_glibc = exe.rootModuleTarget().isGnuLibC() and exe.is_linking_libc; - const other_target_info = exe.root_module.target.?.toNativeTargetInfo(); - switch (b.host.toNativeTargetInfo().getExternalExecutor(&other_target_info, .{ + const other_target = exe.root_module.target.?.target; + switch (std.zig.system.getExternalExecutor(b.host.target, &other_target, .{ .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -752,7 +752,7 @@ fn runCommand( .bad_dl => |foreign_dl| { if (allow_skip) return error.MakeSkipped; - const host_dl = b.host.dynamic_linker.get() orelse "(none)"; + const host_dl = b.host.target.dynamic_linker.get() orelse "(none)"; return step.fail( \\the host system is unable to execute binaries from the target diff --git a/lib/std/Target.zig b/lib/std/Target.zig index f5a207426444..6f30aa75b17d 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1,7 +1,13 @@ +//! All the details about the machine that will be executing code. +//! Unlike `Query` which might leave some things as "default" or "host", this +//! data is fully resolved into a concrete set of OS versions, CPU features, +//! etc. + cpu: Cpu, os: Os, abi: Abi, ofmt: ObjectFormat, +dynamic_linker: DynamicLinker = DynamicLinker.none, pub const Query = @import("Target/Query.zig"); @@ -1529,13 +1535,19 @@ pub inline fn hasDynamicLinker(self: Target) bool { } pub const DynamicLinker = struct { - /// Contains the memory used to store the dynamic linker path. This field should - /// not be used directly. See `get` and `set`. This field exists so that this API requires no allocator. - buffer: [255]u8 = undefined, + /// Contains the memory used to store the dynamic linker path. This field + /// should not be used directly. See `get` and `set`. This field exists so + /// that this API requires no allocator. + buffer: [255]u8, /// Used to construct the dynamic linker path. This field should not be used /// directly. See `get` and `set`. - max_byte: ?u8 = null, + max_byte: ?u8, + + pub const none: DynamicLinker = .{ + .buffer = undefined, + .max_byte = null, + }; /// Asserts that the length is less than or equal to 255 bytes. pub fn init(dl_or_null: ?[]const u8) DynamicLinker { @@ -1561,8 +1573,12 @@ pub const DynamicLinker = struct { } }; -pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { - var result: DynamicLinker = .{}; +pub fn standardDynamicLinkerPath(target: Target) DynamicLinker { + return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi); +} + +pub fn standardDynamicLinkerPath_cpu_os_abi(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker { + var result = DynamicLinker.none; const S = struct { fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker { r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1)); @@ -1577,32 +1593,32 @@ pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { const print = S.print; const copy = S.copy; - if (self.abi == .android) { - const suffix = if (self.ptrBitWidth() == 64) "64" else ""; + if (abi == .android) { + const suffix = if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""; return print(&result, "/system/bin/linker{s}", .{suffix}); } - if (self.abi.isMusl()) { - const is_arm = switch (self.cpu.arch) { + if (abi.isMusl()) { + const is_arm = switch (cpu.arch) { .arm, .armeb, .thumb, .thumbeb => true, else => false, }; - const arch_part = switch (self.cpu.arch) { + const arch_part = switch (cpu.arch) { .arm, .thumb => "arm", .armeb, .thumbeb => "armeb", else => |arch| @tagName(arch), }; - const arch_suffix = if (is_arm and self.abi.floatAbi() == .hard) "hf" else ""; + const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else ""; return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix }); } - switch (self.os.tag) { + switch (os_tag) { .freebsd => return copy(&result, "/libexec/ld-elf.so.1"), .netbsd => return copy(&result, "/libexec/ld.elf_so"), .openbsd => return copy(&result, "/usr/libexec/ld.so"), .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"), .solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"), - .linux => switch (self.cpu.arch) { + .linux => switch (cpu.arch) { .x86, .sparc, .sparcel, @@ -1616,7 +1632,7 @@ pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { .armeb, .thumb, .thumbeb, - => return copy(&result, switch (self.abi.floatAbi()) { + => return copy(&result, switch (abi.floatAbi()) { .hard => "/lib/ld-linux-armhf.so.3", else => "/lib/ld-linux.so.3", }), @@ -1626,12 +1642,12 @@ pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { .mips64, .mips64el, => { - const lib_suffix = switch (self.abi) { + const lib_suffix = switch (abi) { .gnuabin32, .gnux32 => "32", .gnuabi64 => "64", else => "", }; - const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008); + const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008); const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1"; return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader }); }, @@ -1640,7 +1656,7 @@ pub fn standardDynamicLinkerPath(self: Target) DynamicLinker { .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"), .s390x => return copy(&result, "/lib64/ld64.so.1"), .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"), - .x86_64 => return copy(&result, switch (self.abi) { + .x86_64 => return copy(&result, switch (abi) { .gnux32 => "/libx32/ld-linux-x32.so.2", else => "/lib64/ld-linux-x86-64.so.2", }), @@ -1862,17 +1878,17 @@ pub fn maxIntAlignment(target: Target) u16 { }; } -pub fn ptrBitWidth(target: Target) u16 { - switch (target.abi) { +pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { + switch (abi) { .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32, .gnuabi64 => return 64, else => {}, } - switch (target.cpu.arch) { + return switch (cpu.arch) { .avr, .msp430, .spu_2, - => return 16, + => 16, .arc, .arm, @@ -1908,7 +1924,7 @@ pub fn ptrBitWidth(target: Target) u16 { .loongarch32, .dxil, .xtensa, - => return 32, + => 32, .aarch64, .aarch64_be, @@ -1933,10 +1949,14 @@ pub fn ptrBitWidth(target: Target) u16 { .ve, .spirv64, .loongarch64, - => return 64, + => 64, - .sparc => return if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) 64 else 32, - } + .sparc => if (std.Target.sparc.featureSetHas(cpu.features, .v9)) 64 else 32, + }; +} + +pub fn ptrBitWidth(target: Target) u16 { + return ptrBitWidth_cpu_abi(target.cpu, target.abi); } pub fn stackAlignment(target: Target) u16 { diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig index 617d141d3980..bb5949d597cc 100644 --- a/lib/std/Target/Query.zig +++ b/lib/std/Target/Query.zig @@ -34,7 +34,7 @@ abi: ?Target.Abi = null, /// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path /// based on the `os_tag`. -dynamic_linker: DynamicLinker = DynamicLinker{}, +dynamic_linker: Target.DynamicLinker = Target.DynamicLinker.none, /// `null` means default for the cpu/arch/os combo. ofmt: ?Target.ObjectFormat = null, @@ -61,8 +61,6 @@ pub const OsVersion = union(enum) { pub const SemanticVersion = std.SemanticVersion; -pub const DynamicLinker = Target.DynamicLinker; - pub fn fromTarget(target: Target) Query { var result: Query = .{ .cpu_arch = target.cpu.arch, @@ -164,7 +162,7 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void { } } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn toTarget(self: Query) Target { return .{ .cpu = self.getCpu(), @@ -232,7 +230,7 @@ pub fn parse(args: ParseOptions) !Query { const diags = args.diagnostics orelse &dummy_diags; var result: Query = .{ - .dynamic_linker = DynamicLinker.init(args.dynamic_linker), + .dynamic_linker = Target.DynamicLinker.init(args.dynamic_linker), }; var it = mem.splitScalar(u8, args.arch_os_abi, '-'); @@ -379,13 +377,13 @@ test parseVersion { try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn getCpu(self: Query) Target.Cpu { switch (self.cpu_model) { .native => { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. + // will need to be integrated with `std.zig.system.resolveTargetQuery`. return builtin.cpu; }, .baseline => { @@ -396,7 +394,7 @@ pub fn getCpu(self: Query) Target.Cpu { .determined_by_cpu_arch => if (self.cpu_arch == null) { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. + // will need to be integrated with `std.zig.system.resolveTargetQuery`. return builtin.cpu; } else { var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch()); @@ -426,11 +424,11 @@ pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set { return self.getCpu().features; } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn getOs(self: Query) Target.Os { // `builtin.os` works when doing `zig build` because Zig generates a build executable using // native OS version range. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. + // will need to be integrated with `std.zig.system.resolveTargetQuery`. var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os; if (self.os_version_min) |min| switch (min) { @@ -463,7 +461,7 @@ pub fn getOsTag(self: Query) Target.Os.Tag { return self.os_tag orelse builtin.os.tag; } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn getOsVersionMin(self: Query) OsVersion { if (self.os_version_min) |version_min| return version_min; var tmp: Query = undefined; @@ -471,7 +469,7 @@ pub fn getOsVersionMin(self: Query) OsVersion { return tmp.os_version_min.?; } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn getOsVersionMax(self: Query) OsVersion { if (self.os_version_max) |version_max| return version_max; var tmp: Query = undefined; @@ -479,14 +477,14 @@ pub fn getOsVersionMax(self: Query) OsVersion { return tmp.os_version_max.?; } -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. pub fn getAbi(self: Query) Target.Abi { if (self.abi) |abi| return abi; if (self.os_tag == null) { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. + // will need to be integrated with `std.zig.system.resolveTargetQuery`. return builtin.abi; } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 3ec92c8274e0..6920999ef06d 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -1,13 +1,1127 @@ pub const NativePaths = @import("system/NativePaths.zig"); -pub const NativeTargetInfo = @import("system/NativeTargetInfo.zig"); pub const windows = @import("system/windows.zig"); pub const darwin = @import("system/darwin.zig"); pub const linux = @import("system/linux.zig"); +pub const Executor = union(enum) { + native, + rosetta, + qemu: []const u8, + wine: []const u8, + wasmtime: []const u8, + darling: []const u8, + bad_dl: []const u8, + bad_os_or_cpu, +}; + +pub const GetExternalExecutorOptions = struct { + allow_darling: bool = true, + allow_qemu: bool = true, + allow_rosetta: bool = true, + allow_wasmtime: bool = true, + allow_wine: bool = true, + qemu_fixes_dl: bool = false, + link_libc: bool = false, +}; + +/// Return whether or not the given host is capable of running executables of +/// the other target. +pub fn getExternalExecutor( + host: std.Target, + candidate: *const std.Target, + options: GetExternalExecutorOptions, +) Executor { + const os_match = host.os.tag == candidate.os.tag; + const cpu_ok = cpu_ok: { + if (host.cpu.arch == candidate.cpu.arch) + break :cpu_ok true; + + if (host.cpu.arch == .x86_64 and candidate.cpu.arch == .x86) + break :cpu_ok true; + + if (host.cpu.arch == .aarch64 and candidate.cpu.arch == .arm) + break :cpu_ok true; + + if (host.cpu.arch == .aarch64_be and candidate.cpu.arch == .armeb) + break :cpu_ok true; + + // TODO additionally detect incompatible CPU features. + // Note that in some cases the OS kernel will emulate missing CPU features + // when an illegal instruction is encountered. + + break :cpu_ok false; + }; + + var bad_result: Executor = .bad_os_or_cpu; + + if (os_match and cpu_ok) native: { + if (options.link_libc) { + if (candidate.dynamic_linker.get()) |candidate_dl| { + fs.cwd().access(candidate_dl, .{}) catch { + bad_result = .{ .bad_dl = candidate_dl }; + break :native; + }; + } + } + return .native; + } + + // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2 + // to emulate the foreign architecture. + if (options.allow_rosetta and os_match and + host.os.tag == .macos and host.cpu.arch == .aarch64) + { + switch (candidate.cpu.arch) { + .x86_64 => return .rosetta, + else => return bad_result, + } + } + + // If the OS matches, we can use QEMU to emulate a foreign architecture. + if (options.allow_qemu and os_match and (!cpu_ok or options.qemu_fixes_dl)) { + return switch (candidate.cpu.arch) { + .aarch64 => Executor{ .qemu = "qemu-aarch64" }, + .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, + .arm => Executor{ .qemu = "qemu-arm" }, + .armeb => Executor{ .qemu = "qemu-armeb" }, + .hexagon => Executor{ .qemu = "qemu-hexagon" }, + .x86 => Executor{ .qemu = "qemu-i386" }, + .m68k => Executor{ .qemu = "qemu-m68k" }, + .mips => Executor{ .qemu = "qemu-mips" }, + .mipsel => Executor{ .qemu = "qemu-mipsel" }, + .mips64 => Executor{ .qemu = "qemu-mips64" }, + .mips64el => Executor{ .qemu = "qemu-mips64el" }, + .powerpc => Executor{ .qemu = "qemu-ppc" }, + .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, + .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, + .riscv32 => Executor{ .qemu = "qemu-riscv32" }, + .riscv64 => Executor{ .qemu = "qemu-riscv64" }, + .s390x => Executor{ .qemu = "qemu-s390x" }, + .sparc => Executor{ .qemu = "qemu-sparc" }, + .sparc64 => Executor{ .qemu = "qemu-sparc64" }, + .x86_64 => Executor{ .qemu = "qemu-x86_64" }, + else => return bad_result, + }; + } + + switch (candidate.os.tag) { + .windows => { + if (options.allow_wine) { + // x86_64 wine does not support emulating aarch64-windows and + // vice versa. + if (candidate.cpu.arch != builtin.cpu.arch) { + return bad_result; + } + switch (candidate.ptrBitWidth()) { + 32 => return Executor{ .wine = "wine" }, + 64 => return Executor{ .wine = "wine64" }, + else => return bad_result, + } + } + return bad_result; + }, + .wasi => { + if (options.allow_wasmtime) { + switch (candidate.ptrBitWidth()) { + 32 => return Executor{ .wasmtime = "wasmtime" }, + else => return bad_result, + } + } + return bad_result; + }, + .macos => { + if (options.allow_darling) { + // This check can be loosened once darling adds a QEMU-based emulation + // layer for non-host architectures: + // https://github.com/darlinghq/darling/issues/863 + if (candidate.cpu.arch != builtin.cpu.arch) { + return bad_result; + } + return Executor{ .darling = "darling" }; + } + return bad_result; + }, + else => return bad_result, + } +} + +pub const DetectError = error{ + FileSystem, + SystemResources, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + DeviceBusy, + OSVersionDetectionFail, + Unexpected, +}; + +/// Given a `Target.Query`, which specifies in detail which parts of the +/// target should be detected natively, which should be standard or default, +/// and which are provided explicitly, this function resolves the native +/// components by detecting the native system, and then resolves +/// standard/default parts relative to that. +pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { + var os = query.getOsTag().defaultVersionRange(query.getCpuArch()); + if (query.os_tag == null) { + switch (builtin.target.os.tag) { + .linux => { + const uts = std.os.uname(); + const release = mem.sliceTo(&uts.release, 0); + // The release field sometimes has a weird format, + // `Version.parse` will attempt to find some meaningful interpretation. + if (std.SemanticVersion.parse(release)) |ver| { + os.version_range.linux.range.min = ver; + os.version_range.linux.range.max = ver; + } else |err| switch (err) { + error.Overflow => {}, + error.InvalidVersion => {}, + } + }, + .solaris, .illumos => { + const uts = std.os.uname(); + const release = mem.sliceTo(&uts.release, 0); + if (std.SemanticVersion.parse(release)) |ver| { + os.version_range.semver.min = ver; + os.version_range.semver.max = ver; + } else |err| switch (err) { + error.Overflow => {}, + error.InvalidVersion => {}, + } + }, + .windows => { + const detected_version = windows.detectRuntimeVersion(); + os.version_range.windows.min = detected_version; + os.version_range.windows.max = detected_version; + }, + .macos => try darwin.macos.detect(&os), + .freebsd, .netbsd, .dragonfly => { + const key = switch (builtin.target.os.tag) { + .freebsd => "kern.osreldate", + .netbsd, .dragonfly => "kern.osrevision", + else => unreachable, + }; + var value: u32 = undefined; + var len: usize = @sizeOf(@TypeOf(value)); + + std.os.sysctlbynameZ(key, &value, &len, null, 0) catch |err| switch (err) { + error.NameTooLong => unreachable, // constant, known good value + error.PermissionDenied => unreachable, // only when setting values, + error.SystemResources => unreachable, // memory already on the stack + error.UnknownName => unreachable, // constant, known good value + error.Unexpected => return error.OSVersionDetectionFail, + }; + + switch (builtin.target.os.tag) { + .freebsd => { + // https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html + // Major * 100,000 has been convention since FreeBSD 2.2 (1997) + // Minor * 1(0),000 summed has been convention since FreeBSD 2.2 (1997) + // e.g. 492101 = 4.11-STABLE = 4.(9+2) + const major = value / 100_000; + const minor1 = value % 100_000 / 10_000; // usually 0 since 5.1 + const minor2 = value % 10_000 / 1_000; // 0 before 5.1, minor version since + const patch = value % 1_000; + os.version_range.semver.min = .{ .major = major, .minor = minor1 + minor2, .patch = patch }; + os.version_range.semver.max = os.version_range.semver.min; + }, + .netbsd => { + // #define __NetBSD_Version__ MMmmrrpp00 + // + // M = major version + // m = minor version; a minor number of 99 indicates current. + // r = 0 (*) + // p = patchlevel + const major = value / 100_000_000; + const minor = value % 100_000_000 / 1_000_000; + const patch = value % 10_000 / 100; + os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; + os.version_range.semver.max = os.version_range.semver.min; + }, + .dragonfly => { + // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/cb2cde83771754aeef9bb3251ee48959138dec87/Makefile.inc1#L15-L17 + // flat base10 format: Mmmmpp + // M = major + // m = minor; odd-numbers indicate current dev branch + // p = patch + const major = value / 100_000; + const minor = value % 100_000 / 100; + const patch = value % 100; + os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; + os.version_range.semver.max = os.version_range.semver.min; + }, + else => unreachable, + } + }, + .openbsd => { + const mib: [2]c_int = [_]c_int{ + std.os.CTL.KERN, + std.os.KERN.OSRELEASE, + }; + var buf: [64]u8 = undefined; + // consider that sysctl result includes null-termination + // reserve 1 byte to ensure we never overflow when appending ".0" + var len: usize = buf.len - 1; + + std.os.sysctl(&mib, &buf, &len, null, 0) catch |err| switch (err) { + error.NameTooLong => unreachable, // constant, known good value + error.PermissionDenied => unreachable, // only when setting values, + error.SystemResources => unreachable, // memory already on the stack + error.UnknownName => unreachable, // constant, known good value + error.Unexpected => return error.OSVersionDetectionFail, + }; + + // append ".0" to satisfy semver + buf[len - 1] = '.'; + buf[len] = '0'; + len += 1; + + if (std.SemanticVersion.parse(buf[0..len])) |ver| { + os.version_range.semver.min = ver; + os.version_range.semver.max = ver; + } else |_| { + return error.OSVersionDetectionFail; + } + }, + else => { + // Unimplemented, fall back to default version range. + }, + } + } + + if (query.os_version_min) |min| switch (min) { + .none => {}, + .semver => |semver| switch (query.getOsTag()) { + .linux => os.version_range.linux.range.min = semver, + else => os.version_range.semver.min = semver, + }, + .windows => |win_ver| os.version_range.windows.min = win_ver, + }; + + if (query.os_version_max) |max| switch (max) { + .none => {}, + .semver => |semver| switch (query.getOsTag()) { + .linux => os.version_range.linux.range.max = semver, + else => os.version_range.semver.max = semver, + }, + .windows => |win_ver| os.version_range.windows.max = win_ver, + }; + + if (query.glibc_version) |glibc| { + assert(query.isGnuLibC()); + os.version_range.linux.glibc = glibc; + } + + // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the + // native CPU architecture as being different than the current target), we use this: + const cpu_arch = query.getCpuArch(); + + const cpu = switch (query.cpu_model) { + .native => detectNativeCpuAndFeatures(cpu_arch, os, query), + .baseline => Target.Cpu.baseline(cpu_arch), + .determined_by_cpu_arch => if (query.cpu_arch == null) + detectNativeCpuAndFeatures(cpu_arch, os, query) + else + Target.Cpu.baseline(cpu_arch), + .explicit => |model| model.toCpu(cpu_arch), + } orelse backup_cpu_detection: { + break :backup_cpu_detection Target.Cpu.baseline(cpu_arch); + }; + var result = try detectAbiAndDynamicLinker(cpu, os, query); + // For x86, we need to populate some CPU feature flags depending on architecture + // and mode: + // * 16bit_mode => if the abi is code16 + // * 32bit_mode => if the arch is x86 + // However, the "mode" flags can be used as overrides, so if the user explicitly + // sets one of them, that takes precedence. + switch (cpu_arch) { + .x86 => { + if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ + .@"16bit_mode", .@"32bit_mode", + })) { + switch (result.abi) { + .code16 => result.cpu.features.addFeature( + @intFromEnum(Target.x86.Feature.@"16bit_mode"), + ), + else => result.cpu.features.addFeature( + @intFromEnum(Target.x86.Feature.@"32bit_mode"), + ), + } + } + }, + .arm, .armeb => { + // XXX What do we do if the target has the noarm feature? + // What do we do if the user specifies +thumb_mode? + }, + .thumb, .thumbeb => { + result.cpu.features.addFeature( + @intFromEnum(Target.arm.Feature.thumb_mode), + ); + }, + else => {}, + } + query.updateCpuFeatures(&result.cpu.features); + return result; +} + +fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { + // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, + // although it is a runtime value, is guaranteed to be one of the architectures in the set + // of the respective switch prong. + switch (builtin.cpu.arch) { + .x86_64, .x86 => { + return @import("system/x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query); + }, + else => {}, + } + + switch (builtin.os.tag) { + .linux => return linux.detectNativeCpuAndFeatures(), + .macos => return darwin.macos.detectNativeCpuAndFeatures(), + .windows => return windows.detectNativeCpuAndFeatures(), + else => {}, + } + + // This architecture does not have CPU model & feature detection yet. + // See https://github.com/ziglang/zig/issues/4591 + return null; +} + +pub const AbiAndDynamicLinkerFromFileError = error{ + FileSystem, + SystemResources, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + UnableToReadElfFile, + InvalidElfClass, + InvalidElfVersion, + InvalidElfEndian, + InvalidElfFile, + InvalidElfMagic, + Unexpected, + UnexpectedEndOfFile, + NameTooLong, +}; + +pub fn abiAndDynamicLinkerFromFile( + file: fs.File, + cpu: Target.Cpu, + os: Target.Os, + ld_info_list: []const LdInfo, + query: Target.Query, +) AbiAndDynamicLinkerFromFileError!Target { + var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; + _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); + const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); + const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf)); + if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; + const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { + elf.ELFDATA2LSB => .little, + elf.ELFDATA2MSB => .big, + else => return error.InvalidElfEndian, + }; + const need_bswap = elf_endian != native_endian; + if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; + + const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { + elf.ELFCLASS32 => false, + elf.ELFCLASS64 => true, + else => return error.InvalidElfClass, + }; + var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff); + const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize); + const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum); + + var result: Target = .{ + .cpu = cpu, + .os = os, + .abi = query.abi orelse Target.Abi.default(cpu.arch, os), + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .dynamic_linker = query.dynamic_linker, + }; + var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC + const look_for_ld = query.dynamic_linker.get() == null; + + var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined; + if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile; + + var ph_i: u16 = 0; + while (ph_i < phnum) { + // Reserve some bytes so that we can deref the 64-bit struct fields + // even when the ELF file is 32-bits. + const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr); + const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize); + var ph_buf_i: usize = 0; + while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({ + ph_i += 1; + phoff += phentsize; + ph_buf_i += phentsize; + }) { + const ph32: *elf.Elf32_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i])); + const ph64: *elf.Elf64_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i])); + const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type); + switch (p_type) { + elf.PT_INTERP => if (look_for_ld) { + const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); + const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); + if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong; + const filesz = @as(usize, @intCast(p_filesz)); + _ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz); + // PT_INTERP includes a null byte in filesz. + const len = filesz - 1; + // dynamic_linker.max_byte is "max", not "len". + // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. + result.dynamic_linker.max_byte = @as(u8, @intCast(len - 1)); + + // Use it to determine ABI. + const full_ld_path = result.dynamic_linker.buffer[0..len]; + for (ld_info_list) |ld_info| { + const standard_ld_basename = fs.path.basename(ld_info.ld.get().?); + if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) { + result.abi = ld_info.abi; + break; + } + } + }, + // We only need this for detecting glibc version. + elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.isGnuLibC() and + query.glibc_version == null) + { + var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); + const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); + const dyn_size: usize = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn); + const dyn_num = p_filesz / dyn_size; + var dyn_buf: [16 * @sizeOf(elf.Elf64_Dyn)]u8 align(@alignOf(elf.Elf64_Dyn)) = undefined; + var dyn_i: usize = 0; + dyn: while (dyn_i < dyn_num) { + // Reserve some bytes so that we can deref the 64-bit struct fields + // even when the ELF file is 32-bits. + const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn); + const dyn_read_byte_len = try preadMin( + file, + dyn_buf[0 .. dyn_buf.len - dyn_reserve], + dyn_off, + dyn_size, + ); + var dyn_buf_i: usize = 0; + while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num) : ({ + dyn_i += 1; + dyn_off += dyn_size; + dyn_buf_i += dyn_size; + }) { + const dyn32: *elf.Elf32_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i])); + const dyn64: *elf.Elf64_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i])); + const tag = elfInt(is_64, need_bswap, dyn32.d_tag, dyn64.d_tag); + const val = elfInt(is_64, need_bswap, dyn32.d_val, dyn64.d_val); + if (tag == elf.DT_RUNPATH) { + rpath_offset = val; + break :dyn; + } + } + } + }, + else => continue, + } + } + } + + if (builtin.target.os.tag == .linux and result.isGnuLibC() and + query.glibc_version == null) + { + const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); + + var shoff = elfInt(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff); + const shentsize = elfInt(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize); + const str_section_off = shoff + @as(u64, shentsize) * @as(u64, shstrndx); + + var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined; + if (sh_buf.len < shentsize) return error.InvalidElfFile; + + _ = try preadMin(file, &sh_buf, str_section_off, shentsize); + const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf)); + const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf)); + const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset); + const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size); + var strtab_buf: [4096:0]u8 = undefined; + const shstrtab_len = @min(shstrtab_size, strtab_buf.len); + const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len); + const shstrtab = strtab_buf[0..shstrtab_read_len]; + + const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); + var sh_i: u16 = 0; + const dynstr: ?struct { offset: u64, size: u64 } = find_dyn_str: while (sh_i < shnum) { + // Reserve some bytes so that we can deref the 64-bit struct fields + // even when the ELF file is 32-bits. + const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); + const sh_read_byte_len = try preadMin( + file, + sh_buf[0 .. sh_buf.len - sh_reserve], + shoff, + shentsize, + ); + var sh_buf_i: usize = 0; + while (sh_buf_i < sh_read_byte_len and sh_i < shnum) : ({ + sh_i += 1; + shoff += shentsize; + sh_buf_i += shentsize; + }) { + const sh32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); + const sh64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); + const sh_name_off = elfInt(is_64, need_bswap, sh32.sh_name, sh64.sh_name); + const sh_name = mem.sliceTo(shstrtab[sh_name_off..], 0); + if (mem.eql(u8, sh_name, ".dynstr")) { + break :find_dyn_str .{ + .offset = elfInt(is_64, need_bswap, sh32.sh_offset, sh64.sh_offset), + .size = elfInt(is_64, need_bswap, sh32.sh_size, sh64.sh_size), + }; + } + } + } else null; + + if (dynstr) |ds| { + if (rpath_offset) |rpoff| { + if (rpoff > ds.size) return error.InvalidElfFile; + const rpoff_file = ds.offset + rpoff; + const rp_max_size = ds.size - rpoff; + + const strtab_len = @min(rp_max_size, strtab_buf.len); + const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len); + const strtab = strtab_buf[0..strtab_read_len]; + + const rpath_list = mem.sliceTo(strtab, 0); + var it = mem.tokenizeScalar(u8, rpath_list, ':'); + while (it.next()) |rpath| { + if (glibcVerFromRPath(rpath)) |ver| { + result.os.version_range.linux.glibc = ver; + return result; + } else |err| switch (err) { + error.GLibCNotFound => continue, + else => |e| return e, + } + } + } + } + + if (result.dynamic_linker.get()) |dl_path| glibc_ver: { + // There is no DT_RUNPATH so we try to find libc.so.6 inside the same + // directory as the dynamic linker. + if (fs.path.dirname(dl_path)) |rpath| { + if (glibcVerFromRPath(rpath)) |ver| { + result.os.version_range.linux.glibc = ver; + return result; + } else |err| switch (err) { + error.GLibCNotFound => {}, + else => |e| return e, + } + } + + // So far, no luck. Next we try to see if the information is + // present in the symlink data for the dynamic linker path. + var link_buf: [std.os.PATH_MAX]u8 = undefined; + const link_name = std.os.readlink(dl_path, &link_buf) catch |err| switch (err) { + error.NameTooLong => unreachable, + error.InvalidUtf8 => unreachable, // Windows only + error.BadPathName => unreachable, // Windows only + error.UnsupportedReparsePointType => unreachable, // Windows only + error.NetworkNotFound => unreachable, // Windows only + + error.AccessDenied, + error.FileNotFound, + error.NotLink, + error.NotDir, + => break :glibc_ver, + + error.SystemResources, + error.FileSystem, + error.SymLinkLoop, + error.Unexpected, + => |e| return e, + }; + result.os.version_range.linux.glibc = glibcVerFromLinkName( + fs.path.basename(link_name), + "ld-", + ) catch |err| switch (err) { + error.UnrecognizedGnuLibCFileName, + error.InvalidGnuLibCVersion, + => break :glibc_ver, + }; + return result; + } + + // Nothing worked so far. Finally we fall back to hard-coded search paths. + // Some distros such as Debian keep their libc.so.6 in `/lib/$triple/`. + var path_buf: [std.os.PATH_MAX]u8 = undefined; + var index: usize = 0; + const prefix = "/lib/"; + const cpu_arch = @tagName(result.cpu.arch); + const os_tag = @tagName(result.os.tag); + const abi = @tagName(result.abi); + @memcpy(path_buf[index..][0..prefix.len], prefix); + index += prefix.len; + @memcpy(path_buf[index..][0..cpu_arch.len], cpu_arch); + index += cpu_arch.len; + path_buf[index] = '-'; + index += 1; + @memcpy(path_buf[index..][0..os_tag.len], os_tag); + index += os_tag.len; + path_buf[index] = '-'; + index += 1; + @memcpy(path_buf[index..][0..abi.len], abi); + index += abi.len; + const rpath = path_buf[0..index]; + if (glibcVerFromRPath(rpath)) |ver| { + result.os.version_range.linux.glibc = ver; + return result; + } else |err| switch (err) { + error.GLibCNotFound => {}, + else => |e| return e, + } + } + + return result; +} + +fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ UnrecognizedGnuLibCFileName, InvalidGnuLibCVersion }!std.SemanticVersion { + // example: "libc-2.3.4.so" + // example: "libc-2.27.so" + // example: "ld-2.33.so" + const suffix = ".so"; + if (!mem.startsWith(u8, link_name, prefix) or !mem.endsWith(u8, link_name, suffix)) { + return error.UnrecognizedGnuLibCFileName; + } + // chop off "libc-" and ".so" + const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; + return Target.Query.parseVersion(link_name_chopped) catch |err| switch (err) { + error.Overflow => return error.InvalidGnuLibCVersion, + error.InvalidVersion => return error.InvalidGnuLibCVersion, + }; +} + +test glibcVerFromLinkName { + try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("ld-2.37.so", "this-prefix-does-not-exist")); + try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("libc-2.37.so-is-not-end", "libc-")); + + try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.so", "ld-")); + try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.so", "ld-")); + try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.0.so", "ld-")); + try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 1 }, try glibcVerFromLinkName("ld-2.37.1.so", "ld-")); + try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.37.4.5.so", "ld-")); +} + +fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { + var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) { + error.NameTooLong => unreachable, + error.InvalidUtf8 => unreachable, + error.BadPathName => unreachable, + error.DeviceBusy => unreachable, + error.NetworkNotFound => unreachable, // Windows-only + + error.FileNotFound, + error.NotDir, + error.InvalidHandle, + error.AccessDenied, + error.NoDevice, + => return error.GLibCNotFound, + + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + error.SystemResources, + error.SymLinkLoop, + error.Unexpected, + => |e| return e, + }; + defer dir.close(); + + // Now we have a candidate for the path to libc shared object. In + // the past, we used readlink() here because the link name would + // reveal the glibc version. However, in more recent GNU/Linux + // installations, there is no symlink. Thus we instead use a more + // robust check of opening the libc shared object and looking at the + // .dynstr section, and finding the max version number of symbols + // that start with "GLIBC_2.". + const glibc_so_basename = "libc.so.6"; + var f = dir.openFile(glibc_so_basename, .{}) catch |err| switch (err) { + error.NameTooLong => unreachable, + error.InvalidUtf8 => unreachable, // Windows only + error.BadPathName => unreachable, // Windows only + error.PipeBusy => unreachable, // Windows-only + error.SharingViolation => unreachable, // Windows-only + error.NetworkNotFound => unreachable, // Windows-only + error.FileLocksNotSupported => unreachable, // No lock requested. + error.NoSpaceLeft => unreachable, // read-only + error.PathAlreadyExists => unreachable, // read-only + error.DeviceBusy => unreachable, // read-only + error.FileBusy => unreachable, // read-only + error.InvalidHandle => unreachable, // should not be in the error set + error.WouldBlock => unreachable, // not using O_NONBLOCK + error.NoDevice => unreachable, // not asking for a special device + + error.AccessDenied, + error.FileNotFound, + error.NotDir, + error.IsDir, + => return error.GLibCNotFound, + + error.FileTooBig => return error.Unexpected, + + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + error.SystemResources, + error.SymLinkLoop, + error.Unexpected, + => |e| return e, + }; + defer f.close(); + + return glibcVerFromSoFile(f) catch |err| switch (err) { + error.InvalidElfMagic, + error.InvalidElfEndian, + error.InvalidElfClass, + error.InvalidElfFile, + error.InvalidElfVersion, + error.InvalidGnuLibCVersion, + error.UnexpectedEndOfFile, + => return error.GLibCNotFound, + + error.SystemResources, + error.UnableToReadElfFile, + error.Unexpected, + error.FileSystem, + => |e| return e, + }; +} + +fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { + var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; + _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); + const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); + const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf)); + if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; + const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { + elf.ELFDATA2LSB => .little, + elf.ELFDATA2MSB => .big, + else => return error.InvalidElfEndian, + }; + const need_bswap = elf_endian != native_endian; + if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; + + const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { + elf.ELFCLASS32 => false, + elf.ELFCLASS64 => true, + else => return error.InvalidElfClass, + }; + const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); + var shoff = elfInt(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff); + const shentsize = elfInt(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize); + const str_section_off = shoff + @as(u64, shentsize) * @as(u64, shstrndx); + var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined; + if (sh_buf.len < shentsize) return error.InvalidElfFile; + + _ = try preadMin(file, &sh_buf, str_section_off, shentsize); + const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf)); + const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf)); + const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset); + const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size); + var strtab_buf: [4096:0]u8 = undefined; + const shstrtab_len = @min(shstrtab_size, strtab_buf.len); + const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len); + const shstrtab = strtab_buf[0..shstrtab_read_len]; + const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); + var sh_i: u16 = 0; + const dynstr: struct { offset: u64, size: u64 } = find_dyn_str: while (sh_i < shnum) { + // Reserve some bytes so that we can deref the 64-bit struct fields + // even when the ELF file is 32-bits. + const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); + const sh_read_byte_len = try preadMin( + file, + sh_buf[0 .. sh_buf.len - sh_reserve], + shoff, + shentsize, + ); + var sh_buf_i: usize = 0; + while (sh_buf_i < sh_read_byte_len and sh_i < shnum) : ({ + sh_i += 1; + shoff += shentsize; + sh_buf_i += shentsize; + }) { + const sh32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); + const sh64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); + const sh_name_off = elfInt(is_64, need_bswap, sh32.sh_name, sh64.sh_name); + const sh_name = mem.sliceTo(shstrtab[sh_name_off..], 0); + if (mem.eql(u8, sh_name, ".dynstr")) { + break :find_dyn_str .{ + .offset = elfInt(is_64, need_bswap, sh32.sh_offset, sh64.sh_offset), + .size = elfInt(is_64, need_bswap, sh32.sh_size, sh64.sh_size), + }; + } + } + } else return error.InvalidGnuLibCVersion; + + // Here we loop over all the strings in the dynstr string table, assuming that any + // strings that start with "GLIBC_2." indicate the existence of such a glibc version, + // and furthermore, that the system-installed glibc is at minimum that version. + + // Empirically, glibc 2.34 libc.so .dynstr section is 32441 bytes on my system. + // Here I use double this value plus some headroom. This makes it only need + // a single read syscall here. + var buf: [80000]u8 = undefined; + if (buf.len < dynstr.size) return error.InvalidGnuLibCVersion; + + const dynstr_size: usize = @intCast(dynstr.size); + const dynstr_bytes = buf[0..dynstr_size]; + _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len); + var it = mem.splitScalar(u8, dynstr_bytes, 0); + var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 }; + while (it.next()) |s| { + if (mem.startsWith(u8, s, "GLIBC_2.")) { + const chopped = s["GLIBC_".len..]; + const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) { + error.Overflow => return error.InvalidGnuLibCVersion, + error.InvalidVersion => return error.InvalidGnuLibCVersion, + }; + switch (ver.order(max_ver)) { + .gt => max_ver = ver, + .lt, .eq => continue, + } + } + } + return max_ver; +} + +/// In the past, this function attempted to use the executable's own binary if it was dynamically +/// linked to answer both the C ABI question and the dynamic linker question. However, this +/// could be problematic on a system that uses a RUNPATH for the compiler binary, locking +/// it to an older glibc version, while system binaries such as /usr/bin/env use a newer glibc +/// version. The problem is that libc.so.6 glibc version will match that of the system while +/// the dynamic linker will match that of the compiler binary. Executables with these versions +/// mismatching will fail to run. +/// +/// Therefore, this function works the same regardless of whether the compiler binary is +/// dynamically or statically linked. It inspects `/usr/bin/env` as an ELF file to find the +/// answer to these questions, or if there is a shebang line, then it chases the referenced +/// file recursively. If that does not provide the answer, then the function falls back to +/// defaults. +fn detectAbiAndDynamicLinker( + cpu: Target.Cpu, + os: Target.Os, + query: Target.Query, +) DetectError!Target { + const native_target_has_ld = comptime builtin.target.hasDynamicLinker(); + const is_linux = builtin.target.os.tag == .linux; + const is_solarish = builtin.target.os.tag.isSolarish(); + const have_all_info = query.dynamic_linker.get() != null and + query.abi != null and (!is_linux or query.abi.?.isGnu()); + const os_is_non_native = query.os_tag != null; + // The Solaris/illumos environment is always the same. + if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) { + return defaultAbiAndDynamicLinker(cpu, os, query); + } + if (query.abi) |abi| { + if (abi.isMusl()) { + // musl implies static linking. + return defaultAbiAndDynamicLinker(cpu, os, query); + } + } + // The current target's ABI cannot be relied on for this. For example, we may build the zig + // compiler for target riscv64-linux-musl and provide a tarball for users to download. + // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined + // and supported by Zig. But that means that we must detect the system ABI here rather than + // relying on `builtin.target`. + const all_abis = comptime blk: { + assert(@intFromEnum(Target.Abi.none) == 0); + const fields = std.meta.fields(Target.Abi)[1..]; + var array: [fields.len]Target.Abi = undefined; + for (fields, 0..) |field, i| { + array[i] = @field(Target.Abi, field.name); + } + break :blk array; + }; + var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; + var ld_info_list_len: usize = 0; + const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); + + for (all_abis) |abi| { + // This may be a nonsensical parameter. We detect this with + // error.UnknownDynamicLinkerPath and skip adding it to `ld_info_list`. + const target: Target = .{ + .cpu = cpu, + .os = os, + .abi = abi, + .ofmt = ofmt, + }; + const ld = target.standardDynamicLinkerPath(); + if (ld.get() == null) continue; + + ld_info_list_buffer[ld_info_list_len] = .{ + .ld = ld, + .abi = abi, + }; + ld_info_list_len += 1; + } + const ld_info_list = ld_info_list_buffer[0..ld_info_list_len]; + + // Best case scenario: the executable is dynamically linked, and we can iterate + // over our own shared objects and find a dynamic linker. + const elf_file = blk: { + // This block looks for a shebang line in /usr/bin/env, + // if it finds one, then instead of using /usr/bin/env as the ELF file to examine, it uses the file it references instead, + // doing the same logic recursively in case it finds another shebang line. + + // Since /usr/bin/env is hard-coded into the shebang line of many portable scripts, it's a + // reasonably reliable path to start with. + var file_name: []const u8 = "/usr/bin/env"; + // #! (2) + 255 (max length of shebang line since Linux 5.1) + \n (1) + var buffer: [258]u8 = undefined; + while (true) { + const file = fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) { + error.NoSpaceLeft => unreachable, + error.NameTooLong => unreachable, + error.PathAlreadyExists => unreachable, + error.SharingViolation => unreachable, + error.InvalidUtf8 => unreachable, + error.BadPathName => unreachable, + error.PipeBusy => unreachable, + error.FileLocksNotSupported => unreachable, + error.WouldBlock => unreachable, + error.FileBusy => unreachable, // opened without write permissions + + error.IsDir, + error.NotDir, + error.InvalidHandle, + error.AccessDenied, + error.NoDevice, + error.FileNotFound, + error.NetworkNotFound, + error.FileTooBig, + error.Unexpected, + => |e| { + std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); + return defaultAbiAndDynamicLinker(cpu, os, query); + }, + + else => |e| return e, + }; + errdefer file.close(); + + const len = preadMin(file, &buffer, 0, buffer.len) catch |err| switch (err) { + error.UnexpectedEndOfFile, + error.UnableToReadElfFile, + => break :blk file, + + else => |e| return e, + }; + const newline = mem.indexOfScalar(u8, buffer[0..len], '\n') orelse break :blk file; + const line = buffer[0..newline]; + if (!mem.startsWith(u8, line, "#!")) break :blk file; + var it = mem.tokenizeScalar(u8, line[2..], ' '); + file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, query); + file.close(); + } + }; + defer elf_file.close(); + + // If Zig is statically linked, such as via distributed binary static builds, the above + // trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file. + // TODO: inline this function and combine the buffer we already read above to find + // the possible shebang line with the buffer we use for the ELF header. + return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, query) catch |err| switch (err) { + error.FileSystem, + error.SystemResources, + error.SymLinkLoop, + error.ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded, + => |e| return e, + + error.UnableToReadElfFile, + error.InvalidElfClass, + error.InvalidElfVersion, + error.InvalidElfEndian, + error.InvalidElfFile, + error.InvalidElfMagic, + error.Unexpected, + error.UnexpectedEndOfFile, + error.NameTooLong, + // Finally, we fall back on the standard path. + => |e| { + std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); + return defaultAbiAndDynamicLinker(cpu, os, query); + }, + }; +} + +fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) !Target { + const abi = query.abi orelse Target.Abi.default(cpu.arch, os); + return .{ + .cpu = cpu, + .os = os, + .abi = abi, + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .dynamic_linker = if (query.dynamic_linker.get() == null) + Target.standardDynamicLinkerPath_cpu_os_abi(cpu, os.tag, abi) + else + query.dynamic_linker, + }; +} + +const LdInfo = struct { + ld: Target.DynamicLinker, + abi: Target.Abi, +}; + +fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize { + var i: usize = 0; + while (i < min_read_len) { + const len = file.pread(buf[i..], offset + i) catch |err| switch (err) { + error.OperationAborted => unreachable, // Windows-only + error.WouldBlock => unreachable, // Did not request blocking mode + error.NotOpenForReading => unreachable, + error.SystemResources => return error.SystemResources, + error.IsDir => return error.UnableToReadElfFile, + error.BrokenPipe => return error.UnableToReadElfFile, + error.Unseekable => return error.UnableToReadElfFile, + error.ConnectionResetByPeer => return error.UnableToReadElfFile, + error.ConnectionTimedOut => return error.UnableToReadElfFile, + error.SocketNotConnected => return error.UnableToReadElfFile, + error.NetNameDeleted => return error.UnableToReadElfFile, + error.Unexpected => return error.Unexpected, + error.InputOutput => return error.FileSystem, + error.AccessDenied => return error.Unexpected, + }; + if (len == 0) return error.UnexpectedEndOfFile; + i += len; + } + return i; +} + +fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { + if (is_64) { + if (need_bswap) { + return @byteSwap(int_64); + } else { + return int_64; + } + } else { + if (need_bswap) { + return @byteSwap(int_32); + } else { + return int_32; + } + } +} + +const builtin = @import("builtin"); +const std = @import("../std.zig"); +const mem = std.mem; +const elf = std.elf; +const fs = std.fs; +const assert = std.debug.assert; +const Target = std.Target; +const native_endian = builtin.cpu.arch.endian(); + test { _ = NativePaths; - _ = NativeTargetInfo; _ = darwin; _ = linux; diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig index 833d698d4285..715c172c39bc 100644 --- a/lib/std/zig/system/NativePaths.zig +++ b/lib/std/zig/system/NativePaths.zig @@ -5,7 +5,6 @@ const process = std.process; const mem = std.mem; const NativePaths = @This(); -const NativeTargetInfo = std.zig.system.NativeTargetInfo; arena: Allocator, include_dirs: std.ArrayListUnmanaged([]const u8) = .{}, @@ -14,8 +13,7 @@ framework_dirs: std.ArrayListUnmanaged([]const u8) = .{}, rpaths: std.ArrayListUnmanaged([]const u8) = .{}, warnings: std.ArrayListUnmanaged([]const u8) = .{}, -pub fn detect(arena: Allocator, native_info: NativeTargetInfo) !NativePaths { - const native_target = native_info.target; +pub fn detect(arena: Allocator, native_target: std.Target) !NativePaths { var self: NativePaths = .{ .arena = arena }; var is_nix = false; if (process.getEnvVarOwned(arena, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig deleted file mode 100644 index c4562cf7d552..000000000000 --- a/lib/std/zig/system/NativeTargetInfo.zig +++ /dev/null @@ -1,1130 +0,0 @@ -const std = @import("../../std.zig"); -const builtin = @import("builtin"); -const mem = std.mem; -const assert = std.debug.assert; -const fs = std.fs; -const elf = std.elf; -const native_endian = builtin.cpu.arch.endian(); - -const NativeTargetInfo = @This(); -const Target = std.Target; -const Allocator = std.mem.Allocator; -const windows = std.zig.system.windows; -const darwin = std.zig.system.darwin; -const linux = std.zig.system.linux; - -target: Target, -dynamic_linker: DynamicLinker = DynamicLinker{}, - -pub const DynamicLinker = Target.DynamicLinker; - -pub const DetectError = error{ - FileSystem, - SystemResources, - SymLinkLoop, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - DeviceBusy, - OSVersionDetectionFail, - Unexpected, -}; - -/// Given a `Target.Query`, which specifies in detail which parts of the -/// target should be detected natively, which should be standard or default, -/// and which are provided explicitly, this function resolves the native -/// components by detecting the native system, and then resolves -/// standard/default parts relative to that. -pub fn detect(query: Target.Query) DetectError!NativeTargetInfo { - var os = query.getOsTag().defaultVersionRange(query.getCpuArch()); - if (query.os_tag == null) { - switch (builtin.target.os.tag) { - .linux => { - const uts = std.os.uname(); - const release = mem.sliceTo(&uts.release, 0); - // The release field sometimes has a weird format, - // `Version.parse` will attempt to find some meaningful interpretation. - if (std.SemanticVersion.parse(release)) |ver| { - os.version_range.linux.range.min = ver; - os.version_range.linux.range.max = ver; - } else |err| switch (err) { - error.Overflow => {}, - error.InvalidVersion => {}, - } - }, - .solaris, .illumos => { - const uts = std.os.uname(); - const release = mem.sliceTo(&uts.release, 0); - if (std.SemanticVersion.parse(release)) |ver| { - os.version_range.semver.min = ver; - os.version_range.semver.max = ver; - } else |err| switch (err) { - error.Overflow => {}, - error.InvalidVersion => {}, - } - }, - .windows => { - const detected_version = windows.detectRuntimeVersion(); - os.version_range.windows.min = detected_version; - os.version_range.windows.max = detected_version; - }, - .macos => try darwin.macos.detect(&os), - .freebsd, .netbsd, .dragonfly => { - const key = switch (builtin.target.os.tag) { - .freebsd => "kern.osreldate", - .netbsd, .dragonfly => "kern.osrevision", - else => unreachable, - }; - var value: u32 = undefined; - var len: usize = @sizeOf(@TypeOf(value)); - - std.os.sysctlbynameZ(key, &value, &len, null, 0) catch |err| switch (err) { - error.NameTooLong => unreachable, // constant, known good value - error.PermissionDenied => unreachable, // only when setting values, - error.SystemResources => unreachable, // memory already on the stack - error.UnknownName => unreachable, // constant, known good value - error.Unexpected => return error.OSVersionDetectionFail, - }; - - switch (builtin.target.os.tag) { - .freebsd => { - // https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html - // Major * 100,000 has been convention since FreeBSD 2.2 (1997) - // Minor * 1(0),000 summed has been convention since FreeBSD 2.2 (1997) - // e.g. 492101 = 4.11-STABLE = 4.(9+2) - const major = value / 100_000; - const minor1 = value % 100_000 / 10_000; // usually 0 since 5.1 - const minor2 = value % 10_000 / 1_000; // 0 before 5.1, minor version since - const patch = value % 1_000; - os.version_range.semver.min = .{ .major = major, .minor = minor1 + minor2, .patch = patch }; - os.version_range.semver.max = os.version_range.semver.min; - }, - .netbsd => { - // #define __NetBSD_Version__ MMmmrrpp00 - // - // M = major version - // m = minor version; a minor number of 99 indicates current. - // r = 0 (*) - // p = patchlevel - const major = value / 100_000_000; - const minor = value % 100_000_000 / 1_000_000; - const patch = value % 10_000 / 100; - os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; - os.version_range.semver.max = os.version_range.semver.min; - }, - .dragonfly => { - // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/cb2cde83771754aeef9bb3251ee48959138dec87/Makefile.inc1#L15-L17 - // flat base10 format: Mmmmpp - // M = major - // m = minor; odd-numbers indicate current dev branch - // p = patch - const major = value / 100_000; - const minor = value % 100_000 / 100; - const patch = value % 100; - os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; - os.version_range.semver.max = os.version_range.semver.min; - }, - else => unreachable, - } - }, - .openbsd => { - const mib: [2]c_int = [_]c_int{ - std.os.CTL.KERN, - std.os.KERN.OSRELEASE, - }; - var buf: [64]u8 = undefined; - // consider that sysctl result includes null-termination - // reserve 1 byte to ensure we never overflow when appending ".0" - var len: usize = buf.len - 1; - - std.os.sysctl(&mib, &buf, &len, null, 0) catch |err| switch (err) { - error.NameTooLong => unreachable, // constant, known good value - error.PermissionDenied => unreachable, // only when setting values, - error.SystemResources => unreachable, // memory already on the stack - error.UnknownName => unreachable, // constant, known good value - error.Unexpected => return error.OSVersionDetectionFail, - }; - - // append ".0" to satisfy semver - buf[len - 1] = '.'; - buf[len] = '0'; - len += 1; - - if (std.SemanticVersion.parse(buf[0..len])) |ver| { - os.version_range.semver.min = ver; - os.version_range.semver.max = ver; - } else |_| { - return error.OSVersionDetectionFail; - } - }, - else => { - // Unimplemented, fall back to default version range. - }, - } - } - - if (query.os_version_min) |min| switch (min) { - .none => {}, - .semver => |semver| switch (query.getOsTag()) { - .linux => os.version_range.linux.range.min = semver, - else => os.version_range.semver.min = semver, - }, - .windows => |win_ver| os.version_range.windows.min = win_ver, - }; - - if (query.os_version_max) |max| switch (max) { - .none => {}, - .semver => |semver| switch (query.getOsTag()) { - .linux => os.version_range.linux.range.max = semver, - else => os.version_range.semver.max = semver, - }, - .windows => |win_ver| os.version_range.windows.max = win_ver, - }; - - if (query.glibc_version) |glibc| { - assert(query.isGnuLibC()); - os.version_range.linux.glibc = glibc; - } - - // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the - // native CPU architecture as being different than the current target), we use this: - const cpu_arch = query.getCpuArch(); - - const cpu = switch (query.cpu_model) { - .native => detectNativeCpuAndFeatures(cpu_arch, os, query), - .baseline => Target.Cpu.baseline(cpu_arch), - .determined_by_cpu_arch => if (query.cpu_arch == null) - detectNativeCpuAndFeatures(cpu_arch, os, query) - else - Target.Cpu.baseline(cpu_arch), - .explicit => |model| model.toCpu(cpu_arch), - } orelse backup_cpu_detection: { - break :backup_cpu_detection Target.Cpu.baseline(cpu_arch); - }; - var result = try detectAbiAndDynamicLinker(cpu, os, query); - // For x86, we need to populate some CPU feature flags depending on architecture - // and mode: - // * 16bit_mode => if the abi is code16 - // * 32bit_mode => if the arch is x86 - // However, the "mode" flags can be used as overrides, so if the user explicitly - // sets one of them, that takes precedence. - switch (cpu_arch) { - .x86 => { - if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ - .@"16bit_mode", .@"32bit_mode", - })) { - switch (result.target.abi) { - .code16 => result.target.cpu.features.addFeature( - @intFromEnum(Target.x86.Feature.@"16bit_mode"), - ), - else => result.target.cpu.features.addFeature( - @intFromEnum(Target.x86.Feature.@"32bit_mode"), - ), - } - } - }, - .arm, .armeb => { - // XXX What do we do if the target has the noarm feature? - // What do we do if the user specifies +thumb_mode? - }, - .thumb, .thumbeb => { - result.target.cpu.features.addFeature( - @intFromEnum(Target.arm.Feature.thumb_mode), - ); - }, - else => {}, - } - query.updateCpuFeatures(&result.target.cpu.features); - return result; -} - -/// In the past, this function attempted to use the executable's own binary if it was dynamically -/// linked to answer both the C ABI question and the dynamic linker question. However, this -/// could be problematic on a system that uses a RUNPATH for the compiler binary, locking -/// it to an older glibc version, while system binaries such as /usr/bin/env use a newer glibc -/// version. The problem is that libc.so.6 glibc version will match that of the system while -/// the dynamic linker will match that of the compiler binary. Executables with these versions -/// mismatching will fail to run. -/// -/// Therefore, this function works the same regardless of whether the compiler binary is -/// dynamically or statically linked. It inspects `/usr/bin/env` as an ELF file to find the -/// answer to these questions, or if there is a shebang line, then it chases the referenced -/// file recursively. If that does not provide the answer, then the function falls back to -/// defaults. -fn detectAbiAndDynamicLinker( - cpu: Target.Cpu, - os: Target.Os, - query: Target.Query, -) DetectError!NativeTargetInfo { - const native_target_has_ld = comptime builtin.target.hasDynamicLinker(); - const is_linux = builtin.target.os.tag == .linux; - const is_solarish = builtin.target.os.tag.isSolarish(); - const have_all_info = query.dynamic_linker.get() != null and - query.abi != null and (!is_linux or query.abi.?.isGnu()); - const os_is_non_native = query.os_tag != null; - // The Solaris/illumos environment is always the same. - if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) { - return defaultAbiAndDynamicLinker(cpu, os, query); - } - if (query.abi) |abi| { - if (abi.isMusl()) { - // musl implies static linking. - return defaultAbiAndDynamicLinker(cpu, os, query); - } - } - // The current target's ABI cannot be relied on for this. For example, we may build the zig - // compiler for target riscv64-linux-musl and provide a tarball for users to download. - // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined - // and supported by Zig. But that means that we must detect the system ABI here rather than - // relying on `builtin.target`. - const all_abis = comptime blk: { - assert(@intFromEnum(Target.Abi.none) == 0); - const fields = std.meta.fields(Target.Abi)[1..]; - var array: [fields.len]Target.Abi = undefined; - for (fields, 0..) |field, i| { - array[i] = @field(Target.Abi, field.name); - } - break :blk array; - }; - var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; - var ld_info_list_len: usize = 0; - const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); - - for (all_abis) |abi| { - // This may be a nonsensical parameter. We detect this with - // error.UnknownDynamicLinkerPath and skip adding it to `ld_info_list`. - const target: Target = .{ - .cpu = cpu, - .os = os, - .abi = abi, - .ofmt = ofmt, - }; - const ld = target.standardDynamicLinkerPath(); - if (ld.get() == null) continue; - - ld_info_list_buffer[ld_info_list_len] = .{ - .ld = ld, - .abi = abi, - }; - ld_info_list_len += 1; - } - const ld_info_list = ld_info_list_buffer[0..ld_info_list_len]; - - // Best case scenario: the executable is dynamically linked, and we can iterate - // over our own shared objects and find a dynamic linker. - const elf_file = blk: { - // This block looks for a shebang line in /usr/bin/env, - // if it finds one, then instead of using /usr/bin/env as the ELF file to examine, it uses the file it references instead, - // doing the same logic recursively in case it finds another shebang line. - - // Since /usr/bin/env is hard-coded into the shebang line of many portable scripts, it's a - // reasonably reliable path to start with. - var file_name: []const u8 = "/usr/bin/env"; - // #! (2) + 255 (max length of shebang line since Linux 5.1) + \n (1) - var buffer: [258]u8 = undefined; - while (true) { - const file = fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, - error.NameTooLong => unreachable, - error.PathAlreadyExists => unreachable, - error.SharingViolation => unreachable, - error.InvalidUtf8 => unreachable, - error.BadPathName => unreachable, - error.PipeBusy => unreachable, - error.FileLocksNotSupported => unreachable, - error.WouldBlock => unreachable, - error.FileBusy => unreachable, // opened without write permissions - - error.IsDir, - error.NotDir, - error.InvalidHandle, - error.AccessDenied, - error.NoDevice, - error.FileNotFound, - error.NetworkNotFound, - error.FileTooBig, - error.Unexpected, - => |e| { - std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, query); - }, - - else => |e| return e, - }; - errdefer file.close(); - - const len = preadMin(file, &buffer, 0, buffer.len) catch |err| switch (err) { - error.UnexpectedEndOfFile, - error.UnableToReadElfFile, - => break :blk file, - - else => |e| return e, - }; - const newline = mem.indexOfScalar(u8, buffer[0..len], '\n') orelse break :blk file; - const line = buffer[0..newline]; - if (!mem.startsWith(u8, line, "#!")) break :blk file; - var it = mem.tokenizeScalar(u8, line[2..], ' '); - file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, query); - file.close(); - } - }; - defer elf_file.close(); - - // If Zig is statically linked, such as via distributed binary static builds, the above - // trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file. - // TODO: inline this function and combine the buffer we already read above to find - // the possible shebang line with the buffer we use for the ELF header. - return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, query) catch |err| switch (err) { - error.FileSystem, - error.SystemResources, - error.SymLinkLoop, - error.ProcessFdQuotaExceeded, - error.SystemFdQuotaExceeded, - => |e| return e, - - error.UnableToReadElfFile, - error.InvalidElfClass, - error.InvalidElfVersion, - error.InvalidElfEndian, - error.InvalidElfFile, - error.InvalidElfMagic, - error.Unexpected, - error.UnexpectedEndOfFile, - error.NameTooLong, - // Finally, we fall back on the standard path. - => |e| { - std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, query); - }, - }; -} - -fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { - var dir = fs.cwd().openDir(rpath, .{}) catch |err| switch (err) { - error.NameTooLong => unreachable, - error.InvalidUtf8 => unreachable, - error.BadPathName => unreachable, - error.DeviceBusy => unreachable, - error.NetworkNotFound => unreachable, // Windows-only - - error.FileNotFound, - error.NotDir, - error.InvalidHandle, - error.AccessDenied, - error.NoDevice, - => return error.GLibCNotFound, - - error.ProcessFdQuotaExceeded, - error.SystemFdQuotaExceeded, - error.SystemResources, - error.SymLinkLoop, - error.Unexpected, - => |e| return e, - }; - defer dir.close(); - - // Now we have a candidate for the path to libc shared object. In - // the past, we used readlink() here because the link name would - // reveal the glibc version. However, in more recent GNU/Linux - // installations, there is no symlink. Thus we instead use a more - // robust check of opening the libc shared object and looking at the - // .dynstr section, and finding the max version number of symbols - // that start with "GLIBC_2.". - const glibc_so_basename = "libc.so.6"; - var f = dir.openFile(glibc_so_basename, .{}) catch |err| switch (err) { - error.NameTooLong => unreachable, - error.InvalidUtf8 => unreachable, // Windows only - error.BadPathName => unreachable, // Windows only - error.PipeBusy => unreachable, // Windows-only - error.SharingViolation => unreachable, // Windows-only - error.NetworkNotFound => unreachable, // Windows-only - error.FileLocksNotSupported => unreachable, // No lock requested. - error.NoSpaceLeft => unreachable, // read-only - error.PathAlreadyExists => unreachable, // read-only - error.DeviceBusy => unreachable, // read-only - error.FileBusy => unreachable, // read-only - error.InvalidHandle => unreachable, // should not be in the error set - error.WouldBlock => unreachable, // not using O_NONBLOCK - error.NoDevice => unreachable, // not asking for a special device - - error.AccessDenied, - error.FileNotFound, - error.NotDir, - error.IsDir, - => return error.GLibCNotFound, - - error.FileTooBig => return error.Unexpected, - - error.ProcessFdQuotaExceeded, - error.SystemFdQuotaExceeded, - error.SystemResources, - error.SymLinkLoop, - error.Unexpected, - => |e| return e, - }; - defer f.close(); - - return glibcVerFromSoFile(f) catch |err| switch (err) { - error.InvalidElfMagic, - error.InvalidElfEndian, - error.InvalidElfClass, - error.InvalidElfFile, - error.InvalidElfVersion, - error.InvalidGnuLibCVersion, - error.UnexpectedEndOfFile, - => return error.GLibCNotFound, - - error.SystemResources, - error.UnableToReadElfFile, - error.Unexpected, - error.FileSystem, - => |e| return e, - }; -} - -fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { - var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; - _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); - const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); - const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf)); - if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; - const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { - elf.ELFDATA2LSB => .little, - elf.ELFDATA2MSB => .big, - else => return error.InvalidElfEndian, - }; - const need_bswap = elf_endian != native_endian; - if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; - - const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { - elf.ELFCLASS32 => false, - elf.ELFCLASS64 => true, - else => return error.InvalidElfClass, - }; - const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); - var shoff = elfInt(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff); - const shentsize = elfInt(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize); - const str_section_off = shoff + @as(u64, shentsize) * @as(u64, shstrndx); - var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined; - if (sh_buf.len < shentsize) return error.InvalidElfFile; - - _ = try preadMin(file, &sh_buf, str_section_off, shentsize); - const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf)); - const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf)); - const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset); - const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size); - var strtab_buf: [4096:0]u8 = undefined; - const shstrtab_len = @min(shstrtab_size, strtab_buf.len); - const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len); - const shstrtab = strtab_buf[0..shstrtab_read_len]; - const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); - var sh_i: u16 = 0; - const dynstr: struct { offset: u64, size: u64 } = find_dyn_str: while (sh_i < shnum) { - // Reserve some bytes so that we can deref the 64-bit struct fields - // even when the ELF file is 32-bits. - const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); - const sh_read_byte_len = try preadMin( - file, - sh_buf[0 .. sh_buf.len - sh_reserve], - shoff, - shentsize, - ); - var sh_buf_i: usize = 0; - while (sh_buf_i < sh_read_byte_len and sh_i < shnum) : ({ - sh_i += 1; - shoff += shentsize; - sh_buf_i += shentsize; - }) { - const sh32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); - const sh64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); - const sh_name_off = elfInt(is_64, need_bswap, sh32.sh_name, sh64.sh_name); - const sh_name = mem.sliceTo(shstrtab[sh_name_off..], 0); - if (mem.eql(u8, sh_name, ".dynstr")) { - break :find_dyn_str .{ - .offset = elfInt(is_64, need_bswap, sh32.sh_offset, sh64.sh_offset), - .size = elfInt(is_64, need_bswap, sh32.sh_size, sh64.sh_size), - }; - } - } - } else return error.InvalidGnuLibCVersion; - - // Here we loop over all the strings in the dynstr string table, assuming that any - // strings that start with "GLIBC_2." indicate the existence of such a glibc version, - // and furthermore, that the system-installed glibc is at minimum that version. - - // Empirically, glibc 2.34 libc.so .dynstr section is 32441 bytes on my system. - // Here I use double this value plus some headroom. This makes it only need - // a single read syscall here. - var buf: [80000]u8 = undefined; - if (buf.len < dynstr.size) return error.InvalidGnuLibCVersion; - - const dynstr_size: usize = @intCast(dynstr.size); - const dynstr_bytes = buf[0..dynstr_size]; - _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len); - var it = mem.splitScalar(u8, dynstr_bytes, 0); - var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 }; - while (it.next()) |s| { - if (mem.startsWith(u8, s, "GLIBC_2.")) { - const chopped = s["GLIBC_".len..]; - const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) { - error.Overflow => return error.InvalidGnuLibCVersion, - error.InvalidVersion => return error.InvalidGnuLibCVersion, - }; - switch (ver.order(max_ver)) { - .gt => max_ver = ver, - .lt, .eq => continue, - } - } - } - return max_ver; -} - -fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ UnrecognizedGnuLibCFileName, InvalidGnuLibCVersion }!std.SemanticVersion { - // example: "libc-2.3.4.so" - // example: "libc-2.27.so" - // example: "ld-2.33.so" - const suffix = ".so"; - if (!mem.startsWith(u8, link_name, prefix) or !mem.endsWith(u8, link_name, suffix)) { - return error.UnrecognizedGnuLibCFileName; - } - // chop off "libc-" and ".so" - const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; - return Target.Query.parseVersion(link_name_chopped) catch |err| switch (err) { - error.Overflow => return error.InvalidGnuLibCVersion, - error.InvalidVersion => return error.InvalidGnuLibCVersion, - }; -} - -test glibcVerFromLinkName { - try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("ld-2.37.so", "this-prefix-does-not-exist")); - try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("libc-2.37.so-is-not-end", "libc-")); - - try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.so", "ld-")); - try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.so", "ld-")); - try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.0.so", "ld-")); - try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 1 }, try glibcVerFromLinkName("ld-2.37.1.so", "ld-")); - try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.37.4.5.so", "ld-")); -} - -pub const AbiAndDynamicLinkerFromFileError = error{ - FileSystem, - SystemResources, - SymLinkLoop, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - UnableToReadElfFile, - InvalidElfClass, - InvalidElfVersion, - InvalidElfEndian, - InvalidElfFile, - InvalidElfMagic, - Unexpected, - UnexpectedEndOfFile, - NameTooLong, -}; - -pub fn abiAndDynamicLinkerFromFile( - file: fs.File, - cpu: Target.Cpu, - os: Target.Os, - ld_info_list: []const LdInfo, - query: Target.Query, -) AbiAndDynamicLinkerFromFileError!NativeTargetInfo { - var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; - _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); - const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); - const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf)); - if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; - const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { - elf.ELFDATA2LSB => .little, - elf.ELFDATA2MSB => .big, - else => return error.InvalidElfEndian, - }; - const need_bswap = elf_endian != native_endian; - if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; - - const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { - elf.ELFCLASS32 => false, - elf.ELFCLASS64 => true, - else => return error.InvalidElfClass, - }; - var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff); - const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize); - const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum); - - var result: NativeTargetInfo = .{ - .target = .{ - .cpu = cpu, - .os = os, - .abi = query.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), - }, - .dynamic_linker = query.dynamic_linker, - }; - var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC - const look_for_ld = query.dynamic_linker.get() == null; - - var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined; - if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile; - - var ph_i: u16 = 0; - while (ph_i < phnum) { - // Reserve some bytes so that we can deref the 64-bit struct fields - // even when the ELF file is 32-bits. - const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr); - const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize); - var ph_buf_i: usize = 0; - while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({ - ph_i += 1; - phoff += phentsize; - ph_buf_i += phentsize; - }) { - const ph32: *elf.Elf32_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i])); - const ph64: *elf.Elf64_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i])); - const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type); - switch (p_type) { - elf.PT_INTERP => if (look_for_ld) { - const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); - const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); - if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong; - const filesz = @as(usize, @intCast(p_filesz)); - _ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz); - // PT_INTERP includes a null byte in filesz. - const len = filesz - 1; - // dynamic_linker.max_byte is "max", not "len". - // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. - result.dynamic_linker.max_byte = @as(u8, @intCast(len - 1)); - - // Use it to determine ABI. - const full_ld_path = result.dynamic_linker.buffer[0..len]; - for (ld_info_list) |ld_info| { - const standard_ld_basename = fs.path.basename(ld_info.ld.get().?); - if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) { - result.target.abi = ld_info.abi; - break; - } - } - }, - // We only need this for detecting glibc version. - elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - query.glibc_version == null) - { - var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); - const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); - const dyn_size: usize = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn); - const dyn_num = p_filesz / dyn_size; - var dyn_buf: [16 * @sizeOf(elf.Elf64_Dyn)]u8 align(@alignOf(elf.Elf64_Dyn)) = undefined; - var dyn_i: usize = 0; - dyn: while (dyn_i < dyn_num) { - // Reserve some bytes so that we can deref the 64-bit struct fields - // even when the ELF file is 32-bits. - const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn); - const dyn_read_byte_len = try preadMin( - file, - dyn_buf[0 .. dyn_buf.len - dyn_reserve], - dyn_off, - dyn_size, - ); - var dyn_buf_i: usize = 0; - while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num) : ({ - dyn_i += 1; - dyn_off += dyn_size; - dyn_buf_i += dyn_size; - }) { - const dyn32: *elf.Elf32_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i])); - const dyn64: *elf.Elf64_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i])); - const tag = elfInt(is_64, need_bswap, dyn32.d_tag, dyn64.d_tag); - const val = elfInt(is_64, need_bswap, dyn32.d_val, dyn64.d_val); - if (tag == elf.DT_RUNPATH) { - rpath_offset = val; - break :dyn; - } - } - } - }, - else => continue, - } - } - } - - if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - query.glibc_version == null) - { - const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); - - var shoff = elfInt(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff); - const shentsize = elfInt(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize); - const str_section_off = shoff + @as(u64, shentsize) * @as(u64, shstrndx); - - var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined; - if (sh_buf.len < shentsize) return error.InvalidElfFile; - - _ = try preadMin(file, &sh_buf, str_section_off, shentsize); - const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf)); - const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf)); - const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset); - const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size); - var strtab_buf: [4096:0]u8 = undefined; - const shstrtab_len = @min(shstrtab_size, strtab_buf.len); - const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len); - const shstrtab = strtab_buf[0..shstrtab_read_len]; - - const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); - var sh_i: u16 = 0; - const dynstr: ?struct { offset: u64, size: u64 } = find_dyn_str: while (sh_i < shnum) { - // Reserve some bytes so that we can deref the 64-bit struct fields - // even when the ELF file is 32-bits. - const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); - const sh_read_byte_len = try preadMin( - file, - sh_buf[0 .. sh_buf.len - sh_reserve], - shoff, - shentsize, - ); - var sh_buf_i: usize = 0; - while (sh_buf_i < sh_read_byte_len and sh_i < shnum) : ({ - sh_i += 1; - shoff += shentsize; - sh_buf_i += shentsize; - }) { - const sh32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); - const sh64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf[sh_buf_i])); - const sh_name_off = elfInt(is_64, need_bswap, sh32.sh_name, sh64.sh_name); - const sh_name = mem.sliceTo(shstrtab[sh_name_off..], 0); - if (mem.eql(u8, sh_name, ".dynstr")) { - break :find_dyn_str .{ - .offset = elfInt(is_64, need_bswap, sh32.sh_offset, sh64.sh_offset), - .size = elfInt(is_64, need_bswap, sh32.sh_size, sh64.sh_size), - }; - } - } - } else null; - - if (dynstr) |ds| { - if (rpath_offset) |rpoff| { - if (rpoff > ds.size) return error.InvalidElfFile; - const rpoff_file = ds.offset + rpoff; - const rp_max_size = ds.size - rpoff; - - const strtab_len = @min(rp_max_size, strtab_buf.len); - const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len); - const strtab = strtab_buf[0..strtab_read_len]; - - const rpath_list = mem.sliceTo(strtab, 0); - var it = mem.tokenizeScalar(u8, rpath_list, ':'); - while (it.next()) |rpath| { - if (glibcVerFromRPath(rpath)) |ver| { - result.target.os.version_range.linux.glibc = ver; - return result; - } else |err| switch (err) { - error.GLibCNotFound => continue, - else => |e| return e, - } - } - } - } - - if (result.dynamic_linker.get()) |dl_path| glibc_ver: { - // There is no DT_RUNPATH so we try to find libc.so.6 inside the same - // directory as the dynamic linker. - if (fs.path.dirname(dl_path)) |rpath| { - if (glibcVerFromRPath(rpath)) |ver| { - result.target.os.version_range.linux.glibc = ver; - return result; - } else |err| switch (err) { - error.GLibCNotFound => {}, - else => |e| return e, - } - } - - // So far, no luck. Next we try to see if the information is - // present in the symlink data for the dynamic linker path. - var link_buf: [std.os.PATH_MAX]u8 = undefined; - const link_name = std.os.readlink(dl_path, &link_buf) catch |err| switch (err) { - error.NameTooLong => unreachable, - error.InvalidUtf8 => unreachable, // Windows only - error.BadPathName => unreachable, // Windows only - error.UnsupportedReparsePointType => unreachable, // Windows only - error.NetworkNotFound => unreachable, // Windows only - - error.AccessDenied, - error.FileNotFound, - error.NotLink, - error.NotDir, - => break :glibc_ver, - - error.SystemResources, - error.FileSystem, - error.SymLinkLoop, - error.Unexpected, - => |e| return e, - }; - result.target.os.version_range.linux.glibc = glibcVerFromLinkName( - fs.path.basename(link_name), - "ld-", - ) catch |err| switch (err) { - error.UnrecognizedGnuLibCFileName, - error.InvalidGnuLibCVersion, - => break :glibc_ver, - }; - return result; - } - - // Nothing worked so far. Finally we fall back to hard-coded search paths. - // Some distros such as Debian keep their libc.so.6 in `/lib/$triple/`. - var path_buf: [std.os.PATH_MAX]u8 = undefined; - var index: usize = 0; - const prefix = "/lib/"; - const cpu_arch = @tagName(result.target.cpu.arch); - const os_tag = @tagName(result.target.os.tag); - const abi = @tagName(result.target.abi); - @memcpy(path_buf[index..][0..prefix.len], prefix); - index += prefix.len; - @memcpy(path_buf[index..][0..cpu_arch.len], cpu_arch); - index += cpu_arch.len; - path_buf[index] = '-'; - index += 1; - @memcpy(path_buf[index..][0..os_tag.len], os_tag); - index += os_tag.len; - path_buf[index] = '-'; - index += 1; - @memcpy(path_buf[index..][0..abi.len], abi); - index += abi.len; - const rpath = path_buf[0..index]; - if (glibcVerFromRPath(rpath)) |ver| { - result.target.os.version_range.linux.glibc = ver; - return result; - } else |err| switch (err) { - error.GLibCNotFound => {}, - else => |e| return e, - } - } - - return result; -} - -fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize { - var i: usize = 0; - while (i < min_read_len) { - const len = file.pread(buf[i..], offset + i) catch |err| switch (err) { - error.OperationAborted => unreachable, // Windows-only - error.WouldBlock => unreachable, // Did not request blocking mode - error.NotOpenForReading => unreachable, - error.SystemResources => return error.SystemResources, - error.IsDir => return error.UnableToReadElfFile, - error.BrokenPipe => return error.UnableToReadElfFile, - error.Unseekable => return error.UnableToReadElfFile, - error.ConnectionResetByPeer => return error.UnableToReadElfFile, - error.ConnectionTimedOut => return error.UnableToReadElfFile, - error.SocketNotConnected => return error.UnableToReadElfFile, - error.NetNameDeleted => return error.UnableToReadElfFile, - error.Unexpected => return error.Unexpected, - error.InputOutput => return error.FileSystem, - error.AccessDenied => return error.Unexpected, - }; - if (len == 0) return error.UnexpectedEndOfFile; - i += len; - } - return i; -} - -fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) !NativeTargetInfo { - const target: Target = .{ - .cpu = cpu, - .os = os, - .abi = query.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), - }; - return NativeTargetInfo{ - .target = target, - .dynamic_linker = if (query.dynamic_linker.get() == null) - target.standardDynamicLinkerPath() - else - query.dynamic_linker, - }; -} - -pub const LdInfo = struct { - ld: DynamicLinker, - abi: Target.Abi, -}; - -pub fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { - if (is_64) { - if (need_bswap) { - return @byteSwap(int_64); - } else { - return int_64; - } - } else { - if (need_bswap) { - return @byteSwap(int_32); - } else { - return int_32; - } - } -} - -fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { - // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, - // although it is a runtime value, is guaranteed to be one of the architectures in the set - // of the respective switch prong. - switch (builtin.cpu.arch) { - .x86_64, .x86 => { - return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query); - }, - else => {}, - } - - switch (builtin.os.tag) { - .linux => return linux.detectNativeCpuAndFeatures(), - .macos => return darwin.macos.detectNativeCpuAndFeatures(), - .windows => return windows.detectNativeCpuAndFeatures(), - else => {}, - } - - // This architecture does not have CPU model & feature detection yet. - // See https://github.com/ziglang/zig/issues/4591 - return null; -} - -pub const Executor = union(enum) { - native, - rosetta, - qemu: []const u8, - wine: []const u8, - wasmtime: []const u8, - darling: []const u8, - bad_dl: []const u8, - bad_os_or_cpu, -}; - -pub const GetExternalExecutorOptions = struct { - allow_darling: bool = true, - allow_qemu: bool = true, - allow_rosetta: bool = true, - allow_wasmtime: bool = true, - allow_wine: bool = true, - qemu_fixes_dl: bool = false, - link_libc: bool = false, -}; - -/// Return whether or not the given host is capable of running executables of -/// the other target. -pub fn getExternalExecutor( - host: NativeTargetInfo, - candidate: *const NativeTargetInfo, - options: GetExternalExecutorOptions, -) Executor { - const os_match = host.target.os.tag == candidate.target.os.tag; - const cpu_ok = cpu_ok: { - if (host.target.cpu.arch == candidate.target.cpu.arch) - break :cpu_ok true; - - if (host.target.cpu.arch == .x86_64 and candidate.target.cpu.arch == .x86) - break :cpu_ok true; - - if (host.target.cpu.arch == .aarch64 and candidate.target.cpu.arch == .arm) - break :cpu_ok true; - - if (host.target.cpu.arch == .aarch64_be and candidate.target.cpu.arch == .armeb) - break :cpu_ok true; - - // TODO additionally detect incompatible CPU features. - // Note that in some cases the OS kernel will emulate missing CPU features - // when an illegal instruction is encountered. - - break :cpu_ok false; - }; - - var bad_result: Executor = .bad_os_or_cpu; - - if (os_match and cpu_ok) native: { - if (options.link_libc) { - if (candidate.dynamic_linker.get()) |candidate_dl| { - fs.cwd().access(candidate_dl, .{}) catch { - bad_result = .{ .bad_dl = candidate_dl }; - break :native; - }; - } - } - return .native; - } - - // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2 - // to emulate the foreign architecture. - if (options.allow_rosetta and os_match and - host.target.os.tag == .macos and host.target.cpu.arch == .aarch64) - { - switch (candidate.target.cpu.arch) { - .x86_64 => return .rosetta, - else => return bad_result, - } - } - - // If the OS matches, we can use QEMU to emulate a foreign architecture. - if (options.allow_qemu and os_match and (!cpu_ok or options.qemu_fixes_dl)) { - return switch (candidate.target.cpu.arch) { - .aarch64 => Executor{ .qemu = "qemu-aarch64" }, - .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, - .arm => Executor{ .qemu = "qemu-arm" }, - .armeb => Executor{ .qemu = "qemu-armeb" }, - .hexagon => Executor{ .qemu = "qemu-hexagon" }, - .x86 => Executor{ .qemu = "qemu-i386" }, - .m68k => Executor{ .qemu = "qemu-m68k" }, - .mips => Executor{ .qemu = "qemu-mips" }, - .mipsel => Executor{ .qemu = "qemu-mipsel" }, - .mips64 => Executor{ .qemu = "qemu-mips64" }, - .mips64el => Executor{ .qemu = "qemu-mips64el" }, - .powerpc => Executor{ .qemu = "qemu-ppc" }, - .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, - .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, - .riscv32 => Executor{ .qemu = "qemu-riscv32" }, - .riscv64 => Executor{ .qemu = "qemu-riscv64" }, - .s390x => Executor{ .qemu = "qemu-s390x" }, - .sparc => Executor{ .qemu = "qemu-sparc" }, - .sparc64 => Executor{ .qemu = "qemu-sparc64" }, - .x86_64 => Executor{ .qemu = "qemu-x86_64" }, - else => return bad_result, - }; - } - - switch (candidate.target.os.tag) { - .windows => { - if (options.allow_wine) { - // x86_64 wine does not support emulating aarch64-windows and - // vice versa. - if (candidate.target.cpu.arch != builtin.cpu.arch) { - return bad_result; - } - switch (candidate.target.ptrBitWidth()) { - 32 => return Executor{ .wine = "wine" }, - 64 => return Executor{ .wine = "wine64" }, - else => return bad_result, - } - } - return bad_result; - }, - .wasi => { - if (options.allow_wasmtime) { - switch (candidate.target.ptrBitWidth()) { - 32 => return Executor{ .wasmtime = "wasmtime" }, - else => return bad_result, - } - } - return bad_result; - }, - .macos => { - if (options.allow_darling) { - // This check can be loosened once darling adds a QEMU-based emulation - // layer for non-host architectures: - // https://github.com/darlinghq/darling/issues/863 - if (candidate.target.cpu.arch != builtin.cpu.arch) { - return bad_result; - } - return Executor{ .darling = "darling" }; - } - return bad_result; - }, - else => return bad_result, - } -} diff --git a/src/Compilation.zig b/src/Compilation.zig index 7831a5884008..0b275f97c116 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6527,7 +6527,6 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca try buffer.writer().print(" .{},\n", .{std.zig.fmtId(feature.name)}); } } - try buffer.writer().print( \\ }}), \\}}; @@ -6607,15 +6606,31 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca .{ windows.min, windows.max }, ), } - try buffer.appendSlice("};\n"); - - try buffer.writer().print( - \\pub const target = std.Target{{ + try buffer.appendSlice( + \\}; + \\pub const target: std.Target = .{ \\ .cpu = cpu, \\ .os = os, \\ .abi = abi, \\ .ofmt = object_format, - \\}}; + \\ + ); + + if (target.dynamic_linker.get()) |dl| { + try buffer.writer().print( + \\ .dynamic_linker = std.Target.DynamicLinker.init("{s}"), + \\}}; + \\ + , .{dl}); + } else { + try buffer.appendSlice( + \\ .dynamic_linker = std.Target.DynamicLinker.none, + \\}; + \\ + ); + } + + try buffer.writer().print( \\pub const object_format = std.Target.ObjectFormat.{}; \\pub const mode = std.builtin.OptimizeMode.{}; \\pub const link_libc = {}; diff --git a/src/main.zig b/src/main.zig index 17603acf2c8f..716be60763e7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -321,13 +321,14 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi } else if (mem.eql(u8, cmd, "init")) { return cmdInit(gpa, arena, cmd_args); } else if (mem.eql(u8, cmd, "targets")) { - const info = try detectNativeTargetInfo(.{}); + const host = try std.zig.system.resolveTargetQuery(.{}); const stdout = io.getStdOut().writer(); - return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, info.target); + return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host); } else if (mem.eql(u8, cmd, "version")) { try std.io.getStdOut().writeAll(build_options.version ++ "\n"); - // Check libc++ linkage to make sure Zig was built correctly, but only for "env" and "version" - // to avoid affecting the startup time for build-critical commands (check takes about ~10 μs) + // Check libc++ linkage to make sure Zig was built correctly, but only + // for "env" and "version" to avoid affecting the startup time for + // build-critical commands (check takes about ~10 μs) return verifyLibcxxCorrectlyLinked(); } else if (mem.eql(u8, cmd, "env")) { verifyLibcxxCorrectlyLinked(); @@ -2608,9 +2609,9 @@ fn buildOutputType( } const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options); - const target_info = try detectNativeTargetInfo(target_query); + const target = try std.zig.system.resolveTargetQuery(target_query); - if (target_info.target.os.tag != .freestanding) { + if (target.os.tag != .freestanding) { if (ensure_libc_on_non_freestanding) link_libc = true; if (ensure_libcpp_on_non_freestanding) @@ -2621,7 +2622,7 @@ fn buildOutputType( if (!force) { entry = null; } else if (entry == null and output_mode == .Exe) { - entry = switch (target_info.target.ofmt) { + entry = switch (target.ofmt) { .coff => "wWinMainCRTStartup", .macho => "_main", .elf, .plan9 => "_start", @@ -2629,12 +2630,12 @@ fn buildOutputType( else => |tag| fatal("No default entry point available for output format {s}", .{@tagName(tag)}), }; } - } else if (entry == null and target_info.target.isWasm() and output_mode == .Exe) { + } else if (entry == null and target.isWasm() and output_mode == .Exe) { // For WebAssembly the compiler defaults to setting the entry name when no flags are set. entry = defaultWasmEntryName(wasi_exec_model); } - if (target_info.target.ofmt == .coff) { + if (target.ofmt == .coff) { // Now that we know the target supports resources, // we can add the res files as link objects. for (res_files.items) |res_file| { @@ -2652,7 +2653,7 @@ fn buildOutputType( } } - if (target_info.target.cpu.arch.isWasm()) blk: { + if (target.cpu.arch.isWasm()) blk: { if (single_threaded == null) { single_threaded = true; } @@ -2678,8 +2679,8 @@ fn buildOutputType( fatal("shared memory is not allowed in object files", .{}); } - if (!target_info.target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.atomics)) or - !target_info.target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.bulk_memory))) + if (!target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.atomics)) or + !target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.bulk_memory))) { fatal("'atomics' and 'bulk-memory' features must be enabled to use shared memory", .{}); } @@ -2777,15 +2778,15 @@ fn buildOutputType( } for (system_libs.keys(), system_libs.values()) |lib_name, info| { - if (target_info.target.is_libc_lib_name(lib_name)) { + if (target.is_libc_lib_name(lib_name)) { link_libc = true; continue; } - if (target_info.target.is_libcpp_lib_name(lib_name)) { + if (target.is_libcpp_lib_name(lib_name)) { link_libcpp = true; continue; } - switch (target_util.classifyCompilerRtLibName(target_info.target, lib_name)) { + switch (target_util.classifyCompilerRtLibName(target, lib_name)) { .none => {}, .only_libunwind, .both => { link_libunwind = true; @@ -2797,8 +2798,8 @@ fn buildOutputType( }, } - if (target_info.target.isMinGW()) { - const exists = mingw.libExists(arena, target_info.target, zig_lib_directory, lib_name) catch |err| { + if (target.isMinGW()) { + const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| { fatal("failed to check zig installation for DLL import libs: {s}", .{ @errorName(err), }); @@ -2820,7 +2821,7 @@ fn buildOutputType( fatal("cannot use absolute path as a system library: {s}", .{lib_name}); } - if (target_info.target.os.tag == .wasi) { + if (target.os.tag == .wasi) { if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { try wasi_emulated_libs.append(crt_file); continue; @@ -2838,7 +2839,7 @@ fn buildOutputType( if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and (external_system_libs.len != 0 or want_native_include_dirs)) { - const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { + const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| { fatal("unable to detect native system paths: {s}", .{@errorName(err)}); }; for (paths.warnings.items) |warning| { @@ -2857,7 +2858,7 @@ fn buildOutputType( } if (builtin.target.os.tag == .windows and - target_info.target.abi == .msvc and + target.abi == .msvc and external_system_libs.len != 0) { if (libc_installation == null) { @@ -2902,7 +2903,7 @@ fn buildOutputType( &checked_paths, lib_dir_path, lib_name, - target_info.target, + target, info.preferred_mode, )) { const path = try arena.dupe(u8, test_path.items); @@ -2936,7 +2937,7 @@ fn buildOutputType( &checked_paths, lib_dir_path, lib_name, - target_info.target, + target, info.fallbackMode(), )) { const path = try arena.dupe(u8, test_path.items); @@ -2970,7 +2971,7 @@ fn buildOutputType( &checked_paths, lib_dir_path, lib_name, - target_info.target, + target, info.preferred_mode, )) { const path = try arena.dupe(u8, test_path.items); @@ -2994,7 +2995,7 @@ fn buildOutputType( &checked_paths, lib_dir_path, lib_name, - target_info.target, + target, info.fallbackMode(), )) { const path = try arena.dupe(u8, test_path.items); @@ -3089,15 +3090,13 @@ fn buildOutputType( } // After this point, resolved_frameworks is used instead of frameworks. - const object_format = target_info.target.ofmt; - - if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) { + if (output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) { const total_obj_count = c_source_files.items.len + @intFromBool(root_src_file != null) + rc_source_files.items.len + link_objects.items.len; if (total_obj_count > 1) { - fatal("{s} does not support linking multiple objects into one", .{@tagName(object_format)}); + fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)}); } } @@ -3110,7 +3109,7 @@ fn buildOutputType( const resolved_soname: ?[]const u8 = switch (soname) { .yes => |explicit| explicit, .no => null, - .yes_default_value => switch (object_format) { + .yes_default_value => switch (target.ofmt) { .elf => if (have_version) try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ root_name, version.major }) else @@ -3119,7 +3118,7 @@ fn buildOutputType( }, }; - const a_out_basename = switch (object_format) { + const a_out_basename = switch (target.ofmt) { .coff => "a.exe", else => "a.out", }; @@ -3141,7 +3140,7 @@ fn buildOutputType( }, .basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, - .target = target_info.target, + .target = target, .output_mode = output_mode, .link_mode = link_mode, .version = optional_version, @@ -3269,7 +3268,7 @@ fn buildOutputType( // Note that cmake when targeting Windows will try to execute // zig cc to make an executable and output an implib too. const implib_eligible = is_exe_or_dyn_lib and - emit_bin_loc != null and target_info.target.os.tag == .windows; + emit_bin_loc != null and target.os.tag == .windows; if (!implib_eligible) { if (!emit_implib_arg_provided) { emit_implib = .no; @@ -3419,7 +3418,7 @@ fn buildOutputType( // "-" is stdin. Dump it to a real file. const sep = fs.path.sep_str; const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{ - std.crypto.random.int(u64), ext.canonicalName(target_info.target), + std.crypto.random.int(u64), ext.canonicalName(target), }); try local_cache_directory.handle.makePath("tmp"); // Note that in one of the happy paths, execve() is used to switch @@ -3454,10 +3453,10 @@ fn buildOutputType( .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, .root_name = root_name, - .target = target_info.target, + .target = target, .is_native_os = target_query.isNativeOs(), .is_native_abi = target_query.isNativeAbi(), - .dynamic_linker = target_info.dynamic_linker.get(), + .dynamic_linker = target.dynamic_linker.get(), .sysroot = sysroot, .output_mode = output_mode, .main_mod = main_mod, @@ -3603,7 +3602,6 @@ fn buildOutputType( .want_structured_cfg = want_structured_cfg, }) catch |err| switch (err) { error.LibCUnavailable => { - const target = target_info.target; const triple_name = try target.zigTriple(arena); std.log.err("unable to find or provide libc for target '{s}'", .{triple_name}); @@ -3692,7 +3690,7 @@ fn buildOutputType( try comp.makeBinFileExecutable(); saveState(comp, debug_incremental); - if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: { + if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: { // Default to using `zig run` to execute the produced .c code from `zig test`. const c_code_loc = emit_bin_loc orelse break :default_exec_args; const c_code_directory = c_code_loc.directory orelse comp.bin_file.options.emit.?.directory; @@ -3707,7 +3705,7 @@ fn buildOutputType( if (link_libc) { try test_exec_args.append("-lc"); - } else if (target_info.target.os.tag == .windows) { + } else if (target.os.tag == .windows) { try test_exec_args.appendSlice(&.{ "--subsystem", "console", "-lkernel32", "-lntdll", @@ -3741,7 +3739,7 @@ fn buildOutputType( test_exec_args.items, self_exe_path.?, arg_mode, - &target_info, + &target, &comp_destroyed, all_args, runtime_args_start, @@ -3861,7 +3859,7 @@ fn serve( // test_exec_args, // self_exe_path.?, // arg_mode, - // target_info, + // target, // true, // &comp_destroyed, // all_args, @@ -4071,7 +4069,7 @@ fn runOrTest( test_exec_args: []const ?[]const u8, self_exe_path: []const u8, arg_mode: ArgMode, - target_info: *const std.zig.system.NativeTargetInfo, + target: *const std.Target, comp_destroyed: *bool, all_args: []const []const u8, runtime_args_start: ?usize, @@ -4105,7 +4103,7 @@ fn runOrTest( if (process.can_execv and arg_mode == .run) { // execv releases the locks; no need to destroy the Compilation here. const err = process.execve(gpa, argv.items, &env_map); - try warnAboutForeignBinaries(arena, arg_mode, target_info, link_libc); + try warnAboutForeignBinaries(arena, arg_mode, target, link_libc); const cmd = try std.mem.join(arena, " ", argv.items); fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd }); } else if (process.can_spawn) { @@ -4121,7 +4119,7 @@ fn runOrTest( comp_destroyed.* = true; const term = child.spawnAndWait() catch |err| { - try warnAboutForeignBinaries(arena, arg_mode, target_info, link_libc); + try warnAboutForeignBinaries(arena, arg_mode, target, link_libc); const cmd = try std.mem.join(arena, " ", argv.items); fatal("the following command failed with '{s}':\n{s}", .{ @errorName(err), cmd }); }; @@ -4820,12 +4818,10 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { if (!target_query.isNative()) { fatal("unable to detect libc for non-native target", .{}); } - const target_info = try detectNativeTargetInfo(target_query); - var libc = LibCInstallation.findNative(.{ .allocator = gpa, .verbose = true, - .target = target_info.target, + .target = try std.zig.system.resolveTargetQuery(target_query), }) catch |err| { fatal("unable to detect native libc: {s}", .{@errorName(err)}); }; @@ -5114,11 +5110,11 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi gimmeMoreOfThoseSweetSweetFileDescriptors(); const target_query: std.Target.Query = .{}; - const target_info = try detectNativeTargetInfo(target_query); + const target = try std.zig.system.resolveTargetQuery(target_query); const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", - .target = target_info.target, + .target = target, .output_mode = .Exe, }); const emit_bin: Compilation.EmitLoc = .{ @@ -5282,10 +5278,10 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, .root_name = "build", - .target = target_info.target, + .target = target, .is_native_os = target_query.isNativeOs(), .is_native_abi = target_query.isNativeAbi(), - .dynamic_linker = target_info.dynamic_linker.get(), + .dynamic_linker = target.dynamic_linker.get(), .output_mode = .Exe, .main_mod = &main_mod, .emit_bin = emit_bin, @@ -6269,10 +6265,6 @@ test "fds" { gimmeMoreOfThoseSweetSweetFileDescriptors(); } -fn detectNativeTargetInfo(target_query: std.Target.Query) !std.zig.system.NativeTargetInfo { - return std.zig.system.NativeTargetInfo.detect(target_query); -} - const usage_ast_check = \\Usage: zig ast-check [file] \\ @@ -6669,24 +6661,24 @@ fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 { fn warnAboutForeignBinaries( arena: Allocator, arg_mode: ArgMode, - target_info: *const std.zig.system.NativeTargetInfo, + target: *const std.Target, link_libc: bool, ) !void { const host_query: std.Target.Query = .{}; - const host_target_info = try detectNativeTargetInfo(host_query); + const host_target = try std.zig.system.resolveTargetQuery(host_query); - switch (host_target_info.getExternalExecutor(target_info, .{ .link_libc = link_libc })) { + switch (std.zig.system.getExternalExecutor(host_target, target, .{ .link_libc = link_libc })) { .native => return, .rosetta => { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); warn("the host system ({s}) does not appear to be capable of executing binaries from the target ({s}). Consider installing Rosetta.", .{ host_name, foreign_name, }); }, .qemu => |qemu| { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); switch (arg_mode) { .zig_test => warn( "the host system ({s}) does not appear to be capable of executing binaries " ++ @@ -6702,8 +6694,8 @@ fn warnAboutForeignBinaries( } }, .wine => |wine| { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); switch (arg_mode) { .zig_test => warn( "the host system ({s}) does not appear to be capable of executing binaries " ++ @@ -6719,8 +6711,8 @@ fn warnAboutForeignBinaries( } }, .wasmtime => |wasmtime| { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); switch (arg_mode) { .zig_test => warn( "the host system ({s}) does not appear to be capable of executing binaries " ++ @@ -6736,8 +6728,8 @@ fn warnAboutForeignBinaries( } }, .darling => |darling| { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); switch (arg_mode) { .zig_test => warn( "the host system ({s}) does not appear to be capable of executing binaries " ++ @@ -6753,7 +6745,7 @@ fn warnAboutForeignBinaries( } }, .bad_dl => |foreign_dl| { - const host_dl = host_target_info.dynamic_linker.get() orelse "(none)"; + const host_dl = host_target.dynamic_linker.get() orelse "(none)"; const tip_suffix = switch (arg_mode) { .zig_test => ", '--test-no-exec', or '--test-cmd'", else => "", @@ -6763,8 +6755,8 @@ fn warnAboutForeignBinaries( }); }, .bad_os_or_cpu => { - const host_name = try host_target_info.target.zigTriple(arena); - const foreign_name = try target_info.target.zigTriple(arena); + const host_name = try host_target.zigTriple(arena); + const foreign_name = try target.zigTriple(arena); const tip_suffix = switch (arg_mode) { .zig_test => ". Consider using '--test-no-exec' or '--test-cmd'", else => "", diff --git a/src/print_env.zig b/src/print_env.zig index 89c6ffe754bc..46ca10d14932 100644 --- a/src/print_env.zig +++ b/src/print_env.zig @@ -17,8 +17,8 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Wr const global_cache_dir = try introspect.resolveGlobalCacheDir(arena); - const info = try std.zig.system.NativeTargetInfo.detect(.{}); - const triple = try info.target.zigTriple(arena); + const host = try std.zig.system.resolveTargetQuery(.{}); + const triple = try host.zigTriple(arena); var bw = std.io.bufferedWriter(stdout); const w = bw.writer(); diff --git a/test/src/Cases.zig b/test/src/Cases.zig index de7378d10acd..0f2645f0e036 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -541,7 +541,7 @@ pub fn lowerToBuildSteps( cases_dir_path: []const u8, incremental_exe: *std.Build.Step.Compile, ) void { - const host = std.zig.system.NativeTargetInfo.detect(.{}) catch |err| + const host = std.zig.system.resolveTargetQuery(.{}) catch |err| std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)}); for (self.incremental_cases.items) |incr_case| { @@ -648,8 +648,7 @@ pub fn lowerToBuildSteps( }, .Execution => |expected_stdout| no_exec: { const run = if (case.target.target.ofmt == .c) run_step: { - const target_info = case.target.toNativeTargetInfo(); - if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(host, &case.target.target, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; } @@ -694,8 +693,7 @@ pub fn lowerToBuildSteps( continue; // Pass test. } - const target_info = case.target.toNativeTargetInfo(); - if (host.getExternalExecutor(&target_info, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(host, &case.target.target, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. continue; // Pass test. } @@ -1199,6 +1197,8 @@ const builtin = @import("builtin"); const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; +const getExternalExecutor = std.zig.system.getExternalExecutor; + const Compilation = @import("../../src/Compilation.zig"); const zig_h = @import("../../src/link.zig").File.C.zig_h; const introspect = @import("../../src/introspect.zig"); @@ -1386,18 +1386,15 @@ pub fn main() !void { } fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget { - const result = std.zig.system.NativeTargetInfo.detect(query) catch - @panic("unable to resolve target query"); - return .{ .query = query, - .target = result.target, - .dynamic_linker = result.dynamic_linker, + .target = std.zig.system.resolveTargetQuery(query) catch + @panic("unable to resolve target query"), }; } fn runCases(self: *Cases, zig_exe_path: []const u8) !void { - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const host = try std.zig.system.resolveTargetQuery(.{}); var progress = std.Progress{}; const root_node = progress.start("compiler", self.cases.items.len); @@ -1478,7 +1475,7 @@ fn runOneCase( zig_exe_path: []const u8, thread_pool: *ThreadPool, global_cache_directory: Compilation.Directory, - host: std.zig.system.NativeTargetInfo, + host: std.Target, ) !void { const tmp_src_path = "tmp.zig"; const enable_rosetta = build_options.enable_rosetta; @@ -1488,8 +1485,7 @@ fn runOneCase( const enable_darling = build_options.enable_darling; const glibc_runtimes_dir: ?[]const u8 = build_options.glibc_runtimes_dir; - const target_info = try std.zig.system.NativeTargetInfo.detect(case.target); - const target = target_info.target; + const target = try std.zig.system.resolveTargetQuery(case.target); var arena_allocator = std.heap.ArenaAllocator.init(allocator); defer arena_allocator.deinit(); @@ -1579,7 +1575,7 @@ fn runOneCase( .keep_source_files_loaded = true, .is_native_os = case.target.isNativeOs(), .is_native_abi = case.target.isNativeAbi(), - .dynamic_linker = target_info.dynamic_linker.get(), + .dynamic_linker = target.dynamic_linker.get(), .link_libc = case.link_libc, .use_llvm = use_llvm, .self_exe_path = zig_exe_path, @@ -1715,7 +1711,7 @@ fn runOneCase( .{ &tmp.sub_path, bin_name }, ); if (case.target.ofmt != null and case.target.ofmt.? == .c) { - if (host.getExternalExecutor(target_info, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(host, &target, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. continue :update; // Pass test. } @@ -1734,7 +1730,7 @@ fn runOneCase( if (zig_lib_directory.path) |p| { try argv.appendSlice(&.{ "-I", p }); } - } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) { + } else switch (getExternalExecutor(host, &target, .{ .link_libc = case.link_libc })) { .native => { if (case.backend == .stage2 and case.target.getCpuArch().isArmOrThumb()) { // https://github.com/ziglang/zig/issues/13623 From 8c44954bc6a91ae66f5aea92ea8380c28b50b3f0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 20:30:32 -0700 Subject: [PATCH 016/133] std.Target.Query: remove deprecated API These functions have been doomed for a long time. Finally I figured out what the proper relationship between this API and std.Target is. --- deps/aro/aro/Driver.zig | 9 +- lib/std/Build.zig | 136 +++------------- lib/std/Build/Module.zig | 4 +- lib/std/Target.zig | 13 +- lib/std/Target/Query.zig | 334 +++++++++++++++----------------------- lib/std/zig.zig | 46 +++++- lib/std/zig/system.zig | 29 +++- src/libc_installation.zig | 13 +- src/main.zig | 16 +- test/tests.zig | 48 +++--- 10 files changed, 275 insertions(+), 373 deletions(-) diff --git a/deps/aro/aro/Driver.zig b/deps/aro/aro/Driver.zig index 18a24b86a7ed..1738b14093cb 100644 --- a/deps/aro/aro/Driver.zig +++ b/deps/aro/aro/Driver.zig @@ -366,12 +366,15 @@ pub fn parseArgs( } else if (mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--assemble")) { d.only_preprocess_and_compile = true; } else if (option(arg, "--target=")) |triple| { - const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = triple }) catch { + const query = std.Target.Query.parse(.{ .arch_os_abi = triple }) catch { try d.comp.addDiagnostic(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{}); continue; }; - d.comp.target = cross.toTarget(); // TODO deprecated - d.comp.langopts.setEmulatedCompiler(target_util.systemCompiler(d.comp.target)); + const target = std.zig.system.resolveTargetQuery(query) catch |e| { + return d.fatal("unable to resolve target: {s}", .{errorDescription(e)}); + }; + d.comp.target = target; + d.comp.langopts.setEmulatedCompiler(target_util.systemCompiler(target)); d.raw_target_triple = triple; } else if (mem.eql(u8, arg, "--verbose-ast")) { d.verbose_ast = true; diff --git a/lib/std/Build.zig b/lib/std/Build.zig index cb5a503593ad..96b98b8583dc 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -383,12 +383,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption }) catch @panic("OOM"); user_input_options.put("cpu", .{ .name = "cpu", - .value = .{ - .scalar = if (v.isNativeCpu()) - "native" - else - serializeCpu(allocator, v.getCpu()) catch unreachable, - }, + .value = .{ .scalar = v.serializeCpuAlloc(allocator) catch @panic("OOM") }, .used = false, }) catch @panic("OOM"); }, @@ -400,12 +395,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption }) catch @panic("OOM"); user_input_options.put("cpu", .{ .name = "cpu", - .value = .{ - .scalar = if (v.query.isNativeCpu()) - "native" - else - serializeCpu(allocator, v.target.cpu) catch unreachable, - }, + .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") }, .used = false, }) catch @panic("OOM"); }, @@ -1196,7 +1186,6 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio pub const StandardTargetOptionsArgs = struct { whitelist: ?[]const Target.Query = null, - default_target: Target.Query = .{}, }; @@ -1208,13 +1197,13 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve } /// Exposes standard `zig build` options for choosing a target. -pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) Target.Query { - const maybe_triple = self.option( +pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query { + const maybe_triple = b.option( []const u8, "target", "The CPU architecture, OS, and ABI to build for", ); - const mcpu = self.option([]const u8, "cpu", "Target CPU features to add or subtract"); + const mcpu = b.option([]const u8, "cpu", "Target CPU features to add or subtract"); if (maybe_triple == null and mcpu == null) { return args.default_target; @@ -1236,7 +1225,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA for (diags.arch.?.allCpuModels()) |cpu| { log.err(" {s}", .{cpu.name}); } - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, error.UnknownCpuFeature => { @@ -1251,7 +1240,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA for (diags.arch.?.allFeaturesList()) |feature| { log.err(" {s}: {s}", .{ feature.name, feature.description }); } - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, error.UnknownOperatingSystem => { @@ -1263,80 +1252,35 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA inline for (std.meta.fields(Target.Os.Tag)) |field| { log.err(" {s}", .{field.name}); } - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, else => |e| { log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) }); - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, }; - const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch @panic("OOM"); - - if (args.whitelist) |list| whitelist_check: { - // Make sure it's a match of one of the list. - var mismatch_triple = true; - var mismatch_cpu_features = true; - var whitelist_item: Target.Query = .{}; - for (list) |t| { - mismatch_cpu_features = true; - mismatch_triple = true; - - const t_triple = t.zigTriple(self.allocator) catch @panic("OOM"); - if (mem.eql(u8, t_triple, selected_canonicalized_triple)) { - mismatch_triple = false; - whitelist_item = t; - if (t.getCpuFeatures().isSuperSetOf(selected_target.getCpuFeatures())) { - mismatch_cpu_features = false; - break :whitelist_check; - } else { - break; - } - } - } - if (mismatch_triple) { - log.err("Chosen target '{s}' does not match one of the supported targets:", .{ - selected_canonicalized_triple, - }); - for (list) |t| { - const t_triple = t.zigTriple(self.allocator) catch @panic("OOM"); - log.err(" {s}", .{t_triple}); - } - } else { - assert(mismatch_cpu_features); - const whitelist_cpu = whitelist_item.getCpu(); - const selected_cpu = selected_target.getCpu(); - log.err("Chosen CPU model '{s}' does not match one of the supported targets:", .{ - selected_cpu.model.name, - }); - log.err(" Supported feature Set: ", .{}); - const all_features = whitelist_cpu.arch.allFeaturesList(); - var populated_cpu_features = whitelist_cpu.model.features; - populated_cpu_features.populateDependencies(all_features); - for (all_features, 0..) |feature, i_usize| { - const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); - const in_cpu_set = populated_cpu_features.isEnabled(i); - if (in_cpu_set) { - log.err("{s} ", .{feature.name}); - } - } - log.err(" Remove: ", .{}); - for (all_features, 0..) |feature, i_usize| { - const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); - const in_cpu_set = populated_cpu_features.isEnabled(i); - const in_actual_set = selected_cpu.features.isEnabled(i); - if (in_actual_set and !in_cpu_set) { - log.err("{s} ", .{feature.name}); - } - } - } - self.markInvalidUserInput(); - return args.default_target; + const whitelist = args.whitelist orelse return selected_target; + + // Make sure it's a match of one of the list. + for (whitelist) |q| { + if (q.eql(selected_target)) + return selected_target; } - return selected_target; + for (whitelist) |q| { + log.info("allowed target: -Dtarget={s} -Dcpu={s}", .{ + q.zigTriple(b.allocator) catch @panic("OOM"), + q.serializeCpuAlloc(b.allocator) catch @panic("OOM"), + }); + } + log.err("chosen target '{s}' does not match one of the allowed targets", .{ + selected_target.zigTriple(b.allocator) catch @panic("OOM"), + }); + b.markInvalidUserInput(); + return args.default_target; } pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const u8) !bool { @@ -2064,34 +2008,6 @@ pub const InstalledFile = struct { } }; -pub fn serializeCpu(allocator: Allocator, cpu: Target.Cpu) ![]const u8 { - // TODO this logic can disappear if cpu model + features becomes part of the target triple - const all_features = cpu.arch.allFeaturesList(); - var populated_cpu_features = cpu.model.features; - populated_cpu_features.populateDependencies(all_features); - - if (populated_cpu_features.eql(cpu.features)) { - // The CPU name alone is sufficient. - return cpu.model.name; - } else { - var mcpu_buffer = ArrayList(u8).init(allocator); - try mcpu_buffer.appendSlice(cpu.model.name); - - for (all_features, 0..) |feature, i_usize| { - const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); - const in_cpu_set = populated_cpu_features.isEnabled(i); - const in_actual_set = cpu.features.isEnabled(i); - if (in_cpu_set and !in_actual_set) { - try mcpu_buffer.writer().print("-{s}", .{feature.name}); - } else if (!in_cpu_set and in_actual_set) { - try mcpu_buffer.writer().print("+{s}", .{feature.name}); - } - } - - return try mcpu_buffer.toOwnedSlice(); - } -} - /// This function is intended to be called in the `configure` phase only. /// It returns an absolute directory path, which is potentially going to be a /// source of API breakage in the future, so keep that in mind when using this diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 5482ca25ec12..9c98dd0a46e4 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -627,12 +627,12 @@ pub fn appendZigProcessFlags( try zig_args.append(@tagName(m.code_model)); } - if (m.target) |target| { + if (m.target) |*target| { // Communicate the query via CLI since it's more compact. if (!target.query.isNative()) { try zig_args.appendSlice(&.{ "-target", try target.query.zigTriple(b.allocator), - "-mcpu", try std.Build.serializeCpu(b.allocator, target.query.getCpu()), + "-mcpu", try target.query.serializeCpuAlloc(b.allocator), }); if (target.query.dynamic_linker.get()) |dynamic_linker| { diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 6f30aa75b17d..f8ce63b37fb8 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1394,7 +1394,7 @@ pub const Cpu = struct { } }; -pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 { +pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 { return Query.fromTarget(self).zigTriple(allocator); } @@ -1566,11 +1566,20 @@ pub const DynamicLinker = struct { pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void { if (dl_or_null) |dl| { @memcpy(self.buffer[0..dl.len], dl); - self.max_byte = @as(u8, @intCast(dl.len - 1)); + self.max_byte = @intCast(dl.len - 1); } else { self.max_byte = null; } } + + pub fn eql(a: DynamicLinker, b: DynamicLinker) bool { + const a_m = a.max_byte orelse return b.max_byte == null; + const b_m = b.max_byte orelse return false; + if (a_m != b_m) return false; + const a_s = a.buffer[0 .. a_m + 1]; + const b_s = b.buffer[0 .. a_m + 1]; + return std.mem.eql(u8, a_s, b_s); + } }; pub fn standardDynamicLinkerPath(target: Target) DynamicLinker { diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig index bb5949d597cc..1deff022cc39 100644 --- a/lib/std/Target/Query.zig +++ b/lib/std/Target/Query.zig @@ -51,12 +51,41 @@ pub const CpuModel = union(enum) { determined_by_cpu_arch, explicit: *const Target.Cpu.Model, + + pub fn eql(a: CpuModel, b: CpuModel) bool { + const Tag = @typeInfo(CpuModel).Union.tag_type.?; + const a_tag: Tag = a; + const b_tag: Tag = b; + if (a_tag != b_tag) return false; + return switch (a) { + .native, .baseline, .determined_by_cpu_arch => true, + .explicit => |a_model| a_model == b.explicit, + }; + } }; pub const OsVersion = union(enum) { none: void, semver: SemanticVersion, windows: Target.Os.WindowsVersion, + + pub fn eql(a: OsVersion, b: OsVersion) bool { + const Tag = @typeInfo(OsVersion).Union.tag_type.?; + const a_tag: Tag = a; + const b_tag: Tag = b; + if (a_tag != b_tag) return false; + return switch (a) { + .none => true, + .semver => |a_semver| a_semver.order(b.semver) == .eq, + .windows => |a_windows| a_windows == b.windows, + }; + } + + pub fn eqlOpt(a: ?OsVersion, b: ?OsVersion) bool { + if (a == null and b == null) return true; + if (a == null or b == null) return false; + return OsVersion.eql(a.?, b.?); + } }; pub const SemanticVersion = std.SemanticVersion; @@ -162,16 +191,6 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void { } } -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn toTarget(self: Query) Target { - return .{ - .cpu = self.getCpu(), - .os = self.getOs(), - .abi = self.getAbi(), - .ofmt = self.getObjectFormat(), - }; -} - pub const ParseOptions = struct { /// This is sometimes called a "triple". It looks roughly like this: /// riscv64-linux-musl @@ -240,7 +259,7 @@ pub fn parse(args: ParseOptions) !Query { result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse return error.UnknownArchitecture; } - const arch = result.getCpuArch(); + const arch = result.cpu_arch orelse builtin.cpu.arch; diags.arch = arch; if (it.next()) |os_text| { @@ -259,7 +278,7 @@ pub fn parse(args: ParseOptions) !Query { const abi_ver_text = abi_it.rest(); if (abi_it.next() != null) { - if (result.isGnuLibC()) { + if (Target.isGnuLibC_os_tag_abi(result.os_tag orelse builtin.os.tag, abi)) { result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) { error.Overflow => return error.InvalidAbiVersion, error.InvalidVersion => return error.InvalidAbiVersion, @@ -377,168 +396,6 @@ test parseVersion { try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); } -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn getCpu(self: Query) Target.Cpu { - switch (self.cpu_model) { - .native => { - // This works when doing `zig build` because Zig generates a build executable using - // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.resolveTargetQuery`. - return builtin.cpu; - }, - .baseline => { - var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch()); - self.updateCpuFeatures(&adjusted_baseline.features); - return adjusted_baseline; - }, - .determined_by_cpu_arch => if (self.cpu_arch == null) { - // This works when doing `zig build` because Zig generates a build executable using - // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.resolveTargetQuery`. - return builtin.cpu; - } else { - var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch()); - self.updateCpuFeatures(&adjusted_baseline.features); - return adjusted_baseline; - }, - .explicit => |model| { - var adjusted_model = model.toCpu(self.getCpuArch()); - self.updateCpuFeatures(&adjusted_model.features); - return adjusted_model; - }, - } -} - -pub fn getCpuArch(self: Query) Target.Cpu.Arch { - return self.cpu_arch orelse builtin.cpu.arch; -} - -pub fn getCpuModel(self: Query) *const Target.Cpu.Model { - return switch (self.cpu_model) { - .explicit => |cpu_model| cpu_model, - else => self.getCpu().model, - }; -} - -pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set { - return self.getCpu().features; -} - -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn getOs(self: Query) Target.Os { - // `builtin.os` works when doing `zig build` because Zig generates a build executable using - // native OS version range. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.resolveTargetQuery`. - var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os; - - if (self.os_version_min) |min| switch (min) { - .none => {}, - .semver => |semver| switch (self.getOsTag()) { - .linux => adjusted_os.version_range.linux.range.min = semver, - else => adjusted_os.version_range.semver.min = semver, - }, - .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver, - }; - - if (self.os_version_max) |max| switch (max) { - .none => {}, - .semver => |semver| switch (self.getOsTag()) { - .linux => adjusted_os.version_range.linux.range.max = semver, - else => adjusted_os.version_range.semver.max = semver, - }, - .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver, - }; - - if (self.glibc_version) |glibc| { - assert(self.isGnuLibC()); - adjusted_os.version_range.linux.glibc = glibc; - } - - return adjusted_os; -} - -pub fn getOsTag(self: Query) Target.Os.Tag { - return self.os_tag orelse builtin.os.tag; -} - -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn getOsVersionMin(self: Query) OsVersion { - if (self.os_version_min) |version_min| return version_min; - var tmp: Query = undefined; - tmp.updateOsVersionRange(self.getOs()); - return tmp.os_version_min.?; -} - -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn getOsVersionMax(self: Query) OsVersion { - if (self.os_version_max) |version_max| return version_max; - var tmp: Query = undefined; - tmp.updateOsVersionRange(self.getOs()); - return tmp.os_version_max.?; -} - -/// TODO deprecated, use `std.zig.system.resolveTargetQuery`. -pub fn getAbi(self: Query) Target.Abi { - if (self.abi) |abi| return abi; - - if (self.os_tag == null) { - // This works when doing `zig build` because Zig generates a build executable using - // native CPU model & features. However this will not be accurate otherwise, and - // will need to be integrated with `std.zig.system.resolveTargetQuery`. - return builtin.abi; - } - - return Target.Abi.default(self.getCpuArch(), self.getOs()); -} - -pub fn isFreeBSD(self: Query) bool { - return self.getOsTag() == .freebsd; -} - -pub fn isDarwin(self: Query) bool { - return self.getOsTag().isDarwin(); -} - -pub fn isNetBSD(self: Query) bool { - return self.getOsTag() == .netbsd; -} - -pub fn isOpenBSD(self: Query) bool { - return self.getOsTag() == .openbsd; -} - -pub fn isUefi(self: Query) bool { - return self.getOsTag() == .uefi; -} - -pub fn isDragonFlyBSD(self: Query) bool { - return self.getOsTag() == .dragonfly; -} - -pub fn isLinux(self: Query) bool { - return self.getOsTag() == .linux; -} - -pub fn isWindows(self: Query) bool { - return self.getOsTag() == .windows; -} - -pub fn exeFileExt(self: Query) [:0]const u8 { - return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); -} - -pub fn staticLibSuffix(self: Query) [:0]const u8 { - return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi()); -} - -pub fn dynamicLibSuffix(self: Query) [:0]const u8 { - return self.getOsTag().dynamicLibSuffix(); -} - -pub fn libPrefix(self: Query) [:0]const u8 { - return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi()); -} - pub fn isNativeCpu(self: Query) bool { return self.cpu_arch == null and (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and @@ -568,7 +425,7 @@ fn formatVersion(version: SemanticVersion, writer: anytype) !void { } } -pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 { +pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { if (self.isNative()) { return allocator.dupe(u8, "native"); } @@ -583,14 +440,16 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 // The zig target syntax does not allow specifying a max os version with no min, so // if either are present, we need the min. - if (self.os_version_min != null or self.os_version_max != null) { - switch (self.getOsVersionMin()) { + if (self.os_version_min) |min| { + switch (min) { .none => {}, .semver => |v| { try result.writer().writeAll("."); try formatVersion(v, result.writer()); }, - .windows => |v| try result.writer().print("{s}", .{v}), + .windows => |v| { + try result.writer().print("{s}", .{v}); + }, } } if (self.os_version_max) |max| { @@ -600,48 +459,88 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 try result.writer().writeAll("..."); try formatVersion(v, result.writer()); }, - .windows => |v| try result.writer().print("..{s}", .{v}), + .windows => |v| { + try result.writer().print("...{s}", .{v}); + }, } } if (self.glibc_version) |v| { - try result.writer().print("-{s}.", .{@tagName(self.getAbi())}); + const name = @tagName(self.abi orelse builtin.target.abi); + try result.ensureUnusedCapacity(name.len + 2); + result.appendAssumeCapacity('-'); + result.appendSliceAssumeCapacity(name); + result.appendAssumeCapacity('.'); try formatVersion(v, result.writer()); } else if (self.abi) |abi| { - try result.writer().print("-{s}", .{@tagName(abi)}); + const name = @tagName(abi); + try result.ensureUnusedCapacity(name.len + 1); + result.appendAssumeCapacity('-'); + result.appendSliceAssumeCapacity(name); } return result.toOwnedSlice(); } -pub fn allocDescription(self: Query, allocator: mem.Allocator) ![]u8 { - // TODO is there anything else worthy of the description that is not - // already captured in the triple? - return self.zigTriple(allocator); -} +/// Renders the query into a textual representation that can be parsed via the +/// `-mcpu` flag passed to the Zig compiler. +/// Appends the result to `buffer`. +pub fn serializeCpu(q: Query, buffer: *std.ArrayList(u8)) Allocator.Error!void { + try buffer.ensureUnusedCapacity(8); + switch (q.cpu_model) { + .native => { + buffer.appendSliceAssumeCapacity("native"); + }, + .baseline => { + buffer.appendSliceAssumeCapacity("baseline"); + }, + .determined_by_cpu_arch => { + if (q.cpu_arch == null) { + buffer.appendSliceAssumeCapacity("native"); + } else { + buffer.appendSliceAssumeCapacity("baseline"); + } + }, + .explicit => |model| { + try buffer.appendSlice(model.name); + }, + } -pub fn linuxTriple(self: Query, allocator: mem.Allocator) ![]u8 { - return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); -} + if (q.cpu_features_add.isEmpty() and q.cpu_features_sub.isEmpty()) { + // The CPU name alone is sufficient. + return; + } -pub fn isGnuLibC(self: Query) bool { - return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); + const cpu_arch = q.cpu_arch orelse builtin.cpu.arch; + const all_features = cpu_arch.allFeaturesList(); + + for (all_features, 0..) |feature, i_usize| { + const i: Target.Cpu.Feature.Set.Index = @intCast(i_usize); + try buffer.ensureUnusedCapacity(feature.name.len + 1); + if (q.cpu_features_sub.isEnabled(i)) { + buffer.appendAssumeCapacity('-'); + buffer.appendSliceAssumeCapacity(feature.name); + } else if (q.cpu_features_add.isEnabled(i)) { + buffer.appendAssumeCapacity('+'); + buffer.appendSliceAssumeCapacity(feature.name); + } + } } -pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { - assert(self.isGnuLibC()); - self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; +pub fn serializeCpuAlloc(q: Query, ally: Allocator) Allocator.Error![]u8 { + var buffer = std.ArrayList(u8).init(ally); + try serializeCpu(q, &buffer); + return buffer.toOwnedSlice(); } -pub fn getObjectFormat(self: Query) Target.ObjectFormat { - return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); +pub fn allocDescription(self: Query, allocator: Allocator) ![]u8 { + // TODO is there anything else worthy of the description that is not + // already captured in the triple? + return self.zigTriple(allocator); } -pub fn updateCpuFeatures(self: Query, set: *Target.Cpu.Feature.Set) void { - set.removeFeatureSet(self.cpu_features_sub); - set.addFeatureSet(self.cpu_features_add); - set.populateDependencies(self.getCpuArch().allFeaturesList()); - set.removeFeatureSet(self.cpu_features_sub); +pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { + self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; } fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !void { @@ -653,7 +552,7 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) ! result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse return error.UnknownOperatingSystem; } - const tag = result.getOsTag(); + const tag = result.os_tag orelse builtin.os.tag; diags.os_tag = tag; const version_text = it.rest(); @@ -741,12 +640,35 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) ! } } +pub fn eql(a: Query, b: Query) bool { + if (a.cpu_arch != b.cpu_arch) return false; + if (!a.cpu_model.eql(b.cpu_model)) return false; + if (!a.cpu_features_add.eql(b.cpu_features_add)) return false; + if (!a.cpu_features_sub.eql(b.cpu_features_sub)) return false; + if (a.os_tag != b.os_tag) return false; + if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false; + if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false; + if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false; + if (a.abi != b.abi) return false; + if (!a.dynamic_linker.eql(b.dynamic_linker)) return false; + if (a.ofmt != b.ofmt) return false; + + return true; +} + +fn versionEqualOpt(a: ?SemanticVersion, b: ?SemanticVersion) bool { + if (a == null and b == null) return true; + if (a == null or b == null) return false; + return SemanticVersion.order(a.?, b.?) == .eq; +} + const Query = @This(); const std = @import("../std.zig"); const builtin = @import("builtin"); const assert = std.debug.assert; const Target = std.Target; const mem = std.mem; +const Allocator = std.mem.Allocator; test parse { if (builtin.target.isGnuLibC()) { @@ -760,7 +682,7 @@ test parse { const triple = std.fmt.bufPrint( buf[0..], "native-native-{s}.2.1.1", - .{@tagName(builtin.abi)}, + .{@tagName(builtin.target.abi)}, ) catch unreachable; try std.testing.expectEqualSlices(u8, triple, text); @@ -789,7 +711,7 @@ test parse { .arch_os_abi = "x86_64-linux-gnu", .cpu_features = "x86_64-sse-sse2-avx-cx8", }); - const target = query.toTarget(); + const target = try std.zig.system.resolveTargetQuery(query); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .gnu); @@ -814,7 +736,7 @@ test parse { .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }); - const target = query.toTarget(); + const target = try std.zig.system.resolveTargetQuery(query); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .musleabihf); @@ -831,7 +753,7 @@ test parse { .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", .cpu_features = "generic+v8a", }); - const target = query.toTarget(); + const target = try std.zig.system.resolveTargetQuery(query); try std.testing.expect(target.cpu.arch == .aarch64); try std.testing.expect(target.os.tag == .linux); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 481768bfb237..84feb2cf0a4b 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -1,7 +1,4 @@ -const std = @import("std.zig"); -const tokenizer = @import("zig/tokenizer.zig"); pub const fmt = @import("zig/fmt.zig"); -const assert = std.debug.assert; pub const ErrorBundle = @import("zig/ErrorBundle.zig"); pub const Server = @import("zig/Server.zig"); @@ -115,7 +112,7 @@ pub const BinNameOptions = struct { }; /// Returns the standard file system basename of a binary generated by the Zig compiler. -pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 { +pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 { const root_name = options.root_name; const target = options.target; switch (target.ofmt) { @@ -281,6 +278,47 @@ pub const BuildId = union(enum) { } }; +/// Renders a `std.Target.Cpu` value into a textual representation that can be parsed +/// via the `-mcpu` flag passed to the Zig compiler. +/// Appends the result to `buffer`. +pub fn serializeCpu(buffer: *std.ArrayList(u8), cpu: std.Target.Cpu) Allocator.Error!void { + const all_features = cpu.arch.allFeaturesList(); + var populated_cpu_features = cpu.model.features; + populated_cpu_features.populateDependencies(all_features); + + try buffer.appendSlice(cpu.model.name); + + if (populated_cpu_features.eql(cpu.features)) { + // The CPU name alone is sufficient. + return; + } + + for (all_features, 0..) |feature, i_usize| { + const i: std.Target.Cpu.Feature.Set.Index = @intCast(i_usize); + const in_cpu_set = populated_cpu_features.isEnabled(i); + const in_actual_set = cpu.features.isEnabled(i); + try buffer.ensureUnusedCapacity(feature.name.len + 1); + if (in_cpu_set and !in_actual_set) { + buffer.appendAssumeCapacity('-'); + buffer.appendSliceAssumeCapacity(feature.name); + } else if (!in_cpu_set and in_actual_set) { + buffer.appendAssumeCapacity('+'); + buffer.appendSliceAssumeCapacity(feature.name); + } + } +} + +pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![]u8 { + var buffer = std.ArrayList(u8).init(ally); + try serializeCpu(&buffer, cpu); + return buffer.toOwnedSlice(); +} + +const std = @import("std.zig"); +const tokenizer = @import("zig/tokenizer.zig"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; + test { @import("std").testing.refAllDecls(@This()); } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 6920999ef06d..c2a9fa4f9fe3 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -163,7 +163,8 @@ pub const DetectError = error{ /// components by detecting the native system, and then resolves /// standard/default parts relative to that. pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { - var os = query.getOsTag().defaultVersionRange(query.getCpuArch()); + const query_os_tag = query.os_tag orelse builtin.os.tag; + var os = query_os_tag.defaultVersionRange(query.cpu_arch orelse builtin.cpu.arch); if (query.os_tag == null) { switch (builtin.target.os.tag) { .linux => { @@ -292,7 +293,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { if (query.os_version_min) |min| switch (min) { .none => {}, - .semver => |semver| switch (query.getOsTag()) { + .semver => |semver| switch (os.tag) { .linux => os.version_range.linux.range.min = semver, else => os.version_range.semver.min = semver, }, @@ -301,7 +302,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { if (query.os_version_max) |max| switch (max) { .none => {}, - .semver => |semver| switch (query.getOsTag()) { + .semver => |semver| switch (os.tag) { .linux => os.version_range.linux.range.max = semver, else => os.version_range.semver.max = semver, }, @@ -309,13 +310,12 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { }; if (query.glibc_version) |glibc| { - assert(query.isGnuLibC()); os.version_range.linux.glibc = glibc; } // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the // native CPU architecture as being different than the current target), we use this: - const cpu_arch = query.getCpuArch(); + const cpu_arch = query.cpu_arch orelse builtin.cpu.arch; const cpu = switch (query.cpu_model) { .native => detectNativeCpuAndFeatures(cpu_arch, os, query), @@ -361,10 +361,27 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { }, else => {}, } - query.updateCpuFeatures(&result.cpu.features); + updateCpuFeatures( + &result.cpu.features, + cpu_arch.allFeaturesList(), + query.cpu_features_add, + query.cpu_features_sub, + ); return result; } +fn updateCpuFeatures( + set: *Target.Cpu.Feature.Set, + all_features_list: []const Target.Cpu.Feature, + add_set: Target.Cpu.Feature.Set, + sub_set: Target.Cpu.Feature.Set, +) void { + set.removeFeatureSet(sub_set); + set.addFeatureSet(add_set); + set.populateDependencies(all_features_list); + set.removeFeatureSet(sub_set); +} + fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, // although it is a runtime value, is guaranteed to be one of the architectures in the set diff --git a/src/libc_installation.zig b/src/libc_installation.zig index facb16257e61..0901194dd83a 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -41,7 +41,7 @@ pub const LibCInstallation = struct { pub fn parse( allocator: Allocator, libc_file: []const u8, - target: std.Target.Query, + target: std.Target, ) !LibCInstallation { var self: LibCInstallation = .{}; @@ -95,24 +95,23 @@ pub const LibCInstallation = struct { return error.ParseError; } - const os_tag = target.getOsTag(); + const os_tag = target.os.tag; if (self.crt_dir == null and !target.isDarwin()) { log.err("crt_dir may not be empty for {s}\n", .{@tagName(os_tag)}); return error.ParseError; } - const abi = target.getAbi(); - if (self.msvc_lib_dir == null and target.isWindows() and abi == .msvc) { + if (self.msvc_lib_dir == null and os_tag == .windows and target.abi == .msvc) { log.err("msvc_lib_dir may not be empty for {s}-{s}\n", .{ @tagName(os_tag), - @tagName(abi), + @tagName(target.abi), }); return error.ParseError; } - if (self.kernel32_lib_dir == null and target.isWindows() and abi == .msvc) { + if (self.kernel32_lib_dir == null and os_tag == .windows and target.abi == .msvc) { log.err("kernel32_lib_dir may not be empty for {s}-{s}\n", .{ @tagName(os_tag), - @tagName(abi), + @tagName(target.abi), }); return error.ParseError; } diff --git a/src/main.zig b/src/main.zig index 716be60763e7..3abe6ed3e41f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2696,13 +2696,13 @@ fn buildOutputType( } if (use_lld) |opt| { - if (opt and target_query.isDarwin()) { + if (opt and target.isDarwin()) { fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{}); } } if (want_lto) |opt| { - if (opt and target_query.isDarwin()) { + if (opt and target.isDarwin()) { fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{}); } } @@ -2772,7 +2772,7 @@ fn buildOutputType( var libc_installation: ?LibCInstallation = null; if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, target_query) catch |err| { + libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); }; } @@ -2865,7 +2865,7 @@ fn buildOutputType( libc_installation = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, - .target = target_query.toTarget(), + .target = target, }); try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? }); @@ -4755,6 +4755,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { const target_query = try parseTargetQueryOrReportFatalError(gpa, .{ .arch_os_abi = target_arch_os_abi, }); + const target = try std.zig.system.resolveTargetQuery(target_query); if (print_includes) { var arena_state = std.heap.ArenaAllocator.init(gpa); @@ -4764,7 +4765,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { const libc_installation: ?*LibCInstallation = libc: { if (input_file) |libc_file| { const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.parse(arena, libc_file, target_query) catch |err| { + libc.* = LibCInstallation.parse(arena, libc_file, target) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; break :libc libc; @@ -4779,7 +4780,6 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { }; defer zig_lib_directory.handle.close(); - const target = target_query.toTarget(); const is_native_abi = target_query.isNativeAbi(); const libc_dirs = Compilation.detectLibCIncludeDirs( @@ -4810,7 +4810,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } if (input_file) |libc_file| { - var libc = LibCInstallation.parse(gpa, libc_file, target_query) catch |err| { + var libc = LibCInstallation.parse(gpa, libc_file, target) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; defer libc.deinit(gpa); @@ -4821,7 +4821,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { var libc = LibCInstallation.findNative(.{ .allocator = gpa, .verbose = true, - .target = try std.zig.system.resolveTargetQuery(target_query), + .target = target, }) catch |err| { fatal("unable to detect native libc: {s}", .{@errorName(err)}); }; diff --git a/test/tests.zig b/test/tests.zig index 29d181c60522..64c0f3a42e8c 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1036,14 +1036,17 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { for (test_targets) |test_target| { const is_native = test_target.target.isNative() or - (test_target.target.getOsTag() == builtin.os.tag and - test_target.target.getCpuArch() == builtin.cpu.arch); + (test_target.target.os_tag == builtin.os.tag and + test_target.target.cpu_arch == builtin.cpu.arch); if (options.skip_non_native and !is_native) continue; + const resolved_target = b.resolveTargetQuery(test_target.target); + const target = resolved_target.target; + if (options.skip_cross_glibc and !test_target.target.isNative() and - test_target.target.isGnuLibC() and test_target.link_libc == true) + target.isGnuLibC() and test_target.link_libc == true) continue; if (options.skip_libc and test_target.link_libc == true) @@ -1053,35 +1056,30 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { continue; // TODO get compiler-rt tests passing for self-hosted backends. - if ((test_target.target.getCpuArch() != .x86_64 or - test_target.target.getObjectFormat() != .elf) and + if ((target.cpu.arch != .x86_64 or target.ofmt != .elf) and test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt")) continue; // TODO get compiler-rt tests passing for wasm32-wasi // currently causes "LLVM ERROR: Unable to expand fixed point multiplication." - if (test_target.target.getCpuArch() == .wasm32 and - test_target.target.getOsTag() == .wasi and + if (target.cpu.arch == .wasm32 and target.os.tag == .wasi and mem.eql(u8, options.name, "compiler-rt")) { continue; } // TODO get universal-libc tests passing for other self-hosted backends. - if (test_target.target.getCpuArch() != .x86_64 and + if (target.cpu.arch != .x86_64 and test_target.use_llvm == false and mem.eql(u8, options.name, "universal-libc")) continue; // TODO get std lib tests passing for other self-hosted backends. - if ((test_target.target.getCpuArch() != .x86_64 or - test_target.target.getOsTag() != .linux) and + if ((target.cpu.arch != .x86_64 or target.os.tag != .linux) and test_target.use_llvm == false and mem.eql(u8, options.name, "std")) continue; - if (test_target.target.getCpuArch() == .x86_64 and - test_target.target.getOsTag() == .windows and - test_target.target.cpu_arch == null and - test_target.optimize_mode != .Debug and + if (target.cpu.arch == .x86_64 and target.os.tag == .windows and + test_target.target.cpu_arch == null and test_target.optimize_mode != .Debug and mem.eql(u8, options.name, "std")) { // https://github.com/ziglang/zig/issues/17902 @@ -1094,11 +1092,11 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { if (!want_this_mode) continue; const libc_suffix = if (test_target.link_libc == true) "-libc" else ""; - const triple_txt = test_target.target.zigTriple(b.allocator) catch @panic("OOM"); - const model_txt = test_target.target.getCpuModel().name; + const triple_txt = target.zigTriple(b.allocator) catch @panic("OOM"); + const model_txt = target.cpu.model.name; // wasm32-wasi builds need more RAM, idk why - const max_rss = if (test_target.target.getOs().tag == .wasi) + const max_rss = if (target.os.tag == .wasi) options.max_rss * 2 else options.max_rss; @@ -1106,7 +1104,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const these_tests = b.addTest(.{ .root_source_file = .{ .path = options.root_src }, .optimize = test_target.optimize_mode, - .target = b.resolveTargetQuery(test_target.target), + .target = resolved_target, .max_rss = max_rss, .filter = options.test_filter, .link_libc = test_target.link_libc, @@ -1120,7 +1118,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else ""; const backend_suffix = if (test_target.use_llvm == true) "-llvm" - else if (test_target.target.ofmt == std.Target.ObjectFormat.c) + else if (target.ofmt == std.Target.ObjectFormat.c) "-cbe" else if (test_target.use_llvm == false) "-selfhosted" @@ -1131,7 +1129,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { these_tests.addIncludePath(.{ .path = "test" }); - if (test_target.target.getOs().tag == .wasi) { + if (target.os.tag == .wasi) { // WASI's default stack size can be too small for some big tests. these_tests.stack_size = 2 * 1024 * 1024; } @@ -1148,14 +1146,14 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { use_pic, }); - if (test_target.target.ofmt == std.Target.ObjectFormat.c) { - var altered_target = test_target.target; - altered_target.ofmt = null; + if (target.ofmt == std.Target.ObjectFormat.c) { + var altered_query = test_target.target; + altered_query.ofmt = null; const compile_c = b.addExecutable(.{ .name = qualified_name, .link_libc = test_target.link_libc, - .target = b.resolveTargetQuery(altered_target), + .target = b.resolveTargetQuery(altered_query), .zig_lib_dir = .{ .path = "lib" }, }); compile_c.addCSourceFile(.{ @@ -1179,7 +1177,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { }, }); compile_c.addIncludePath(.{ .path = "lib" }); // for zig.h - if (test_target.target.getOsTag() == .windows) { + if (target.os.tag == .windows) { if (true) { // Unfortunately this requires about 8G of RAM for clang to compile // and our Windows CI runners do not have this much. From 3e52302644e29fec3917385f2b998f53941f8376 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 20:38:09 -0700 Subject: [PATCH 017/133] std.Build: fix userInputOptionsFromArgs ResolvedTarget it wasn't using the Target.Query like it was supposed to for the triple --- lib/std/Build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 96b98b8583dc..da2bb49397d8 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -390,7 +390,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption ResolvedTarget => { user_input_options.put(field.name, .{ .name = field.name, - .value = .{ .scalar = v.target.zigTriple(allocator) catch @panic("OOM") }, + .value = .{ .scalar = v.query.zigTriple(allocator) catch @panic("OOM") }, .used = false, }) catch @panic("OOM"); user_input_options.put("cpu", .{ From ce94c28e53e706e506d4c95c25c8bf99e7a597eb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 20:46:26 -0700 Subject: [PATCH 018/133] resinator: update std.Target.Query usage --- src/main.zig | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 3abe6ed3e41f..121b7515a81d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4664,8 +4664,11 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: while (true) { switch (cur_includes) { .any, .msvc => { - const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable; - const target = target_query.toTarget(); + const target_query: std.Target.Query = .{ + .os_tag = .windows, + .abi = .msvc, + }; + const target = try std.zig.system.resolveTargetQuery(target_query); const is_native_abi = target_query.isNativeAbi(); const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| { if (cur_includes == .any) { @@ -4689,8 +4692,11 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: }; }, .gnu => { - const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable; - const target = target_query.toTarget(); + const target_query: std.Target.Query = .{ + .os_tag = .windows, + .abi = .gnu, + }; + const target = try std.zig.system.resolveTargetQuery(target_query); const is_native_abi = target_query.isNativeAbi(); const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null); return .{ From 77420af9d01b1932a583fdcbfa169f2eb2b7c221 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 21:56:29 -0700 Subject: [PATCH 019/133] compiler: get the dynamic linker from the target instead of passing it to Compilation separately and storing it separately in the linker options. --- src/Compilation.zig | 4 +--- src/link.zig | 1 - src/link/Elf.zig | 24 ++++++++++++------------ src/main.zig | 2 -- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 0b275f97c116..4f65dc22f2fc 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -803,7 +803,6 @@ pub const InitOptions = struct { main_mod: ?*Package.Module, output_mode: std.builtin.OutputMode, thread_pool: *ThreadPool, - dynamic_linker: ?[]const u8 = null, sysroot: ?[]const u8 = null, /// `null` means to not emit a binary file. emit_bin: ?EmitLoc, @@ -1836,7 +1835,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .root_name = root_name, .module = module, .target = options.target, - .dynamic_linker = options.dynamic_linker, .sysroot = sysroot, .output_mode = options.output_mode, .link_mode = link_mode, @@ -2800,7 +2798,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptionalBytes(libc_installation.kernel32_lib_dir); } } - man.hash.addOptionalBytes(comp.bin_file.options.dynamic_linker); + man.hash.addOptionalBytes(target.dynamic_linker.get()); } man.hash.addOptionalBytes(comp.bin_file.options.soname); man.hash.addOptional(comp.bin_file.options.version); diff --git a/src/link.zig b/src/link.zig index 09669f4dbedc..1ad66eaf7aff 100644 --- a/src/link.zig +++ b/src/link.zig @@ -103,7 +103,6 @@ pub const Options = struct { root_name: [:0]const u8, /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. module: ?*Module, - dynamic_linker: ?[]const u8, /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) sysroot: ?[]const u8, /// Used for calculating how much space to reserve for symbols in case the binary file diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d52a5fa423a5..6f3c59c4e74e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1574,7 +1574,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } else { if (!self.isStatic()) { - if (self.base.options.dynamic_linker) |path| { + if (self.base.options.target.dynamic_linker.get()) |path| { try argv.append("-dynamic-linker"); try argv.append(path); } @@ -2374,7 +2374,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addBytes(libc_installation.crt_dir.?); } if (have_dynamic_linker) { - man.hash.addOptionalBytes(self.base.options.dynamic_linker); + man.hash.addOptionalBytes(self.base.options.target.dynamic_linker.get()); } } man.hash.addOptionalBytes(self.base.options.soname); @@ -2687,7 +2687,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } if (have_dynamic_linker) { - if (self.base.options.dynamic_linker) |dynamic_linker| { + if (self.base.options.target.dynamic_linker.get()) |dynamic_linker| { try argv.append("-dynamic-linker"); try argv.append(dynamic_linker); } @@ -3503,7 +3503,7 @@ fn initSyntheticSections(self: *Elf) !void { // a segfault in the dynamic linker trying to load a binary that is static // and doesn't contain .dynamic section. if (self.isStatic() and !self.base.options.pie) break :blk false; - break :blk self.base.options.dynamic_linker != null; + break :blk self.base.options.target.dynamic_linker.get() != null; }; if (needs_interp) { self.interp_section_index = try self.addSection(.{ @@ -4244,7 +4244,7 @@ fn updateSectionSizes(self: *Elf) !void { } if (self.interp_section_index) |index| { - self.shdrs.items[index].sh_size = self.base.options.dynamic_linker.?.len + 1; + self.shdrs.items[index].sh_size = self.base.options.target.dynamic_linker.get().?.len + 1; } if (self.hash_section_index) |index| { @@ -4938,14 +4938,14 @@ fn writeSyntheticSections(self: *Elf) !void { const gpa = self.base.allocator; if (self.interp_section_index) |shndx| { + var buffer: [256]u8 = undefined; + const interp = self.base.options.target.dynamic_linker.get().?; + @memcpy(buffer[0..interp.len], interp); + buffer[interp.len] = 0; + const contents = buffer[0 .. interp.len + 1]; const shdr = self.shdrs.items[shndx]; - const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; - var buffer = try gpa.alloc(u8, sh_size); - defer gpa.free(buffer); - const dylinker = self.base.options.dynamic_linker.?; - @memcpy(buffer[0..dylinker.len], dylinker); - buffer[dylinker.len] = 0; - try self.base.file.?.pwriteAll(buffer, shdr.sh_offset); + assert(shdr.sh_size == contents.len); + try self.base.file.?.pwriteAll(contents, shdr.sh_offset); } if (self.hash_section_index) |shndx| { diff --git a/src/main.zig b/src/main.zig index 121b7515a81d..681833857b97 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3456,7 +3456,6 @@ fn buildOutputType( .target = target, .is_native_os = target_query.isNativeOs(), .is_native_abi = target_query.isNativeAbi(), - .dynamic_linker = target.dynamic_linker.get(), .sysroot = sysroot, .output_mode = output_mode, .main_mod = main_mod, @@ -5287,7 +5286,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .target = target, .is_native_os = target_query.isNativeOs(), .is_native_abi = target_query.isNativeAbi(), - .dynamic_linker = target.dynamic_linker.get(), .output_mode = .Exe, .main_mod = &main_mod, .emit_bin = emit_bin, From 8d5da5558827d9152dc8453c87c41ac6519f8a05 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 23:15:53 -0700 Subject: [PATCH 020/133] std.Target.Query: fix regression with windows os version range somebody left a landmine here without even a comment to warn about it --- lib/std/Target/Query.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig index 1deff022cc39..10130e03bba6 100644 --- a/lib/std/Target/Query.zig +++ b/lib/std/Target/Query.zig @@ -460,7 +460,9 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { try formatVersion(v, result.writer()); }, .windows => |v| { - try result.writer().print("...{s}", .{v}); + // This is counting on a custom format() function defined on `WindowsVersion` + // to add a prefix '.' and make there be a total of three dots. + try result.writer().print("..{s}", .{v}); }, } } From f5613a0e3589fcca51411ce379f3c90eace99fa6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 4 Dec 2023 23:16:42 -0700 Subject: [PATCH 021/133] update docgen for std Target.Query API breaks --- tools/docgen.zig | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tools/docgen.zig b/tools/docgen.zig index 669f6bca8d5d..1003db0b5ac2 100644 --- a/tools/docgen.zig +++ b/tools/docgen.zig @@ -9,13 +9,12 @@ const print = std.debug.print; const mem = std.mem; const testing = std.testing; const Allocator = std.mem.Allocator; +const getExternalExecutor = std.zig.system.getExternalExecutor; const max_doc_file_size = 10 * 1024 * 1024; -const exe_ext = @as(std.zig.CrossTarget, .{}).exeFileExt(); const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); const tmp_dir_name = "docgen_tmp"; -const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext; const usage = \\Usage: docgen [--zig] [--skip-code-tests] input output" @@ -1309,7 +1308,7 @@ fn genHtml( var env_map = try process.getEnvMap(allocator); try env_map.put("YES_COLOR", "1"); - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const host = try std.zig.system.resolveTargetQuery(.{}); const builtin_code = try getBuiltinCode(allocator, &env_map, zig_exe, opt_zig_lib_dir); for (toc.nodes) |node| { @@ -1424,9 +1423,7 @@ fn genHtml( try build_args.append("-lc"); try shell_out.print("-lc ", .{}); } - const target = try std.zig.CrossTarget.parse(.{ - .arch_os_abi = code.target_str orelse "native", - }); + if (code.target_str) |triple| { try build_args.appendSlice(&[_][]const u8{ "-target", triple }); try shell_out.print("-target {s} ", .{triple}); @@ -1490,9 +1487,13 @@ fn genHtml( } } + const target_query = try std.Target.Query.parse(.{ + .arch_os_abi = code.target_str orelse "native", + }); + const target = try std.zig.system.resolveTargetQuery(target_query); + const path_to_exe = try std.fmt.allocPrint(allocator, "./{s}{s}", .{ - code.name, - target.exeFileExt(), + code.name, target.exeFileExt(), }); const run_args = &[_][]const u8{path_to_exe}; @@ -1565,13 +1566,13 @@ fn genHtml( try test_args.appendSlice(&[_][]const u8{ "-target", triple }); try shell_out.print("-target {s} ", .{triple}); - const cross_target = try std.zig.CrossTarget.parse(.{ + const target_query = try std.Target.Query.parse(.{ .arch_os_abi = triple, }); - const target_info = try std.zig.system.NativeTargetInfo.detect( - cross_target, + const target = try std.zig.system.resolveTargetQuery( + target_query, ); - switch (host.getExternalExecutor(&target_info, .{ + switch (getExternalExecutor(host, &target, .{ .link_libc = code.link_libc, })) { .native => {}, From b92e30ff0bd2b77a486451b21d17666a311407f3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 Dec 2023 16:09:07 -0700 Subject: [PATCH 022/133] std.Build.ResolvedTarget: rename target field to result This change is seemingly insignificant but I actually agonized over this for three days. Some other things I considered: * (status quo in master branch) make Compile step creation functions accept a Target.Query and delete the ResolvedTarget struct. - downside: redundantly resolve target queries many times * same as before but additionally add a hash map to cache target query resolutions. - downside: now there is a hash map that doesn't actually need to exist, just to make the API more ergonomic. * add is_native_os and is_native_abi fields to std.Target and use it directly as the result of resolving a target query. - downside: they really don't belong there. They would be available as comptime booleans via `@import("builtin")` but they should not be exposed that way. With this change the downsides are: * the option name of addExecutable and friends is `target` instead of `resolved_target` matching the type name. - upside: this does not break compatibility with existing build scripts * you likely end up seeing `target.result.cpu.arch` rather than `target.cpu.arch`. - upside: this is an improvement over `target.target.cpu.arch` which it was before this commit. - downside: `b.host.target` is now `b.host.result`. --- build.zig | 8 ++++---- lib/build_runner.zig | 2 +- lib/std/Build.zig | 4 ++-- lib/std/Build/Module.zig | 10 +++++----- lib/std/Build/Step/Compile.zig | 6 +++--- lib/std/Build/Step/Run.zig | 14 ++++++++------ test/link/elf.zig | 2 +- test/link/link.zig | 2 +- test/link/macho/bugs/13056/build.zig | 2 +- test/src/Cases.zig | 10 +++++----- test/standalone/c_compiler/build.zig | 2 +- test/standalone/compiler_rt_panic/build.zig | 8 ++++---- test/standalone/ios/build.zig | 2 +- test/standalone/self_exe_symlink/build.zig | 2 +- test/standalone/stack_iterator/build.zig | 6 +++--- test/tests.zig | 4 ++-- 16 files changed, 43 insertions(+), 41 deletions(-) diff --git a/build.zig b/build.zig index bc4c32035c67..d24b51741aca 100644 --- a/build.zig +++ b/build.zig @@ -221,7 +221,7 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(&exe.step); - if (target.target.os.tag == .windows and target.target.abi == .gnu) { + if (target.result.os.tag == .windows and target.result.abi == .gnu) { // LTO is currently broken on mingw, this can be removed when it's fixed. exe.want_lto = false; check_case_exe.want_lto = false; @@ -347,7 +347,7 @@ pub fn build(b: *std.Build) !void { try addStaticLlvmOptionsToExe(exe); try addStaticLlvmOptionsToExe(check_case_exe); } - if (target.target.os.tag == .windows) { + if (target.result.os.tag == .windows) { inline for (.{ exe, check_case_exe }) |artifact| { artifact.linkSystemLibrary("version"); artifact.linkSystemLibrary("uuid"); @@ -371,7 +371,7 @@ pub fn build(b: *std.Build) !void { ); // On mingw, we need to opt into windows 7+ to get some features required by tracy. - const tracy_c_flags: []const []const u8 = if (target.target.os.tag == .windows and target.target.abi == .gnu) + const tracy_c_flags: []const []const u8 = if (target.result.os.tag == .windows and target.result.abi == .gnu) &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined", "-D_WIN32_WINNT=0x601" } else &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" }; @@ -383,7 +383,7 @@ pub fn build(b: *std.Build) !void { } exe.linkLibC(); - if (target.target.os.tag == .windows) { + if (target.result.os.tag == .windows) { exe.linkSystemLibrary("dbghelp"); exe.linkSystemLibrary("ws2_32"); } diff --git a/lib/build_runner.zig b/lib/build_runner.zig index b485469a381f..687a1eb15198 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -48,7 +48,7 @@ pub fn main() !void { const host: std.Build.ResolvedTarget = .{ .query = .{}, - .target = try std.zig.system.resolveTargetQuery(.{}), + .result = try std.zig.system.resolveTargetQuery(.{}), }; const build_root_directory: std.Build.Cache.Directory = .{ diff --git a/lib/std/Build.zig b/lib/std/Build.zig index da2bb49397d8..2074269c9b6f 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -2044,7 +2044,7 @@ pub fn hex64(x: u64) [16]u8 { /// of the target are "native". This can apply to the CPU, the OS, or even the ABI. pub const ResolvedTarget = struct { query: Target.Query, - target: Target, + result: Target, }; /// Converts a target query into a fully resolved target that can be passed to @@ -2056,7 +2056,7 @@ pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { return .{ .query = query, - .target = std.zig.system.resolveTargetQuery(query) catch + .result = std.zig.system.resolveTargetQuery(query) catch @panic("unable to resolve target query"), }; } diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 9c98dd0a46e4..81fab2be5e69 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -10,7 +10,7 @@ root_source_file: ?LazyPath, /// maintain step dependency edges. import_table: std.StringArrayHashMapUnmanaged(*Module), -target: ?std.Build.ResolvedTarget = null, +resolved_target: ?std.Build.ResolvedTarget = null, optimize: ?std.builtin.OptimizeMode = null, dwarf_format: ?std.dwarf.Format, @@ -192,7 +192,7 @@ pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*St .depending_steps = .{}, .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, .import_table = .{}, - .target = options.target, + .resolved_target = options.target, .optimize = options.optimize, .link_libc = options.link_libc, .link_libcpp = options.link_libcpp, @@ -627,7 +627,7 @@ pub fn appendZigProcessFlags( try zig_args.append(@tagName(m.code_model)); } - if (m.target) |*target| { + if (m.resolved_target) |*target| { // Communicate the query via CLI since it's more compact. if (!target.query.isNative()) { try zig_args.appendSlice(&.{ @@ -737,9 +737,9 @@ fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void { } fn requireKnownTarget(m: *Module) std.Target { - const resolved_target = m.target orelse + const resolved_target = m.resolved_target orelse @panic("this API requires the Module to be created with a known 'target' field"); - return resolved_target.target; + return resolved_target.result; } const Module = @This(); diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index b51304c91006..a984b1618992 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -251,7 +251,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { else owner.fmt("{s} ", .{name}); - const target = options.root_module.target.?.target; + const target = options.root_module.target.?.result; const step_name = owner.fmt("{s} {s}{s} {s}", .{ switch (options.kind) { @@ -954,7 +954,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try addFlag(&zig_args, "llvm", self.use_llvm); try addFlag(&zig_args, "lld", self.use_lld); - if (self.root_module.target.?.query.ofmt) |ofmt| { + if (self.root_module.resolved_target.?.query.ofmt) |ofmt| { try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); } @@ -1845,5 +1845,5 @@ fn matchCompileError(actual: []const u8, expected: []const u8) bool { pub fn rootModuleTarget(c: *Compile) std.Target { // The root module is always given a target, so we know this to be non-null. - return c.root_module.target.?.target; + return c.root_module.resolved_target.?.result; } diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index ad68dce648c8..d48fe2a2f178 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -678,8 +678,8 @@ fn runCommand( const need_cross_glibc = exe.rootModuleTarget().isGnuLibC() and exe.is_linking_libc; - const other_target = exe.root_module.target.?.target; - switch (std.zig.system.getExternalExecutor(b.host.target, &other_target, .{ + const other_target = exe.root_module.resolved_target.?.result; + switch (std.zig.system.getExternalExecutor(b.host.result, &other_target, .{ .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, .link_libc = exe.is_linking_libc, })) { @@ -752,7 +752,7 @@ fn runCommand( .bad_dl => |foreign_dl| { if (allow_skip) return error.MakeSkipped; - const host_dl = b.host.target.dynamic_linker.get() orelse "(none)"; + const host_dl = b.host.result.dynamic_linker.get() orelse "(none)"; return step.fail( \\the host system is unable to execute binaries from the target @@ -764,7 +764,7 @@ fn runCommand( .bad_os_or_cpu => { if (allow_skip) return error.MakeSkipped; - const host_name = try b.host.target.zigTriple(b.allocator); + const host_name = try b.host.result.zigTriple(b.allocator); const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator); return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{ @@ -1295,7 +1295,9 @@ fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void { while (it.next()) |item| { const other = item.compile.?; if (item.module == &other.root_module) { - if (item.module.target.?.target.os.tag == .windows and other.isDynamicLibrary()) { + if (item.module.resolved_target.?.result.os.tag == .windows and + other.isDynamicLibrary()) + { addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); } } @@ -1314,7 +1316,7 @@ fn failForeign( return error.MakeSkipped; const b = self.step.owner; - const host_name = try b.host.target.zigTriple(b.allocator); + const host_name = try b.host.result.zigTriple(b.allocator); const foreign_name = try exe.rootModuleTarget().zigTriple(b.allocator); return self.step.fail( diff --git a/test/link/elf.zig b/test/link/elf.zig index 459244db29a6..dafbf867ed2d 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -1763,7 +1763,7 @@ fn testInitArrayOrder(b: *Build, opts: Options) *Step { exe.addObject(g_o); exe.addObject(h_o); - if (opts.target.target.isGnuLibC()) { + if (opts.target.result.isGnuLibC()) { // TODO I think we need to clarify our use of `-fPIC -fPIE` flags for different targets exe.pie = true; } diff --git a/test/link/link.zig b/test/link/link.zig index 4d31d2d49ac0..ccce03bb0b4f 100644 --- a/test/link/link.zig +++ b/test/link/link.zig @@ -14,7 +14,7 @@ pub const Options = struct { }; pub fn addTestStep(b: *Build, prefix: []const u8, opts: Options) *Step { - const target = opts.target.target.zigTriple(b.allocator) catch @panic("OOM"); + const target = opts.target.result.zigTriple(b.allocator) catch @panic("OOM"); const optimize = @tagName(opts.optimize); const use_llvm = if (opts.use_llvm) "llvm" else "no-llvm"; const name = std.fmt.allocPrint(b.allocator, "test-{s}-{s}-{s}-{s}", .{ diff --git a/test/link/macho/bugs/13056/build.zig b/test/link/macho/bugs/13056/build.zig index c7136bbd7ffe..53bcefb9308b 100644 --- a/test/link/macho/bugs/13056/build.zig +++ b/test/link/macho/bugs/13056/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { const target = b.resolveTargetQuery(.{ .os_tag = .macos }); - const sdk = std.zig.system.darwin.getSdk(b.allocator, target.target) orelse + const sdk = std.zig.system.darwin.getSdk(b.allocator, target.result) orelse @panic("macOS SDK is required to run the test"); const exe = b.addExecutable(.{ diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 0f2645f0e036..6fedf43bf729 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -467,7 +467,7 @@ fn addFromDirInner( // Cross-product to get all possible test combinations for (targets) |target_query| { const resolved_target = b.resolveTargetQuery(target_query); - const target = resolved_target.target; + const target = resolved_target.result; for (backends) |backend| { if (backend == .stage2 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64) @@ -647,8 +647,8 @@ pub fn lowerToBuildSteps( parent_step.dependOn(&artifact.step); }, .Execution => |expected_stdout| no_exec: { - const run = if (case.target.target.ofmt == .c) run_step: { - if (getExternalExecutor(host, &case.target.target, .{ .link_libc = true }) != .native) { + const run = if (case.target.result.ofmt == .c) run_step: { + if (getExternalExecutor(host, &case.target.result, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. break :no_exec; } @@ -667,7 +667,7 @@ pub fn lowerToBuildSteps( "--", "-lc", "-target", - case.target.target.zigTriple(b.allocator) catch @panic("OOM"), + case.target.result.zigTriple(b.allocator) catch @panic("OOM"), }); run_c.addArtifactArg(artifact); break :run_step run_c; @@ -693,7 +693,7 @@ pub fn lowerToBuildSteps( continue; // Pass test. } - if (getExternalExecutor(host, &case.target.target, .{ .link_libc = true }) != .native) { + if (getExternalExecutor(host, &case.target.result, .{ .link_libc = true }) != .native) { // We wouldn't be able to run the compiled C code. continue; // Pass test. } diff --git a/test/standalone/c_compiler/build.zig b/test/standalone/c_compiler/build.zig index 236042d487da..0550ad8cee75 100644 --- a/test/standalone/c_compiler/build.zig +++ b/test/standalone/c_compiler/build.zig @@ -42,7 +42,7 @@ fn add( exe_cpp.addCSourceFile(.{ .file = .{ .path = "test.cpp" }, .flags = &[0][]const u8{} }); exe_cpp.linkLibCpp(); - switch (target.target.os.tag) { + switch (target.result.os.tag) { .windows => { // https://github.com/ziglang/zig/issues/8531 exe_cpp.want_lto = false; diff --git a/test/standalone/compiler_rt_panic/build.zig b/test/standalone/compiler_rt_panic/build.zig index cb275e08dfec..8ad7732a931b 100644 --- a/test/standalone/compiler_rt_panic/build.zig +++ b/test/standalone/compiler_rt_panic/build.zig @@ -4,16 +4,16 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const resolved_target = b.standardTargetOptions(.{}); - const target = resolved_target.target; + const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - if (target.ofmt != .elf or !(target.abi.isMusl() or target.abi.isGnu())) return; + if (target.result.ofmt != .elf or !(target.result.abi.isMusl() or target.result.abi.isGnu())) + return; const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, - .target = resolved_target, + .target = target, }); exe.linkLibC(); exe.addCSourceFile(.{ diff --git a/test/standalone/ios/build.zig b/test/standalone/ios/build.zig index 7642f3a3e843..356f12a3d902 100644 --- a/test/standalone/ios/build.zig +++ b/test/standalone/ios/build.zig @@ -12,7 +12,7 @@ pub fn build(b: *std.Build) void { .cpu_arch = .aarch64, .os_tag = .ios, }); - const sdk = std.zig.system.darwin.getSdk(b.allocator, target.target) orelse + const sdk = std.zig.system.darwin.getSdk(b.allocator, target.result) orelse @panic("no iOS SDK found"); b.sysroot = sdk; diff --git a/test/standalone/self_exe_symlink/build.zig b/test/standalone/self_exe_symlink/build.zig index c4720ce967cb..d61d50257433 100644 --- a/test/standalone/self_exe_symlink/build.zig +++ b/test/standalone/self_exe_symlink/build.zig @@ -11,7 +11,7 @@ pub fn build(b: *std.Build) void { // The test requires getFdPath in order to to get the path of the // File returned by openSelfExe - if (!std.os.isGetFdPathSupportedOnTarget(target.target.os)) return; + if (!std.os.isGetFdPathSupportedOnTarget(target.result.os)) return; const main = b.addExecutable(.{ .name = "main", diff --git a/test/standalone/stack_iterator/build.zig b/test/standalone/stack_iterator/build.zig index 6a98011e411a..d40a377d3958 100644 --- a/test/standalone/stack_iterator/build.zig +++ b/test/standalone/stack_iterator/build.zig @@ -22,7 +22,7 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "unwind.zig" }, .target = target, .optimize = optimize, - .unwind_tables = target.target.isDarwin(), + .unwind_tables = target.result.isDarwin(), .omit_frame_pointer = false, }); @@ -70,7 +70,7 @@ pub fn build(b: *std.Build) void { .strip = false, }); - if (target.target.os.tag == .windows) + if (target.result.os.tag == .windows) c_shared_lib.defineCMacro("LIB_API", "__declspec(dllexport)"); c_shared_lib.addCSourceFile(.{ @@ -84,7 +84,7 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "shared_lib_unwind.zig" }, .target = target, .optimize = optimize, - .unwind_tables = target.target.isDarwin(), + .unwind_tables = target.result.isDarwin(), .omit_frame_pointer = true, }); diff --git a/test/tests.zig b/test/tests.zig index 64c0f3a42e8c..b2fb1e4bca9c 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1043,7 +1043,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { continue; const resolved_target = b.resolveTargetQuery(test_target.target); - const target = resolved_target.target; + const target = resolved_target.result; if (options.skip_cross_glibc and !test_target.target.isNative() and target.isGnuLibC() and test_target.link_libc == true) @@ -1229,7 +1229,7 @@ pub fn addCAbiTests(b: *std.Build, skip_non_native: bool, skip_release: bool) *S if (skip_non_native and !c_abi_target.target.isNative()) continue; const resolved_target = b.resolveTargetQuery(c_abi_target.target); - const target = resolved_target.target; + const target = resolved_target.result; if (target.os.tag == .windows and target.cpu.arch == .aarch64) { // https://github.com/ziglang/zig/issues/14908 From 12de7e3472cb2292e75578d33a8b8cc91f1ef0b0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 10 Dec 2023 15:25:06 -0700 Subject: [PATCH 023/133] WIP: move many global settings to become per-Module Much of the logic from Compilation.create() is extracted into Compilation.Config.resolve() which accepts many optional settings and produces concrete settings. This separate step is needed by API users of Compilation so that they can pass the resolved global settings to the Module creation function, which itself needs to resolve per-Module settings. Since the target and other things are no longer global settings, I did not want them stored in link.File (in the `options` field). That options field was already a kludge; those options should be resolved into concrete settings. This commit also starts to work on that, deleting link.Options, moving the fields into Compilation and ObjectFormat-specific structs instead. Some fields were ephemeral and should not have been stored at all, such as symbol_size_hint. The link.File object of Compilation is now a `?*link.File` and `null` when -fno-emit-bin is passed. It is now arena-allocated along with Compilation itself, avoiding some messy cleanup code that was there before. On the command line, it is now possible to configure the standard library itself by using `--mod std` just like any other module. This meant that the CLI needed to create the standard library module rather than having Compilation create it. There are a lot of changes in this commit and it's still not done. I didn't realize how quickly this changeset was going to balloon out of control, and there are still many lines that need to be changed before it even compiles successfully. * introduce std.Build.Cache.HashHelper.oneShot * add error_tracing to std.Build.Module * extract build.zig file generation into src/Builtin.zig * each CSourceFile and RcSourceFile now has a Module owner, which determines some of the C compiler flags. --- CMakeLists.txt | 1 + lib/std/Build/Cache.zig | 14 + lib/std/Build/Module.zig | 4 + src/Builtin.zig | 240 +++++ src/Compilation.zig | 1457 ++++++++----------------- src/Compilation/Config.zig | 382 +++++++ src/Module.zig | 8 +- src/Package/Module.zig | 409 +++++++- src/Sema.zig | 2 +- src/codegen/llvm.zig | 38 +- src/link.zig | 525 ++++----- src/link/Coff.zig | 315 +++--- src/link/Elf.zig | 186 ++-- src/link/MachO.zig | 257 ++--- src/main.zig | 2045 ++++++++++++++++++++---------------- src/target.zig | 61 +- 16 files changed, 3250 insertions(+), 2694 deletions(-) create mode 100644 src/Builtin.zig create mode 100644 src/Compilation/Config.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index b3004d3254be..202c5d1861aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -521,6 +521,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/Air.zig" "${CMAKE_SOURCE_DIR}/src/AstGen.zig" "${CMAKE_SOURCE_DIR}/src/Compilation.zig" + "${CMAKE_SOURCE_DIR}/src/Compilation/Config.zig" "${CMAKE_SOURCE_DIR}/src/Liveness.zig" "${CMAKE_SOURCE_DIR}/src/Module.zig" "${CMAKE_SOURCE_DIR}/src/Package.zig" diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index b7865e730b5e..18c1ffa07a2a 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -312,6 +312,20 @@ pub const HashHelper = struct { ) catch unreachable; return out_digest; } + + pub fn oneShot(bytes: []const u8) [hex_digest_len]u8 { + var hasher: Hasher = hasher_init; + hasher.update(bytes); + var bin_digest: BinDigest = undefined; + hasher.final(&bin_digest); + var out_digest: [hex_digest_len]u8 = undefined; + _ = fmt.bufPrint( + &out_digest, + "{s}", + .{fmt.fmtSliceHexLower(&bin_digest)}, + ) catch unreachable; + return out_digest; + } }; pub const Lock = struct { diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 81fab2be5e69..9daa89deb8d5 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -34,6 +34,7 @@ valgrind: ?bool, pic: ?bool, red_zone: ?bool, omit_frame_pointer: ?bool, +error_tracing: ?bool, link_libc: ?bool, link_libcpp: ?bool, @@ -177,6 +178,7 @@ pub const CreateOptions = struct { /// Whether to omit the stack frame pointer. Frees up a register and makes it /// more difficult to obtain stack traces. Has target-dependent effects. omit_frame_pointer: ?bool = null, + error_tracing: ?bool = null, }; pub const Import = struct { @@ -216,6 +218,7 @@ pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*St .pic = options.pic, .red_zone = options.red_zone, .omit_frame_pointer = options.omit_frame_pointer, + .error_tracing = options.error_tracing, .export_symbol_names = &.{}, }; @@ -601,6 +604,7 @@ pub fn appendZigProcessFlags( try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check"); try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector"); try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer"); + try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing"); try addFlag(zig_args, m.sanitize_c, "-fsanitize-c", "-fno-sanitize-c"); try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread"); try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind"); diff --git a/src/Builtin.zig b/src/Builtin.zig new file mode 100644 index 000000000000..7224a6fd24fb --- /dev/null +++ b/src/Builtin.zig @@ -0,0 +1,240 @@ +target: std.Target, +zig_backend: std.builtin.CompilerBackend, +output_mode: std.builtin.OutputMode, +link_mode: std.builtin.LinkMode, +is_test: bool, +test_evented_io: bool, +single_threaded: bool, +link_libc: bool, +link_libcpp: bool, +optimize_mode: std.builtin.OptimizeMode, +error_tracing: bool, +valgrind: bool, +sanitize_thread: bool, +pic: bool, +pie: bool, +strip: bool, +code_model: std.builtin.CodeModel, +omit_frame_pointer: bool, +wasi_exec_model: std.builtin.WasiExecModel, + +pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 { + var buffer = std.ArrayList(u8).init(allocator); + defer buffer.deinit(); + + const target = opts.target; + const generic_arch_name = target.cpu.arch.genericName(); + const zig_backend = opts.zig_backend; + + @setEvalBranchQuota(4000); + try buffer.writer().print( + \\const std = @import("std"); + \\/// Zig version. When writing code that supports multiple versions of Zig, prefer + \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. + \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable; + \\pub const zig_version_string = "{s}"; + \\pub const zig_backend = std.builtin.CompilerBackend.{}; + \\ + \\pub const output_mode = std.builtin.OutputMode.{}; + \\pub const link_mode = std.builtin.LinkMode.{}; + \\pub const is_test = {}; + \\pub const single_threaded = {}; + \\pub const abi = std.Target.Abi.{}; + \\pub const cpu: std.Target.Cpu = .{{ + \\ .arch = .{}, + \\ .model = &std.Target.{}.cpu.{}, + \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{ + \\ + , .{ + build_options.version, + std.zig.fmtId(@tagName(zig_backend)), + std.zig.fmtId(@tagName(opts.output_mode)), + std.zig.fmtId(@tagName(opts.link_mode)), + opts.is_test, + opts.single_threaded, + std.zig.fmtId(@tagName(target.abi)), + std.zig.fmtId(@tagName(target.cpu.arch)), + std.zig.fmtId(generic_arch_name), + std.zig.fmtId(target.cpu.model.name), + std.zig.fmtId(generic_arch_name), + std.zig.fmtId(generic_arch_name), + }); + + for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| { + const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); + const is_enabled = target.cpu.features.isEnabled(index); + if (is_enabled) { + try buffer.writer().print(" .{},\n", .{std.zig.fmtId(feature.name)}); + } + } + try buffer.writer().print( + \\ }}), + \\}}; + \\pub const os = std.Target.Os{{ + \\ .tag = .{}, + \\ .version_range = .{{ + , + .{std.zig.fmtId(@tagName(target.os.tag))}, + ); + + switch (target.os.getVersionRange()) { + .none => try buffer.appendSlice(" .none = {} },\n"), + .semver => |semver| try buffer.writer().print( + \\ .semver = .{{ + \\ .min = .{{ + \\ .major = {}, + \\ .minor = {}, + \\ .patch = {}, + \\ }}, + \\ .max = .{{ + \\ .major = {}, + \\ .minor = {}, + \\ .patch = {}, + \\ }}, + \\ }}}}, + \\ + , .{ + semver.min.major, + semver.min.minor, + semver.min.patch, + + semver.max.major, + semver.max.minor, + semver.max.patch, + }), + .linux => |linux| try buffer.writer().print( + \\ .linux = .{{ + \\ .range = .{{ + \\ .min = .{{ + \\ .major = {}, + \\ .minor = {}, + \\ .patch = {}, + \\ }}, + \\ .max = .{{ + \\ .major = {}, + \\ .minor = {}, + \\ .patch = {}, + \\ }}, + \\ }}, + \\ .glibc = .{{ + \\ .major = {}, + \\ .minor = {}, + \\ .patch = {}, + \\ }}, + \\ }}}}, + \\ + , .{ + linux.range.min.major, + linux.range.min.minor, + linux.range.min.patch, + + linux.range.max.major, + linux.range.max.minor, + linux.range.max.patch, + + linux.glibc.major, + linux.glibc.minor, + linux.glibc.patch, + }), + .windows => |windows| try buffer.writer().print( + \\ .windows = .{{ + \\ .min = {s}, + \\ .max = {s}, + \\ }}}}, + \\ + , + .{ windows.min, windows.max }, + ), + } + try buffer.appendSlice( + \\}; + \\pub const target: std.Target = .{ + \\ .cpu = cpu, + \\ .os = os, + \\ .abi = abi, + \\ .ofmt = object_format, + \\ + ); + + if (target.dynamic_linker.get()) |dl| { + try buffer.writer().print( + \\ .dynamic_linker = std.Target.DynamicLinker.init("{s}"), + \\}}; + \\ + , .{dl}); + } else { + try buffer.appendSlice( + \\ .dynamic_linker = std.Target.DynamicLinker.none, + \\}; + \\ + ); + } + + // This is so that compiler_rt and libc.zig libraries know whether they + // will eventually be linked with libc. They make different decisions + // about what to export depending on whether another libc will be linked + // in. For example, compiler_rt will not export the __chkstk symbol if it + // knows libc will provide it, and likewise c.zig will not export memcpy. + const link_libc = opts.link_libc; + + try buffer.writer().print( + \\pub const object_format = std.Target.ObjectFormat.{}; + \\pub const mode = std.builtin.OptimizeMode.{}; + \\pub const link_libc = {}; + \\pub const link_libcpp = {}; + \\pub const have_error_return_tracing = {}; + \\pub const valgrind_support = {}; + \\pub const sanitize_thread = {}; + \\pub const position_independent_code = {}; + \\pub const position_independent_executable = {}; + \\pub const strip_debug_info = {}; + \\pub const code_model = std.builtin.CodeModel.{}; + \\pub const omit_frame_pointer = {}; + \\ + , .{ + std.zig.fmtId(@tagName(target.ofmt)), + std.zig.fmtId(@tagName(opts.optimize_mode)), + link_libc, + opts.link_libcpp, + opts.error_tracing, + opts.valgrind, + opts.sanitize_thread, + opts.pic, + opts.pie, + opts.strip, + std.zig.fmtId(@tagName(opts.code_model)), + opts.omit_frame_pointer, + }); + + if (target.os.tag == .wasi) { + const wasi_exec_model_fmt = std.zig.fmtId(@tagName(opts.wasi_exec_model)); + try buffer.writer().print( + \\pub const wasi_exec_model = std.builtin.WasiExecModel.{}; + \\ + , .{wasi_exec_model_fmt}); + } + + if (opts.is_test) { + try buffer.appendSlice( + \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later + \\ + ); + if (opts.test_evented_io) { + try buffer.appendSlice( + \\pub const test_io_mode = .evented; + \\ + ); + } else { + try buffer.appendSlice( + \\pub const test_io_mode = .blocking; + \\ + ); + } + } + + return buffer.toOwnedSliceSentinel(0); +} + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const build_options = @import("build_options"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 4f65dc22f2fc..ca43e2da079f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -38,12 +38,43 @@ const Autodoc = @import("Autodoc.zig"); const Color = @import("main.zig").Color; const resinator = @import("resinator.zig"); +pub const Config = @import("Compilation/Config.zig"); + /// General-purpose allocator. Used for both temporary and long-term storage. gpa: Allocator, /// Arena-allocated memory, mostly used during initialization. However, it can be used /// for other things requiring the same lifetime as the `Compilation`. arena: std.heap.ArenaAllocator, -bin_file: *link.File, +/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. +/// TODO: rename to zcu: ?*Zcu +module: ?*Module, +/// All compilations have a root module because this is where some important +/// settings are stored, such as target and optimization mode. This module +/// might not have any .zig code associated with it, however. +root_mod: *Package.Module, + +/// User-specified settings that have all the defaults resolved into concrete values. +config: Config, + +/// This is `null` when `-fno-emit-bin` is used. +bin_file: ?*link.File, + +/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) +sysroot: ?[]const u8, +/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used. +implib_emit: ?Emit, +/// This is non-null when `-femit-docs` is provided. +docs_emit: ?Emit, +root_name: [:0]const u8, +cache_mode: CacheMode, +include_compiler_rt: bool, +objects: []Compilation.LinkObject, +/// These are *always* dynamically linked. Static libraries will be +/// provided as positional arguments. +system_libs: std.StringArrayHashMapUnmanaged(SystemLib), +version: ?std.SemanticVersion, +libc_installation: ?*const LibCInstallation, + c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = if (build_options.only_core_functionality) {} else .{}, @@ -87,8 +118,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{}, keep_source_files_loaded: bool, -c_frontend: CFrontend, -sanitize_c: bool, /// When this is `true` it means invoking clang as a sub-process is expected to inherit /// stdin, stdout, stderr, and if it returns non success, to forward the exit code. /// Otherwise we attempt to parse the error messages and expose them via the Compilation API. @@ -107,8 +136,6 @@ verbose_llvm_cpu_features: bool, disable_c_depfile: bool, time_report: bool, stack_report: bool, -unwind_tables: bool, -test_evented_io: bool, debug_compiler_runtime_libs: bool, debug_compile_errors: bool, job_queued_compiler_rt_lib: bool = false, @@ -118,7 +145,6 @@ formatted_panics: bool = false, last_update_was_cache_hit: bool = false, c_source_files: []const CSourceFile, -clang_argv: []const []const u8, rc_source_files: []const RcSourceFile, cache_parent: *Cache, /// Path to own executable for invoking `zig clang`. @@ -194,7 +220,29 @@ emit_llvm_bc: ?EmitLoc, work_queue_wait_group: WaitGroup = .{}, astgen_wait_group: WaitGroup = .{}, -pub const default_stack_protector_buffer_size = 4; +pub const Emit = struct { + /// Where the output will go. + directory: Directory, + /// Path to the output file, relative to `directory`. + sub_path: []const u8, + + /// Returns the full path to `basename` if it were in the same directory as the + /// `Emit` sub_path. + pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 { + const full_path = if (emit.directory.path) |p| + try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path }) + else + emit.sub_path; + + if (std.fs.path.dirname(full_path)) |dirname| { + return try std.fs.path.joinZ(arena, &.{ dirname, basename }); + } else { + return basename; + } + } +}; + +pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; pub const SemaError = Module.SemaError; pub const CRTFile = struct { @@ -208,8 +256,8 @@ pub const CRTFile = struct { } }; -// supported languages for "zig clang -x ". -// Loosely based on llvm-project/clang/include/clang/Driver/Types.def +/// Supported languages for "zig clang -x ". +/// Loosely based on llvm-project/clang/include/clang/Driver/Types.def pub const LangToExt = std.ComptimeStringMap(FileExt, .{ .{ "c", .c }, .{ "c-header", .h }, @@ -226,16 +274,20 @@ pub const LangToExt = std.ComptimeStringMap(FileExt, .{ /// For passing to a C compiler. pub const CSourceFile = struct { + /// Many C compiler flags are determined by settings contained in the owning Module. + owner: *Package.Module, src_path: []const u8, extra_flags: []const []const u8 = &.{}, /// Same as extra_flags except they are not added to the Cache hash. cache_exempt_flags: []const []const u8 = &.{}, - // this field is non-null iff language was explicitly set with "-x lang". + /// This field is non-null if and only if the language was explicitly set + /// with "-x lang". ext: ?FileExt = null, }; /// For passing to resinator. pub const RcSourceFile = struct { + owner: *Package.Module, src_path: []const u8, extra_flags: []const []const u8 = &.{}, }; @@ -742,6 +794,22 @@ pub const EmitLoc = struct { }; pub const cache_helpers = struct { + pub fn addResolvedTarget( + hh: *Cache.HashHelper, + resolved_target: Package.Module.ResolvedTarget, + ) void { + const target = resolved_target.result; + hh.add(target.cpu.arch); + hh.addBytes(target.cpu.model.name); + hh.add(target.cpu.features.ints); + hh.add(target.os.tag); + hh.add(target.os.getVersionRange()); + hh.add(target.abi); + hh.add(target.ofmt); + hh.add(resolved_target.is_native_os); + hh.add(resolved_target.is_native_abi); + } + pub fn addEmitLoc(hh: *Cache.HashHelper, emit_loc: EmitLoc) void { hh.addBytes(emit_loc.basename); } @@ -751,7 +819,7 @@ pub const cache_helpers = struct { addEmitLoc(hh, optional_emit_loc orelse return); } - pub fn hashCSource(self: *Cache.Manifest, c_source: Compilation.CSourceFile) !void { + pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void { _ = try self.addFile(c_source.src_path, null); // Hash the extra flags, with special care to call addFile for file parameters. // TODO this logic can likely be improved by utilizing clang_options_data.zig. @@ -770,8 +838,6 @@ pub const cache_helpers = struct { } }; -pub const CFrontend = enum { clang, aro }; - pub const ClangPreprocessorMode = enum { no, /// This means we are doing `zig cc -E -o `. @@ -798,11 +864,21 @@ pub const InitOptions = struct { zig_lib_directory: Directory, local_cache_directory: Directory, global_cache_directory: Directory, - target: Target, - root_name: []const u8, - main_mod: ?*Package.Module, - output_mode: std.builtin.OutputMode, thread_pool: *ThreadPool, + self_exe_path: ?[]const u8 = null, + + /// Options that have been resolved by calling `resolveDefaults`. + config: Compilation.Config, + + root_mod: *Package.Module, + /// Normally, `main_mod` and `root_mod` are the same. The exception is `zig + /// test`, in which `root_mod` is the test runner, and `main_mod` is the + /// user's source file which has the tests. + main_mod: ?*Package.Module, + /// This is provided so that the API user has a chance to tweak the + /// per-module settings of the standard library. + std_mod: *Package.Module, + root_name: []const u8, sysroot: ?[]const u8 = null, /// `null` means to not emit a binary file. emit_bin: ?EmitLoc, @@ -818,7 +894,6 @@ pub const InitOptions = struct { emit_docs: ?EmitLoc = null, /// `null` means to not emit an import lib. emit_implib: ?EmitLoc = null, - link_mode: ?std.builtin.LinkMode = null, dll_export_fns: ?bool = false, /// Normally when using LLD to link, Zig uses a file named "lld.id" in the /// same directory as the output binary which contains the hash of the link @@ -828,14 +903,12 @@ pub const InitOptions = struct { /// this flag would be set to disable this machinery to avoid false positives. disable_lld_caching: bool = false, cache_mode: CacheMode = .incremental, - optimize_mode: std.builtin.OptimizeMode = .Debug, keep_source_files_loaded: bool = false, - clang_argv: []const []const u8 = &[0][]const u8{}, lib_dirs: []const []const u8 = &[0][]const u8{}, rpath_list: []const []const u8 = &[0][]const u8{}, symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}, - c_source_files: []const CSourceFile = &[0]CSourceFile{}, - rc_source_files: []const RcSourceFile = &[0]RcSourceFile{}, + c_source_files: []const CSourceFile = &.{}, + rc_source_files: []const RcSourceFile = &.{}, manifest_file: ?[]const u8 = null, rc_includes: RcIncludes = .any, link_objects: []LinkObject = &[0]LinkObject{}, @@ -849,40 +922,16 @@ pub const InitOptions = struct { /// * mman /// * signal wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{}, - link_libc: bool = false, - link_libcpp: bool = false, - link_libunwind: bool = false, - want_pic: ?bool = null, /// This means that if the output mode is an executable it will be a /// Position Independent Executable. If the output mode is not an /// executable this field is ignored. - want_pie: ?bool = null, - want_sanitize_c: ?bool = null, - want_stack_check: ?bool = null, - /// null means default. - /// 0 means no stack protector. - /// other number means stack protection with that buffer size. - want_stack_protector: ?u32 = null, - want_red_zone: ?bool = null, - omit_frame_pointer: ?bool = null, - want_valgrind: ?bool = null, - want_tsan: ?bool = null, want_compiler_rt: ?bool = null, want_lto: ?bool = null, - want_unwind_tables: ?bool = null, - use_llvm: ?bool = null, - use_lib_llvm: ?bool = null, - use_lld: ?bool = null, - use_clang: ?bool = null, - single_threaded: ?bool = null, - strip: ?bool = null, formatted_panics: ?bool = null, rdynamic: bool = false, function_sections: bool = false, data_sections: bool = false, no_builtin: bool = false, - is_native_os: bool, - is_native_abi: bool, time_report: bool = false, stack_report: bool = false, link_eh_frame_hdr: bool = false, @@ -893,14 +942,11 @@ pub const InitOptions = struct { linker_gc_sections: ?bool = null, linker_allow_shlib_undefined: ?bool = null, linker_bind_global_refs_locally: ?bool = null, - linker_import_memory: ?bool = null, - linker_export_memory: ?bool = null, linker_import_symbols: bool = false, linker_import_table: bool = false, linker_export_table: bool = false, linker_initial_memory: ?u64 = null, linker_max_memory: ?u64 = null, - linker_shared_memory: bool = false, linker_global_base: ?u64 = null, linker_export_symbol_names: []const []const u8 = &.{}, linker_print_gc_sections: bool = false, @@ -938,8 +984,6 @@ pub const InitOptions = struct { verbose_llvm_bc: ?[]const u8 = null, verbose_cimport: bool = false, verbose_llvm_cpu_features: bool = false, - is_test: bool = false, - test_evented_io: bool = false, debug_compiler_runtime_libs: bool = false, debug_compile_errors: bool = false, /// Normally when you create a `Compilation`, Zig will automatically build @@ -952,23 +996,18 @@ pub const InitOptions = struct { force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, stack_size_override: ?u64 = null, image_base_override: ?u64 = null, - self_exe_path: ?[]const u8 = null, version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation = null, - machine_code_model: std.builtin.CodeModel = .default, clang_preprocessor_mode: ClangPreprocessorMode = .no, /// This is for stage1 and should be deleted upon completion of self-hosting. color: Color = .auto, reference_trace: ?u32 = null, - error_tracing: ?bool = null, test_filter: ?[]const u8 = null, test_name_prefix: ?[]const u8 = null, test_runner_path: ?[]const u8 = null, subsystem: ?std.Target.SubSystem = null, dwarf_format: ?std.dwarf.Format = null, - /// WASI-only. Type of WASI execution model ("command" or "reactor"). - wasi_exec_model: ?std.builtin.WasiExecModel = null, /// (Zig compiler development) Enable dumping linker's state as JSON. enable_link_snapshots: bool = false, /// (Darwin) Install name of the dylib @@ -989,77 +1028,93 @@ pub const InitOptions = struct { pdb_source_path: ?[]const u8 = null, /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, - error_limit: ?Module.ErrorInt = 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( + gpa: Allocator, + arena: Allocator, hash: *Cache.HashHelper, - arena: *std.heap.ArenaAllocator, - mod_table: Package.Module.Deps, - seen_table: *std.AutoHashMap(*Package.Module, void), + root_mod: *Package.Module, hash_type: union(enum) { path_bytes, files: *Cache.Manifest }, ) (error{OutOfMemory} || std.os.GetCwdError)!void { - const allocator = arena.allocator(); - - const module_indices = try allocator.alloc(u32, mod_table.count()); - // Copy over the hashmap entries to our slice - for (module_indices, 0..) |*module_index, index| module_index.* = @intCast(index); - // Sort the slice by package name - mem.sortUnstable(u32, module_indices, &mod_table, struct { - fn lessThan(deps: *const Package.Module.Deps, lhs: u32, rhs: u32) bool { - const keys = deps.keys(); - return std.mem.lessThan(u8, keys[lhs], keys[rhs]); + var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{}; + try seen_table.put(gpa, root_mod, {}); + + const SortByName = struct { + names: []const []const u8, + + pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { + const lhs_key = ctx.names[lhs_index]; + const rhs_key = ctx.names[rhs_index]; + return mem.lessThan(u8, lhs_key, rhs_key); } - }.lessThan); + }; - for (module_indices) |module_index| { - const module = mod_table.values()[module_index]; - if ((try seen_table.getOrPut(module)).found_existing) continue; + var i: usize = 0; + while (i < seen_table.count()) : (i += 1) { + const mod = seen_table.keys()[i]; + + cache_helpers.addResolvedTarget(hash, mod.resolved_target); + hash.add(mod.optimize_mode); + hash.add(mod.code_model); + hash.add(mod.single_threaded); + hash.add(mod.error_tracing); + hash.add(mod.valgrind); + hash.add(mod.pic); + hash.add(mod.strip); + hash.add(mod.omit_frame_pointer); + hash.add(mod.stack_check); + hash.add(mod.red_zone); + hash.add(mod.sanitize_c); + hash.add(mod.sanitize_thread); - // Finally insert the package name and path to the cache hash. - hash.addBytes(mod_table.keys()[module_index]); switch (hash_type) { .path_bytes => { - hash.addBytes(module.root_src_path); - hash.addOptionalBytes(module.root.root_dir.path); - hash.addBytes(module.root.sub_path); + hash.addBytes(mod.root_src_path); + hash.addOptionalBytes(mod.root.root_dir.path); + hash.addBytes(mod.root.sub_path); }, .files => |man| { - const pkg_zig_file = try module.root.joinString( - allocator, - module.root_src_path, - ); + const pkg_zig_file = try mod.root.joinString(arena, mod.root_src_path); _ = try man.addFile(pkg_zig_file, null); }, } - // Recurse to handle the module's dependencies - try addModuleTableToCacheHash(hash, arena, module.deps, seen_table, hash_type); + + mod.deps.sortUnstable(SortByName{ .names = mod.deps.keys() }); + + hash.addListOfBytes(mod.deps.keys()); + + const deps = mod.deps.values(); + try seen_table.ensureUnusedCapacity(gpa, deps.len); + for (deps) |dep| seen_table.putAssumeCapacity(dep, {}); } } pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { - const is_dyn_lib = switch (options.output_mode) { + const output_mode = options.config.output_mode; + const is_dyn_lib = switch (output_mode) { .Obj, .Exe => false, - .Lib => (options.link_mode orelse .Static) == .Dynamic, + .Lib => options.config.link_mode == .Dynamic, }; - const is_exe_or_dyn_lib = switch (options.output_mode) { + const is_exe_or_dyn_lib = switch (output_mode) { .Obj => false, .Lib => is_dyn_lib, .Exe => true, }; - // WASI-only. Resolve the optional exec-model option, defaults to command. - const wasi_exec_model = if (options.target.os.tag != .wasi) undefined else options.wasi_exec_model orelse .command; - if (options.linker_export_table and options.linker_import_table) { return error.ExportTableAndImportTableConflict; } + const have_zcu = options.root_mod.root_src_path.len != 0; + const comp: *Compilation = comp: { - // For allocations that have the same lifetime as Compilation. This arena is used only during this - // initialization and then is freed in deinit(). + // For allocations that have the same lifetime as Compilation. This + // arena is used only during this initialization and then is freed in + // deinit(). var arena_allocator = std.heap.ArenaAllocator.init(gpa); errdefer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -1069,366 +1124,145 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const comp = try arena.create(Compilation); const root_name = try arena.dupeZ(u8, options.root_name); - // Make a decision on whether to use LLVM or our own backend. - const use_lib_llvm = options.use_lib_llvm orelse build_options.have_llvm; - const use_llvm = blk: { - if (options.use_llvm) |explicit| - break :blk explicit; - - // If emitting to LLVM bitcode object format, must use LLVM backend. - if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) - break :blk true; - - // If we have no zig code to compile, no need for LLVM. - if (options.main_mod == null) - break :blk false; - - // If we cannot use LLVM libraries, then our own backends will be a - // better default since the LLVM backend can only produce bitcode - // and not an object file or executable. - if (!use_lib_llvm) - break :blk false; - - // If LLVM does not support the target, then we can't use it. - if (!target_util.hasLlvmSupport(options.target, options.target.ofmt)) - break :blk false; - - // Prefer LLVM for release builds. - if (options.optimize_mode != .Debug) - break :blk true; - - // At this point we would prefer to use our own self-hosted backend, - // because the compilation speed is better than LLVM. But only do it if - // we are confident in the robustness of the backend. - break :blk !target_util.selfHostedBackendIsAsRobustAsLlvm(options.target); - }; - if (!use_llvm) { - if (options.use_llvm == true) { - return error.ZigCompilerNotBuiltWithLLVMExtensions; - } - if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) { - return error.EmittingLlvmModuleRequiresUsingLlvmBackend; - } - } + const use_llvm = options.config.use_llvm; // TODO: once we support incremental compilation for the LLVM backend via // saving the LLVM module into a bitcode file and restoring it, along with // compiler state, the second clause here can be removed so that incremental // cache mode is used for LLVM backend too. We need some fuzz testing before // that can be enabled. - const cache_mode = if ((use_llvm or options.main_mod == null) and !options.disable_lld_caching) + const cache_mode = if ((use_llvm or !have_zcu) and !options.disable_lld_caching) CacheMode.whole else options.cache_mode; - const tsan = options.want_tsan orelse false; - // TSAN is implemented in C++ so it requires linking libc++. - const link_libcpp = options.link_libcpp or tsan; - const link_libc = link_libcpp or options.link_libc or options.link_libunwind or - target_util.osRequiresLibC(options.target); - - const link_libunwind = options.link_libunwind or - (link_libcpp and target_util.libcNeedsLibUnwind(options.target)); - const unwind_tables = options.want_unwind_tables orelse - (link_libunwind or target_util.needUnwindTables(options.target)); - const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables; - const build_id = options.build_id orelse .none; + const any_unwind_tables = options.config.any_unwind_tables; - // Make a decision on whether to use LLD or our own linker. - const use_lld = options.use_lld orelse blk: { - if (options.target.isDarwin()) { - break :blk false; - } - - if (!build_options.have_llvm) - break :blk false; - - if (options.target.ofmt == .c) - break :blk false; - - if (options.want_lto) |lto| { - if (lto) { - break :blk true; - } - } - - // Our linker can't handle objects or most advanced options yet. - if (options.link_objects.len != 0 or - options.c_source_files.len != 0 or - options.frameworks.len != 0 or - options.system_lib_names.len != 0 or - options.link_libc or options.link_libcpp or - link_eh_frame_hdr or - options.link_emit_relocs or - options.output_mode == .Lib or - options.linker_script != null or options.version_script != null or - options.emit_implib != null or - build_id != .none or - options.symbol_wrap_set.count() > 0) - { - break :blk true; - } - - if (use_llvm) { - // If stage1 generates an object file, self-hosted linker is not - // yet sophisticated enough to handle that. - break :blk options.main_mod != null; - } - - break :blk false; - }; - - const lto = blk: { - if (options.want_lto) |want_lto| { - if (want_lto and !use_lld and !options.target.isDarwin()) - return error.LtoUnavailableWithoutLld; - break :blk want_lto; - } else if (!use_lld) { - // zig ld LTO support is tracked by - // https://github.com/ziglang/zig/issues/8680 - break :blk false; - } else if (options.c_source_files.len == 0) { - break :blk false; - } else if (options.target.cpu.arch.isRISCV()) { - // Clang and LLVM currently don't support RISC-V target-abi for LTO. - // Compiling with LTO may fail or produce undesired results. - // See https://reviews.llvm.org/D71387 - // See https://reviews.llvm.org/D102582 - break :blk false; - } else switch (options.output_mode) { - .Lib, .Obj => break :blk false, - .Exe => switch (options.optimize_mode) { - .Debug => break :blk false, - .ReleaseSafe, .ReleaseFast, .ReleaseSmall => break :blk true, - }, - } - }; - - const must_dynamic_link = dl: { - if (target_util.cannotDynamicLink(options.target)) - break :dl false; - if (is_exe_or_dyn_lib and link_libc and - (options.target.isGnuLibC() or target_util.osRequiresLibC(options.target))) - { - break :dl true; - } - const any_dyn_libs: bool = x: { - if (options.system_lib_names.len != 0) - break :x true; - for (options.link_objects) |obj| { - switch (classifyFileExt(obj.path)) { - .shared_library => break :x true, - else => continue, - } - } - break :x false; - }; - if (any_dyn_libs) { - // When creating a executable that links to system libraries, - // we require dynamic linking, but we must not link static libraries - // or object files dynamically! - break :dl (options.output_mode == .Exe); - } + const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; + const build_id = options.build_id orelse .none; - break :dl false; - }; - const default_link_mode: std.builtin.LinkMode = blk: { - if (must_dynamic_link) { - break :blk .Dynamic; - } else if (is_exe_or_dyn_lib and link_libc and - options.is_native_abi and options.target.abi.isMusl()) - { - // If targeting the system's native ABI and the system's - // libc is musl, link dynamically by default. - break :blk .Dynamic; - } else { - break :blk .Static; - } - }; - const link_mode: std.builtin.LinkMode = if (options.link_mode) |lm| blk: { - if (lm == .Static and must_dynamic_link) { - return error.UnableToStaticLink; - } - break :blk lm; - } else default_link_mode; + const link_libc = options.config.link_libc; const dll_export_fns = options.dll_export_fns orelse (is_dyn_lib or options.rdynamic); const libc_dirs = try detectLibCIncludeDirs( arena, options.zig_lib_directory.path.?, - options.target, - options.is_native_abi, + options.root_mod.resolved_target.result, + options.root_mod.resolved_target.is_native_abi, link_libc, options.libc_installation, ); - const rc_dirs = try detectWin32ResourceIncludeDirs( - arena, - options, - ); - - const sysroot = options.sysroot orelse libc_dirs.sysroot; - - const pie: bool = pie: { - if (is_dyn_lib) { - if (options.want_pie == true) return error.OutputModeForbidsPie; - break :pie false; - } - if (target_util.requiresPIE(options.target)) { - if (options.want_pie == false) return error.TargetRequiresPie; - break :pie true; - } - if (tsan) { - if (options.want_pie == false) return error.TsanRequiresPie; - break :pie true; - } - if (options.want_pie) |want_pie| { - break :pie want_pie; - } - break :pie false; - }; - - const must_pic: bool = b: { - if (target_util.requiresPIC(options.target, link_libc)) - break :b true; - break :b link_mode == .Dynamic; - }; - const pic = if (options.want_pic) |explicit| pic: { - if (!explicit) { - if (must_pic) { - return error.TargetRequiresPIC; - } - if (pie) { - return error.PIERequiresPIC; + // The include directories used when preprocessing .rc files are separate from the + // target. Which include directories are used is determined by `options.rc_includes`. + // + // Note: It should be okay that the include directories used when compiling .rc + // files differ from the include directories used when compiling the main + // binary, since the .res format is not dependent on anything ABI-related. The + // only relevant differences would be things like `#define` constants being + // different in the MinGW headers vs the MSVC headers, but any such + // differences would likely be a MinGW bug. + const rc_dirs = b: { + // Set the includes to .none here when there are no rc files to compile + var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none; + const target = options.root_mod.resolved_target.result; + if (!options.root_mod.resolved_target.is_native_os or target.os.tag != .windows) { + switch (includes) { + // MSVC can't be found when the host isn't Windows, so short-circuit. + .msvc => return error.WindowsSdkNotFound, + // Skip straight to gnu since we won't be able to detect + // MSVC on non-Windows hosts. + .any => includes = .gnu, + .none, .gnu => {}, } } - break :pic explicit; - } else pie or must_pic; - - // Make a decision on whether to use Clang or Aro for translate-c and compiling C files. - const c_frontend: CFrontend = blk: { - if (options.use_clang) |want_clang| { - break :blk if (want_clang) .clang else .aro; - } - break :blk if (build_options.have_llvm) .clang else .aro; - }; - if (!build_options.have_llvm and c_frontend == .clang) { - return error.ZigCompilerNotBuiltWithLLVMExtensions; - } - - const is_safe_mode = switch (options.optimize_mode) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, - }; - - const sanitize_c = options.want_sanitize_c orelse is_safe_mode; - - const stack_check: bool = options.want_stack_check orelse b: { - if (!target_util.supportsStackProbing(options.target)) break :b false; - break :b is_safe_mode; + while (true) switch (includes) { + .any, .msvc => break :b detectLibCIncludeDirs( + arena, + options.zig_lib_directory.path.?, + .{ + .cpu = target.cpu, + .os = target.os, + .abi = .msvc, + .ofmt = target.ofmt, + }, + options.root_mod.resolved_target.is_native_abi, + // The .rc preprocessor will need to know the libc include dirs even if we + // are not linking libc, so force 'link_libc' to true + true, + options.libc_installation, + ) catch |err| { + if (includes == .any) { + // fall back to mingw + includes = .gnu; + continue; + } + return err; + }, + .gnu => break :b try detectLibCFromBuilding(arena, options.zig_lib_directory.path.?, .{ + .cpu = target.cpu, + .os = target.os, + .abi = .gnu, + .ofmt = target.ofmt, + }), + .none => break :b LibCDirs{ + .libc_include_dir_list = &[0][]u8{}, + .libc_installation = null, + .libc_framework_dir_list = &.{}, + .sysroot = null, + .darwin_sdk_layout = null, + }, + }; }; - if (stack_check and !target_util.supportsStackProbing(options.target)) - return error.StackCheckUnsupportedByTarget; - - const stack_protector: u32 = sp: { - const zig_backend = zigBackend(options.target, use_llvm); - if (!target_util.supportsStackProtector(options.target, zig_backend)) { - if (options.want_stack_protector) |x| { - if (x > 0) return error.StackProtectorUnsupportedByTarget; - } - break :sp 0; - } - - // This logic is checking for linking libc because otherwise our start code - // which is trying to set up TLS (i.e. the fs/gs registers) but the stack - // protection code depends on fs/gs registers being already set up. - // If we were able to annotate start code, or perhaps the entire std lib, - // as being exempt from stack protection checks, we could change this logic - // to supporting stack protection even when not linking libc. - // TODO file issue about this - if (!link_libc) { - if (options.want_stack_protector) |x| { - if (x > 0) return error.StackProtectorUnavailableWithoutLibC; - } - break :sp 0; - } - if (options.want_stack_protector) |x| break :sp x; - if (is_safe_mode) break :sp default_stack_protector_buffer_size; - break :sp 0; - }; + const sysroot = options.sysroot orelse libc_dirs.sysroot; const include_compiler_rt = options.want_compiler_rt orelse (!options.skip_linker_dependencies and is_exe_or_dyn_lib); - const single_threaded = st: { - if (target_util.isSingleThreaded(options.target)) { - if (options.single_threaded == false) - return error.TargetRequiresSingleThreaded; - break :st true; - } - if (options.main_mod != null) { - const zig_backend = zigBackend(options.target, use_llvm); - if (!target_util.supportsThreads(options.target, zig_backend)) { - if (options.single_threaded == false) - return error.BackendRequiresSingleThreaded; - break :st true; - } - } - break :st options.single_threaded orelse false; - }; - - const llvm_cpu_features: ?[*:0]const u8 = if (use_llvm) blk: { - var buf = std.ArrayList(u8).init(arena); - for (options.target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| { - const index = @as(Target.Cpu.Feature.Set.Index, @intCast(index_usize)); - const is_enabled = options.target.cpu.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - const plus_or_minus = "-+"[@intFromBool(is_enabled)]; - try buf.ensureUnusedCapacity(2 + llvm_name.len); - buf.appendAssumeCapacity(plus_or_minus); - buf.appendSliceAssumeCapacity(llvm_name); - buf.appendSliceAssumeCapacity(","); - } - } - if (buf.items.len == 0) break :blk ""; - assert(mem.endsWith(u8, buf.items, ",")); - buf.items[buf.items.len - 1] = 0; - buf.shrinkAndFree(buf.items.len); - break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; - } else null; + if (include_compiler_rt and output_mode == .Obj) { + // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");` + // injected into the object. + const compiler_rt_mod = try Package.Module.create(arena, .{ + .global_cache_directory = options.global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = options.zig_lib_directory, + }, + .root_src_path = "compiler_rt.zig", + }, + .fully_qualified_name = "compiler_rt", + .cc_argv = &.{}, + .inherited = .{}, + .global = options.config, + .parent = options.root_mod, + .builtin_mod = options.root_mod.getBuiltinDependency(), + }); + try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod); + } if (options.verbose_llvm_cpu_features) { - if (llvm_cpu_features) |cf| print: { + if (options.root_mod.resolved_target.llvm_cpu_features) |cf| print: { + const target = options.root_mod.resolved_target.result; std.debug.getStderrMutex().lock(); defer std.debug.getStderrMutex().unlock(); const stderr = std.io.getStdErr().writer(); - nosuspend stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print; - nosuspend stderr.print(" target: {s}\n", .{try options.target.zigTriple(arena)}) catch break :print; - nosuspend stderr.print(" cpu: {s}\n", .{options.target.cpu.model.name}) catch break :print; - nosuspend stderr.print(" features: {s}\n", .{cf}) catch {}; + nosuspend { + stderr.print("compilation: {s}\n", .{options.root_name}) catch break :print; + stderr.print(" target: {s}\n", .{try target.zigTriple(arena)}) catch break :print; + stderr.print(" cpu: {s}\n", .{target.cpu.model.name}) catch break :print; + stderr.print(" features: {s}\n", .{cf}) catch {}; + } } } - const strip = options.strip orelse !target_util.hasDebugInfo(options.target); - const valgrind: bool = b: { - if (!target_util.hasValgrindSupport(options.target)) break :b false; - if (options.want_valgrind) |explicit| break :b explicit; - if (strip) break :b false; - break :b options.optimize_mode == .Debug; - }; - if (!valgrind and options.want_valgrind == true) - return error.ValgrindUnsupportedOnTarget; - - const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target); - const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug); - const linker_optimization: u8 = options.linker_optimization orelse switch (options.optimize_mode) { + const linker_optimization: u8 = options.linker_optimization orelse switch (options.root_mod.optimize_mode) { .Debug => @as(u8, 0), else => @as(u8, 3), }; - const formatted_panics = options.formatted_panics orelse (options.optimize_mode == .Debug); + // TODO: https://github.com/ziglang/zig/issues/17969 + const formatted_panics = options.formatted_panics orelse (options.root_mod.optimize_mode == .Debug); const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); @@ -1453,43 +1287,25 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // This is shared hasher state common to zig source and all C source files. cache.hash.addBytes(build_options.version); cache.hash.add(builtin.zig_backend); - cache.hash.add(options.optimize_mode); - cache.hash.add(options.target.cpu.arch); - cache.hash.addBytes(options.target.cpu.model.name); - cache.hash.add(options.target.cpu.features.ints); - cache.hash.add(options.target.os.tag); - cache.hash.add(options.target.os.getVersionRange()); - cache.hash.add(options.is_native_os); - cache.hash.add(options.target.abi); - cache.hash.add(options.target.ofmt); - cache.hash.add(pic); - cache.hash.add(pie); - cache.hash.add(lto); - cache.hash.add(unwind_tables); - cache.hash.add(tsan); - cache.hash.add(stack_check); - cache.hash.add(stack_protector); - cache.hash.add(red_zone); - cache.hash.add(omit_frame_pointer); - cache.hash.add(link_mode); + cache.hash.add(options.config.pie); + cache.hash.add(options.config.lto); + cache.hash.add(options.config.link_mode); cache.hash.add(options.function_sections); cache.hash.add(options.data_sections); cache.hash.add(options.no_builtin); - cache.hash.add(strip); cache.hash.add(link_libc); - cache.hash.add(link_libcpp); - cache.hash.add(link_libunwind); - cache.hash.add(options.output_mode); - cache.hash.add(options.machine_code_model); + cache.hash.add(options.config.link_libcpp); + cache.hash.add(options.config.link_libunwind); + cache.hash.add(output_mode); cache.hash.addOptional(options.dwarf_format); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); cache.hash.addBytes(options.root_name); - if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model); + cache.hash.add(options.config.wasi_exec_model); // TODO audit this and make sure everything is in it - const module: ?*Module = if (options.main_mod) |main_mod| blk: { + const zcu: ?*Module = if (have_zcu) blk: { // Options that are specific to zig source files, that cannot be // modified between incremental updates. var hash = cache.hash; @@ -1502,13 +1318,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // do want to namespace different source file names because they are // likely different compilations and therefore this would be likely to // cause cache hits. - hash.addBytes(main_mod.root_src_path); - hash.addOptionalBytes(main_mod.root.root_dir.path); - hash.addBytes(main_mod.root.sub_path); - { - var seen_table = std.AutoHashMap(*Package.Module, void).init(arena); - try addModuleTableToCacheHash(&hash, &arena_allocator, main_mod.deps, &seen_table, .path_bytes); - } + try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, .path_bytes); }, .whole => { // In this case, we postpone adding the input source file until @@ -1518,13 +1328,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } // Synchronize with other matching comments: ZigOnlyHashStuff - hash.add(valgrind); - hash.add(single_threaded); hash.add(use_llvm); - hash.add(use_lib_llvm); + hash.add(options.config.use_lib_llvm); hash.add(dll_export_fns); - hash.add(options.is_test); - hash.add(options.test_evented_io); + hash.add(options.config.is_test); + hash.add(options.config.test_evented_io); hash.addOptionalBytes(options.test_filter); hash.addOptionalBytes(options.test_name_prefix); hash.add(options.skip_linker_dependencies); @@ -1565,85 +1373,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), }; - const builtin_mod = try Package.Module.create(arena, .{ - .root = .{ .root_dir = zig_cache_artifact_directory }, - .root_src_path = "builtin.zig", - .fully_qualified_name = "builtin", - }); - - // When you're testing std, the main module is std. In that case, - // we'll just set the std module to the main one, since avoiding - // the errors caused by duplicating it is more effort than it's - // worth. - const main_mod_is_std = m: { - const std_path = try std.fs.path.resolve(arena, &[_][]const u8{ - options.zig_lib_directory.path orelse ".", - "std", - "std.zig", - }); - const main_path = try std.fs.path.resolve(arena, &[_][]const u8{ - main_mod.root.root_dir.path orelse ".", - main_mod.root.sub_path, - main_mod.root_src_path, - }); - break :m mem.eql(u8, main_path, std_path); - }; - - const std_mod = if (main_mod_is_std) - main_mod - else - try Package.Module.create(arena, .{ - .root = .{ - .root_dir = options.zig_lib_directory, - .sub_path = "std", - }, - .root_src_path = "std.zig", - .fully_qualified_name = "std", - }); - - const root_mod = if (options.is_test) root_mod: { - const test_mod = if (options.test_runner_path) |test_runner| test_mod: { - const pkg = try Package.Module.create(arena, .{ - .root = .{ - .root_dir = Directory.cwd(), - .sub_path = std.fs.path.dirname(test_runner) orelse "", - }, - .root_src_path = std.fs.path.basename(test_runner), - .fully_qualified_name = "root", - }); - - pkg.deps = try main_mod.deps.clone(arena); - break :test_mod pkg; - } else try Package.Module.create(arena, .{ - .root = .{ - .root_dir = options.zig_lib_directory, - }, - .root_src_path = "test_runner.zig", - .fully_qualified_name = "root", - }); - - break :root_mod test_mod; - } else main_mod; - - const compiler_rt_mod = if (include_compiler_rt and options.output_mode == .Obj) compiler_rt_mod: { - break :compiler_rt_mod try Package.Module.create(arena, .{ - .root = .{ - .root_dir = options.zig_lib_directory, - }, - .root_src_path = "compiler_rt.zig", - .fully_qualified_name = "compiler_rt", - }); - } else null; - - { - try main_mod.deps.ensureUnusedCapacity(arena, 4); - main_mod.deps.putAssumeCapacity("builtin", builtin_mod); - main_mod.deps.putAssumeCapacity("root", root_mod); - main_mod.deps.putAssumeCapacity("std", std_mod); - if (compiler_rt_mod) |m| - main_mod.deps.putAssumeCapacity("compiler_rt", m); - } - // Pre-open the directory handles for cached ZIR code so that it does not need // to redundantly happen for each AstGen operation. const zir_sub_dir = "z"; @@ -1674,13 +1403,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // However we currently do not have serialization of such metadata, so for now // we set up an empty Module that does the entire compilation fresh. - const module = try arena.create(Module); - errdefer module.deinit(); - module.* = .{ + const zcu = try arena.create(Module); + errdefer zcu.deinit(); + zcu.* = .{ .gpa = gpa, .comp = comp, - .main_mod = main_mod, - .root_mod = root_mod, + .main_mod = options.main_mod orelse options.root_mod, + .root_mod = options.root_mod, + .std_mod = options.std_mod, .zig_cache_artifact_directory = zig_cache_artifact_directory, .global_zir_cache = global_zir_cache, .local_zir_cache = local_zir_cache, @@ -1688,31 +1418,24 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa), .error_limit = error_limit, }; - try module.init(); + try zcu.init(); - break :blk module; + break :blk zcu; } else blk: { if (options.emit_h != null) return error.NoZigModuleForCHeader; break :blk null; }; - errdefer if (module) |zm| zm.deinit(); - - const error_return_tracing = !strip and switch (options.optimize_mode) { - .Debug, .ReleaseSafe => (!options.target.isWasm() or options.target.os.tag == .emscripten) and - !options.target.cpu.arch.isBpf() and (options.error_tracing orelse true), - .ReleaseFast => options.error_tracing orelse false, - .ReleaseSmall => false, - }; + errdefer if (zcu) |u| u.deinit(); // For resource management purposes. var owned_link_dir: ?std.fs.Dir = null; errdefer if (owned_link_dir) |*dir| dir.close(); - const bin_file_emit: ?link.Emit = blk: { + const bin_file_emit: ?Emit = blk: { const emit_bin = options.emit_bin orelse break :blk null; if (emit_bin.directory) |directory| { - break :blk link.Emit{ + break :blk Emit{ .directory = directory, .sub_path = emit_bin.basename, }; @@ -1725,9 +1448,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .incremental => {}, } - if (module) |zm| { - break :blk link.Emit{ - .directory = zm.zig_cache_artifact_directory, + if (zcu) |u| { + break :blk Emit{ + .directory = u.zig_cache_artifact_directory, .sub_path = emit_bin.basename, }; } @@ -1752,17 +1475,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .handle = artifact_dir, .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), }; - break :blk link.Emit{ + break :blk Emit{ .directory = link_artifact_directory, .sub_path = emit_bin.basename, }; }; - const implib_emit: ?link.Emit = blk: { + const implib_emit: ?Emit = blk: { const emit_implib = options.emit_implib orelse break :blk null; if (emit_implib.directory) |directory| { - break :blk link.Emit{ + break :blk Emit{ .directory = directory, .sub_path = emit_implib.basename, }; @@ -1776,13 +1499,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // Use the same directory as the bin. The CLI already emits an // error if -fno-emit-bin is combined with -femit-implib. - break :blk link.Emit{ + break :blk Emit{ .directory = bin_file_emit.?.directory, .sub_path = emit_implib.basename, }; }; - const docs_emit: ?link.Emit = blk: { + const docs_emit: ?Emit = blk: { const emit_docs = options.emit_docs orelse break :blk null; if (emit_docs.directory) |directory| { @@ -1805,7 +1528,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }; break :blk .{ - .directory = module.?.zig_cache_artifact_directory, + .directory = zcu.?.zig_cache_artifact_directory, .sub_path = emit_docs.basename, }; }; @@ -1828,131 +1551,20 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]); } - const bin_file = try link.File.openPath(gpa, .{ - .emit = bin_file_emit, - .implib_emit = implib_emit, - .docs_emit = docs_emit, - .root_name = root_name, - .module = module, - .target = options.target, - .sysroot = sysroot, - .output_mode = options.output_mode, - .link_mode = link_mode, - .optimize_mode = options.optimize_mode, - .use_lld = use_lld, - .use_llvm = use_llvm, - .use_lib_llvm = use_lib_llvm, - .link_libc = link_libc, - .link_libcpp = link_libcpp, - .link_libunwind = link_libunwind, - .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, - .objects = options.link_objects, - .frameworks = options.frameworks, - .framework_dirs = options.framework_dirs, - .system_libs = system_libs, - .wasi_emulated_libs = options.wasi_emulated_libs, - .lib_dirs = options.lib_dirs, - .rpath_list = options.rpath_list, - .symbol_wrap_set = options.symbol_wrap_set, - .strip = strip, - .is_native_os = options.is_native_os, - .is_native_abi = options.is_native_abi, - .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, - .module_definition_file = options.linker_module_definition_file, - .sort_section = options.linker_sort_section, - .import_memory = options.linker_import_memory orelse false, - .export_memory = options.linker_export_memory orelse !(options.linker_import_memory orelse false), - .import_symbols = options.linker_import_symbols, - .import_table = options.linker_import_table, - .export_table = options.linker_export_table, - .initial_memory = options.linker_initial_memory, - .max_memory = options.linker_max_memory, - .shared_memory = options.linker_shared_memory, - .global_base = options.linker_global_base, - .export_symbol_names = options.linker_export_symbol_names, - .print_gc_sections = options.linker_print_gc_sections, - .print_icf_sections = options.linker_print_icf_sections, - .print_map = options.linker_print_map, - .opt_bisect_limit = options.linker_opt_bisect_limit, - .z_nodelete = options.linker_z_nodelete, - .z_notext = options.linker_z_notext, - .z_defs = options.linker_z_defs, - .z_origin = options.linker_z_origin, - .z_nocopyreloc = options.linker_z_nocopyreloc, - .z_now = options.linker_z_now, - .z_relro = options.linker_z_relro, - .z_common_page_size = options.linker_z_common_page_size, - .z_max_page_size = options.linker_z_max_page_size, - .tsaware = options.linker_tsaware, - .nxcompat = options.linker_nxcompat, - .dynamicbase = options.linker_dynamicbase, - .linker_optimization = linker_optimization, - .major_subsystem_version = options.major_subsystem_version, - .minor_subsystem_version = options.minor_subsystem_version, - .entry = options.entry, - .stack_size_override = options.stack_size_override, - .image_base_override = options.image_base_override, - .include_compiler_rt = include_compiler_rt, - .linker_script = options.linker_script, - .version_script = options.version_script, - .gc_sections = options.linker_gc_sections, - .eh_frame_hdr = link_eh_frame_hdr, - .emit_relocs = options.link_emit_relocs, - .rdynamic = options.rdynamic, - .soname = options.soname, - .version = options.version, - .compatibility_version = options.compatibility_version, - .libc_installation = libc_dirs.libc_installation, - .pic = pic, - .pie = pie, - .lto = lto, - .valgrind = valgrind, - .tsan = tsan, - .stack_check = stack_check, - .stack_protector = stack_protector, - .red_zone = red_zone, - .omit_frame_pointer = omit_frame_pointer, - .single_threaded = single_threaded, - .verbose_link = options.verbose_link, - .machine_code_model = options.machine_code_model, - .dll_export_fns = dll_export_fns, - .error_return_tracing = error_return_tracing, - .llvm_cpu_features = llvm_cpu_features, - .skip_linker_dependencies = options.skip_linker_dependencies, - .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, - .build_id = build_id, - .cache_mode = cache_mode, - .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, - .subsystem = options.subsystem, - .is_test = options.is_test, - .dwarf_format = options.dwarf_format, - .wasi_exec_model = wasi_exec_model, - .hash_style = options.hash_style, - .enable_link_snapshots = options.enable_link_snapshots, - .install_name = options.install_name, - .entitlements = options.entitlements, - .pagezero_size = options.pagezero_size, - .headerpad_size = options.headerpad_size, - .headerpad_max_install_names = options.headerpad_max_install_names, - .dead_strip_dylibs = options.dead_strip_dylibs, - .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, - }); - errdefer bin_file.destroy(); + const each_lib_rpath = options.each_lib_rpath orelse + options.root_mod.resolved_target.is_native_os; + comp.* = .{ .gpa = gpa, .arena = arena_allocator, + .module = zcu, + .root_mod = options.root_mod, + .config = options.config, + .bin_file = null, + .cache_mode = cache_mode, .zig_lib_directory = options.zig_lib_directory, .local_cache_directory = options.local_cache_directory, .global_cache_directory = options.global_cache_directory, - .bin_file = bin_file, .whole_bin_sub_path = whole_bin_sub_path, .whole_implib_sub_path = whole_implib_sub_path, .whole_docs_sub_path = whole_docs_sub_path, @@ -1966,8 +1578,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa), .keep_source_files_loaded = options.keep_source_files_loaded, - .c_frontend = c_frontend, - .clang_argv = options.clang_argv, .c_source_files = options.c_source_files, .rc_source_files = options.rc_source_files, .cache_parent = cache, @@ -1975,7 +1585,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .libc_include_dir_list = libc_dirs.libc_include_dir_list, .libc_framework_dir_list = libc_dirs.libc_framework_dir_list, .rc_include_dir_list = rc_dirs.libc_include_dir_list, - .sanitize_c = sanitize_c, .thread_pool = options.thread_pool, .clang_passthrough_mode = options.clang_passthrough_mode, .clang_preprocessor_mode = options.clang_preprocessor_mode, @@ -1994,22 +1603,110 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .formatted_panics = formatted_panics, .time_report = options.time_report, .stack_report = options.stack_report, - .unwind_tables = unwind_tables, .test_filter = options.test_filter, .test_name_prefix = options.test_name_prefix, - .test_evented_io = options.test_evented_io, .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, .debug_compile_errors = options.debug_compile_errors, .libcxx_abi_version = options.libcxx_abi_version, + .implib_emit = implib_emit, + .docs_emit = docs_emit, + .root_name = root_name, + .sysroot = sysroot, + .system_libs = system_libs, + .version = options.version, + .libc_installation = libc_dirs.libc_installation, + .include_compiler_rt = include_compiler_rt, + .objects = options.link_objects, }; + + 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, + .z_defs = options.linker_z_defs, + .z_origin = options.linker_z_origin, + .z_nocopyreloc = options.linker_z_nocopyreloc, + .z_now = options.linker_z_now, + .z_relro = options.linker_z_relro, + .z_common_page_size = options.linker_z_common_page_size, + .z_max_page_size = options.linker_z_max_page_size, + .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, + .frameworks = options.frameworks, + .framework_dirs = options.framework_dirs, + .wasi_emulated_libs = options.wasi_emulated_libs, + .lib_dirs = options.lib_dirs, + .rpath_list = options.rpath_list, + .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, + .module_definition_file = options.linker_module_definition_file, + .sort_section = options.linker_sort_section, + .import_symbols = options.linker_import_symbols, + .import_table = options.linker_import_table, + .export_table = options.linker_export_table, + .initial_memory = options.linker_initial_memory, + .max_memory = options.linker_max_memory, + .global_base = options.linker_global_base, + .export_symbol_names = options.linker_export_symbol_names, + .print_gc_sections = options.linker_print_gc_sections, + .print_icf_sections = options.linker_print_icf_sections, + .print_map = options.linker_print_map, + .opt_bisect_limit = options.linker_opt_bisect_limit, + .tsaware = options.linker_tsaware, + .nxcompat = options.linker_nxcompat, + .dynamicbase = options.linker_dynamicbase, + .major_subsystem_version = options.major_subsystem_version, + .minor_subsystem_version = options.minor_subsystem_version, + .stack_size_override = options.stack_size_override, + .image_base_override = options.image_base_override, + .version_script = options.version_script, + .gc_sections = options.linker_gc_sections, + .eh_frame_hdr = link_eh_frame_hdr, + .emit_relocs = options.link_emit_relocs, + .rdynamic = options.rdynamic, + .soname = options.soname, + .compatibility_version = options.compatibility_version, + .verbose_link = options.verbose_link, + .dll_export_fns = dll_export_fns, + .skip_linker_dependencies = options.skip_linker_dependencies, + .parent_compilation_link_libc = options.parent_compilation_link_libc, + .each_lib_rpath = each_lib_rpath, + .build_id = build_id, + .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, + .subsystem = options.subsystem, + .dwarf_format = options.dwarf_format, + .hash_style = options.hash_style, + .enable_link_snapshots = options.enable_link_snapshots, + .install_name = options.install_name, + .entitlements = options.entitlements, + .pagezero_size = options.pagezero_size, + .headerpad_size = options.headerpad_size, + .headerpad_max_install_names = options.headerpad_max_install_names, + .dead_strip_dylibs = options.dead_strip_dylibs, + .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?) + }); + } + break :comp comp; }; errdefer comp.destroy(); - const target = comp.getTarget(); + const target = options.root_mod.resolved_target.result; - const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, comp.bin_file.options.use_llvm); - const capable_of_building_zig_libc = canBuildZigLibC(target, comp.bin_file.options.use_llvm); + const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, options.config.use_llvm); + const capable_of_building_zig_libc = canBuildZigLibC(target, options.config.use_llvm); // Add a `CObject` for each `c_source_files`. try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len); @@ -2109,7 +1806,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }); } comp.work_queue.writeAssumeCapacity(&[_]Job{ - .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(wasi_exec_model) }, + .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) }, .{ .wasi_libc_crt_file = .libc_a }, }); } @@ -2171,7 +1868,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { if (is_exe_or_dyn_lib) { log.debug("queuing a job to build compiler_rt_lib", .{}); comp.job_queued_compiler_rt_lib = true; - } else if (options.output_mode != .Obj) { + } else if (output_mode != .Obj) { log.debug("queuing a job to build compiler_rt_obj", .{}); // In this case we are making a static library, so we ask // for a compiler-rt object to put in it. @@ -2283,7 +1980,7 @@ pub fn clearMiscFailures(comp: *Compilation) void { } pub fn getTarget(self: Compilation) Target { - return self.bin_file.options.target; + return self.root_mod.resolved_target.result; } fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Directory) void { @@ -2436,7 +2133,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Make sure std.zig is inside the import_table. We unconditionally need // it for start.zig. - const std_mod = module.main_mod.deps.get("std").?; + const std_mod = module.std_mod; _ = try module.importPkg(std_mod); // Normally we rely on importing std to in turn import the root source file @@ -2449,7 +2146,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void _ = try module.importPkg(module.main_mod); } - if (module.main_mod.deps.get("compiler_rt")) |compiler_rt_mod| { + if (module.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| { _ = try module.importPkg(compiler_rt_mod); } @@ -2474,7 +2171,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void try comp.work_queue.writeItem(.{ .analyze_mod = module.main_mod }); } - if (module.main_mod.deps.get("compiler_rt")) |compiler_rt_mod| { + if (module.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| { try comp.work_queue.writeItem(.{ .analyze_mod = compiler_rt_mod }); } } @@ -2699,16 +2396,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes if (comp.bin_file.options.module) |mod| { const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path); _ = try man.addFile(main_zig_file, null); - { - var seen_table = std.AutoHashMap(*Package.Module, void).init(arena); - - // Skip builtin.zig; it is useless as an input, and we don't want to have to - // write it before checking for a cache hit. - const builtin_mod = mod.main_mod.deps.get("builtin").?; - try seen_table.put(builtin_mod, {}); - - try addModuleTableToCacheHash(&man.hash, &arena_allocator, mod.main_mod.deps, &seen_table, .{ .files = man }); - } + try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.main_mod, .{ .files = man }); // Synchronize with other matching comments: ZigOnlyHashStuff man.hash.add(comp.bin_file.options.valgrind); @@ -2762,8 +2450,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); - man.hash.addListOfBytes(comp.clang_argv); - man.hash.addOptional(comp.bin_file.options.stack_size_override); man.hash.addOptional(comp.bin_file.options.image_base_override); man.hash.addOptional(comp.bin_file.options.gc_sections); @@ -3341,7 +3027,7 @@ pub const ErrorNoteHashContext = struct { const eb = ctx.eb.tmpBundle(); const msg_a = eb.nullTerminatedString(a.msg); const msg_b = eb.nullTerminatedString(b.msg); - if (!std.mem.eql(u8, msg_a, msg_b)) return false; + if (!mem.eql(u8, msg_a, msg_b)) return false; if (a.src_loc == .none and b.src_loc == .none) return true; if (a.src_loc == .none or b.src_loc == .none) return false; @@ -3351,7 +3037,7 @@ pub const ErrorNoteHashContext = struct { const src_path_a = eb.nullTerminatedString(src_a.src_path); const src_path_b = eb.nullTerminatedString(src_b.src_path); - return std.mem.eql(u8, src_path_a, src_path_b) and + return mem.eql(u8, src_path_a, src_path_b) and src_a.line == src_b.line and src_a.column == src_b.column and src_a.span_main == src_b.span_main; @@ -4149,7 +3835,7 @@ pub const CImportResult = struct { cache_hit: bool, errors: std.zig.ErrorBundle, - pub fn deinit(result: *CImportResult, gpa: std.mem.Allocator) void { + pub fn deinit(result: *CImportResult, gpa: mem.Allocator) void { result.errors.deinit(gpa); } }; @@ -5321,9 +5007,9 @@ pub fn addCCArgs( argv.appendAssumeCapacity(arg); } } - const mcmodel = comp.bin_file.options.machine_code_model; - if (mcmodel != .default) { - try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mcmodel)})); + 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)})); } switch (target.os.tag) { @@ -5618,68 +5304,6 @@ fn failCObjWithOwnedDiagBundle( return error.AnalysisFail; } -/// The include directories used when preprocessing .rc files are separate from the -/// target. Which include directories are used is determined by `options.rc_includes`. -/// -/// Note: It should be okay that the include directories used when compiling .rc -/// files differ from the include directories used when compiling the main -/// binary, since the .res format is not dependent on anything ABI-related. The -/// only relevant differences would be things like `#define` constants being -/// different in the MinGW headers vs the MSVC headers, but any such -/// differences would likely be a MinGW bug. -fn detectWin32ResourceIncludeDirs(arena: Allocator, options: InitOptions) !LibCDirs { - // Set the includes to .none here when there are no rc files to compile - var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none; - if (builtin.target.os.tag != .windows) { - switch (includes) { - // MSVC can't be found when the host isn't Windows, so short-circuit. - .msvc => return error.WindowsSdkNotFound, - // Skip straight to gnu since we won't be able to detect MSVC on non-Windows hosts. - .any => includes = .gnu, - .none, .gnu => {}, - } - } - while (true) { - switch (includes) { - .any, .msvc => return detectLibCIncludeDirs( - arena, - options.zig_lib_directory.path.?, - .{ - .cpu = options.target.cpu, - .os = options.target.os, - .abi = .msvc, - .ofmt = options.target.ofmt, - }, - options.is_native_abi, - // The .rc preprocessor will need to know the libc include dirs even if we - // are not linking libc, so force 'link_libc' to true - true, - options.libc_installation, - ) catch |err| { - if (includes == .any) { - // fall back to mingw - includes = .gnu; - continue; - } - return err; - }, - .gnu => return detectLibCFromBuilding(arena, options.zig_lib_directory.path.?, .{ - .cpu = options.target.cpu, - .os = options.target.os, - .abi = .gnu, - .ofmt = options.target.ofmt, - }), - .none => return LibCDirs{ - .libc_include_dir_list = &[0][]u8{}, - .libc_installation = null, - .libc_framework_dir_list = &.{}, - .sysroot = null, - .darwin_sdk_layout = null, - }, - } - } -} - fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptime format: []const u8, args: anytype) SemaError { @setCold(true); var bundle: ErrorBundle.Wip = undefined; @@ -6061,7 +5685,7 @@ const LibCDirs = struct { libc_installation: ?*const LibCInstallation, libc_framework_dir_list: []const []const u8, sysroot: ?[]const u8, - darwin_sdk_layout: ?link.DarwinSdkLayout, + darwin_sdk_layout: ?link.File.MachO.SdkLayout, }; fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs { @@ -6374,7 +5998,7 @@ fn parseLldStderr(comp: *Compilation, comptime prefix: []const u8, stderr: []con err.context_lines = try context_lines.toOwnedSlice(); } - var split = std.mem.splitSequence(u8, line, "error: "); + var split = mem.splitSequence(u8, line, "error: "); _ = split.first(); const duped_msg = try std.fmt.allocPrint(comp.gpa, "{s}: {s}", .{ prefix, split.rest() }); @@ -6427,7 +6051,7 @@ fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool) bool { .spirv32, .spirv64 => return false, else => {}, } - return switch (zigBackend(target, use_llvm)) { + return switch (target_util.zigBackend(target, use_llvm)) { .stage2_llvm => true, .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm, else => build_options.have_llvm, @@ -6445,7 +6069,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool { .spirv32, .spirv64 => return false, else => {}, } - return switch (zigBackend(target, use_llvm)) { + return switch (target_util.zigBackend(target, use_llvm)) { .stage2_llvm => true, .stage2_x86_64 => if (target.ofmt == .elf) true else build_options.have_llvm, else => build_options.have_llvm, @@ -6454,236 +6078,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool { pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend { const target = comp.bin_file.options.target; - return zigBackend(target, comp.bin_file.options.use_llvm); -} - -fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBackend { - if (use_llvm) return .stage2_llvm; - if (target.ofmt == .c) return .stage2_c; - return switch (target.cpu.arch) { - .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm, - .arm, .armeb, .thumb, .thumbeb => .stage2_arm, - .x86_64 => .stage2_x86_64, - .x86 => .stage2_x86, - .aarch64, .aarch64_be, .aarch64_32 => .stage2_aarch64, - .riscv64 => .stage2_riscv64, - .sparc64 => .stage2_sparc64, - .spirv64 => .stage2_spirv64, - else => .other, - }; -} - -pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Allocator.Error![:0]u8 { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - - var buffer = std.ArrayList(u8).init(allocator); - defer buffer.deinit(); - - const target = comp.getTarget(); - const generic_arch_name = target.cpu.arch.genericName(); - const zig_backend = comp.getZigBackend(); - - @setEvalBranchQuota(4000); - try buffer.writer().print( - \\const std = @import("std"); - \\/// Zig version. When writing code that supports multiple versions of Zig, prefer - \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. - \\pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable; - \\pub const zig_version_string = "{s}"; - \\pub const zig_backend = std.builtin.CompilerBackend.{}; - \\ - \\pub const output_mode = std.builtin.OutputMode.{}; - \\pub const link_mode = std.builtin.LinkMode.{}; - \\pub const is_test = {}; - \\pub const single_threaded = {}; - \\pub const abi = std.Target.Abi.{}; - \\pub const cpu: std.Target.Cpu = .{{ - \\ .arch = .{}, - \\ .model = &std.Target.{}.cpu.{}, - \\ .features = std.Target.{}.featureSet(&[_]std.Target.{}.Feature{{ - \\ - , .{ - build_options.version, - std.zig.fmtId(@tagName(zig_backend)), - std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)), - std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)), - comp.bin_file.options.is_test, - comp.bin_file.options.single_threaded, - std.zig.fmtId(@tagName(target.abi)), - std.zig.fmtId(@tagName(target.cpu.arch)), - std.zig.fmtId(generic_arch_name), - std.zig.fmtId(target.cpu.model.name), - std.zig.fmtId(generic_arch_name), - std.zig.fmtId(generic_arch_name), - }); - - for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| { - const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); - const is_enabled = target.cpu.features.isEnabled(index); - if (is_enabled) { - try buffer.writer().print(" .{},\n", .{std.zig.fmtId(feature.name)}); - } - } - try buffer.writer().print( - \\ }}), - \\}}; - \\pub const os = std.Target.Os{{ - \\ .tag = .{}, - \\ .version_range = .{{ - , - .{std.zig.fmtId(@tagName(target.os.tag))}, - ); - - switch (target.os.getVersionRange()) { - .none => try buffer.appendSlice(" .none = {} },\n"), - .semver => |semver| try buffer.writer().print( - \\ .semver = .{{ - \\ .min = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ .max = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}}}, - \\ - , .{ - semver.min.major, - semver.min.minor, - semver.min.patch, - - semver.max.major, - semver.max.minor, - semver.max.patch, - }), - .linux => |linux| try buffer.writer().print( - \\ .linux = .{{ - \\ .range = .{{ - \\ .min = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ .max = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}, - \\ .glibc = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}}}, - \\ - , .{ - linux.range.min.major, - linux.range.min.minor, - linux.range.min.patch, - - linux.range.max.major, - linux.range.max.minor, - linux.range.max.patch, - - linux.glibc.major, - linux.glibc.minor, - linux.glibc.patch, - }), - .windows => |windows| try buffer.writer().print( - \\ .windows = .{{ - \\ .min = {s}, - \\ .max = {s}, - \\ }}}}, - \\ - , - .{ windows.min, windows.max }, - ), - } - try buffer.appendSlice( - \\}; - \\pub const target: std.Target = .{ - \\ .cpu = cpu, - \\ .os = os, - \\ .abi = abi, - \\ .ofmt = object_format, - \\ - ); - - if (target.dynamic_linker.get()) |dl| { - try buffer.writer().print( - \\ .dynamic_linker = std.Target.DynamicLinker.init("{s}"), - \\}}; - \\ - , .{dl}); - } else { - try buffer.appendSlice( - \\ .dynamic_linker = std.Target.DynamicLinker.none, - \\}; - \\ - ); - } - - try buffer.writer().print( - \\pub const object_format = std.Target.ObjectFormat.{}; - \\pub const mode = std.builtin.OptimizeMode.{}; - \\pub const link_libc = {}; - \\pub const link_libcpp = {}; - \\pub const have_error_return_tracing = {}; - \\pub const valgrind_support = {}; - \\pub const sanitize_thread = {}; - \\pub const position_independent_code = {}; - \\pub const position_independent_executable = {}; - \\pub const strip_debug_info = {}; - \\pub const code_model = std.builtin.CodeModel.{}; - \\pub const omit_frame_pointer = {}; - \\ - , .{ - std.zig.fmtId(@tagName(target.ofmt)), - std.zig.fmtId(@tagName(comp.bin_file.options.optimize_mode)), - comp.bin_file.options.link_libc, - comp.bin_file.options.link_libcpp, - comp.bin_file.options.error_return_tracing, - comp.bin_file.options.valgrind, - comp.bin_file.options.tsan, - comp.bin_file.options.pic, - comp.bin_file.options.pie, - comp.bin_file.options.strip, - std.zig.fmtId(@tagName(comp.bin_file.options.machine_code_model)), - comp.bin_file.options.omit_frame_pointer, - }); - - if (target.os.tag == .wasi) { - const wasi_exec_model_fmt = std.zig.fmtId(@tagName(comp.bin_file.options.wasi_exec_model)); - try buffer.writer().print( - \\pub const wasi_exec_model = std.builtin.WasiExecModel.{}; - \\ - , .{wasi_exec_model_fmt}); - } - - if (comp.bin_file.options.is_test) { - try buffer.appendSlice( - \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later - \\ - ); - if (comp.test_evented_io) { - try buffer.appendSlice( - \\pub const test_io_mode = .evented; - \\ - ); - } else { - try buffer.appendSlice( - \\pub const test_io_mode = .blocking; - \\ - ); - } - } - - return buffer.toOwnedSliceSentinel(0); + return target_util.zigBackend(target, comp.bin_file.options.use_llvm); } pub fn updateSubCompilation( @@ -6730,21 +6125,46 @@ fn buildOutputFromZig( const tracy_trace = trace(@src()); defer tracy_trace.end(); + var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + assert(output_mode != .Exe); - var main_mod: Package.Module = .{ - .root = .{ .root_dir = comp.zig_lib_directory }, - .root_src_path = src_basename, + const config = try Config.resolve(.{ + .output_mode = output_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = true, + .emit_bin = true, + .root_optimize_mode = comp.compilerRtOptMode(), + }); + + const root_mod = Package.Module.create(.{ + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = src_basename, + }, .fully_qualified_name = "root", - }; + .inherited = .{ + .strip = comp.compilerRtStrip(), + .stack_check = false, + .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, + .pic = comp.root_mod.pic, + }, + .global = config, + .cc_argv = &.{}, + }); const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; const target = comp.getTarget(); - const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ + const bin_basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, .output_mode = output_mode, }); - defer comp.gpa.free(bin_basename); const emit_bin = Compilation.EmitLoc{ .directory = null, // Put it in the cache directory. @@ -6754,33 +6174,18 @@ fn buildOutputFromZig( .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .resolved = config, .cache_mode = .whole, - .target = target, .root_name = root_name, - .main_mod = &main_mod, - .output_mode = output_mode, + .root_mod = root_mod, .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), .link_mode = .Static, .function_sections = true, .data_sections = true, .no_builtin = true, - .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_unwind_tables = comp.bin_file.options.eh_frame_hdr, - .want_pic = comp.bin_file.options.pic, - .want_pie = null, .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, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, @@ -6815,7 +6220,7 @@ pub fn build_crt_file( output_mode: std.builtin.OutputMode, misc_task_tag: MiscTask, prog_node: *std.Progress.Node, - c_source_files: []const Compilation.CSourceFile, + c_source_files: []const CSourceFile, ) !void { const tracy_trace = trace(@src()); defer tracy_trace.end(); diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig new file mode 100644 index 000000000000..0b9c70fc4244 --- /dev/null +++ b/src/Compilation/Config.zig @@ -0,0 +1,382 @@ +//! User-specified settings that have all the defaults resolved into concrete values. + +have_zcu: bool, +output_mode: std.builtin.OutputMode, +link_mode: std.builtin.LinkMode, +link_libc: bool, +link_libcpp: bool, +link_libunwind: bool, +any_unwind_tables: bool, +pie: bool, +/// If this is true then linker code is responsible for making an LLVM IR +/// Module, outputting it to an object file, and then linking that together +/// with link options and other objects. Otherwise (depending on `use_lld`) +/// linker code directly outputs and updates the final binary. +use_llvm: bool, +/// Whether or not the LLVM library API will be used by the LLVM backend. +use_lib_llvm: bool, +/// If this is true then linker code is responsible for outputting an object +/// file and then using LLD to link it together with the link options and other +/// objects. Otherwise (depending on `use_llvm`) linker code directly outputs +/// and updates the final binary. +use_lld: bool, +c_frontend: CFrontend, +lto: bool, +/// WASI-only. Type of WASI execution model ("command" or "reactor"). +/// Always set to `command` for non-WASI targets. +wasi_exec_model: std.builtin.WasiExecModel, +import_memory: bool, +export_memory: bool, +shared_memory: bool, +is_test: bool, +test_evented_io: bool, +entry: ?[]const u8, + +pub const CFrontend = enum { clang, aro }; + +pub const Options = struct { + output_mode: std.builtin.OutputMode, + resolved_target: Module.ResolvedTarget, + is_test: bool, + have_zcu: bool, + emit_bin: bool, + root_optimize_mode: ?std.builtin.OptimizeMode = null, + link_mode: ?std.builtin.LinkMode = null, + ensure_libc_on_non_freestanding: bool = false, + ensure_libcpp_on_non_freestanding: bool = false, + any_non_single_threaded: bool = false, + any_sanitize_thread: bool = false, + any_unwind_tables: bool = false, + any_dyn_libs: bool = false, + c_source_files_len: usize = 0, + emit_llvm_ir: bool = false, + emit_llvm_bc: bool = false, + link_libc: ?bool = null, + link_libcpp: ?bool = null, + link_libunwind: ?bool = null, + pie: ?bool = null, + use_llvm: ?bool = null, + use_lib_llvm: ?bool = null, + use_lld: ?bool = null, + use_clang: ?bool = null, + lto: ?bool = null, + entry: union(enum) { + default, + disabled, + enabled, + named: []const u8, + } = .default, + /// WASI-only. Type of WASI execution model ("command" or "reactor"). + wasi_exec_model: ?std.builtin.WasiExecModel = null, + import_memory: ?bool = null, + export_memory: ?bool = null, + shared_memory: ?bool = null, + test_evented_io: bool = false, +}; + +pub fn resolve(options: Options) !Config { + const target = options.resolved_target.result; + + // WASI-only. Resolve the optional exec-model option, defaults to command. + if (target.os.tag != .wasi and options.wasi_exec_model != null) + return error.WasiExecModelRequiresWasi; + const wasi_exec_model = options.wasi_exec_model orelse .command; + + const shared_memory = b: { + if (!target.cpu.arch.isWasm()) { + if (options.shared_memory == true) return error.SharedMemoryIsWasmOnly; + break :b false; + } + if (options.output_mode == .Obj) { + if (options.shared_memory == true) return error.ObjectFilesCannotShareMemory; + break :b false; + } + if (!std.Target.wasm.featureSetHasAll(target.cpu.features, .{ .atomics, .bulk_memory })) { + if (options.shared_memory == true) + return error.SharedMemoryRequiresAtomicsAndBulkMemory; + break :b false; + } + if (options.any_non_single_threaded) { + if (options.shared_memory == false) + return error.ThreadsRequireSharedMemory; + break :b true; + } + break :b options.shared_memory orelse false; + }; + + const entry: ?[]const u8 = switch (options.entry) { + .disabled => null, + .default => b: { + if (options.output_mode != .Exe) break :b null; + break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse + return error.UnknownTargetEntryPoint; + }, + .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse + return error.UnknownTargetEntryPoint, + .named => |name| name, + }; + if (entry != null and options.output_mode != .Exe) + return error.NonExecutableEntryPoint; + + // *If* the LLVM backend were to be selected, should Zig use the LLVM + // library to build the LLVM module? + const use_lib_llvm = b: { + if (!build_options.have_llvm) { + if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable; + break :b false; + } + break :b options.use_lib_llvm orelse true; + }; + + const root_optimize_mode = options.root_optimize_mode orelse .Debug; + + // Make a decision on whether to use LLVM backend for machine code generation. + // Note that using the LLVM backend does not necessarily mean using LLVM libraries. + // For example, Zig can emit .bc and .ll files directly, and this is still considered + // using "the LLVM backend". + const use_llvm = b: { + // If emitting to LLVM bitcode object format, must use LLVM backend. + if (options.emit_llvm_ir or options.emit_llvm_bc) { + if (options.use_llvm == false) return error.EmittingLlvmModuleRequiresLlvmBackend; + break :b true; + } + + // If LLVM does not support the target, then we can't use it. + if (!target_util.hasLlvmSupport(target, target.ofmt)) { + if (options.use_llvm == true) return error.LlvmLacksTargetSupport; + break :b false; + } + + if (options.use_llvm) |x| break :b x; + + // If we have no zig code to compile, no need for LLVM. + if (!options.have_zcu) break :b false; + + // If we cannot use LLVM libraries, then our own backends will be a + // better default since the LLVM backend can only produce bitcode + // and not an object file or executable. + if (!use_lib_llvm) break :b false; + + // Prefer LLVM for release builds. + if (root_optimize_mode != .Debug) break :b true; + + // At this point we would prefer to use our own self-hosted backend, + // because the compilation speed is better than LLVM. But only do it if + // we are confident in the robustness of the backend. + break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target); + }; + + if (!use_lib_llvm and use_llvm and options.emit_bin) { + // Explicit request to use LLVM to produce an object file, but without + // using LLVM libraries. Impossible. + return error.EmittingBinaryRequiresLlvmLibrary; + } + + // Make a decision on whether to use LLD or our own linker. + const use_lld = b: { + if (target.isDarwin()) { + if (options.use_lld == true) return error.LldIncompatibleOs; + break :b false; + } + + if (!build_options.have_llvm) { + if (options.use_lld == true) return error.LldUnavailable; + break :b false; + } + + if (target.ofmt == .c) { + if (options.use_lld == true) return error.LldIncompatibleObjectFormat; + break :b false; + } + + if (options.lto == true) { + if (options.use_lld == false) return error.LtoRequiresLld; + break :b true; + } + + if (options.use_lld) |x| break :b x; + break :b true; + }; + + // Make a decision on whether to use Clang or Aro for translate-c and compiling C files. + const c_frontend: CFrontend = b: { + if (!build_options.have_llvm) { + if (options.use_clang == true) return error.ClangUnavailable; + break :b .aro; + } + if (options.use_clang) |clang| { + break :b if (clang) .clang else .aro; + } + break :b .clang; + }; + + const lto = b: { + if (!use_lld) { + // zig ld LTO support is tracked by + // https://github.com/ziglang/zig/issues/8680 + if (options.lto == true) return error.LtoRequiresLld; + break :b false; + } + + if (options.lto) |x| break :b x; + if (options.c_source_files_len == 0) break :b false; + + if (target.cpu.arch.isRISCV()) { + // Clang and LLVM currently don't support RISC-V target-abi for LTO. + // Compiling with LTO may fail or produce undesired results. + // See https://reviews.llvm.org/D71387 + // See https://reviews.llvm.org/D102582 + break :b false; + } + + break :b switch (options.output_mode) { + .Lib, .Obj => false, + .Exe => switch (root_optimize_mode) { + .Debug => false, + .ReleaseSafe, .ReleaseFast, .ReleaseSmall => true, + }, + }; + }; + + const link_libcpp = b: { + if (options.link_libcpp == true) break :b true; + if (options.any_sanitize_thread) { + // TSAN is (for now...) implemented in C++ so it requires linking libc++. + if (options.link_libcpp == false) return error.SanitizeThreadRequiresLibCpp; + break :b true; + } + if (options.ensure_libcpp_on_non_freestanding and target.os.tag != .freestanding) + break :b true; + + break :b false; + }; + + const link_libunwind = b: { + if (link_libcpp and target_util.libcNeedsLibUnwind(target)) { + if (options.link_libunwind == false) return error.LibCppRequiresLibUnwind; + break :b true; + } + break :b options.link_libunwind orelse false; + }; + + const link_libc = b: { + if (target_util.osRequiresLibC(target)) { + if (options.link_libc == false) return error.OsRequiresLibC; + break :b true; + } + if (link_libcpp) { + if (options.link_libc == false) return error.LibCppRequiresLibC; + break :b true; + } + if (link_libunwind) { + if (options.link_libc == false) return error.LibUnwindRequiresLibC; + break :b true; + } + if (options.link_libc) |x| break :b x; + if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding) + break :b true; + + break :b false; + }; + + const any_unwind_tables = options.any_unwind_tables or + link_libunwind or target_util.needUnwindTables(target); + + const link_mode = b: { + const explicitly_exe_or_dyn_lib = switch (options.output_mode) { + .Obj => false, + .Lib => (options.link_mode orelse .Static) == .Dynamic, + .Exe => true, + }; + + if (target_util.cannotDynamicLink(target)) { + if (options.link_mode == .Dynamic) return error.TargetCannotDynamicLink; + break :b .Static; + } + if (explicitly_exe_or_dyn_lib and link_libc and + (target.isGnuLibC() or target_util.osRequiresLibC(target))) + { + if (options.link_mode == .Static) return error.LibCRequiresDynamicLinking; + break :b .Dynamic; + } + // When creating a executable that links to system libraries, we + // require dynamic linking, but we must not link static libraries + // or object files dynamically! + if (options.any_dyn_libs and options.output_mode == .Exe) { + if (options.link_mode == .Static) return error.SharedLibrariesRequireDynamicLinking; + break :b .Dynamic; + } + + if (options.link_mode) |link_mode| break :b link_mode; + + if (explicitly_exe_or_dyn_lib and link_libc and + options.resolved_target.is_native_abi and target.abi.isMusl()) + { + // If targeting the system's native ABI and the system's libc is + // musl, link dynamically by default. + break :b .Dynamic; + } + + // Static is generally a better default. Fight me. + break :b .Static; + }; + + const import_memory = options.import_memory orelse false; + const export_memory = b: { + if (link_mode == .Dynamic) { + if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible; + break :b false; + } + if (options.export_memory) |x| break :b x; + break :b !import_memory; + }; + + const pie: bool = b: { + switch (options.output_mode) { + .Obj, .Exe => {}, + .Lib => if (link_mode == .Dynamic) { + if (options.pie == true) return error.DynamicLibraryPrecludesPie; + break :b false; + }, + } + if (target_util.requiresPIE(target)) { + if (options.pie == false) return error.TargetRequiresPie; + break :b true; + } + if (options.any_sanitize_thread) { + if (options.pie == false) return error.SanitizeThreadRequiresPie; + break :b true; + } + if (options.pie) |pie| break :b pie; + break :b false; + }; + + return .{ + .output_mode = options.output_mode, + .have_zcu = options.have_zcu, + .is_test = options.is_test, + .test_evented_io = options.test_evented_io, + .link_mode = link_mode, + .link_libc = link_libc, + .link_libcpp = link_libcpp, + .link_libunwind = link_libunwind, + .any_unwind_tables = any_unwind_tables, + .pie = pie, + .lto = lto, + .import_memory = import_memory, + .export_memory = export_memory, + .shared_memory = shared_memory, + .c_frontend = c_frontend, + .use_llvm = use_llvm, + .use_lib_llvm = use_lib_llvm, + .use_lld = use_lld, + .entry = entry, + .wasi_exec_model = wasi_exec_model, + }; +} + +const std = @import("std"); +const Module = @import("../Package.zig").Module; +const Config = @This(); +const target_util = @import("../target.zig"); +const build_options = @import("build_options"); diff --git a/src/Module.zig b/src/Module.zig index 6e5609f63c02..5ec949293e55 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -59,6 +59,7 @@ root_mod: *Package.Module, /// Normally, `main_mod` and `root_mod` are the same. The exception is `zig test`, in which /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. main_mod: *Package.Module, +std_mod: *Package.Module, sema_prog_node: std.Progress.Node = undefined, /// Used by AstGen worker to load and store ZIR cache. @@ -3599,7 +3600,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { // TODO: figure out how this works under incremental changes to builtin.zig! const builtin_type_target_index: InternPool.Index = blk: { - const std_mod = mod.main_mod.deps.get("std").?; + const std_mod = mod.std_mod; if (decl.getFileScope(mod).mod != std_mod) break :blk .none; // We're in the std module. const std_file = (try mod.importPkg(std_mod)).file; @@ -3924,10 +3925,7 @@ pub fn importFile( import_string: []const u8, ) !ImportFileResult { if (std.mem.eql(u8, import_string, "std")) { - return mod.importPkg(mod.main_mod.deps.get("std").?); - } - if (std.mem.eql(u8, import_string, "builtin")) { - return mod.importPkg(mod.main_mod.deps.get("builtin").?); + return mod.importPkg(mod.std_mod); } if (std.mem.eql(u8, import_string, "root")) { return mod.importPkg(mod.root_mod); diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 0c8d40bffa65..94431856acf0 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -1,6 +1,6 @@ //! Corresponds to something that Zig source code can `@import`. -//! Not to be confused with src/Module.zig which should be renamed -//! to something else. https://github.com/ziglang/zig/issues/14307 +//! Not to be confused with src/Module.zig which will be renamed +//! to Zcu. https://github.com/ziglang/zig/issues/14307 /// Only files inside this directory can be imported. root: Package.Path, @@ -14,6 +14,26 @@ fully_qualified_name: []const u8, /// responsible for detecting these names and using the correct package. deps: Deps = .{}, +resolved_target: ResolvedTarget, +optimize_mode: std.builtin.OptimizeMode, +code_model: std.builtin.CodeModel, +single_threaded: bool, +error_tracing: bool, +valgrind: bool, +pic: bool, +strip: bool, +omit_frame_pointer: bool, +stack_check: bool, +stack_protector: u32, +red_zone: bool, +sanitize_c: bool, +sanitize_thread: bool, +unwind_tables: bool, +cc_argv: []const []const u8, + +/// The contents of `@import("builtin")` for this module. +generated_builtin_source: []const u8, + pub const Deps = std.StringArrayHashMapUnmanaged(*Module); pub const Tree = struct { @@ -21,10 +41,382 @@ pub const Tree = struct { build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module), }; -pub fn create(allocator: Allocator, m: Module) Allocator.Error!*Module { - const new = try allocator.create(Module); - new.* = m; - return new; +pub const CreateOptions = struct { + /// Where to store builtin.zig. The global cache directory is used because + /// it is a pure function based on CLI flags. + global_cache_directory: Cache.Directory, + paths: Paths, + fully_qualified_name: []const u8, + + cc_argv: []const []const u8, + inherited: Inherited, + global: Compilation.Config, + /// If this is null then `resolved_target` must be non-null. + parent: ?*Package.Module, + + builtin_mod: ?*Package.Module, + + pub const Paths = struct { + root: Package.Path, + /// Relative to `root`. May contain path separators. + root_src_path: []const u8, + }; + + pub const Inherited = struct { + /// If this is null then `parent` must be non-null. + resolved_target: ?ResolvedTarget = null, + optimize_mode: ?std.builtin.OptimizeMode = null, + code_model: ?std.builtin.CodeModel = null, + single_threaded: ?bool = null, + error_tracing: ?bool = null, + valgrind: ?bool = null, + pic: ?bool = null, + strip: ?bool = null, + omit_frame_pointer: ?bool = null, + stack_check: ?bool = null, + /// null means default. + /// 0 means no stack protector. + /// other number means stack protection with that buffer size. + stack_protector: ?u32 = null, + red_zone: ?bool = null, + unwind_tables: ?bool = null, + sanitize_c: ?bool = null, + sanitize_thread: ?bool = null, + }; +}; + +pub const ResolvedTarget = struct { + result: std.Target, + is_native_os: bool, + is_native_abi: bool, + llvm_cpu_features: ?[*:0]const u8 = null, +}; + +/// At least one of `parent` and `resolved_target` must be non-null. +pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { + const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target; + const target = resolved_target.result; + + const optimize_mode = options.inherited.optimize_mode orelse + if (options.parent) |p| p.optimize_mode else .Debug; + + const unwind_tables = options.inherited.unwind_tables orelse + if (options.parent) |p| p.unwind_tables else options.global.any_unwind_tables; + + const strip = b: { + if (options.inherited.strip) |x| break :b x; + if (options.parent) |p| break :b p.strip; + if (optimize_mode == .ReleaseSmall) break :b true; + if (!target_util.hasDebugInfo(target)) break :b true; + break :b false; + }; + + const valgrind = b: { + if (!target_util.hasValgrindSupport(target)) { + if (options.inherited.valgrind == true) + return error.ValgrindUnsupportedOnTarget; + break :b false; + } + if (options.inherited.valgrind) |x| break :b x; + if (options.parent) |p| break :b p.valgrind; + if (strip) break :b false; + break :b optimize_mode == .Debug; + }; + + const zig_backend = target_util.zigBackend(target, options.global.use_llvm); + + const single_threaded = b: { + if (target_util.alwaysSingleThreaded(target)) { + if (options.inherited.single_threaded == false) + return error.TargetRequiresSingleThreaded; + break :b true; + } + + if (options.global.have_zcu) { + if (!target_util.supportsThreads(target, zig_backend)) { + if (options.inherited.single_threaded == false) + return error.BackendRequiresSingleThreaded; + break :b true; + } + } + + if (options.inherited.single_threaded) |x| break :b x; + if (options.parent) |p| break :b p.single_threaded; + break :b target_util.defaultSingleThreaded(target); + }; + + const error_tracing = b: { + if (options.inherited.error_tracing) |x| break :b x; + if (options.parent) |p| break :b p.error_tracing; + if (strip) break :b false; + break :b switch (optimize_mode) { + .Debug => true, + .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, + }; + }; + + const pic = b: { + if (target_util.requiresPIC(target, options.global.link_libc)) { + if (options.inherited.pic == false) + return error.TargetRequiresPic; + break :b true; + } + if (options.global.pie) { + if (options.inherited.pic == false) + return error.PieRequiresPic; + break :b true; + } + if (options.global.link_mode == .Dynamic) { + if (options.inherited.pic == false) + return error.DynamicLinkingRequiresPic; + break :b true; + } + if (options.inherited.pic) |x| break :b x; + if (options.parent) |p| break :b p.pic; + break :b false; + }; + + const red_zone = b: { + if (!target_util.hasRedZone(target)) { + if (options.inherited.red_zone == true) + return error.TargetHasNoRedZone; + break :b true; + } + if (options.inherited.red_zone) |x| break :b x; + if (options.parent) |p| break :b p.red_zone; + break :b true; + }; + + const omit_frame_pointer = b: { + if (options.inherited.omit_frame_pointer) |x| break :b x; + if (options.parent) |p| break :b p.omit_frame_pointer; + if (optimize_mode == .Debug) break :b false; + break :b true; + }; + + const sanitize_thread = b: { + if (options.inherited.sanitize_thread) |x| break :b x; + if (options.parent) |p| break :b p.sanitize_thread; + break :b false; + }; + + const code_model = b: { + if (options.inherited.code_model) |x| break :b x; + if (options.parent) |p| break :b p.code_model; + break :b .default; + }; + + const is_safe_mode = switch (optimize_mode) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, + }; + + const sanitize_c = b: { + if (options.inherited.sanitize_c) |x| break :b x; + if (options.parent) |p| break :b p.sanitize_c; + break :b is_safe_mode; + }; + + const stack_check = b: { + if (!target_util.supportsStackProbing(target)) { + if (options.inherited.stack_check == true) + return error.StackCheckUnsupportedByTarget; + break :b false; + } + if (options.inherited.stack_check) |x| break :b x; + if (options.parent) |p| break :b p.stack_check; + break :b is_safe_mode; + }; + + const stack_protector: u32 = sp: { + if (!target_util.supportsStackProtector(target, zig_backend)) { + if (options.inherited.stack_protector) |x| { + if (x > 0) return error.StackProtectorUnsupportedByTarget; + } + break :sp 0; + } + + // This logic is checking for linking libc because otherwise our start code + // which is trying to set up TLS (i.e. the fs/gs registers) but the stack + // protection code depends on fs/gs registers being already set up. + // If we were able to annotate start code, or perhaps the entire std lib, + // as being exempt from stack protection checks, we could change this logic + // to supporting stack protection even when not linking libc. + // TODO file issue about this + if (!options.global.link_libc) { + if (options.inherited.stack_protector) |x| { + if (x > 0) return error.StackProtectorUnavailableWithoutLibC; + } + break :sp 0; + } + + if (options.inherited.stack_protector) |x| break :sp x; + if (options.parent) |p| break :sp p.stack_protector; + if (!is_safe_mode) break :sp 0; + + break :sp target_util.default_stack_protector_buffer_size; + }; + + 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; + + var buf = std.ArrayList(u8).init(arena); + for (target.cpu.arch.allFeaturesList(), 0..) |feature, index_usize| { + const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); + const is_enabled = target.cpu.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@intFromBool(is_enabled)]; + try buf.ensureUnusedCapacity(2 + llvm_name.len); + buf.appendAssumeCapacity(plus_or_minus); + buf.appendSliceAssumeCapacity(llvm_name); + buf.appendSliceAssumeCapacity(","); + } + } + if (buf.items.len == 0) break :b ""; + assert(std.mem.endsWith(u8, buf.items, ",")); + buf.items[buf.items.len - 1] = 0; + buf.shrinkAndFree(buf.items.len); + break :b buf.items[0 .. buf.items.len - 1 :0].ptr; + }; + + const builtin_mod = options.builtin_mod orelse b: { + const generated_builtin_source = try Builtin.generate(.{ + .target = target, + .zig_backend = zig_backend, + .output_mode = options.global.output_mode, + .link_mode = options.global.link_mode, + .is_test = options.global.is_test, + .test_evented_io = options.global.test_evented_io, + .single_threaded = single_threaded, + .link_libc = options.global.link_libc, + .link_libcpp = options.global.link_libcpp, + .optimize_mode = optimize_mode, + .error_tracing = error_tracing, + .valgrind = valgrind, + .sanitize_thread = sanitize_thread, + .pic = pic, + .pie = options.global.pie, + .strip = strip, + .code_model = code_model, + .omit_frame_pointer = omit_frame_pointer, + .wasi_exec_model = options.global.wasi_exec_model, + }, arena); + + const digest = Cache.HashHelper.oneShot(generated_builtin_source); + const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest); + const new = try arena.create(Module); + new.* = .{ + .root = .{ + .root_dir = options.global_cache_directory, + .sub_path = builtin_sub_path, + }, + .root_src_path = "builtin.zig", + .fully_qualified_name = if (options.parent == null) + "builtin" + else + try std.fmt.allocPrint(arena, "{s}.builtin", .{options.fully_qualified_name}), + .resolved_target = .{ + .result = target, + .is_native_os = resolved_target.is_native_os, + .is_native_abi = resolved_target.is_native_abi, + .llvm_cpu_features = llvm_cpu_features, + }, + .optimize_mode = optimize_mode, + .single_threaded = single_threaded, + .error_tracing = error_tracing, + .valgrind = valgrind, + .pic = pic, + .strip = strip, + .omit_frame_pointer = omit_frame_pointer, + .stack_check = stack_check, + .stack_protector = stack_protector, + .code_model = code_model, + .red_zone = red_zone, + .generated_builtin_source = generated_builtin_source, + .sanitize_c = sanitize_c, + .sanitize_thread = sanitize_thread, + .unwind_tables = unwind_tables, + .cc_argv = &.{}, + }; + break :b new; + }; + + const mod = try arena.create(Module); + mod.* = .{ + .root = options.paths.root, + .root_src_path = options.paths.root_src_path, + .fully_qualified_name = options.fully_qualified_name, + .resolved_target = .{ + .result = target, + .is_native_os = resolved_target.is_native_os, + .is_native_abi = resolved_target.is_native_abi, + .llvm_cpu_features = llvm_cpu_features, + }, + .optimize_mode = optimize_mode, + .single_threaded = single_threaded, + .error_tracing = error_tracing, + .valgrind = valgrind, + .pic = pic, + .strip = strip, + .omit_frame_pointer = omit_frame_pointer, + .stack_check = stack_check, + .stack_protector = stack_protector, + .code_model = code_model, + .red_zone = red_zone, + .generated_builtin_source = builtin_mod.generated_builtin_source, + .sanitize_c = sanitize_c, + .sanitize_thread = sanitize_thread, + .unwind_tables = unwind_tables, + .cc_argv = options.cc_argv, + }; + + try mod.deps.ensureUnusedCapacity(arena, 1); + mod.deps.putAssumeCapacityNoClobber("builtin", builtin_mod); + + return mod; +} + +/// All fields correspond to `CreateOptions`. +pub const LimitedOptions = struct { + root: Package.Path, + root_src_path: []const u8, + fully_qualified_name: []const u8, +}; + +/// This one can only be used if the Module will only be used for AstGen and earlier in +/// the pipeline. Illegal behavior occurs if a limited module touches Sema. +pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*Package.Module { + const mod = try gpa.create(Module); + mod.* = .{ + .root = options.root, + .root_src_path = options.root_src_path, + .fully_qualified_name = options.fully_qualified_name, + + .resolved_target = undefined, + .optimize_mode = undefined, + .code_model = undefined, + .single_threaded = undefined, + .error_tracing = undefined, + .valgrind = undefined, + .pic = undefined, + .strip = undefined, + .omit_frame_pointer = undefined, + .stack_check = undefined, + .stack_protector = undefined, + .red_zone = undefined, + .sanitize_c = undefined, + .sanitize_thread = undefined, + .unwind_tables = undefined, + .cc_argv = undefined, + .generated_builtin_source = undefined, + }; + return mod; +} + +pub fn getBuiltinDependency(m: *Module) *Module { + return m.deps.values()[0]; } const Module = @This(); @@ -32,3 +424,8 @@ const Package = @import("../Package.zig"); const std = @import("std"); const Allocator = std.mem.Allocator; const MultiHashHexDigest = Package.Manifest.MultiHashHexDigest; +const target_util = @import("../target.zig"); +const Cache = std.Build.Cache; +const Builtin = @import("../Builtin.zig"); +const assert = std.debug.assert; +const Compilation = @import("../Compilation.zig"); diff --git a/src/Sema.zig b/src/Sema.zig index 516fee4543da..9d1f65584ed5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -36668,7 +36668,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int const mod = sema.mod; const ip = &mod.intern_pool; - const std_mod = mod.main_mod.deps.get("std").?; + const std_mod = mod.std_mod; const std_file = (mod.importPkg(std_mod) catch unreachable).file; const opt_builtin_inst = (try sema.namespaceLookupRef( block, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 70eab9489cc4..cf6f38a53ea8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -853,16 +853,9 @@ pub const Object = struct { /// want to iterate over it while adding entries to it. pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); - pub fn create(gpa: Allocator, options: link.Options) !*Object { - const obj = try gpa.create(Object); - errdefer gpa.destroy(obj); - obj.* = try Object.init(gpa, options); - return obj; - } - - pub fn init(gpa: Allocator, options: link.Options) !Object { - const llvm_target_triple = try targetTriple(gpa, options.target); - defer gpa.free(llvm_target_triple); + pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object { + const gpa = options.comp.gpa; + const llvm_target_triple = try targetTriple(arena, options.target); var builder = try Builder.init(.{ .allocator = gpa, @@ -899,19 +892,14 @@ pub const Object = struct { // TODO: the only concern I have with this is WASI as either host or target, should // we leave the paths as relative then? const compile_unit_dir_z = blk: { - var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; if (options.module) |mod| m: { - const d = try mod.root_mod.root.joinStringZ(builder.gpa, ""); + const d = try mod.root_mod.root.joinStringZ(arena, ""); if (d.len == 0) break :m; if (std.fs.path.isAbsolute(d)) break :blk d; - const abs = std.fs.realpath(d, &buf) catch break :blk d; - builder.gpa.free(d); - break :blk try builder.gpa.dupeZ(u8, abs); + break :blk std.fs.realpathAlloc(arena, d) catch d; } - const cwd = try std.process.getCwd(&buf); - break :blk try builder.gpa.dupeZ(u8, cwd); + break :blk try std.process.getCwdAlloc(arena); }; - defer builder.gpa.free(compile_unit_dir_z); builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( DW.LANG.C99, @@ -989,7 +977,8 @@ pub const Object = struct { } } - return .{ + const obj = try arena.create(Object); + obj.* = .{ .gpa = gpa, .builder = builder, .module = options.module.?, @@ -1009,9 +998,11 @@ pub const Object = struct { .null_opt_usize = .no_init, .struct_field_map = .{}, }; + return obj; } - pub fn deinit(self: *Object, gpa: Allocator) void { + pub fn deinit(self: *Object) void { + const gpa = self.gpa; self.di_map.deinit(gpa); self.di_type_map.deinit(gpa); if (self.builder.useLibLlvm()) { @@ -1028,11 +1019,6 @@ pub const Object = struct { self.* = undefined; } - pub fn destroy(self: *Object, gpa: Allocator) void { - self.deinit(gpa); - gpa.destroy(self); - } - fn locPath( arena: Allocator, opt_loc: ?Compilation.EmitLoc, @@ -2899,7 +2885,7 @@ pub const Object = struct { fn getStackTraceType(o: *Object) Allocator.Error!Type { const mod = o.module; - const std_mod = mod.main_mod.deps.get("std").?; + const std_mod = mod.std_mod; const std_file = (mod.importPkg(std_mod) catch unreachable).file; const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin"); diff --git a/src/link.zig b/src/link.zig index 1ad66eaf7aff..46dab1b6edbf 100644 --- a/src/link.zig +++ b/src/link.zig @@ -66,237 +66,18 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; -pub const Emit = struct { - /// Where the output will go. - directory: Compilation.Directory, - /// Path to the output file, relative to `directory`. - sub_path: []const u8, - - /// Returns the full path to `basename` if it were in the same directory as the - /// `Emit` sub_path. - pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 { - const full_path = if (emit.directory.path) |p| - try fs.path.join(arena, &[_][]const u8{ p, emit.sub_path }) - else - emit.sub_path; - - if (fs.path.dirname(full_path)) |dirname| { - return try fs.path.joinZ(arena, &.{ dirname, basename }); - } else { - return basename; - } - } -}; - -pub const Options = struct { - /// This is `null` when `-fno-emit-bin` is used. - emit: ?Emit, - /// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used. - implib_emit: ?Emit, - /// This is non-null when `-femit-docs` is provided. - docs_emit: ?Emit, - target: std.Target, - output_mode: std.builtin.OutputMode, - link_mode: std.builtin.LinkMode, - optimize_mode: std.builtin.OptimizeMode, - machine_code_model: std.builtin.CodeModel, - root_name: [:0]const u8, - /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. - module: ?*Module, - /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) - sysroot: ?[]const u8, - /// Used for calculating how much space to reserve for symbols in case the binary file - /// does not already have a symbol table. - symbol_count_hint: u64 = 32, - /// Used for calculating how much space to reserve for executable program code in case - /// the binary file does not already have such a section. - program_code_size_hint: u64 = 256 * 1024, - entry_addr: ?u64 = null, - entry: ?[]const u8, - stack_size_override: ?u64, - image_base_override: ?u64, - /// 0 means no stack protector - /// other value means stack protector with that buffer size. - stack_protector: u32, - cache_mode: CacheMode, - include_compiler_rt: bool, - /// Set to `true` to omit debug info. - strip: bool, - /// If this is true then this link code is responsible for outputting an object - /// file and then using LLD to link it together with the link options and other objects. - /// Otherwise (depending on `use_llvm`) this link code directly outputs and updates the final binary. - use_lld: bool, - /// If this is true then this link code is responsible for making an LLVM IR Module, - /// outputting it to an object file, and then linking that together with link options and - /// other objects. - /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary. - use_llvm: bool, - use_lib_llvm: bool, - link_libc: bool, - link_libcpp: bool, - link_libunwind: bool, - darwin_sdk_layout: ?DarwinSdkLayout, - function_sections: bool, - data_sections: bool, - no_builtin: bool, - eh_frame_hdr: bool, - emit_relocs: bool, - rdynamic: bool, - z_nodelete: bool, - z_notext: bool, - z_defs: bool, - z_origin: bool, - z_nocopyreloc: bool, - z_now: bool, - z_relro: bool, - z_common_page_size: ?u64, - z_max_page_size: ?u64, - tsaware: bool, - nxcompat: bool, - dynamicbase: bool, - linker_optimization: u8, - compress_debug_sections: CompressDebugSections, - bind_global_refs_locally: bool, - import_memory: bool, - export_memory: bool, - import_symbols: bool, - import_table: bool, - export_table: bool, - initial_memory: ?u64, - max_memory: ?u64, - shared_memory: bool, - export_symbol_names: []const []const u8, - global_base: ?u64, - is_native_os: bool, - is_native_abi: bool, - pic: bool, - pie: bool, - lto: bool, - valgrind: bool, - tsan: bool, - stack_check: bool, - red_zone: bool, - omit_frame_pointer: bool, - single_threaded: bool, - verbose_link: bool, - dll_export_fns: bool, - error_return_tracing: bool, - skip_linker_dependencies: bool, - each_lib_rpath: bool, - build_id: std.zig.BuildId, - disable_lld_caching: bool, - is_test: bool, - hash_style: HashStyle, - sort_section: ?SortSection, - major_subsystem_version: ?u32, - minor_subsystem_version: ?u32, - gc_sections: ?bool = null, - allow_shlib_undefined: ?bool, - subsystem: ?std.Target.SubSystem, - linker_script: ?[]const u8, - version_script: ?[]const u8, - soname: ?[]const u8, - llvm_cpu_features: ?[*:0]const u8, - print_gc_sections: bool, - print_icf_sections: bool, - print_map: bool, - opt_bisect_limit: i32, - - objects: []Compilation.LinkObject, - framework_dirs: []const []const u8, - frameworks: []const Framework, - /// These are *always* dynamically linked. Static libraries will be - /// provided as positional arguments. - system_libs: std.StringArrayHashMapUnmanaged(SystemLib), - wasi_emulated_libs: []const wasi_libc.CRTFile, - // TODO: remove this. libraries are resolved by the frontend. - lib_dirs: []const []const u8, - rpath_list: []const []const u8, - - /// List of symbols forced as undefined in the symbol table - /// thus forcing their resolution by the linker. - /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. - force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), - /// Use a wrapper function for symbol. Any undefined reference to symbol - /// will be resolved to __wrap_symbol. Any undefined reference to - /// __real_symbol will be resolved to symbol. This can be used to provide a - /// wrapper for a system function. The wrapper function should be called - /// __wrap_symbol. If it wishes to call the system function, it should call - /// __real_symbol. - symbol_wrap_set: std.StringArrayHashMapUnmanaged(void), - - version: ?std.SemanticVersion, - compatibility_version: ?std.SemanticVersion, - libc_installation: ?*const LibCInstallation, - - dwarf_format: ?std.dwarf.Format, - - /// WASI-only. Type of WASI execution model ("command" or "reactor"). - wasi_exec_model: std.builtin.WasiExecModel = undefined, - - /// (Zig compiler development) Enable dumping of linker's state as JSON. - enable_link_snapshots: bool = false, - - /// (Darwin) Install name for the dylib - install_name: ?[]const u8 = null, - - /// (Darwin) Path to entitlements file - entitlements: ?[]const u8 = null, - - /// (Darwin) size of the __PAGEZERO segment - pagezero_size: ?u64 = null, - - /// (Darwin) set minimum space for future expansion of the load commands - headerpad_size: ?u32 = null, - - /// (Darwin) set enough space as if all paths were MATPATHLEN - headerpad_max_install_names: bool = false, - - /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols - dead_strip_dylibs: bool = false, - - /// (Windows) PDB source path prefix to instruct the linker how to resolve relative - /// paths when consolidating CodeView streams into a single PDB file. - pdb_source_path: ?[]const u8 = null, - - /// (Windows) PDB output path - pdb_out_path: ?[]const u8 = null, - - /// (Windows) .def file to specify when linking - module_definition_file: ?[]const u8 = null, - - /// (SPIR-V) whether to generate a structured control flow graph or not - want_structured_cfg: ?bool = null, - - pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode { - return if (options.use_lld) .Obj else options.output_mode; - } - - pub fn move(self: *Options) Options { - const copied_state = self.*; - self.system_libs = .{}; - self.force_undefined_symbols = .{}; - return copied_state; - } -}; - pub const HashStyle = enum { sysv, gnu, both }; pub const CompressDebugSections = enum { none, zlib, zstd }; -/// The filesystem layout of darwin SDK elements. -pub const DarwinSdkLayout = enum { - /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }. - sdk, - /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, }. - vendored, -}; - pub const File = struct { tag: Tag, - options: Options, + + /// The owner of this output File. + comp: *Compilation, + emit: Compilation.Emit, + file: ?fs.File, - allocator: Allocator, /// When linking with LLD, this linker code will output an object file only at /// this location, and then this path can be placed on the LLD linker line. intermediary_basename: ?[]const u8 = null, @@ -307,103 +88,132 @@ pub const File = struct { child_pid: ?std.ChildProcess.Id = null, + pub const OpenOptions = struct { + comp: *Compilation, + emit: Compilation.Emit, + + symbol_count_hint: u64 = 32, + program_code_size_hint: u64 = 256 * 1024, + + /// Virtual address of the entry point procedure relative to image base. + entry_addr: ?u64, + stack_size_override: ?u64, + image_base_override: ?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, + z_origin: bool, + z_nocopyreloc: bool, + z_now: bool, + z_relro: bool, + z_common_page_size: ?u64, + z_max_page_size: ?u64, + tsaware: bool, + nxcompat: bool, + dynamicbase: bool, + compress_debug_sections: CompressDebugSections, + bind_global_refs_locally: bool, + import_symbols: bool, + import_table: bool, + export_table: bool, + initial_memory: ?u64, + max_memory: ?u64, + export_symbol_names: []const []const u8, + global_base: ?u64, + verbose_link: bool, + dll_export_fns: bool, + skip_linker_dependencies: bool, + parent_compilation_link_libc: bool, + each_lib_rpath: bool, + build_id: std.zig.BuildId, + disable_lld_caching: bool, + hash_style: HashStyle, + sort_section: ?SortSection, + major_subsystem_version: ?u32, + minor_subsystem_version: ?u32, + gc_sections: ?bool = null, + allow_shlib_undefined: ?bool, + subsystem: ?std.Target.SubSystem, + version_script: ?[]const u8, + soname: ?[]const u8, + print_gc_sections: bool, + print_icf_sections: bool, + print_map: bool, + opt_bisect_limit: i32, + + /// List of symbols forced as undefined in the symbol table + /// thus forcing their resolution by the linker. + /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. + force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), + /// Use a wrapper function for symbol. Any undefined reference to symbol + /// will be resolved to __wrap_symbol. Any undefined reference to + /// __real_symbol will be resolved to symbol. This can be used to provide a + /// wrapper for a system function. The wrapper function should be called + /// __wrap_symbol. If it wishes to call the system function, it should call + /// __real_symbol. + symbol_wrap_set: std.StringArrayHashMapUnmanaged(void), + + compatibility_version: ?std.SemanticVersion, + + dwarf_format: ?std.dwarf.Format, + + // TODO: remove this. libraries are resolved by the frontend. + lib_dirs: []const []const u8, + rpath_list: []const []const u8, + + /// (Zig compiler development) Enable dumping of linker's state as JSON. + enable_link_snapshots: bool, + + /// (Darwin) Install name for the dylib + install_name: ?[]const u8, + /// (Darwin) Path to entitlements file + entitlements: ?[]const u8, + /// (Darwin) size of the __PAGEZERO segment + pagezero_size: ?u64, + /// (Darwin) set minimum space for future expansion of the load commands + headerpad_size: ?u32, + /// (Darwin) set enough space as if all paths were MATPATHLEN + headerpad_max_install_names: bool, + /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols + dead_strip_dylibs: bool, + framework_dirs: []const []const u8, + frameworks: []const Framework, + darwin_sdk_layout: ?MachO.SdkLayout, + + /// (Windows) PDB source path prefix to instruct the linker how to resolve relative + /// paths when consolidating CodeView streams into a single PDB file. + pdb_source_path: ?[]const u8, + /// (Windows) PDB output path + pdb_out_path: ?[]const u8, + /// (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, + }; + /// Attempts incremental linking, if the file already exists. If /// incremental linking fails, falls back to truncating the file and /// rewriting it. A malicious file is detected as incremental link failure /// and does not cause Illegal Behavior. This operation is not atomic. - pub fn openPath(allocator: Allocator, options: Options) !*File { - const have_macho = !build_options.only_c; - if (have_macho and options.target.ofmt == .macho) { - return &(try MachO.openPath(allocator, options)).base; - } - - if (options.emit == null) { - return switch (options.target.ofmt) { - .coff => &(try Coff.createEmpty(allocator, options)).base, - .elf => &(try Elf.createEmpty(allocator, options)).base, - .macho => unreachable, - .wasm => &(try Wasm.createEmpty(allocator, options)).base, - .plan9 => return &(try Plan9.createEmpty(allocator, options)).base, - .c => unreachable, // Reported error earlier. - .spirv => &(try SpirV.createEmpty(allocator, options)).base, - .nvptx => &(try NvPtx.createEmpty(allocator, options)).base, - .hex => return error.HexObjectFormatUnimplemented, - .raw => return error.RawObjectFormatUnimplemented, - .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, - }; - } - const emit = options.emit.?; - const use_lld = build_options.have_llvm and options.use_lld; // comptime-known false when !have_llvm - const sub_path = if (use_lld) blk: { - if (options.module == null) { - // No point in opening a file, we would not write anything to it. - // Initialize with empty. - return switch (options.target.ofmt) { - .coff => &(try Coff.createEmpty(allocator, options)).base, - .elf => &(try Elf.createEmpty(allocator, options)).base, - .macho => unreachable, - .plan9 => &(try Plan9.createEmpty(allocator, options)).base, - .wasm => &(try Wasm.createEmpty(allocator, options)).base, - .c => unreachable, // Reported error earlier. - .spirv => &(try SpirV.createEmpty(allocator, options)).base, - .nvptx => &(try NvPtx.createEmpty(allocator, options)).base, - .hex => return error.HexObjectFormatUnimplemented, - .raw => return error.RawObjectFormatUnimplemented, - .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, - }; - } - // Open a temporary object file, not the final output file because we - // want to link with LLD. - break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{ - emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), - }); - } else emit.sub_path; - errdefer if (use_lld) allocator.free(sub_path); - - const file: *File = f: { - switch (options.target.ofmt) { - .coff => { - if (build_options.only_c) unreachable; - break :f &(try Coff.openPath(allocator, sub_path, options)).base; - }, - .elf => { - if (build_options.only_c) unreachable; - break :f &(try Elf.openPath(allocator, sub_path, options)).base; - }, - .macho => unreachable, - .plan9 => { - if (build_options.only_c) unreachable; - break :f &(try Plan9.openPath(allocator, sub_path, options)).base; - }, - .wasm => { - if (build_options.only_c) unreachable; - break :f &(try Wasm.openPath(allocator, sub_path, options)).base; - }, - .c => { - break :f &(try C.openPath(allocator, sub_path, options)).base; - }, - .spirv => { - if (build_options.only_c) unreachable; - break :f &(try SpirV.openPath(allocator, sub_path, options)).base; - }, - .nvptx => { - if (build_options.only_c) unreachable; - break :f &(try NvPtx.openPath(allocator, sub_path, options)).base; - }, - .hex => return error.HexObjectFormatUnimplemented, - .raw => return error.RawObjectFormatUnimplemented, - .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, - } - }; - - if (use_lld) { - // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`, - // we also want to put the intermediary object file in the cache while the - // main emit directory is the cwd. - file.intermediary_basename = sub_path; + /// `arena` is used for allocations with the same lifetime as the created File. + pub fn open(arena: Allocator, options: OpenOptions) !*File { + switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) { + inline else => |tag| { + const ptr = try tag.Type().open(arena, options); + return &ptr.base; + }, } - - return file; } pub fn cast(base: *File, comptime T: type) ?*T { @@ -664,56 +474,45 @@ pub const File = struct { pub fn destroy(base: *File) void { base.releaseLock(); if (base.file) |f| f.close(); - if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); - base.options.system_libs.deinit(base.allocator); - base.options.force_undefined_symbols.deinit(base.allocator); switch (base.tag) { .coff => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(Coff, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .elf => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(Elf, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .macho => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(MachO, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .c => { const parent = @fieldParentPtr(C, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .wasm => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(Wasm, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .spirv => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(SpirV, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .plan9 => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(Plan9, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, .nvptx => { if (build_options.only_c) unreachable; const parent = @fieldParentPtr(NvPtx, "base", base); parent.deinit(); - base.allocator.destroy(parent); }, } } @@ -1197,6 +996,35 @@ pub const File = struct { spirv, plan9, nvptx, + + pub fn Type(comptime tag: Tag) type { + return switch (tag) { + .coff => Coff, + .elf => Elf, + .macho => MachO, + .c => C, + .wasm => Wasm, + .spirv => SpirV, + .plan9 => Plan9, + .nvptx => NvPtx, + }; + } + + pub fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag { + return switch (ofmt) { + .coff => .coff, + .elf => .elf, + .macho => .macho, + .wasm => .wasm, + .plan9 => .plan9, + .c => .c, + .spirv => .spirv, + .nvptx => .nvptx, + .hex => @panic("TODO implement hex object format"), + .raw => @panic("TODO implement raw object format"), + .dxcontainer => @panic("TODO implement dxcontainer object format"), + }; + } }; pub const ErrorFlags = struct { @@ -1235,6 +1063,33 @@ pub const File = struct { } }; + pub fn effectiveOutputMode( + use_lld: bool, + output_mode: std.builtin.OutputMode, + ) std.builtin.OutputMode { + return if (use_lld) .Obj else output_mode; + } + + pub fn determineMode( + use_lld: bool, + output_mode: std.builtin.OutputMode, + link_mode: std.builtin.LinkMode, + ) fs.File.Mode { + // On common systems with a 0o022 umask, 0o777 will still result in a file created + // with 0o755 permissions, but it works appropriately if the system is configured + // more leniently. As another data point, C's fopen seems to open files with the + // 666 mode. + const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777; + switch (effectiveOutputMode(use_lld, output_mode)) { + .Lib => return switch (link_mode) { + .Dynamic => executable_mode, + .Static => fs.File.default_mode, + }, + .Exe => return executable_mode, + .Obj => return fs.File.default_mode, + } + } + pub const C = @import("link/C.zig"); pub const Coff = @import("link/Coff.zig"); pub const Plan9 = @import("link/Plan9.zig"); @@ -1245,19 +1100,3 @@ pub const File = struct { pub const NvPtx = @import("link/NvPtx.zig"); pub const Dwarf = @import("link/Dwarf.zig"); }; - -pub fn determineMode(options: Options) fs.File.Mode { - // On common systems with a 0o022 umask, 0o777 will still result in a file created - // with 0o755 permissions, but it works appropriately if the system is configured - // more leniently. As another data point, C's fopen seems to open files with the - // 666 mode. - const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777; - switch (options.effectiveOutputMode()) { - .Lib => return switch (options.link_mode) { - .Dynamic => executable_mode, - .Static => fs.File.default_mode, - }, - .Exe => return executable_mode, - .Obj => return fs.File.default_mode, - } -} diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 5fbf02871adf..e477aeffcf48 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -48,9 +48,6 @@ got_table_count_dirty: bool = true, got_table_contents_dirty: bool = true, imports_count_dirty: bool = true, -/// Virtual address of the entry point procedure relative to image base. -entry_addr: ?u32 = null, - /// Table of tracked LazySymbols. lazy_syms: LazySymbolTable = .{}, @@ -226,44 +223,150 @@ const ideal_factor = 3; const minimum_text_block_size = 64; pub const min_text_capacity = padToIdeal(minimum_text_block_size); -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Coff { - assert(options.target.ofmt == .coff); +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { + if (build_options.only_c) unreachable; + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .coff); + + const self = try createEmpty(arena, options); + errdefer self.base.destroy(); + + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; - if (options.use_llvm) { - return createEmpty(allocator, options); + if (use_lld and use_llvm) { + // LLVM emits the object file; LLD links it into the final product. + return self; } - const self = try createEmpty(allocator, options); - errdefer self.base.destroy(); + const sub_path = if (!use_lld) options.emit.sub_path else p: { + // Open a temporary object file, not the final output file because we + // want to link with LLD. + const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ + options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + }); + self.base.intermediary_basename = o_file_path; + break :p o_file_path; + }; - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + self.base.file = try options.emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode( + use_lld, + options.comp.config.output_mode, + options.comp.config.link_mode, + ), }); - self.base.file = file; - try self.populateMissingMetadata(); + assert(self.llvm_object == null); + const gpa = self.base.comp.gpa; + + try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32)); + self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32)); + + try self.temp_strtab.buffer.append(gpa, 0); + + // Index 0 is always a null symbol. + try self.locals.append(gpa, .{ + .name = [_]u8{0} ** 8, + .value = 0, + .section_number = .UNDEFINED, + .type = .{ .base_type = .NULL, .complex_type = .NULL }, + .storage_class = .NULL, + .number_of_aux_symbols = 0, + }); + + if (self.text_section_index == null) { + const file_size: u32 = @intCast(options.program_code_size_hint); + self.text_section_index = try self.allocateSection(".text", file_size, .{ + .CNT_CODE = 1, + .MEM_EXECUTE = 1, + .MEM_READ = 1, + }); + } + + if (self.got_section_index == null) { + const file_size = @as(u32, @intCast(options.symbol_count_hint)) * self.ptr_width.size(); + self.got_section_index = try self.allocateSection(".got", file_size, .{ + .CNT_INITIALIZED_DATA = 1, + .MEM_READ = 1, + }); + } + + if (self.rdata_section_index == null) { + const file_size: u32 = self.page_size; + self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{ + .CNT_INITIALIZED_DATA = 1, + .MEM_READ = 1, + }); + } + + if (self.data_section_index == null) { + const file_size: u32 = self.page_size; + self.data_section_index = try self.allocateSection(".data", file_size, .{ + .CNT_INITIALIZED_DATA = 1, + .MEM_READ = 1, + .MEM_WRITE = 1, + }); + } + + if (self.idata_section_index == null) { + const file_size = @as(u32, @intCast(options.symbol_count_hint)) * self.ptr_width.size(); + self.idata_section_index = try self.allocateSection(".idata", file_size, .{ + .CNT_INITIALIZED_DATA = 1, + .MEM_READ = 1, + }); + } + + if (self.reloc_section_index == null) { + const file_size = @as(u32, @intCast(options.symbol_count_hint)) * @sizeOf(coff.BaseRelocation); + self.reloc_section_index = try self.allocateSection(".reloc", file_size, .{ + .CNT_INITIALIZED_DATA = 1, + .MEM_DISCARDABLE = 1, + .MEM_READ = 1, + }); + } + + if (self.strtab_offset == null) { + const file_size = @as(u32, @intCast(self.strtab.buffer.items.len)); + self.strtab_offset = self.findFreeSpace(file_size, @alignOf(u32)); // 4bytes aligned seems like a good idea here + log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + file_size }); + } + + { + // We need to find out what the max file offset is according to section headers. + // Otherwise, we may end up with an COFF binary with file size not matching the final section's + // offset + it's filesize. + // TODO I don't like this here one bit + var max_file_offset: u64 = 0; + for (self.sections.items(.header)) |header| { + if (header.pointer_to_raw_data + header.size_of_raw_data > max_file_offset) { + max_file_offset = header.pointer_to_raw_data + header.size_of_raw_data; + } + } + try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset); + } return self; } -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { - const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) { +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { + const target = options.comp.root_mod.resolved_target.result; + const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, else => return error.UnsupportedCOFFArchitecture, }; - const page_size: u32 = switch (options.target.cpu.arch) { + const page_size: u32 = switch (target.cpu.arch) { else => 0x1000, }; - const self = try gpa.create(Coff); - errdefer gpa.destroy(self); + const self = try arena.create(Coff); self.* = .{ .base = .{ .tag = .coff, - .options = options, - .allocator = gpa, + .comp = options.comp, + .emit = options.emit, .file = null, }, .ptr_width = ptr_width, @@ -271,16 +374,17 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory), }; - if (options.use_llvm) { - self.llvm_object = try LlvmObject.create(gpa, options); + const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; + if (use_llvm and options.comp.config.have_zcu) { + self.llvm_object = try LlvmObject.create(arena, options); } return self; } pub fn deinit(self: *Coff) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; - if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); + if (self.llvm_object) |llvm_object| llvm_object.deinit(); for (self.objects.items) |*object| { object.deinit(gpa); @@ -349,97 +453,6 @@ pub fn deinit(self: *Coff) void { self.base_relocs.deinit(gpa); } -fn populateMissingMetadata(self: *Coff) !void { - assert(self.llvm_object == null); - const gpa = self.base.allocator; - - try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32)); - self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32)); - - try self.temp_strtab.buffer.append(gpa, 0); - - // Index 0 is always a null symbol. - try self.locals.append(gpa, .{ - .name = [_]u8{0} ** 8, - .value = 0, - .section_number = .UNDEFINED, - .type = .{ .base_type = .NULL, .complex_type = .NULL }, - .storage_class = .NULL, - .number_of_aux_symbols = 0, - }); - - if (self.text_section_index == null) { - const file_size = @as(u32, @intCast(self.base.options.program_code_size_hint)); - self.text_section_index = try self.allocateSection(".text", file_size, .{ - .CNT_CODE = 1, - .MEM_EXECUTE = 1, - .MEM_READ = 1, - }); - } - - if (self.got_section_index == null) { - const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * self.ptr_width.size(); - self.got_section_index = try self.allocateSection(".got", file_size, .{ - .CNT_INITIALIZED_DATA = 1, - .MEM_READ = 1, - }); - } - - if (self.rdata_section_index == null) { - const file_size: u32 = self.page_size; - self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{ - .CNT_INITIALIZED_DATA = 1, - .MEM_READ = 1, - }); - } - - if (self.data_section_index == null) { - const file_size: u32 = self.page_size; - self.data_section_index = try self.allocateSection(".data", file_size, .{ - .CNT_INITIALIZED_DATA = 1, - .MEM_READ = 1, - .MEM_WRITE = 1, - }); - } - - if (self.idata_section_index == null) { - const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * self.ptr_width.size(); - self.idata_section_index = try self.allocateSection(".idata", file_size, .{ - .CNT_INITIALIZED_DATA = 1, - .MEM_READ = 1, - }); - } - - if (self.reloc_section_index == null) { - const file_size = @as(u32, @intCast(self.base.options.symbol_count_hint)) * @sizeOf(coff.BaseRelocation); - self.reloc_section_index = try self.allocateSection(".reloc", file_size, .{ - .CNT_INITIALIZED_DATA = 1, - .MEM_DISCARDABLE = 1, - .MEM_READ = 1, - }); - } - - if (self.strtab_offset == null) { - const file_size = @as(u32, @intCast(self.strtab.buffer.items.len)); - self.strtab_offset = self.findFreeSpace(file_size, @alignOf(u32)); // 4bytes aligned seems like a good idea here - log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + file_size }); - } - - { - // We need to find out what the max file offset is according to section headers. - // Otherwise, we may end up with an COFF binary with file size not matching the final section's - // offset + it's filesize. - // TODO I don't like this here one bit - var max_file_offset: u64 = 0; - for (self.sections.items(.header)) |header| { - if (header.pointer_to_raw_data + header.size_of_raw_data > max_file_offset) { - max_file_offset = header.pointer_to_raw_data + header.size_of_raw_data; - } - } - try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset); - } -} - fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.SectionHeaderFlags) !u16 { const index = @as(u16, @intCast(self.sections.slice().len)); const off = self.findFreeSpace(size, default_file_alignment); @@ -471,8 +484,9 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section .number_of_linenumbers = 0, .flags = flags, }; + const gpa = self.base.comp.gpa; try self.setSectionName(&header, name); - try self.sections.append(self.base.allocator, .{ .header = header }); + try self.sections.append(gpa, .{ .header = header }); return index; } @@ -654,7 +668,7 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme } pub fn allocateSymbol(self: *Coff) !u32 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.locals.ensureUnusedCapacity(gpa, 1); const index = blk: { @@ -682,7 +696,7 @@ pub fn allocateSymbol(self: *Coff) !u32 { } fn allocateGlobal(self: *Coff) !u32 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.globals.ensureUnusedCapacity(gpa, 1); const index = blk: { @@ -706,15 +720,16 @@ fn allocateGlobal(self: *Coff) !u32 { } fn addGotEntry(self: *Coff, target: SymbolWithLoc) !void { + const gpa = self.base.comp.gpa; if (self.got_table.lookup.contains(target)) return; - const got_index = try self.got_table.allocateEntry(self.base.allocator, target); + const got_index = try self.got_table.allocateEntry(gpa, target); try self.writeOffsetTableEntry(got_index); self.got_table_count_dirty = true; self.markRelocsDirtyByTarget(target); } pub fn createAtom(self: *Coff) !Atom.Index { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const atom_index = @as(Atom.Index, @intCast(self.atoms.items.len)); const atom = try self.atoms.addOne(gpa); const sym_index = try self.allocateSymbol(); @@ -759,7 +774,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void { file_offset + code.len, }); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; // Gather relocs which can be resolved. // We need to do this as we will be applying different slide values depending @@ -870,7 +885,7 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void { if (is_hot_update_compatible) { if (self.base.child_pid) |handle| { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const slide = @intFromPtr(self.hot_state.loaded_base_address.?); const actual_vmaddr = vmaddr + slide; const pvaddr = @as(*anyopaque, @ptrFromInt(actual_vmaddr)); @@ -974,7 +989,7 @@ pub fn ptraceDetach(self: *Coff, handle: std.ChildProcess.Id) void { fn freeAtom(self: *Coff, atom_index: Atom.Index) void { log.debug("freeAtom {d}", .{atom_index}); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; // Remove any relocs and base relocs associated with this Atom Atom.freeRelocations(self, atom_index); @@ -1061,7 +1076,8 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: self.freeUnnamedConsts(decl_index); Atom.freeRelocations(self, atom_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); const res = try codegen.generateFunction( @@ -1090,7 +1106,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: } pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); @@ -1121,7 +1137,7 @@ const LowerConstResult = union(enum) { }; fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); @@ -1174,13 +1190,14 @@ pub fn updateDecl( return; } + const gpa = self.base.comp.gpa; if (decl.isExtern(mod)) { // TODO make this part of getGlobalSymbol const variable = decl.getOwnedVariable(mod).?; const name = mod.intern_pool.stringToSlice(decl.name); const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); const global_index = try self.getGlobalSymbol(name, lib_name); - try self.need_got_table.put(self.base.allocator, global_index, {}); + try self.need_got_table.put(gpa, global_index, {}); return; } @@ -1188,7 +1205,7 @@ pub fn updateDecl( Atom.freeRelocations(self, atom_index); const atom = self.getAtom(atom_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; @@ -1220,7 +1237,7 @@ fn updateLazySymbolAtom( atom_index: Atom.Index, section_index: u16, ) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; var required_alignment: InternPool.Alignment = .none; @@ -1281,8 +1298,9 @@ fn updateLazySymbolAtom( } pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index { + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; - const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod)); + const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { @@ -1305,7 +1323,8 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato } pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !Atom.Index { - const gop = try self.decls.getOrPut(self.base.allocator, decl_index); + const gpa = self.base.comp.gpa; + const gop = try self.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{ .atom = try self.createAtom(), @@ -1401,7 +1420,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com } fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; for (unnamed_consts.items) |atom_index| { self.freeAtom(atom_index); @@ -1412,6 +1431,7 @@ fn freeUnnamedConsts(self: *Coff, decl_index: InternPool.DeclIndex) void { pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void { if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); @@ -1421,7 +1441,7 @@ pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void { var kv = const_kv; self.freeAtom(kv.value.atom); self.freeUnnamedConsts(decl_index); - kv.value.exports.deinit(self.base.allocator); + kv.value.exports.deinit(gpa); } } @@ -1476,7 +1496,7 @@ pub fn updateExports( if (self.base.options.emit == null) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -1574,7 +1594,7 @@ pub fn deleteDeclExport( const name = mod.intern_pool.stringToSlice(name_ip); const sym_index = metadata.getExportPtr(self, name) orelse return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null }; const sym = self.getSymbolPtr(sym_loc); log.debug("deleting export '{s}'", .{name}); @@ -1602,7 +1622,7 @@ pub fn deleteDeclExport( } fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym = self.getSymbol(current); const sym_name = self.getSymbolName(current); @@ -1653,7 +1673,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod sub_prog_node.activate(); defer sub_prog_node.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; @@ -1794,7 +1814,7 @@ pub fn lowerAnonDecl( explicit_alignment: InternPool.Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const decl_alignment = switch (explicit_alignment) { @@ -1868,7 +1888,7 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; gop.value_ptr.* = sym_loc; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym = self.getSymbolPtr(sym_loc); try self.setSymbolName(sym, name); sym.storage_class = .EXTERNAL; @@ -1895,7 +1915,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl_index: InternPool /// TODO: note that .ABSOLUTE is used as padding within each block; we could use this fact to do /// incremental updates and writes into the table instead of doing it all at once fn writeBaseRelocations(self: *Coff) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var page_table = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa); defer { @@ -2006,7 +2026,7 @@ fn writeImportTables(self: *Coff) !void { if (self.idata_section_index == null) return; if (!self.imports_count_dirty) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const ext = ".dll"; const header = &self.sections.items(.header)[self.idata_section_index.?]; @@ -2154,7 +2174,8 @@ fn writeStrtab(self: *Coff) !void { log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size }); - var buffer = std.ArrayList(u8).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var buffer = std.ArrayList(u8).init(gpa); defer buffer.deinit(); try buffer.ensureTotalCapacityPrecise(needed_size); buffer.appendSliceAssumeCapacity(self.strtab.buffer.items); @@ -2176,7 +2197,7 @@ fn writeDataDirectoriesHeaders(self: *Coff) !void { } fn writeHeader(self: *Coff) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var buffer = std.ArrayList(u8).init(gpa); defer buffer.deinit(); const writer = buffer.writer(); @@ -2499,7 +2520,7 @@ pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult if (self.getGlobalPtr(name)) |ptr| { return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; } - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const global_index = try self.allocateGlobal(); const global_name = try gpa.dupe(u8, name); _ = try self.resolver.put(gpa, global_name, global_index); @@ -2530,7 +2551,8 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v @memset(header.name[name.len..], 0); return; } - const offset = try self.strtab.insert(self.base.allocator, name); + const gpa = self.base.comp.gpa; + const offset = try self.strtab.insert(gpa, name); const name_offset = fmt.bufPrint(&header.name, "/{d}", .{offset}) catch unreachable; @memset(header.name[name_offset.len..], 0); } @@ -2549,7 +2571,8 @@ fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void { @memset(symbol.name[name.len..], 0); return; } - const offset = try self.strtab.insert(self.base.allocator, name); + const gpa = self.base.comp.gpa; + const offset = try self.strtab.insert(gpa, name); @memset(symbol.name[0..4], 0); mem.writeInt(u32, symbol.name[4..8], offset, .little); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 6f3c59c4e74e..ef25c63e3221 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -200,26 +200,34 @@ pub const min_text_capacity = padToIdeal(minimum_atom_size); pub const PtrWidth = enum { p32, p64 }; -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf { - assert(options.target.ofmt == .elf); +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { + if (build_options.only_c) unreachable; + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .elf); - const self = try createEmpty(allocator, options); + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; + + const self = try createEmpty(arena, options); errdefer self.base.destroy(); + if (use_lld and use_llvm) { + // LLVM emits the object file; LLD links it into the final product. + return self; + } + const is_obj = options.output_mode == .Obj; const is_obj_or_ar = is_obj or (options.output_mode == .Lib and options.link_mode == .Static); - if (options.use_llvm) { - const use_lld = build_options.have_llvm and self.base.options.use_lld; - if (use_lld) return self; - - if (options.module != null) { - self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{ - sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), - }); - } - } - errdefer if (self.base.intermediary_basename) |path| allocator.free(path); + const sub_path = if (!use_lld) options.emit.sub_path else p: { + // Open a temporary object file, not the final output file because we + // want to link with LLD. + const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ + options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + }); + self.base.intermediary_basename = o_file_path; + break :p o_file_path; + }; self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = false, @@ -227,24 +235,26 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option .mode = link.determineMode(options), }); + const gpa = options.comp.gpa; + // Index 0 is always a null symbol. - try self.symbols.append(allocator, .{}); + try self.symbols.append(gpa, .{}); // Index 0 is always a null symbol. - try self.symbols_extra.append(allocator, 0); + try self.symbols_extra.append(gpa, 0); // Allocate atom index 0 to null atom - try self.atoms.append(allocator, .{}); + try self.atoms.append(gpa, .{}); // Append null file at index 0 - try self.files.append(allocator, .null); + try self.files.append(gpa, .null); // Append null byte to string tables - try self.shstrtab.append(allocator, 0); - try self.strtab.append(allocator, 0); + try self.shstrtab.append(gpa, 0); + try self.strtab.append(gpa, 0); // There must always be a null shdr in index 0 _ = try self.addSection(.{ .name = "" }); // Append null symbol in output symtab - try self.symtab.append(allocator, null_sym); + try self.symtab.append(gpa, null_sym); if (!is_obj_or_ar) { - try self.dynstrtab.append(allocator, 0); + try self.dynstrtab.append(gpa, 0); // Initialize PT_PHDR program header const p_align: u16 = switch (self.ptr_width) { @@ -283,10 +293,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option } if (options.module != null and !options.use_llvm) { - const index = @as(File.Index, @intCast(try self.files.addOne(allocator))); + const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); self.files.set(index, .{ .zig_object = .{ .index = index, - .path = try std.fmt.allocPrint(self.base.allocator, "{s}.o", .{std.fs.path.stem( + .path = try std.fmt.allocPrint(arena, "{s}.o", .{std.fs.path.stem( options.module.?.main_mod.root_src_path, )}), } }); @@ -298,16 +308,16 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option return self; } -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { - const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) { +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { + const target = options.comp.root_mod.resolved_target.result; + const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, else => return error.UnsupportedELFArchitecture, }; - const self = try gpa.create(Elf); - errdefer gpa.destroy(self); + const self = try arena.create(Elf); - const page_size: u32 = switch (options.target.cpu.arch) { + const page_size: u32 = switch (target.cpu.arch) { .powerpc64le => 0x10000, .sparc64 => 0x2000, else => 0x1000, @@ -321,25 +331,25 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { self.* = .{ .base = .{ .tag = .elf, - .options = options, - .allocator = gpa, + .comp = options.comp, + .emit = options.emit, .file = null, }, .ptr_width = ptr_width, .page_size = page_size, .default_sym_version = default_sym_version, }; - if (options.use_llvm and options.module != null) { - self.llvm_object = try LlvmObject.create(gpa, options); + if (options.use_llvm and options.comp.config.have_zcu) { + self.llvm_object = try LlvmObject.create(arena, options); } return self; } pub fn deinit(self: *Elf) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; - if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); + if (self.llvm_object) |llvm_object| llvm_object.deinit(); for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) { .null => {}, @@ -496,10 +506,11 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { /// TODO move to ZigObject pub fn initMetadata(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const ptr_size = self.ptrWidthBytes(); - const ptr_bit_width = self.base.options.target.ptrBitWidth(); - const is_linux = self.base.options.target.os.tag == .linux; + const target = self.base.comp.root_mod.resolved_target.result; + const ptr_bit_width = target.ptrBitWidth(); + const is_linux = target.os.tag == .linux; const zig_object = self.zigObjectPtr().?; const fillSection = struct { @@ -943,7 +954,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (use_lld) return; } - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var sub_prog_node = prog_node.start("ELF Flush", 0); sub_prog_node.activate(); defer sub_prog_node.end(); @@ -952,7 +963,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const target = self.base.options.target; + const target = self.base.comp.root_mod.resolved_target.result; const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { @@ -1303,7 +1314,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); defer positionals.deinit(); @@ -1447,7 +1458,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const } pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); defer positionals.deinit(); @@ -1524,7 +1535,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const target = self.base.options.target; + const target = self.base.comp.root_mod.resolved_target.result; const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { @@ -1574,7 +1585,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } else { if (!self.isStatic()) { - if (self.base.options.target.dynamic_linker.get()) |path| { + if (target.dynamic_linker.get()) |path| { try argv.append("-dynamic-linker"); try argv.append(path); } @@ -1842,7 +1853,7 @@ fn parseObject(self: *Elf, path: []const u8) ParseError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const in_file = try std.fs.cwd().openFile(path, .{}); defer in_file.close(); const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); @@ -1862,7 +1873,7 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const in_file = try std.fs.cwd().openFile(path, .{}); defer in_file.close(); const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); @@ -1888,7 +1899,7 @@ fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const in_file = try std.fs.cwd().openFile(lib.path, .{}); defer in_file.close(); const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); @@ -1910,7 +1921,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const in_file = try std.fs.cwd().openFile(lib.path, .{}); defer in_file.close(); const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); @@ -1996,7 +2007,7 @@ fn accessLibPath( link_mode: ?std.builtin.LinkMode, ) !bool { const sep = fs.path.sep_str; - const target = self.base.options.target; + const target = self.base.comp.root_mod.resolved_target.result; test_path.clearRetainingCapacity(); const prefix = if (link_mode != null) "lib" else ""; const suffix = if (link_mode) |mode| switch (mode) { @@ -2190,7 +2201,7 @@ fn claimUnresolvedObject(self: *Elf) void { /// This is also the point where we will report undefined symbols for any /// alloc sections. fn scanRelocs(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa); defer { @@ -2293,7 +2304,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; const have_dynamic_linker = self.base.options.link_libc and self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; - const target = self.base.options.target; + const target = self.base.comp.root_mod.resolved_target.result; const gc_sections = self.base.options.gc_sections orelse !is_obj; const stack_size = self.base.options.stack_size_override orelse 16777216; const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; @@ -2374,7 +2385,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addBytes(libc_installation.crt_dir.?); } if (have_dynamic_linker) { - man.hash.addOptionalBytes(self.base.options.target.dynamic_linker.get()); + man.hash.addOptionalBytes(target.dynamic_linker.get()); } } man.hash.addOptionalBytes(self.base.options.soname); @@ -2687,7 +2698,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } if (have_dynamic_linker) { - if (self.base.options.target.dynamic_linker.get()) |dynamic_linker| { + if (target.dynamic_linker.get()) |dynamic_linker| { try argv.append("-dynamic-linker"); try argv.append(dynamic_linker); } @@ -2937,7 +2948,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void { - const target_endian = self.base.options.target.cpu.arch.endian(); + const target = self.base.comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); switch (self.ptr_width) { .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian), .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian), @@ -2945,8 +2957,9 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) } fn writeShdrTable(self: *Elf) !void { - const gpa = self.base.allocator; - const target_endian = self.base.options.target.cpu.arch.endian(); + const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); const foreign_endian = target_endian != builtin.cpu.arch.endian(); const shsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Shdr), @@ -3001,8 +3014,9 @@ fn writeShdrTable(self: *Elf) !void { } fn writePhdrTable(self: *Elf) !void { - const gpa = self.base.allocator; - const target_endian = self.base.options.target.cpu.arch.endian(); + const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); const foreign_endian = target_endian != builtin.cpu.arch.endian(); const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; @@ -3054,7 +3068,8 @@ fn writeElfHeader(self: *Elf) !void { }; index += 1; - const endian = self.base.options.target.cpu.arch.endian(); + const target = self.base.comp.root_mod.resolved_target.result; + const endian = target.cpu.arch.endian(); hdr_buf[index] = switch (endian) { .little => elf.ELFDATA2LSB, .big => elf.ELFDATA2MSB, @@ -3083,7 +3098,7 @@ fn writeElfHeader(self: *Elf) !void { mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(elf_type), endian); index += 2; - const machine = self.base.options.target.cpu.arch.toElfMachine(); + const machine = target.cpu.arch.toElfMachine(); mem.writeInt(u16, hdr_buf[index..][0..2], @intFromEnum(machine), endian); index += 2; @@ -3248,7 +3263,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { for (self.shdrs.items) |shdr| { if (self.getStartStopBasename(shdr)) |name| { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); @@ -3394,6 +3409,7 @@ fn initOutputSections(self: *Elf) !void { } fn initSyntheticSections(self: *Elf) !void { + const target = self.base.comp.root_mod.resolved_target.result; const ptr_size = self.ptrWidthBytes(); const needs_eh_frame = for (self.objects.items) |index| { @@ -3503,7 +3519,7 @@ fn initSyntheticSections(self: *Elf) !void { // a segfault in the dynamic linker trying to load a binary that is static // and doesn't contain .dynamic section. if (self.isStatic() and !self.base.options.pie) break :blk false; - break :blk self.base.options.target.dynamic_linker.get() != null; + break :blk target.dynamic_linker.get() != null; }; if (needs_interp) { self.interp_section_index = try self.addSection(.{ @@ -3613,7 +3629,7 @@ fn initSectionsObject(self: *Elf) !void { } fn initComdatGroups(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (self.objects.items) |index| { const object = self.file(index).?.object; @@ -3732,7 +3748,7 @@ fn initSpecialPhdrs(self: *Elf) !void { /// Ties are broken by the file prority which corresponds to the inclusion of input sections in this output section /// we are about to sort. fn sortInitFini(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const Entry = struct { priority: i32, @@ -3872,7 +3888,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { } }; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len); defer entries.deinit(); for (0..self.phdrs.items.len) |phndx| { @@ -3977,7 +3993,7 @@ fn sortShdrs(self: *Elf) !void { } }; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len); defer entries.deinit(); for (0..self.shdrs.items.len) |shndx| { @@ -4004,7 +4020,7 @@ fn sortShdrs(self: *Elf) !void { } fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (&[_]*?u16{ &self.eh_frame_section_index, @@ -4187,6 +4203,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void { } fn updateSectionSizes(self: *Elf) !void { + const target = self.base.comp.root_mod.resolved_target.result; for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { const shdr = &self.shdrs.items[shndx]; for (atom_list.items) |atom_index| { @@ -4244,7 +4261,7 @@ fn updateSectionSizes(self: *Elf) !void { } if (self.interp_section_index) |index| { - self.shdrs.items[index].sh_size = self.base.options.target.dynamic_linker.get().?.len + 1; + self.shdrs.items[index].sh_size = target.dynamic_linker.get().?.len + 1; } if (self.hash_section_index) |index| { @@ -4453,7 +4470,7 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { // as we are more interested in quick turnaround and compatibility // with `findFreeSpace` mechanics than anything else. const Cover = std.ArrayList(u16); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var covers: [max_number_of_object_segments]Cover = undefined; for (&covers) |*cover| { cover.* = Cover.init(gpa); @@ -4691,7 +4708,7 @@ fn allocateAtoms(self: *Elf) void { } fn writeAtoms(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa); defer { @@ -4779,7 +4796,7 @@ fn writeAtoms(self: *Elf) !void { } fn writeAtomsObject(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; // TODO iterate over `output_sections` directly for (self.shdrs.items, 0..) |shdr, shndx| { @@ -4852,7 +4869,7 @@ fn updateSymtabSize(self: *Elf) !void { var nglobals: u32 = 0; var strsize: u32 = 0; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var files = std.ArrayList(File.Index).init(gpa); defer files.deinit(); try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 2); @@ -4935,11 +4952,12 @@ fn updateSymtabSize(self: *Elf) !void { } fn writeSyntheticSections(self: *Elf) !void { - const gpa = self.base.allocator; + const target = self.base.comp.root_mod.resolved_target.result; + const gpa = self.base.comp.gpa; if (self.interp_section_index) |shndx| { var buffer: [256]u8 = undefined; - const interp = self.base.options.target.dynamic_linker.get().?; + const interp = target.dynamic_linker.get().?; @memcpy(buffer[0..interp.len], interp); buffer[interp.len] = 0; const contents = buffer[0 .. interp.len + 1]; @@ -5065,7 +5083,7 @@ fn writeSyntheticSections(self: *Elf) !void { } fn writeSyntheticSectionsObject(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (self.output_rela_sections.values()) |sec| { if (sec.atom_list.items.len == 0) continue; @@ -5135,7 +5153,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void { } fn writeComdatGroups(self: *Elf) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (self.comdat_group_sections.items) |cgs| { const shdr = self.shdrs.items[cgs.shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; @@ -5160,7 +5178,8 @@ fn writeShStrtab(self: *Elf) !void { } fn writeSymtab(self: *Elf) !void { - const gpa = self.base.allocator; + const target = self.base.comp.root_mod.resolved_target.result; + const gpa = self.base.comp.gpa; const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; const strtab_shdr = self.shdrs.items[self.strtab_section_index.?]; const sym_size: u64 = switch (self.ptr_width) { @@ -5220,7 +5239,7 @@ fn writeSymtab(self: *Elf) !void { self.plt_got.writeSymtab(self); } - const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); + const foreign_endian = target.cpu.arch.endian() != builtin.cpu.arch.endian(); switch (self.ptr_width) { .p32 => { const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len); @@ -5299,7 +5318,8 @@ fn ptrWidthBytes(self: Elf) u8 { /// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes /// in a 32-bit ELF file. pub fn archPtrWidthBytes(self: Elf) u8 { - return @as(u8, @intCast(@divExact(self.base.options.target.ptrBitWidth(), 8))); + const target = self.base.comp.root_mod.resolved_target.result; + return @intCast(@divExact(target.ptrBitWidth(), 8)); } fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { @@ -5694,7 +5714,7 @@ pub const AddSectionOpts = struct { }; pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const index = @as(u16, @intCast(self.shdrs.items.len)); const shdr = try self.shdrs.addOne(gpa); shdr.* = .{ @@ -5887,7 +5907,7 @@ const GetOrPutGlobalResult = struct { }; pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const name_off = try self.strings.insert(gpa, name); const gop = try self.resolver.getOrPut(gpa, name_off); if (!gop.found_existing) { @@ -5923,7 +5943,7 @@ const GetOrCreateComdatGroupOwnerResult = struct { }; pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateComdatGroupOwnerResult { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const off = try self.strings.insert(gpa, name); const gop = try self.comdat_groups_table.getOrPut(gpa, off); if (!gop.found_existing) { @@ -6039,7 +6059,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { } fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const max_notes = 4; try self.misc_errors.ensureUnusedCapacity(gpa, undefs.count()); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 61446b3300d6..f61e78c2331a 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -143,14 +143,23 @@ tlv_table: TlvSymbolTable = .{}, /// Hot-code swapping state. hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, -pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { - assert(options.target.ofmt == .macho); +darwin_sdk_layout: ?SdkLayout, + +/// The filesystem layout of darwin SDK elements. +pub const SdkLayout = enum { + /// macOS SDK layout: TOP { /usr/include, /usr/lib, /System/Library/Frameworks }. + sdk, + /// Shipped libc layout: TOP { /lib/libc/include, /lib/libc/darwin, }. + vendored, +}; - if (options.emit == null) { - return createEmpty(allocator, options); - } +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { + if (build_options.only_c) unreachable; + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .macho); - const emit = options.emit.?; + const gpa = options.comp.gpa; + const emit = options.emit; const mode: Mode = mode: { if (options.use_llvm or options.module == null or options.cache_mode == .whole) break :mode .zld; @@ -160,17 +169,16 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { if (options.module == null) { // No point in opening a file, we would not write anything to it. // Initialize with empty. - return createEmpty(allocator, options); + return createEmpty(arena, options); } // Open a temporary object file, not the final output file because we // want to link with LLD. - break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{ - emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), + break :blk try std.fmt.allocPrint(arena, "{s}{s}", .{ + emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); } else emit.sub_path; - errdefer if (mode == .zld) allocator.free(sub_path); - const self = try createEmpty(allocator, options); + const self = try createEmpty(arena, options); errdefer self.base.destroy(); if (mode == .zld) { @@ -186,7 +194,6 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { .read = true, .mode = link.determineMode(options), }); - errdefer file.close(); self.base.file = file; if (!options.strip and options.module != null) { @@ -194,11 +201,10 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { log.debug("creating {s}.dSYM bundle", .{sub_path}); const d_sym_path = try std.fmt.allocPrint( - allocator, + arena, "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", .{sub_path}, ); - defer allocator.free(d_sym_path); var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); defer d_sym_bundle.close(); @@ -209,21 +215,21 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { }); self.d_sym = .{ - .allocator = allocator, - .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32), + .allocator = gpa, + .dwarf = link.File.Dwarf.init(gpa, &self.base, .dwarf32), .file = d_sym_file, }; } // Index 0 is always a null symbol. - try self.locals.append(allocator, .{ + try self.locals.append(gpa, .{ .n_strx = 0, .n_type = 0, .n_sect = 0, .n_desc = 0, .n_value = 0, }); - try self.strtab.buffer.append(allocator, 0); + try self.strtab.buffer.append(gpa, 0); try self.populateMissingMetadata(); @@ -234,15 +240,14 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { return self; } -pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { - const self = try gpa.create(MachO); - errdefer gpa.destroy(self); +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { + const self = try arena.create(MachO); self.* = .{ .base = .{ .tag = .macho, - .options = options, - .allocator = gpa, + .comp = options.comp, + .emit = options.emit, .file = null, }, .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole) @@ -252,7 +257,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { }; if (options.use_llvm and options.module != null) { - self.llvm_object = try LlvmObject.create(gpa, options); + self.llvm_object = try LlvmObject.create(arena, options); } log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); @@ -261,20 +266,15 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { } pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (self.base.options.emit == null) { - if (self.llvm_object) |llvm_object| { - try llvm_object.flushModule(comp, prog_node); - } - return; - } + const gpa = self.base.comp.gpa; if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) { if (build_options.have_llvm) { return self.base.linkAsArchive(comp, prog_node); } else { - try self.misc_errors.ensureUnusedCapacity(self.base.allocator, 1); + try self.misc_errors.ensureUnusedCapacity(gpa, 1); self.misc_errors.appendAssumeCapacity(.{ - .msg = try self.base.allocator.dupe(u8, "TODO: non-LLVM archiver for MachO object files"), + .msg = try gpa.dupe(u8, "TODO: non-LLVM archiver for MachO object files"), }); return error.FlushFailure; } @@ -294,7 +294,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No return try llvm_object.flushModule(comp, prog_node); } - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = self.base.comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -391,7 +392,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No if (cache_miss) { for (self.dylibs.items) |*dylib| { - dylib.deinit(self.base.allocator); + dylib.deinit(gpa); } self.dylibs.clearRetainingCapacity(); self.dylibs_map.clearRetainingCapacity(); @@ -403,7 +404,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No const in_file = try std.fs.cwd().openFile(path, .{}); defer in_file.close(); - var parse_ctx = ParseErrorCtx.init(self.base.allocator); + var parse_ctx = ParseErrorCtx.init(gpa); defer parse_ctx.deinit(); self.parseLibrary( @@ -470,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No const section = self.sections.get(sym.n_sect - 1).header; const file_offset = section.offset + sym.n_value - section.addr; - var code = std.ArrayList(u8).init(self.base.allocator); + var code = std.ArrayList(u8).init(gpa); defer code.deinit(); try code.resize(math.cast(usize, atom.size) orelse return error.Overflow); @@ -518,12 +519,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch)); codesig.code_directory.ident = self.base.options.emit.?.sub_path; if (self.base.options.entitlements) |path| { - try codesig.addEntitlements(self.base.allocator, path); + try codesig.addEntitlements(gpa, path); } try self.writeCodeSignaturePadding(&codesig); break :blk codesig; } else null; - defer if (codesig) |*csig| csig.deinit(self.base.allocator); + defer if (codesig) |*csig| csig.deinit(gpa); // Write load commands var lc_buffer = std.ArrayList(u8).init(arena); @@ -555,12 +556,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No }); }, .Lib => if (self.base.options.link_mode == .Dynamic) { - try load_commands.writeDylibIdLC(self.base.allocator, &self.base.options, lc_writer); + try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer); }, else => {}, } - try load_commands.writeRpathLCs(self.base.allocator, &self.base.options, lc_writer); + try load_commands.writeRpathLCs(gpa, &self.base.options, lc_writer); try lc_writer.writeStruct(macho.source_version_command{ .version = 0, }); @@ -644,7 +645,8 @@ pub fn resolveLibSystem( search_dirs: []const []const u8, out_libs: anytype, ) !void { - var tmp_arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = self.base.comp.gpa; + var tmp_arena_allocator = std.heap.ArenaAllocator.init(gpa); defer tmp_arena_allocator.deinit(); const tmp_arena = tmp_arena_allocator.allocator(); @@ -775,7 +777,7 @@ fn parseObject( const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mtime: u64 = mtime: { const stat = file.stat() catch break :mtime 0; break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000))); @@ -868,7 +870,7 @@ pub fn parseFatLibrary( cpu_arch: std.Target.Cpu.Arch, ctx: *ParseErrorCtx, ) ParseError!u64 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const fat_archs = try fat.parseArchs(gpa, file); defer gpa.free(fat_archs); @@ -892,7 +894,7 @@ fn parseArchive( must_link: bool, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; // We take ownership of the file so that we can store it for the duration of symbol resolution. // TODO we shouldn't need to do that and could pre-parse the archive like we do for zld/ELF? @@ -973,7 +975,7 @@ fn parseDylib( dylib_options: DylibOpts, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const file_stat = try file.stat(); const file_size = math.cast(usize, file_stat.size - offset) orelse return error.Overflow; @@ -1019,7 +1021,7 @@ fn parseLibStub( dylib_options: DylibOpts, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var lib_stub = try LibStub.loadFromFile(gpa, file); defer lib_stub.deinit(); @@ -1072,7 +1074,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts, ctx: *ParseErr } } - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const gop = try self.dylibs_map.getOrPut(gpa, dylib.id.?.name); if (gop.found_existing) return error.DylibAlreadyExists; @@ -1098,7 +1100,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void { // 2) afterwards, we parse dependents of the included dylibs // TODO this should not be performed if the user specifies `-flat_namespace` flag. // See ld64 manpages. - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; while (dependent_libs.readItem()) |dep_id| { defer dep_id.id.deinit(gpa); @@ -1162,7 +1164,8 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset }); // Gather relocs which can be resolved. - var relocs = std.ArrayList(*Relocation).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var relocs = std.ArrayList(*Relocation).init(gpa); defer relocs.deinit(); if (self.relocs.getPtr(atom_index)) |rels| { @@ -1237,7 +1240,7 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void { fn writeStubHelperPreamble(self: *MachO) !void { if (self.stub_helper_preamble_allocated) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const cpu_arch = self.base.options.target.cpu.arch; const size = stubs.stubHelperPreambleSize(cpu_arch); @@ -1290,7 +1293,7 @@ fn writeStubTableEntry(self: *MachO, index: usize) !void { self.stub_table_count_dirty = false; } - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const stubs_header = self.sections.items(.header)[stubs_sect_id]; const stub_helper_header = self.sections.items(.header)[stub_helper_sect_id]; @@ -1469,7 +1472,7 @@ const CreateAtomOpts = struct { }; pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Index { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const index = @as(Atom.Index, @intCast(self.atoms.items.len)); const atom = try self.atoms.addOne(gpa); atom.* = .{}; @@ -1481,7 +1484,7 @@ pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Inde } pub fn createTentativeDefAtoms(self: *MachO) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (self.globals.items) |global| { const sym = self.getSymbolPtr(global); @@ -1536,7 +1539,8 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { .size = @sizeOf(u64), .alignment = .@"8", }); - try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index); + const gpa = self.base.comp.gpa; + try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index); if (self.data_section_index == null) { self.data_section_index = try self.initSection("__DATA", "__data", .{}); @@ -1560,7 +1564,7 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { } fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: SymbolWithLoc) !Atom.Index { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const size = 3 * @sizeOf(u64); const required_alignment: Alignment = .@"1"; const sym_index = try self.allocateSymbol(); @@ -1595,7 +1599,7 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S pub fn createMhExecuteHeaderSymbol(self: *MachO) !void { if (self.base.options.output_mode != .Exe) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym_index = try self.allocateSymbol(); const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; const sym = self.getSymbolPtr(sym_loc); @@ -1622,7 +1626,7 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { const global = self.getGlobalPtr("___dso_handle") orelse return; if (!self.getSymbol(global.*).undf()) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym_index = try self.allocateSymbol(); const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; const sym = self.getSymbolPtr(sym_loc); @@ -1686,7 +1690,7 @@ pub fn resolveSymbols(self: *MachO) !void { } fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym = self.getSymbol(current); const sym_name = self.getSymbolName(current); @@ -1800,7 +1804,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void { fn resolveSymbolsInArchives(self: *MachO) !void { if (self.archives.items.len == 0) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var next_sym: usize = 0; loop: while (next_sym < self.unresolved.count()) { const global = self.globals.items[self.unresolved.keys()[next_sym]]; @@ -1829,7 +1833,7 @@ fn resolveSymbolsInArchives(self: *MachO) !void { fn resolveSymbolsInDylibs(self: *MachO) !void { if (self.dylibs.items.len == 0) return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var next_sym: usize = 0; loop: while (next_sym < self.unresolved.count()) { const global_index = self.unresolved.keys()[next_sym]; @@ -1899,6 +1903,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void { } fn resolveBoundarySymbols(self: *MachO) !void { + const gpa = self.base.comp.gpa; var next_sym: usize = 0; while (next_sym < self.unresolved.count()) { const global_index = self.unresolved.keys()[next_sym]; @@ -1909,7 +1914,7 @@ fn resolveBoundarySymbols(self: *MachO) !void { const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; const sym = self.getSymbolPtr(sym_loc); sym.* = .{ - .n_strx = try self.strtab.insert(self.base.allocator, self.getSymbolName(global.*)), + .n_strx = try self.strtab.insert(gpa, self.getSymbolName(global.*)), .n_type = macho.N_SECT | macho.N_EXT, .n_sect = 0, .n_desc = N_BOUNDARY, @@ -1929,9 +1934,9 @@ fn resolveBoundarySymbols(self: *MachO) !void { } pub fn deinit(self: *MachO) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; - if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); + if (self.llvm_object) |llvm_object| llvm_object.deinit(); if (self.d_sym) |*d_sym| { d_sym.deinit(); @@ -2032,7 +2037,7 @@ pub fn deinit(self: *MachO) void { } fn freeAtom(self: *MachO, atom_index: Atom.Index) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; log.debug("freeAtom {d}", .{atom_index}); // Remove any relocs and base relocs associated with this Atom @@ -2124,7 +2129,8 @@ fn growAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignment: } pub fn allocateSymbol(self: *MachO) !u32 { - try self.locals.ensureUnusedCapacity(self.base.allocator, 1); + const gpa = self.base.comp.gpa; + try self.locals.ensureUnusedCapacity(gpa, 1); const index = blk: { if (self.locals_free_list.popOrNull()) |index| { @@ -2150,7 +2156,8 @@ pub fn allocateSymbol(self: *MachO) !u32 { } fn allocateGlobal(self: *MachO) !u32 { - try self.globals.ensureUnusedCapacity(self.base.allocator, 1); + const gpa = self.base.comp.gpa; + try self.globals.ensureUnusedCapacity(gpa, 1); const index = blk: { if (self.globals_free_list.popOrNull()) |index| { @@ -2171,7 +2178,8 @@ fn allocateGlobal(self: *MachO) !u32 { pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.got_table.lookup.contains(target)) return; - const got_index = try self.got_table.allocateEntry(self.base.allocator, target); + const gpa = self.base.comp.gpa; + const got_index = try self.got_table.allocateEntry(gpa, target); if (self.got_section_index == null) { self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{ .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, @@ -2186,7 +2194,8 @@ pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.stub_table.lookup.contains(target)) return; - const stub_index = try self.stub_table.allocateEntry(self.base.allocator, target); + const gpa = self.base.comp.gpa; + const stub_index = try self.stub_table.allocateEntry(gpa, target); if (self.stubs_section_index == null) { self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{ .flags = macho.S_SYMBOL_STUBS | @@ -2212,7 +2221,8 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { pub fn addTlvPtrEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.tlv_ptr_table.lookup.contains(target)) return; - _ = try self.tlv_ptr_table.allocateEntry(self.base.allocator, target); + const gpa = self.base.comp.gpa; + _ = try self.tlv_ptr_table.allocateEntry(gpa, target); if (self.tlv_ptr_section_index == null) { self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{ .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, @@ -2236,7 +2246,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: self.freeUnnamedConsts(decl_index); Atom.freeRelocations(self, atom_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); var decl_state = if (self.d_sym) |*d_sym| @@ -2279,7 +2290,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: } pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); if (!gop.found_existing) { @@ -2318,7 +2329,7 @@ fn lowerConst( sect_id: u8, src_loc: Module.SrcLoc, ) !LowerConstResult { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); @@ -2366,6 +2377,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) const tracy = trace(@src()); defer tracy.end(); + const gpa = self.base.comp.gpa; const decl = mod.declPtr(decl_index); if (decl.val.getExternFunc(mod)) |_| { @@ -2375,8 +2387,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) if (decl.isExtern(mod)) { // TODO make this part of getGlobalSymbol const name = mod.intern_pool.stringToSlice(decl.name); - const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); - defer self.base.allocator.free(sym_name); + const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); + defer gpa.free(sym_name); _ = try self.addUndefined(sym_name, .{ .add_got = true }); return; } @@ -2391,7 +2403,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) const sym_index = self.getAtom(atom_index).getSymbolIndex().?; Atom.freeRelocations(self, atom_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym| @@ -2449,7 +2461,7 @@ fn updateLazySymbolAtom( atom_index: Atom.Index, section_index: u8, ) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; var required_alignment: Alignment = .none; @@ -2515,7 +2527,8 @@ fn updateLazySymbolAtom( pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index { const mod = self.base.options.module.?; - const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod)); + const gpa = self.base.comp.gpa; + const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { @@ -2529,7 +2542,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In .unused => { const sym_index = try self.allocateSymbol(); metadata.atom.* = try self.createAtom(sym_index, .{}); - try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, metadata.atom.*); + try self.atom_by_index_table.putNoClobber(gpa, sym_index, metadata.atom.*); }, .pending_flush => return metadata.atom.*, .flushed => {}, @@ -2556,7 +2569,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo const init_sym_index = init_atom.getSymbolIndex().?; Atom.freeRelocations(self, init_atom_index); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); @@ -2640,11 +2653,12 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPo } pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: InternPool.DeclIndex) !Atom.Index { - const gop = try self.decls.getOrPut(self.base.allocator, decl_index); + const gpa = self.base.comp.gpa; + const gop = try self.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { const sym_index = try self.allocateSymbol(); const atom_index = try self.createAtom(sym_index, .{}); - try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index); + try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index); gop.value_ptr.* = .{ .atom = atom_index, .section = self.getDeclOutputSection(decl_index), @@ -2694,7 +2708,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 { } fn updateDeclCode(self: *MachO, decl_index: InternPool.DeclIndex, code: []u8) !u64 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); @@ -2787,7 +2801,7 @@ pub fn updateExports( const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -2912,7 +2926,7 @@ pub fn deleteDeclExport( if (self.llvm_object) |_| return; const metadata = self.decls.getPtr(decl_index) orelse return; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)}); defer gpa.free(exp_name); @@ -2941,7 +2955,7 @@ pub fn deleteDeclExport( } fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; for (unnamed_consts.items) |atom| { self.freeAtom(atom); @@ -2951,6 +2965,7 @@ fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void { pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); @@ -2960,7 +2975,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { var kv = const_kv; self.freeAtom(kv.value.atom); self.freeUnnamedConsts(decl_index); - kv.value.exports.deinit(self.base.allocator); + kv.value.exports.deinit(gpa); } if (self.d_sym) |*d_sym| { @@ -2993,7 +3008,7 @@ pub fn lowerAnonDecl( explicit_alignment: InternPool.Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const decl_alignment = switch (explicit_alignment) { @@ -3060,7 +3075,7 @@ pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: li fn populateMissingMetadata(self: *MachO) !void { assert(self.mode == .incremental); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const cpu_arch = self.base.options.target.cpu.arch; const pagezero_vmsize = self.calcPagezeroSize(); @@ -3228,7 +3243,8 @@ const InitSectionOpts = struct { pub fn initSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: InitSectionOpts) !u8 { log.debug("creating section '{s},{s}'", .{ segname, sectname }); const index = @as(u8, @intCast(self.sections.slice().len)); - try self.sections.append(self.base.allocator, .{ + const gpa = self.base.comp.gpa; + try self.sections.append(gpa, .{ .segment_index = undefined, // Segments will be created automatically later down the pipeline .header = .{ .sectname = makeStaticString(sectname), @@ -3248,7 +3264,7 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts flags: u32 = macho.S_REGULAR, reserved2: u32 = 0, }) !u8 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const page_size = getPageSize(self.base.options.target.cpu.arch); // In incremental context, we create one section per segment pairing. This way, // we can move the segment in raw file as we please. @@ -3521,7 +3537,7 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u32 { _ = lib_name; - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); defer gpa.free(sym_name); return self.addUndefined(sym_name, .{ .add_stub = true }); @@ -3582,7 +3598,7 @@ pub fn writeLinkeditSegmentData(self: *MachO) !void { } fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, table: anytype) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const header = self.sections.items(.header)[sect_id]; const segment_index = self.sections.items(.segment_index)[sect_id]; const segment = self.segments.items[segment_index]; @@ -3605,7 +3621,7 @@ fn collectRebaseDataFromTableSection(self: *MachO, sect_id: u8, rebase: *Rebase, } fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const slice = self.sections.slice(); for (self.rebases.keys(), 0..) |atom_index, i| { @@ -3715,7 +3731,7 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { } fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, table: anytype) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const header = self.sections.items(.header)[sect_id]; const segment_index = self.sections.items(.segment_index)[sect_id]; const segment = self.segments.items[segment_index]; @@ -3746,7 +3762,7 @@ fn collectBindDataFromTableSection(self: *MachO, sect_id: u8, bind: anytype, tab } fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const slice = self.sections.slice(); for (raw_bindings.keys(), 0..) |atom_index, i| { @@ -3885,12 +3901,13 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void { fn collectLazyBindData(self: *MachO, bind: anytype) !void { const sect_id = self.la_symbol_ptr_section_index orelse return; + const gpa = self.base.comp.gpa; try self.collectBindDataFromTableSection(sect_id, bind, self.stub_table); - try bind.finalize(self.base.allocator, self); + try bind.finalize(gpa, self); } fn collectExportData(self: *MachO, trie: *Trie) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER. log.debug("generating export trie", .{}); @@ -3922,7 +3939,7 @@ fn writeDyldInfoData(self: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var rebase = Rebase{}; defer rebase.deinit(gpa); @@ -4046,7 +4063,7 @@ fn addSymbolToFunctionStarts(self: *MachO, sym_loc: SymbolWithLoc, addresses: *s } fn writeFunctionStarts(self: *MachO) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const seg = self.segments.items[self.header_segment_cmd_index.?]; // We need to sort by address first @@ -4133,7 +4150,7 @@ fn filterDataInCode( } pub fn writeDataInCode(self: *MachO) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var out_dice = std.ArrayList(macho.data_in_code_entry).init(gpa); defer out_dice.deinit(); @@ -4211,13 +4228,14 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList if (sym.n_desc == N_BOUNDARY) return; // boundary symbol, skip if (sym.ext()) return; // an export lands in its own symtab section, skip if (self.symbolIsTemp(sym_loc)) return; // local temp symbol, skip + const gpa = self.base.comp.gpa; var out_sym = sym; - out_sym.n_strx = try self.strtab.insert(self.base.allocator, self.getSymbolName(sym_loc)); + out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc)); try locals.append(out_sym); } fn writeSymtab(self: *MachO) !SymtabCtx { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var locals = std.ArrayList(macho.nlist_64).init(gpa); defer locals.deinit(); @@ -4322,7 +4340,7 @@ fn generateSymbolStabs( ) !void { log.debug("generating stabs for '{s}'", .{object.name}); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; var debug_info = object.parseDwarfInfo(); var lookup = DwarfInfo.AbbrevLookupTable.init(gpa); @@ -4450,7 +4468,7 @@ fn generateSymbolStabsForSymbol( lookup: ?DwarfInfo.SubprogramLookupByName, buf: *[4]macho.nlist_64, ) ![]const macho.nlist_64 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const object = self.objects.items[sym_loc.getFile().?]; const sym = self.getSymbol(sym_loc); const sym_name = self.getSymbolName(sym_loc); @@ -4536,7 +4554,7 @@ fn generateSymbolStabsForSymbol( } pub fn writeStrtab(self: *MachO) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const seg = self.getLinkeditSegmentPtr(); const offset = seg.fileoff + seg.filesize; assert(mem.isAlignedGeneric(u64, offset, @alignOf(u64))); @@ -4565,7 +4583,7 @@ const SymtabCtx = struct { }; pub fn writeDysymtab(self: *MachO, ctx: SymtabCtx) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const nstubs = @as(u32, @intCast(self.stub_table.lookup.count())); const ngot_entries = @as(u32, @intCast(self.got_table.lookup.count())); const nindirectsyms = nstubs * 2 + ngot_entries; @@ -4671,7 +4689,8 @@ pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *Cod const seg = self.segments.items[seg_id]; const offset = self.codesig_cmd.dataoff; - var buffer = std.ArrayList(u8).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var buffer = std.ArrayList(u8).init(gpa); defer buffer.deinit(); try buffer.ensureTotalCapacityPrecise(code_sig.size()); try code_sig.writeAdhocSignature(comp, .{ @@ -4817,7 +4836,7 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { } pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const gop = try self.getOrPutGlobalPtr(name); const global_index = self.getGlobalIndex(name).?; @@ -4842,7 +4861,8 @@ pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 { } fn updateRelocActions(self: *MachO, global_index: u32, flags: RelocFlags) !void { - const act_gop = try self.actions.getOrPut(self.base.allocator, global_index); + const gpa = self.base.comp.gpa; + const act_gop = try self.actions.getOrPut(gpa, global_index); if (!act_gop.found_existing) { act_gop.value_ptr.* = .{}; } @@ -5022,7 +5042,7 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul if (self.getGlobalPtr(name)) |ptr| { return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; } - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const global_index = try self.allocateGlobal(); const global_name = try gpa.dupe(u8, name); _ = try self.resolver.put(gpa, global_name, global_index); @@ -5171,6 +5191,7 @@ pub fn handleAndReportParseError( err: ParseError, ctx: *const ParseErrorCtx, ) error{OutOfMemory}!void { + const gpa = self.base.comp.gpa; const cpu_arch = self.base.options.target.cpu.arch; switch (err) { error.DylibAlreadyExists => {}, @@ -5188,7 +5209,7 @@ pub fn handleAndReportParseError( }, error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), error.InvalidTarget, error.InvalidTargetFatLibrary => { - var targets_string = std.ArrayList(u8).init(self.base.allocator); + var targets_string = std.ArrayList(u8).init(gpa); defer targets_string.deinit(); if (ctx.detected_targets.items.len > 1) { @@ -5226,7 +5247,7 @@ fn reportMissingLibraryError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len); errdefer gpa.free(notes); @@ -5246,7 +5267,7 @@ fn reportDependencyError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); defer notes.deinit(); @@ -5266,7 +5287,7 @@ pub fn reportParseError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); @@ -5283,7 +5304,7 @@ pub fn reportUnresolvedBoundarySymbol( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); @@ -5295,7 +5316,7 @@ pub fn reportUnresolvedBoundarySymbol( } pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const count = self.unresolved.count(); try self.misc_errors.ensureUnusedCapacity(gpa, count); @@ -5327,7 +5348,7 @@ fn reportSymbolCollision( first: SymbolWithLoc, other: SymbolWithLoc, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); @@ -5355,7 +5376,7 @@ fn reportSymbolCollision( } fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.misc_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, 1); diff --git a/src/main.zig b/src/main.zig index 681833857b97..5685ddad27b2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -269,8 +269,6 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi } } - defer log_scopes.deinit(gpa); - const cmd = args[1]; const cmd_args = args[2..]; if (mem.eql(u8, cmd, "build-exe")) { @@ -321,7 +319,7 @@ pub fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi } else if (mem.eql(u8, cmd, "init")) { return cmdInit(gpa, arena, cmd_args); } else if (mem.eql(u8, cmd, "targets")) { - const host = try std.zig.system.resolveTargetQuery(.{}); + const host = resolveTargetQueryOrFatal(.{}); const stdout = io.getStdOut().writer(); return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host); } else if (mem.eql(u8, cmd, "version")) { @@ -404,37 +402,69 @@ const usage_build_generic = \\ --global-cache-dir [path] Override the global cache directory \\ --zig-lib-dir [path] Override path to Zig installation lib directory \\ - \\Compile Options: + \\Global Compile Options: + \\ --name [name] Compilation unit name (not a file path) + \\ --libc [file] Provide a file which specifies libc paths + \\ -x language Treat subsequent input files as having type + \\ --dep [[import=]name] Add an entry to the next module's import table + \\ --mod [name] [src] Create a module based on the current per-module settings. + \\ The first module is the main module. + \\ "std" can be configured by leaving src blank. + \\ After a --mod argument, per-module settings are reset. + \\ --error-limit [num] Set the maximum amount of distinct error values + \\ -fllvm Force using LLVM as the codegen backend + \\ -fno-llvm Prevent using LLVM as the codegen backend + \\ -flibllvm Force using the LLVM API in the codegen backend + \\ -fno-libllvm Prevent using the LLVM API in the codegen backend + \\ -fclang Force using Clang as the C/C++ compilation backend + \\ -fno-clang Prevent using Clang as the C/C++ compilation backend + \\ -fPIE Force-enable Position Independent Executable + \\ -fno-PIE Force-disable Position Independent Executable + \\ -flto Force-enable Link Time Optimization (requires LLVM extensions) + \\ -fno-lto Force-disable Link Time Optimization + \\ -fdll-export-fns Mark exported functions as DLL exports (Windows) + \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports + \\ -freference-trace[=num] Show num lines of reference trace per compile error + \\ -fno-reference-trace Disable reference trace + \\ -fbuiltin Enable implicit builtin knowledge of functions + \\ -fno-builtin Disable implicit builtin knowledge of functions + \\ -ffunction-sections Places each function in a separate section + \\ -fno-function-sections All functions go into same section + \\ -fdata-sections Places each data in a separate section + \\ -fno-data-sections All data go into same section + \\ -fformatted-panics Enable formatted safety panics + \\ -fno-formatted-panics Disable formatted safety panics + \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow + \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow + \\ -mexec-model=[value] (WASI) Execution model + \\ + \\Per-Module Compile Options: \\ -target [name] -- see the targets command + \\ -O [mode] Choose what to optimize for + \\ Debug (default) Optimizations off, safety on + \\ ReleaseFast Optimize for performance, safety off + \\ ReleaseSafe Optimize for performance, safety on + \\ ReleaseSmall Optimize for small binary, safety off + \\ -ofmt=[fmt] Override target object format + \\ elf Executable and Linking Format + \\ c C source code + \\ wasm WebAssembly + \\ coff Common Object File Format (Windows) + \\ macho macOS relocatables + \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) + \\ plan9 Plan 9 from Bell Labs object format + \\ hex (planned feature) Intel IHEX + \\ raw (planned feature) Dump machine code directly \\ -mcpu [cpu] Specify target CPU and feature set \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses \\ small|kernel| \\ medium|large] - \\ -x language Treat subsequent input files as having type \\ -mred-zone Force-enable the "red-zone" \\ -mno-red-zone Force-disable the "red-zone" \\ -fomit-frame-pointer Omit the stack frame pointer \\ -fno-omit-frame-pointer Store the stack frame pointer - \\ -mexec-model=[value] (WASI) Execution model - \\ --name [name] Override root name (not a file path) - \\ -O [mode] Choose what to optimize for - \\ Debug (default) Optimizations off, safety on - \\ ReleaseFast Optimize for performance, safety off - \\ ReleaseSafe Optimize for performance, safety on - \\ ReleaseSmall Optimize for small binary, safety off - \\ --mod [name]:[deps]:[src] Make a module available for dependency under the given name - \\ deps: [dep],[dep],... - \\ dep: [[import=]name] - \\ --deps [dep],[dep],... Set dependency names for the root package - \\ dep: [[import=]name] - \\ --main-mod-path Set the directory of the root module - \\ --error-limit [num] Set the maximum amount of distinct error values \\ -fPIC Force-enable Position Independent Code \\ -fno-PIC Force-disable Position Independent Code - \\ -fPIE Force-enable Position Independent Executable - \\ -fno-PIE Force-disable Position Independent Executable - \\ -flto Force-enable Link Time Optimization (requires LLVM extensions) - \\ -fno-lto Force-disable Link Time Optimization \\ -fstack-check Enable stack probing in unsafe builds \\ -fno-stack-check Disable stack probing in safe builds \\ -fstack-protector Enable stack protection in unsafe builds @@ -445,47 +475,18 @@ const usage_build_generic = \\ -fno-valgrind Omit valgrind client requests in debug builds \\ -fsanitize-thread Enable Thread Sanitizer \\ -fno-sanitize-thread Disable Thread Sanitizer - \\ -fdll-export-fns Mark exported functions as DLL exports (Windows) - \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports \\ -funwind-tables Always produce unwind table entries for all functions \\ -fno-unwind-tables Never produce unwind table entries - \\ -fllvm Force using LLVM as the codegen backend - \\ -fno-llvm Prevent using LLVM as the codegen backend - \\ -flibllvm Force using the LLVM API in the codegen backend - \\ -fno-libllvm Prevent using the LLVM API in the codegen backend - \\ -fclang Force using Clang as the C/C++ compilation backend - \\ -fno-clang Prevent using Clang as the C/C++ compilation backend - \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error - \\ -fno-reference-trace Disable reference trace \\ -ferror-tracing Enable error tracing in ReleaseFast mode \\ -fno-error-tracing Disable error tracing in Debug and ReleaseSafe mode \\ -fsingle-threaded Code assumes there is only one thread \\ -fno-single-threaded Code may not assume there is only one thread - \\ -fbuiltin Enable implicit builtin knowledge of functions - \\ -fno-builtin Disable implicit builtin knowledge of functions - \\ -ffunction-sections Places each function in a separate section - \\ -fno-function-sections All functions go into same section - \\ -fdata-sections Places each data in a separate section - \\ -fno-data-sections All data go into same section \\ -fstrip Omit debug symbols \\ -fno-strip Keep debug symbols - \\ -fformatted-panics Enable formatted safety panics - \\ -fno-formatted-panics Disable formatted safety panics - \\ -ofmt=[mode] Override target object format - \\ elf Executable and Linking Format - \\ c C source code - \\ wasm WebAssembly - \\ coff Common Object File Format (Windows) - \\ macho macOS relocatables - \\ spirv Standard, Portable Intermediate Representation V (SPIR-V) - \\ plan9 Plan 9 from Bell Labs object format - \\ hex (planned feature) Intel IHEX - \\ raw (planned feature) Dump machine code directly \\ -idirafter [dir] Add directory to AFTER include search path \\ -isystem [dir] Add directory to SYSTEM include search path \\ -I[dir] Add directory to include search path \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted) - \\ --libc [file] Provide a file which specifies libc paths \\ -cflags [flags] -- Set extra flags for the next positional C source files \\ -rcflags [flags] -- Set extra flags for the next positional .rc source files \\ -rcincludes=[type] Set the type of includes to use when compiling .rc source files @@ -493,26 +494,8 @@ const usage_build_generic = \\ msvc Use msvc include paths (must be present on the system) \\ gnu Use mingw include paths (distributed with Zig) \\ none Do not use any autodetected include paths - \\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow - \\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow \\ - \\Link Options: - \\ -l[lib], --library [lib] Link against system library (only if actually used) - \\ -needed-l[lib], Link against system library (even if unused) - \\ --needed-library [lib] - \\ -weak-l[lib] link against system library marking it and all - \\ -weak_library [lib] referenced symbols as weak - \\ -L[d], --library-directory [d] Add a directory to the library search path - \\ -search_paths_first For each library search path, check for dynamic - \\ lib then static lib before proceeding to next path. - \\ -search_paths_first_static For each library search path, check for static - \\ lib then dynamic lib before proceeding to next path. - \\ -search_dylibs_first Search for dynamic libs in all library search - \\ paths, then static libs. - \\ -search_static_first Search for static libs in all library search - \\ paths, then dynamic libs. - \\ -search_dylibs_only Only search for dynamic libs. - \\ -search_static_only Only search for static libs. + \\Global Link Options: \\ -T[script], --script [script] Use a custom linker script \\ --version-script [path] Provide a version .map file \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) @@ -529,7 +512,6 @@ const usage_build_generic = \\ -fcompiler-rt Always include compiler-rt symbols in output \\ -fno-compiler-rt Prevent including compiler-rt symbols in output \\ -rdynamic Add all symbols to the dynamic symbol table - \\ -rpath [path] Add directory to the runtime library search path \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries @@ -566,11 +548,6 @@ const usage_build_generic = \\ --subsystem [subsystem] (Windows) /SUBSYSTEM: to the linker \\ --stack [size] Override default stack size \\ --image-base [addr] Set base address for executable image - \\ -framework [name] (Darwin) link against framework - \\ -needed_framework [name] (Darwin) link against framework (even if unused) - \\ -needed_library [lib] link against system library (even if unused) - \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak - \\ -F[dir] (Darwin) add search path for frameworks \\ -install_name=[value] (Darwin) add dylib's install name \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation @@ -587,6 +564,30 @@ const usage_build_generic = \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory \\ --shared-memory (WebAssembly) use shared linear memory \\ --global-base=[addr] (WebAssembly) where to start to place global data + \\ + \\Per-Module Link Options: + \\ -l[lib], --library [lib] Link against system library (only if actually used) + \\ -needed-l[lib], Link against system library (even if unused) + \\ --needed-library [lib] + \\ -weak-l[lib] link against system library marking it and all + \\ -weak_library [lib] referenced symbols as weak + \\ -L[d], --library-directory [d] Add a directory to the library search path + \\ -search_paths_first For each library search path, check for dynamic + \\ lib then static lib before proceeding to next path. + \\ -search_paths_first_static For each library search path, check for static + \\ lib then dynamic lib before proceeding to next path. + \\ -search_dylibs_first Search for dynamic libs in all library search + \\ paths, then static libs. + \\ -search_static_first Search for static libs in all library search + \\ paths, then dynamic libs. + \\ -search_dylibs_only Only search for dynamic libs. + \\ -search_static_only Only search for static libs. + \\ -rpath [path] Add directory to the runtime library search path + \\ -framework [name] (Darwin) link against framework + \\ -needed_framework [name] (Darwin) link against framework (even if unused) + \\ -needed_library [lib] link against system library (even if unused) + \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak + \\ -F[dir] (Darwin) add search path for frameworks \\ --export=[value] (WebAssembly) Force a symbol to be exported \\ \\Test Options: @@ -758,9 +759,24 @@ const Framework = struct { }; const CliModule = struct { - mod: *Package.Module, - /// still in CLI arg format - deps_str: []const u8, + paths: Package.Module.CreateOptions.Paths, + cc_argv: []const []const u8, + inherited: Package.Module.CreateOptions.Inherited, + target_arch_os_abi: ?[]const u8, + target_mcpu: ?[]const u8, + + deps: []const Dep, + resolved: ?*Package.Module, + + c_source_files_start: usize, + c_source_files_end: usize, + rc_source_files_start: usize, + rc_source_files_end: usize, + + pub const Dep = struct { + key: []const u8, + value: []const u8, + }; }; fn buildOutputType( @@ -769,17 +785,12 @@ fn buildOutputType( all_args: []const []const u8, arg_mode: ArgMode, ) !void { - var color: Color = .auto; - var optimize_mode: std.builtin.OptimizeMode = .Debug; var provided_name: ?[]const u8 = null; - var link_mode: ?std.builtin.LinkMode = null; var dll_export_fns: ?bool = null; - var single_threaded: ?bool = null; var root_src_file: ?[]const u8 = null; var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 }; var have_version = false; var compatibility_version: ?std.SemanticVersion = null; - var strip: ?bool = null; var formatted_panics: ?bool = null; var function_sections = false; var data_sections = false; @@ -807,30 +818,11 @@ fn buildOutputType( var emit_docs: Emit = .no; var emit_implib: Emit = .yes_default_path; var emit_implib_arg_provided = false; - var target_arch_os_abi: []const u8 = "native"; + var target_arch_os_abi: ?[]const u8 = null; var target_mcpu: ?[]const u8 = null; - var target_dynamic_linker: ?[]const u8 = null; - var target_ofmt: ?[]const u8 = null; - var output_mode: std.builtin.OutputMode = undefined; var emit_h: Emit = .no; var soname: SOName = undefined; - var ensure_libc_on_non_freestanding = false; - var ensure_libcpp_on_non_freestanding = false; - var link_libc = false; - var link_libcpp = false; - var link_libunwind = false; var want_native_include_dirs = false; - var want_pic: ?bool = null; - var want_pie: ?bool = null; - var want_lto: ?bool = null; - var want_unwind_tables: ?bool = null; - var want_sanitize_c: ?bool = null; - var want_stack_check: ?bool = null; - var want_stack_protector: ?u32 = null; - var want_red_zone: ?bool = null; - var omit_frame_pointer: ?bool = null; - var want_valgrind: ?bool = null; - var want_tsan: ?bool = null; var want_compiler_rt: ?bool = null; var rdynamic: bool = false; var linker_script: ?[]const u8 = null; @@ -841,15 +833,11 @@ fn buildOutputType( var linker_compress_debug_sections: ?link.CompressDebugSections = null; var linker_allow_shlib_undefined: ?bool = null; var linker_bind_global_refs_locally: ?bool = null; - var linker_import_memory: ?bool = null; - var linker_export_memory: ?bool = null; var linker_import_symbols: bool = false; var linker_import_table: bool = false; var linker_export_table: bool = false; - var linker_force_entry: ?bool = null; var linker_initial_memory: ?u64 = null; var linker_max_memory: ?u64 = null; - var linker_shared_memory: bool = false; var linker_global_base: ?u64 = null; var linker_print_gc_sections: bool = false; var linker_print_icf_sections: bool = false; @@ -869,23 +857,16 @@ fn buildOutputType( var linker_dynamicbase = true; var linker_optimization: ?u8 = null; var linker_module_definition_file: ?[]const u8 = null; - var test_evented_io = false; var test_no_exec = false; - var entry: ?[]const u8 = null; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; var stack_size_override: ?u64 = null; var image_base_override: ?u64 = null; - var use_llvm: ?bool = null; - var use_lib_llvm: ?bool = null; - var use_lld: ?bool = null; - var use_clang: ?bool = null; var link_eh_frame_hdr = false; var link_emit_relocs = false; var each_lib_rpath: ?bool = null; var build_id: ?std.zig.BuildId = null; var sysroot: ?[]const u8 = null; var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena); - var machine_code_model: std.builtin.CodeModel = .default; var runtime_args_start: ?usize = null; var test_filter: ?[]const u8 = null; var test_name_prefix: ?[]const u8 = null; @@ -893,12 +874,10 @@ fn buildOutputType( var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena); var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); - var main_mod_path: ?[]const u8 = null; var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; var major_subsystem_version: ?u32 = null; var minor_subsystem_version: ?u32 = null; - var wasi_exec_model: ?std.builtin.WasiExecModel = null; var enable_link_snapshots: bool = false; var debug_incremental: bool = false; var install_name: ?[]const u8 = null; @@ -910,63 +889,100 @@ fn buildOutputType( var headerpad_size: ?u32 = null; var headerpad_max_install_names: bool = false; var dead_strip_dylibs: bool = false; + var contains_res_file: bool = false; var reference_trace: ?u32 = null; - var error_tracing: ?bool = null; var pdb_out_path: ?[]const u8 = null; var dwarf_format: ?std.dwarf.Format = null; var error_limit: ?Module.ErrorInt = null; var want_structured_cfg: ?bool = null; - // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. - // This array is populated by zig cc frontend and then has to be converted to zig-style - // CPU features. - var llvm_m_args = std.ArrayList([]const u8).init(arena); - var system_libs = std.StringArrayHashMap(SystemLib).init(arena); - var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(arena); - var clang_argv = std.ArrayList([]const u8).init(arena); - var extra_cflags = std.ArrayList([]const u8).init(arena); - var extra_rcflags = std.ArrayList([]const u8).init(arena); // These are before resolving sysroot. - var lib_dir_args = std.ArrayList([]const u8).init(arena); - var rpath_list = std.ArrayList([]const u8).init(arena); + var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{}; + var extra_cflags: std.ArrayListUnmanaged([]const u8) = .{}; + var extra_rcflags: std.ArrayListUnmanaged([]const u8) = .{}; var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}; - var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena); - var rc_source_files = std.ArrayList(Compilation.RcSourceFile).init(arena); + var rpath_list: std.ArrayListUnmanaged([]const u8) = .{}; var rc_includes: Compilation.RcIncludes = .any; - var res_files = std.ArrayList(Compilation.LinkObject).init(arena); var manifest_file: ?[]const u8 = null; - var link_objects = std.ArrayList(Compilation.LinkObject).init(arena); - var framework_dirs = std.ArrayList([]const u8).init(arena); + var link_objects: std.ArrayListUnmanaged(Compilation.LinkObject) = .{}; + var framework_dirs: std.ArrayListUnmanaged([]const u8) = .{}; var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}; + var linker_export_symbol_names: std.ArrayListUnmanaged([]const u8) = .{}; + + // Tracks the position in c_source_files which have already their owner populated. + var c_source_files_owner_index: usize = 0; + // Tracks the position in rc_source_files which have already their owner populated. + var rc_source_files_owner_index: usize = 0; + // null means replace with the test executable binary var test_exec_args = std.ArrayList(?[]const u8).init(arena); - var linker_export_symbol_names = std.ArrayList([]const u8).init(arena); + + // These get set by CLI flags and then snapshotted when a `--mod` flag is + // encountered. + var mod_opts: Package.Module.CreateOptions.Inherited = .{}; + + // These get appended to by CLI flags and then slurped when a `--mod` flag + // is encountered. + var cssan: ClangSearchSanitizer = .{}; + var clang_argv: std.ArrayListUnmanaged([]const u8) = .{}; + var deps: std.ArrayListUnmanaged(CliModule.Dep) = .{}; + // Contains every module specified via --mod. The dependencies are added // after argument parsing is completed. We use a StringArrayHashMap to make - // error output consistent. - var modules = std.StringArrayHashMap(CliModule).init(arena); + // error output consistent. "root" is special. + var create_module: CreateModule = .{ + // Populated just before the call to `createModule`. + .global_cache_directory = undefined, + .object_format = null, + .dynamic_linker = null, + .modules = .{}, + .opts = .{ + .is_test = arg_mode == .zig_test, + // Populated while parsing CLI args. + .output_mode = undefined, + // Populated in the call to `createModule` for the root module. + .resolved_target = undefined, + .have_zcu = false, + // Populated just before the call to `createModule`. + .emit_llvm_ir = undefined, + // Populated just before the call to `createModule`. + .emit_llvm_bc = undefined, + // Populated just before the call to `createModule`. + .emit_bin = undefined, + // Populated just before the call to `createModule`. + .c_source_files_len = undefined, + }, + // Populated in the call to `createModule` for the root module. + .resolved_options = undefined, - // The dependency string for the root package - var root_deps_str: ?[]const u8 = null; + .system_libs = .{}, + .external_system_libs = .{}, + .resolved_system_libs = .{}, + .wasi_emulated_libs = .{}, + + .c_source_files = .{}, + .rc_source_files = .{}, + + .llvm_m_args = .{}, + }; // before arg parsing, check for the NO_COLOR environment variable // if it exists, default the color setting to .off // explicit --color arguments will still override this setting. // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/162 - color = if (builtin.os.tag == .wasi or EnvVar.NO_COLOR.isSet()) .off else .auto; + var color: Color = if (builtin.os.tag == .wasi or EnvVar.NO_COLOR.isSet()) .off else .auto; switch (arg_mode) { .build, .translate_c, .zig_test, .run => { - var optimize_mode_string: ?[]const u8 = null; switch (arg_mode) { .build => |m| { - output_mode = m; + create_module.opts.output_mode = m; }, .translate_c => { emit_bin = .no; - output_mode = .Obj; + create_module.opts.output_mode = .Obj; }, .zig_test, .run => { - output_mode = .Exe; + create_module.opts.output_mode = .Exe; }, else => unreachable, } @@ -977,9 +993,6 @@ fn buildOutputType( .args = all_args[2..], }; - var cssan = ClangSearchSanitizer.init(gpa, &clang_argv); - defer cssan.map.deinit(); - var file_ext: ?Compilation.FileExt = null; args_loop: while (args_iter.next()) |arg| { if (mem.startsWith(u8, arg, "@")) { @@ -1002,49 +1015,73 @@ fn buildOutputType( } else { fatal("unexpected end-of-parameter mark: --", .{}); } - } else if (mem.eql(u8, arg, "--mod")) { - const info = args_iter.nextOrFatal(); - var info_it = mem.splitScalar(u8, info, ':'); - const mod_name = info_it.next() orelse fatal("expected non-empty argument after {s}", .{arg}); - const deps_str = info_it.next() orelse fatal("expected 'name:deps:path' after {s}", .{arg}); - const root_src_orig = info_it.rest(); - if (root_src_orig.len == 0) fatal("expected 'name:deps:path' after {s}", .{arg}); - if (mod_name.len == 0) fatal("empty name for module at '{s}'", .{root_src_orig}); - - const root_src = try introspect.resolvePath(arena, root_src_orig); - - for ([_][]const u8{ "std", "root", "builtin" }) |name| { - if (mem.eql(u8, mod_name, name)) { - fatal("unable to add module '{s}' -> '{s}': conflicts with builtin module", .{ - mod_name, root_src, + } else if (mem.eql(u8, arg, "--dep")) { + var it = mem.splitScalar(u8, args_iter.nextOrFatal(), '='); + const key = it.next().?; + const value = it.next() orelse key; + if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) { + fatal("unable to import as '{s}': conflicts with builtin module", .{ + key, + }); + } + for ([_][]const u8{ "root", "builtin" }) |name| { + if (mem.eql(u8, key, name)) { + fatal("unable to import as '{s}': conflicts with builtin module", .{ + key, }); } } + try deps.append(arena, .{ + .key = key, + .value = value, + }); + } else if (mem.eql(u8, arg, "--mod")) { + const mod_name = args_iter.nextOrFatal(); + const root_src_orig = args_iter.nextOrFatal(); - if (modules.get(mod_name)) |value| { - fatal("unable to add module '{s}' -> '{s}': already exists as '{s}'", .{ - mod_name, root_src, value.mod.root_src_path, + const gop = try create_module.modules.getOrPut(arena, mod_name); + + if (gop.found_existing) { + fatal("unable to add module '{s}': already exists as '{s}'", .{ + mod_name, gop.value_ptr.paths.root_src_path, }); } - try modules.put(mod_name, .{ - .mod = try Package.Module.create(arena, .{ + // See duplicate logic: ModCreationGlobalFlags + create_module.opts.have_zcu = true; + if (mod_opts.single_threaded == false) + create_module.opts.any_non_single_threaded = true; + if (mod_opts.sanitize_thread == true) + create_module.opts.any_sanitize_thread = true; + if (mod_opts.unwind_tables == true) + create_module.opts.any_unwind_tables = true; + + const root_src = try introspect.resolvePath(arena, root_src_orig); + try create_module.modules.put(arena, mod_name, .{ + .paths = .{ .root = .{ .root_dir = Cache.Directory.cwd(), .sub_path = fs.path.dirname(root_src) orelse "", }, .root_src_path = fs.path.basename(root_src), - .fully_qualified_name = mod_name, - }), - .deps_str = deps_str, + }, + .cc_argv = try clang_argv.toOwnedSlice(arena), + .inherited = mod_opts, + .target_arch_os_abi = target_arch_os_abi, + .target_mcpu = target_mcpu, + .deps = try deps.toOwnedSlice(arena), + .resolved = null, + .c_source_files_start = c_source_files_owner_index, + .c_source_files_end = create_module.c_source_files.items.len, + .rc_source_files_start = rc_source_files_owner_index, + .rc_source_files_end = create_module.rc_source_files.items.len, }); - } else if (mem.eql(u8, arg, "--deps")) { - if (root_deps_str != null) { - fatal("only one --deps argument is allowed", .{}); - } - root_deps_str = args_iter.nextOrFatal(); - } else if (mem.eql(u8, arg, "--main-mod-path")) { - main_mod_path = args_iter.nextOrFatal(); + cssan.reset(); + mod_opts = .{}; + target_arch_os_abi = null; + target_mcpu = null; + c_source_files_owner_index = create_module.c_source_files.items.len; + rc_source_files_owner_index = create_module.rc_source_files.items.len; } else if (mem.eql(u8, arg, "--error-limit")) { const next_arg = args_iter.nextOrFatal(); error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| { @@ -1057,7 +1094,7 @@ fn buildOutputType( fatal("expected -- after -cflags", .{}); }; if (mem.eql(u8, next_arg, "--")) break; - try extra_cflags.append(next_arg); + try extra_cflags.append(arena, next_arg); } } else if (mem.eql(u8, arg, "-rcincludes")) { rc_includes = parseRcIncludes(args_iter.nextOrFatal()); @@ -1070,7 +1107,7 @@ fn buildOutputType( fatal("expected -- after -rcflags", .{}); }; if (mem.eql(u8, next_arg, "--")) break; - try extra_rcflags.append(next_arg); + try extra_rcflags.append(arena, next_arg); } } else if (mem.startsWith(u8, arg, "-fstructured-cfg")) { want_structured_cfg = true; @@ -1086,11 +1123,11 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--subsystem")) { subsystem = try parseSubSystem(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-O")) { - optimize_mode_string = args_iter.nextOrFatal(); + mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal()); } else if (mem.startsWith(u8, arg, "-fentry=")) { - entry = arg["-fentry=".len..]; + create_module.opts.entry = .{ .named = arg["-fentry=".len..] }; } else if (mem.eql(u8, arg, "--force_undefined")) { - try force_undefined_symbols.put(gpa, args_iter.nextOrFatal(), {}); + try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack")) { const next_arg = args_iter.nextOrFatal(); stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { @@ -1106,17 +1143,17 @@ fn buildOutputType( if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?))) fatal("invalid package name '{s}': cannot contain folder separators", .{provided_name.?}); } else if (mem.eql(u8, arg, "-rpath")) { - try rpath_list.append(args_iter.nextOrFatal()); + try rpath_list.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - try lib_dir_args.append(args_iter.nextOrFatal()); + try lib_dir_args.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-F")) { - try framework_dirs.append(args_iter.nextOrFatal()); + try framework_dirs.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-framework")) { - try frameworks.put(gpa, args_iter.nextOrFatal(), .{}); + try frameworks.put(arena, args_iter.nextOrFatal(), .{}); } else if (mem.eql(u8, arg, "-weak_framework")) { - try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .weak = true }); + try frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true }); } else if (mem.eql(u8, arg, "-needed_framework")) { - try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .needed = true }); + try frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true }); } else if (mem.eql(u8, arg, "-install_name")) { install_name = args_iter.nextOrFatal(); } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) { @@ -1168,7 +1205,7 @@ fn buildOutputType( // We don't know whether this library is part of libc // or libc++ until we resolve the target, so we append // to the list for now. - try system_libs.put(args_iter.nextOrFatal(), .{ + try create_module.system_libs.put(arena, args_iter.nextOrFatal(), .{ .needed = false, .weak = false, .preferred_mode = lib_preferred_mode, @@ -1179,38 +1216,37 @@ fn buildOutputType( mem.eql(u8, arg, "-needed_library")) { const next_arg = args_iter.nextOrFatal(); - try system_libs.put(next_arg, .{ + try create_module.system_libs.put(arena, next_arg, .{ .needed = true, .weak = false, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) { - try system_libs.put(args_iter.nextOrFatal(), .{ + try create_module.system_libs.put(arena, args_iter.nextOrFatal(), .{ .needed = false, .weak = true, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-D")) { - try clang_argv.append(arg); - try clang_argv.append(args_iter.nextOrFatal()); + try clang_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() }); } else if (mem.eql(u8, arg, "-I")) { - try cssan.addIncludePath(.I, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &clang_argv, .I, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-isystem")) { - try cssan.addIncludePath(.isystem, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &clang_argv, .isystem, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-iwithsysroot")) { - try cssan.addIncludePath(.iwithsysroot, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &clang_argv, .iwithsysroot, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-idirafter")) { - try cssan.addIncludePath(.idirafter, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &clang_argv, .idirafter, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-iframework")) { const path = args_iter.nextOrFatal(); - try cssan.addIncludePath(.iframework, arg, path, false); - try framework_dirs.append(path); // Forward to the backend as -F + try cssan.addIncludePath(arena, &clang_argv, .iframework, arg, path, false); + try framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) { const path = args_iter.nextOrFatal(); - try cssan.addIncludePath(.iframeworkwithsysroot, arg, path, false); - try framework_dirs.append(path); // Forward to the backend as -F + try cssan.addIncludePath(arena, &clang_argv, .iframeworkwithsysroot, arg, path, false); + try framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "--version")) { const next_arg = args_iter.nextOrFatal(); version = std.SemanticVersion.parse(next_arg) catch |err| { @@ -1222,21 +1258,21 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-mcpu")) { target_mcpu = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "-mcmodel")) { - machine_code_model = parseCodeModel(args_iter.nextOrFatal()); + mod_opts.code_model = parseCodeModel(args_iter.nextOrFatal()); + } else if (mem.startsWith(u8, arg, "-mcmodel=")) { + mod_opts.code_model = parseCodeModel(arg["-mcmodel=".len..]); } else if (mem.startsWith(u8, arg, "-ofmt=")) { - target_ofmt = arg["-ofmt=".len..]; + create_module.object_format = arg["-ofmt=".len..]; } else if (mem.startsWith(u8, arg, "-mcpu=")) { target_mcpu = arg["-mcpu=".len..]; - } else if (mem.startsWith(u8, arg, "-mcmodel=")) { - machine_code_model = parseCodeModel(arg["-mcmodel=".len..]); } else if (mem.startsWith(u8, arg, "-O")) { - optimize_mode_string = arg["-O".len..]; + mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]); } else if (mem.eql(u8, arg, "--dynamic-linker")) { - target_dynamic_linker = args_iter.nextOrFatal(); + create_module.dynamic_linker = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--sysroot")) { - sysroot = args_iter.nextOrFatal(); - try clang_argv.append("-isysroot"); - try clang_argv.append(sysroot.?); + const next_arg = args_iter.nextOrFatal(); + sysroot = next_arg; + try clang_argv.appendSlice(arena, &.{ "-isysroot", next_arg }); } else if (mem.eql(u8, arg, "--libc")) { libc_paths_file = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--test-filter")) { @@ -1258,7 +1294,7 @@ fn buildOutputType( warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); _ = args_iter.nextOrFatal(); } else { - try log_scopes.append(gpa, args_iter.nextOrFatal()); + try log_scopes.append(arena, args_iter.nextOrFatal()); } } else if (mem.eql(u8, arg, "--listen")) { const next_arg = args_iter.nextOrFatal(); @@ -1298,7 +1334,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--test-cmd-bin")) { try test_exec_args.append(null); } else if (mem.eql(u8, arg, "--test-evented-io")) { - test_evented_io = true; + create_module.opts.test_evented_io = true; } else if (mem.eql(u8, arg, "--test-no-exec")) { test_no_exec = true; } else if (mem.eql(u8, arg, "-ftime-report")) { @@ -1306,65 +1342,65 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fstack-report")) { stack_report = true; } else if (mem.eql(u8, arg, "-fPIC")) { - want_pic = true; + mod_opts.pic = true; } else if (mem.eql(u8, arg, "-fno-PIC")) { - want_pic = false; + mod_opts.pic = false; } else if (mem.eql(u8, arg, "-fPIE")) { - want_pie = true; + create_module.opts.pie = true; } else if (mem.eql(u8, arg, "-fno-PIE")) { - want_pie = false; + create_module.opts.pie = false; } else if (mem.eql(u8, arg, "-flto")) { - want_lto = true; + create_module.opts.lto = true; } else if (mem.eql(u8, arg, "-fno-lto")) { - want_lto = false; + create_module.opts.lto = false; } else if (mem.eql(u8, arg, "-funwind-tables")) { - want_unwind_tables = true; + mod_opts.unwind_tables = true; } else if (mem.eql(u8, arg, "-fno-unwind-tables")) { - want_unwind_tables = false; + mod_opts.unwind_tables = false; } else if (mem.eql(u8, arg, "-fstack-check")) { - want_stack_check = true; + mod_opts.stack_check = true; } else if (mem.eql(u8, arg, "-fno-stack-check")) { - want_stack_check = false; + mod_opts.stack_check = false; } else if (mem.eql(u8, arg, "-fstack-protector")) { - want_stack_protector = Compilation.default_stack_protector_buffer_size; + mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size; } else if (mem.eql(u8, arg, "-fno-stack-protector")) { - want_stack_protector = 0; + mod_opts.stack_protector = 0; } else if (mem.eql(u8, arg, "-mred-zone")) { - want_red_zone = true; + mod_opts.red_zone = true; } else if (mem.eql(u8, arg, "-mno-red-zone")) { - want_red_zone = false; + mod_opts.red_zone = false; } else if (mem.eql(u8, arg, "-fomit-frame-pointer")) { - omit_frame_pointer = true; + mod_opts.omit_frame_pointer = true; } else if (mem.eql(u8, arg, "-fno-omit-frame-pointer")) { - omit_frame_pointer = false; + mod_opts.omit_frame_pointer = false; } else if (mem.eql(u8, arg, "-fsanitize-c")) { - want_sanitize_c = true; + mod_opts.sanitize_c = true; } else if (mem.eql(u8, arg, "-fno-sanitize-c")) { - want_sanitize_c = false; + mod_opts.sanitize_c = false; } else if (mem.eql(u8, arg, "-fvalgrind")) { - want_valgrind = true; + mod_opts.valgrind = true; } else if (mem.eql(u8, arg, "-fno-valgrind")) { - want_valgrind = false; + mod_opts.valgrind = false; } else if (mem.eql(u8, arg, "-fsanitize-thread")) { - want_tsan = true; + mod_opts.sanitize_thread = true; } else if (mem.eql(u8, arg, "-fno-sanitize-thread")) { - want_tsan = false; + mod_opts.sanitize_thread = false; } else if (mem.eql(u8, arg, "-fllvm")) { - use_llvm = true; + create_module.opts.use_llvm = true; } else if (mem.eql(u8, arg, "-fno-llvm")) { - use_llvm = false; + create_module.opts.use_llvm = false; } else if (mem.eql(u8, arg, "-flibllvm")) { - use_lib_llvm = true; + create_module.opts.use_lib_llvm = true; } else if (mem.eql(u8, arg, "-fno-libllvm")) { - use_lib_llvm = false; + create_module.opts.use_lib_llvm = false; } else if (mem.eql(u8, arg, "-flld")) { - use_lld = true; + create_module.opts.use_lld = true; } else if (mem.eql(u8, arg, "-fno-lld")) { - use_lld = false; + create_module.opts.use_lld = false; } else if (mem.eql(u8, arg, "-fclang")) { - use_clang = true; + create_module.opts.use_clang = true; } else if (mem.eql(u8, arg, "-fno-clang")) { - use_clang = false; + create_module.opts.use_clang = false; } else if (mem.eql(u8, arg, "-freference-trace")) { reference_trace = 256; } else if (mem.startsWith(u8, arg, "-freference-trace=")) { @@ -1375,9 +1411,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-reference-trace")) { reference_trace = null; } else if (mem.eql(u8, arg, "-ferror-tracing")) { - error_tracing = true; + mod_opts.error_tracing = true; } else if (mem.eql(u8, arg, "-fno-error-tracing")) { - error_tracing = false; + mod_opts.error_tracing = false; } else if (mem.eql(u8, arg, "-rdynamic")) { rdynamic = true; } else if (mem.eql(u8, arg, "-fsoname")) { @@ -1432,11 +1468,11 @@ fn buildOutputType( emit_implib = .no; emit_implib_arg_provided = true; } else if (mem.eql(u8, arg, "-dynamic")) { - link_mode = .Dynamic; + create_module.opts.link_mode = .Dynamic; lib_preferred_mode = .Dynamic; lib_search_strategy = .mode_first; } else if (mem.eql(u8, arg, "-static")) { - link_mode = .Static; + create_module.opts.link_mode = .Static; lib_preferred_mode = .Static; lib_search_strategy = .no_fallback; } else if (mem.eql(u8, arg, "-fdll-export-fns")) { @@ -1447,9 +1483,9 @@ fn buildOutputType( show_builtin = true; emit_bin = .no; } else if (mem.eql(u8, arg, "-fstrip")) { - strip = true; + mod_opts.strip = true; } else if (mem.eql(u8, arg, "-fno-strip")) { - strip = false; + mod_opts.strip = false; } else if (mem.eql(u8, arg, "-gdwarf32")) { dwarf_format = .@"32"; } else if (mem.eql(u8, arg, "-gdwarf64")) { @@ -1459,9 +1495,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { formatted_panics = false; } else if (mem.eql(u8, arg, "-fsingle-threaded")) { - single_threaded = true; + mod_opts.single_threaded = true; } else if (mem.eql(u8, arg, "-fno-single-threaded")) { - single_threaded = false; + mod_opts.single_threaded = false; } else if (mem.eql(u8, arg, "-ffunction-sections")) { function_sections = true; } else if (mem.eql(u8, arg, "-fno-function-sections")) { @@ -1518,13 +1554,16 @@ fn buildOutputType( fatal("unsupported linker extension flag: -z {s}", .{z_arg}); } } else if (mem.eql(u8, arg, "--import-memory")) { - linker_import_memory = true; + create_module.opts.import_memory = true; } else if (mem.eql(u8, arg, "-fentry")) { - linker_force_entry = true; + switch (create_module.opts.entry) { + .default, .disabled => create_module.opts.entry = .enabled, + .enabled, .named => {}, + } } else if (mem.eql(u8, arg, "-fno-entry")) { - linker_force_entry = false; + create_module.opts.entry = .disabled; } else if (mem.eql(u8, arg, "--export-memory")) { - linker_export_memory = true; + create_module.opts.export_memory = true; } else if (mem.eql(u8, arg, "--import-symbols")) { linker_import_symbols = true; } else if (mem.eql(u8, arg, "--import-table")) { @@ -1536,11 +1575,11 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "--max-memory=")) { linker_max_memory = parseIntSuffix(arg, "--max-memory=".len); } else if (mem.eql(u8, arg, "--shared-memory")) { - linker_shared_memory = true; + create_module.opts.shared_memory = true; } else if (mem.startsWith(u8, arg, "--global-base=")) { linker_global_base = parseIntSuffix(arg, "--global-base=".len); } else if (mem.startsWith(u8, arg, "--export=")) { - try linker_export_symbol_names.append(arg["--export=".len..]); + try linker_export_symbol_names.append(arena, arg["--export=".len..]); } else if (mem.eql(u8, arg, "-Bsymbolic")) { linker_bind_global_refs_locally = true; } else if (mem.eql(u8, arg, "--gc-sections")) { @@ -1585,37 +1624,37 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-T")) { linker_script = arg[2..]; } else if (mem.startsWith(u8, arg, "-L")) { - try lib_dir_args.append(arg[2..]); + try lib_dir_args.append(arena, arg[2..]); } else if (mem.startsWith(u8, arg, "-F")) { - try framework_dirs.append(arg[2..]); + try framework_dirs.append(arena, arg[2..]); } else if (mem.startsWith(u8, arg, "-l")) { // We don't know whether this library is part of libc // or libc++ until we resolve the target, so we append // to the list for now. - try system_libs.put(arg["-l".len..], .{ + try create_module.system_libs.put(arena, arg["-l".len..], .{ .needed = false, .weak = false, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-needed-l")) { - try system_libs.put(arg["-needed-l".len..], .{ + try create_module.system_libs.put(arena, arg["-needed-l".len..], .{ .needed = true, .weak = false, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-weak-l")) { - try system_libs.put(arg["-weak-l".len..], .{ + try create_module.system_libs.put(arena, arg["-weak-l".len..], .{ .needed = false, .weak = true, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-D")) { - try clang_argv.append(arg); + try clang_argv.append(arena, arg); } else if (mem.startsWith(u8, arg, "-I")) { - try cssan.addIncludePath(.I, arg, arg[2..], true); + try cssan.addIncludePath(arena, &clang_argv, .I, arg, arg[2..], true); } else if (mem.eql(u8, arg, "-x")) { const lang = args_iter.nextOrFatal(); if (mem.eql(u8, lang, "none")) { @@ -1626,23 +1665,27 @@ fn buildOutputType( fatal("language not recognized: '{s}'", .{lang}); } } else if (mem.startsWith(u8, arg, "-mexec-model=")) { - wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, arg["-mexec-model=".len..]) orelse { - fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{arg["-mexec-model=".len..]}); - }; + create_module.opts.wasi_exec_model = parseWasiExecModel(arg["-mexec-model=".len..]); } else { fatal("unrecognized parameter: '{s}'", .{arg}); } - } else switch (file_ext orelse - Compilation.classifyFileExt(arg)) { - .object, .static_library, .shared_library => try link_objects.append(.{ .path = arg }), - .res => try res_files.append(.{ .path = arg }), + } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { + .object, .static_library, .shared_library => { + try link_objects.append(arena, .{ .path = arg }); + }, + .res => { + try link_objects.append(arena, .{ .path = arg }); + contains_res_file = true; + }, .manifest => { if (manifest_file) |other| { fatal("only one manifest file can be specified, found '{s}' after '{s}'", .{ arg, other }); } else manifest_file = arg; }, .assembly, .assembly_with_cpp, .c, .cpp, .h, .ll, .bc, .m, .mm, .cu => { - try c_source_files.append(.{ + try create_module.c_source_files.append(arena, .{ + // Populated after module creation. + .owner = undefined, .src_path = arg, .extra_flags = try arena.dupe([]const u8, extra_cflags.items), // duped when parsing the args. @@ -1650,7 +1693,9 @@ fn buildOutputType( }); }, .rc => { - try rc_source_files.append(.{ + try create_module.rc_source_files.append(arena, .{ + // Populated after module creation. + .owner = undefined, .src_path = arg, .extra_flags = try arena.dupe([]const u8, extra_rcflags.items), }); @@ -1668,18 +1713,14 @@ fn buildOutputType( }, } } - if (optimize_mode_string) |s| { - optimize_mode = std.meta.stringToEnum(std.builtin.OptimizeMode, s) orelse - fatal("unrecognized optimization mode: '{s}'", .{s}); - } }, .cc, .cpp => { if (build_options.only_c) unreachable; emit_h = .no; soname = .no; - ensure_libc_on_non_freestanding = true; - ensure_libcpp_on_non_freestanding = arg_mode == .cpp; + create_module.opts.ensure_libc_on_non_freestanding = true; + create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp; want_native_include_dirs = true; // Clang's driver enables this switch unconditionally. // Disabling the emission of .eh_frame_hdr can unexpectedly break @@ -1733,24 +1774,30 @@ fn buildOutputType( } }, .other => { - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); }, - .positional => switch (file_ext orelse - Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) { + .positional => switch (file_ext orelse Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) { .assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .m, .mm, .cu => { - try c_source_files.append(.{ + try create_module.c_source_files.append(arena, .{ + // Populated after module creation. + .owner = undefined, .src_path = it.only_arg, .ext = file_ext, // duped while parsing the args. }); }, - .unknown, .shared_library, .object, .static_library => try link_objects.append(.{ - .path = it.only_arg, - .must_link = must_link, - }), - .res => try res_files.append(.{ - .path = it.only_arg, - .must_link = must_link, - }), + .unknown, .shared_library, .object, .static_library => { + try link_objects.append(arena, .{ + .path = it.only_arg, + .must_link = must_link, + }); + }, + .res => { + try link_objects.append(arena, .{ + .path = it.only_arg, + .must_link = must_link, + }); + contains_res_file = true; + }, .manifest => { if (manifest_file) |other| { fatal("only one manifest file can be specified, found '{s}' after previously specified manifest '{s}'", .{ it.only_arg, other }); @@ -1760,7 +1807,11 @@ fn buildOutputType( linker_module_definition_file = it.only_arg; }, .rc => { - try rc_source_files.append(.{ .src_path = it.only_arg }); + try create_module.rc_source_files.append(arena, .{ + // Populated after module creation. + .owner = undefined, + .src_path = it.only_arg, + }); }, .zig => { if (root_src_file) |other| { @@ -1777,13 +1828,13 @@ fn buildOutputType( // more control over what's in the resulting // binary: no extra rpaths and DSO filename exactly // as provided. Hello, Go. - try link_objects.append(.{ + try link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, .loption = true, }); } else { - try system_libs.put(it.only_arg, .{ + try create_module.system_libs.put(arena, it.only_arg, .{ .needed = needed, .weak = false, .preferred_mode = lib_preferred_mode, @@ -1796,16 +1847,16 @@ fn buildOutputType( // Never mind what we're doing, just pass the args directly. For example --help. return process.exit(try clangMain(arena, all_args)); }, - .pic => want_pic = true, - .no_pic => want_pic = false, - .pie => want_pie = true, - .no_pie => want_pie = false, - .lto => want_lto = true, - .no_lto => want_lto = false, - .red_zone => want_red_zone = true, - .no_red_zone => want_red_zone = false, - .omit_frame_pointer => omit_frame_pointer = true, - .no_omit_frame_pointer => omit_frame_pointer = false, + .pic => mod_opts.pic = true, + .no_pic => mod_opts.pic = false, + .pie => create_module.opts.pie = true, + .no_pie => create_module.opts.pie = false, + .lto => create_module.opts.lto = true, + .no_lto => create_module.opts.lto = false, + .red_zone => mod_opts.red_zone = true, + .no_red_zone => mod_opts.red_zone = false, + .omit_frame_pointer => mod_opts.omit_frame_pointer = true, + .no_omit_frame_pointer => mod_opts.omit_frame_pointer = false, .function_sections => function_sections = true, .no_function_sections => function_sections = false, .data_sections => data_sections = true, @@ -1814,23 +1865,23 @@ fn buildOutputType( .no_builtin => no_builtin = true, .color_diagnostics => color = .on, .no_color_diagnostics => color = .off, - .stack_check => want_stack_check = true, - .no_stack_check => want_stack_check = false, + .stack_check => mod_opts.stack_check = true, + .no_stack_check => mod_opts.stack_check = false, .stack_protector => { - if (want_stack_protector == null) { - want_stack_protector = Compilation.default_stack_protector_buffer_size; + if (mod_opts.stack_protector == null) { + mod_opts.stack_protector = Compilation.default_stack_protector_buffer_size; } }, - .no_stack_protector => want_stack_protector = 0, - .unwind_tables => want_unwind_tables = true, - .no_unwind_tables => want_unwind_tables = false, + .no_stack_protector => mod_opts.stack_protector = 0, + .unwind_tables => mod_opts.unwind_tables = true, + .no_unwind_tables => mod_opts.unwind_tables = false, .nostdlib => { - ensure_libc_on_non_freestanding = false; - ensure_libcpp_on_non_freestanding = false; + create_module.opts.ensure_libc_on_non_freestanding = false; + create_module.opts.ensure_libcpp_on_non_freestanding = false; }, - .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false, + .nostdlib_cpp => create_module.opts.ensure_libcpp_on_non_freestanding = false, .shared => { - link_mode = .Dynamic; + create_module.opts.link_mode = .Dynamic; is_shared_lib = true; }, .rdynamic => rdynamic = true, @@ -1870,7 +1921,7 @@ fn buildOutputType( } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { needed = true; } else if (mem.eql(u8, linker_arg, "-no-pie")) { - want_pie = false; + create_module.opts.pie = false; } else if (mem.eql(u8, linker_arg, "--sort-common")) { // from ld.lld(1): --sort-common is ignored for GNU compatibility, // this ignores plain --sort-common @@ -1912,50 +1963,50 @@ fn buildOutputType( if (mem.eql(u8, level, "s") or mem.eql(u8, level, "z")) { - optimize_mode = .ReleaseSmall; + mod_opts.optimize_mode = .ReleaseSmall; } else if (mem.eql(u8, level, "1") or mem.eql(u8, level, "2") or mem.eql(u8, level, "3") or mem.eql(u8, level, "4") or mem.eql(u8, level, "fast")) { - optimize_mode = .ReleaseFast; + mod_opts.optimize_mode = .ReleaseFast; } else if (mem.eql(u8, level, "g") or mem.eql(u8, level, "0")) { - optimize_mode = .Debug; + mod_opts.optimize_mode = .Debug; } else { - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); } }, .debug => { - strip = false; + mod_opts.strip = false; if (mem.eql(u8, it.only_arg, "g")) { // We handled with strip = false above. } else if (mem.eql(u8, it.only_arg, "g1") or mem.eql(u8, it.only_arg, "gline-tables-only")) { // We handled with strip = false above. but we also want reduced debug info. - try clang_argv.append("-gline-tables-only"); + try clang_argv.append(arena, "-gline-tables-only"); } else { - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); } }, .gdwarf32 => { - strip = false; + mod_opts.strip = false; dwarf_format = .@"32"; }, .gdwarf64 => { - strip = false; + mod_opts.strip = false; dwarf_format = .@"64"; }, .sanitize => { if (mem.eql(u8, it.only_arg, "undefined")) { - want_sanitize_c = true; + mod_opts.sanitize_c = true; } else if (mem.eql(u8, it.only_arg, "thread")) { - want_tsan = true; + mod_opts.sanitize_thread = true; } else { - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); } }, .linker_script => linker_script = it.only_arg, @@ -1964,59 +2015,57 @@ fn buildOutputType( // Have Clang print more infos, some tools such as CMake // parse this to discover any implicit include and // library dir to look-up into. - try clang_argv.append("-v"); + try clang_argv.append(arena, "-v"); }, .dry_run => { // This flag means "dry run". Clang will not actually output anything // to the file system. verbose_link = true; disable_c_depfile = true; - try clang_argv.append("-###"); + try clang_argv.append(arena, "-###"); }, .for_linker => try linker_args.append(it.only_arg), .linker_input_z => { try linker_args.append("-z"); try linker_args.append(it.only_arg); }, - .lib_dir => try lib_dir_args.append(it.only_arg), + .lib_dir => try lib_dir_args.append(arena, it.only_arg), .mcpu => target_mcpu = it.only_arg, - .m => try llvm_m_args.append(it.only_arg), + .m => try create_module.llvm_m_args.append(arena, it.only_arg), .dep_file => { disable_c_depfile = true; - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); }, .dep_file_to_stdout => { // -M, -MM // "Like -MD, but also implies -E and writes to stdout by default" // "Like -MMD, but also implies -E and writes to stdout by default" c_out_mode = .preprocessor; disable_c_depfile = true; - try clang_argv.appendSlice(it.other_args); + try clang_argv.appendSlice(arena, it.other_args); }, - .framework_dir => try framework_dirs.append(it.only_arg), - .framework => try frameworks.put(gpa, it.only_arg, .{}), + .framework_dir => try framework_dirs.append(arena, it.only_arg), + .framework => try frameworks.put(arena, it.only_arg, .{}), .nostdlibinc => want_native_include_dirs = false, - .strip => strip = true, + .strip => mod_opts.strip = true, .exec_model => { - wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, it.only_arg) orelse { - fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{it.only_arg}); - }; + create_module.opts.wasi_exec_model = parseWasiExecModel(it.only_arg); }, .sysroot => { sysroot = it.only_arg; }, .entry => { - entry = it.only_arg; + create_module.opts.entry = .{ .named = it.only_arg }; }, .force_undefined_symbol => { - try force_undefined_symbols.put(gpa, it.only_arg, {}); + try force_undefined_symbols.put(arena, it.only_arg, {}); }, - .weak_library => try system_libs.put(it.only_arg, .{ + .weak_library => try create_module.system_libs.put(arena, it.only_arg, .{ .needed = false, .weak = true, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }), - .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), + .weak_framework => try frameworks.put(arena, it.only_arg, .{ .weak = true }), .headerpad_max_install_names => headerpad_max_install_names = true, .compress_debug_sections => { if (it.only_arg.len == 0) { @@ -2077,14 +2126,14 @@ fn buildOutputType( } provided_name = name[prefix..end]; } else if (mem.eql(u8, arg, "-rpath")) { - try rpath_list.append(linker_args_it.nextOrFatal()); + try rpath_list.append(arena, linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--subsystem")) { subsystem = try parseSubSystem(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "-I") or mem.eql(u8, arg, "--dynamic-linker") or mem.eql(u8, arg, "-dynamic-linker")) { - target_dynamic_linker = linker_args_it.nextOrFatal(); + create_module.dynamic_linker = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "-E") or mem.eql(u8, arg, "--export-dynamic") or mem.eql(u8, arg, "-export-dynamic")) @@ -2145,9 +2194,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-Bsymbolic")) { linker_bind_global_refs_locally = true; } else if (mem.eql(u8, arg, "--import-memory")) { - linker_import_memory = true; + create_module.opts.import_memory = true; } else if (mem.eql(u8, arg, "--export-memory")) { - linker_export_memory = true; + create_module.opts.export_memory = true; } else if (mem.eql(u8, arg, "--import-symbols")) { linker_import_symbols = true; } else if (mem.eql(u8, arg, "--import-table")) { @@ -2155,7 +2204,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--export-table")) { linker_export_table = true; } else if (mem.eql(u8, arg, "--no-entry")) { - linker_force_entry = false; + create_module.opts.entry = .disabled; } else if (mem.eql(u8, arg, "--initial-memory")) { const next_arg = linker_args_it.nextOrFatal(); linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2167,14 +2216,14 @@ fn buildOutputType( fatal("unable to parse max memory size '{s}': {s}", .{ next_arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--shared-memory")) { - linker_shared_memory = true; + create_module.opts.shared_memory = true; } else if (mem.eql(u8, arg, "--global-base")) { const next_arg = linker_args_it.nextOrFatal(); linker_global_base = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { fatal("unable to parse global base '{s}': {s}", .{ next_arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--export")) { - try linker_export_symbol_names.append(linker_args_it.nextOrFatal()); + 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 { @@ -2232,9 +2281,9 @@ fn buildOutputType( }; have_version = true; } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { - entry = linker_args_it.nextOrFatal(); + create_module.opts.entry = .{ .named = linker_args_it.nextOrFatal() }; } else if (mem.eql(u8, arg, "-u")) { - try force_undefined_symbols.put(gpa, linker_args_it.nextOrFatal(), {}); + try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { const stack_size = linker_args_it.nextOrFatal(); stack_size_override = std.fmt.parseUnsigned(u64, stack_size, 0) catch |err| { @@ -2276,7 +2325,7 @@ fn buildOutputType( { // -s, --strip-all Strip all symbols // -S, --strip-debug Strip debugging symbols - strip = true; + mod_opts.strip = true; } else if (mem.eql(u8, arg, "--start-group") or mem.eql(u8, arg, "--end-group")) { @@ -2307,27 +2356,27 @@ fn buildOutputType( fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) }); }; } else if (mem.eql(u8, arg, "-framework")) { - try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{}); + try frameworks.put(arena, linker_args_it.nextOrFatal(), .{}); } else if (mem.eql(u8, arg, "-weak_framework")) { - try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .weak = true }); + try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true }); } else if (mem.eql(u8, arg, "-needed_framework")) { - try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .needed = true }); + try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true }); } else if (mem.eql(u8, arg, "-needed_library")) { - try system_libs.put(linker_args_it.nextOrFatal(), .{ + try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{ .weak = false, .needed = true, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-weak-l")) { - try system_libs.put(arg["-weak-l".len..], .{ + try create_module.system_libs.put(arena, arg["-weak-l".len..], .{ .weak = true, .needed = false, .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-weak_library")) { - try system_libs.put(linker_args_it.nextOrFatal(), .{ + try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true, .needed = false, .preferred_mode = lib_preferred_mode, @@ -2361,7 +2410,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-install_name")) { install_name = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "-force_load")) { - try link_objects.append(.{ + try link_objects.append(arena, .{ .path = linker_args_it.nextOrFatal(), .must_link = true, }); @@ -2402,22 +2451,22 @@ fn buildOutputType( } } - if (want_sanitize_c) |wsc| { - if (wsc and optimize_mode == .ReleaseFast) { - optimize_mode = .ReleaseSafe; + if (mod_opts.sanitize_c) |wsc| { + if (wsc and mod_opts.optimize_mode == .ReleaseFast) { + mod_opts.optimize_mode = .ReleaseSafe; } } switch (c_out_mode) { .link => { - output_mode = if (is_shared_lib) .Lib else .Exe; + create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe; emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out; if (emit_llvm) { fatal("-emit-llvm cannot be used when linking", .{}); } }, .object => { - output_mode = .Obj; + create_module.opts.output_mode = .Obj; if (emit_llvm) { emit_bin = .no; if (out_path) |p| { @@ -2434,7 +2483,7 @@ fn buildOutputType( } }, .assembly => { - output_mode = .Obj; + create_module.opts.output_mode = .Obj; emit_bin = .no; if (emit_llvm) { if (out_path) |p| { @@ -2451,9 +2500,9 @@ fn buildOutputType( } }, .preprocessor => { - output_mode = .Obj; + create_module.opts.output_mode = .Obj; // An error message is generated when there is more than 1 C source file. - if (c_source_files.items.len != 1) { + if (create_module.c_source_files.items.len != 1) { // For example `zig cc` and no args should print the "no input files" message. return process.exit(try clangMain(arena, all_args)); } @@ -2465,7 +2514,7 @@ fn buildOutputType( } }, } - if (c_source_files.items.len == 0 and + if (create_module.c_source_files.items.len == 0 and link_objects.items.len == 0 and root_src_file == null) { @@ -2476,258 +2525,72 @@ fn buildOutputType( }, } - { - // Resolve module dependencies - var it = modules.iterator(); - while (it.next()) |kv| { - const deps_str = kv.value_ptr.deps_str; - var deps_it = ModuleDepIterator.init(deps_str); - while (deps_it.next()) |dep| { - if (dep.expose.len == 0) { - fatal("module '{s}' depends on '{s}' with a blank name", .{ - kv.key_ptr.*, dep.name, - }); - } - - for ([_][]const u8{ "std", "root", "builtin" }) |name| { - if (mem.eql(u8, dep.expose, name)) { - fatal("unable to add module '{s}' under name '{s}': conflicts with builtin module", .{ - dep.name, dep.expose, - }); - } - } - - const dep_mod = modules.get(dep.name) orelse { - fatal("module '{s}' depends on module '{s}' which does not exist", .{ - kv.key_ptr.*, dep.name, - }); - }; - - try kv.value_ptr.mod.deps.put(arena, dep.expose, dep_mod.mod); - } - } - } - - if (arg_mode == .build and optimize_mode == .ReleaseSmall and strip == null) - strip = true; - - if (arg_mode == .translate_c and c_source_files.items.len != 1) { - fatal("translate-c expects exactly 1 source file (found {d})", .{c_source_files.items.len}); + if (arg_mode == .translate_c and create_module.c_source_files.items.len != 1) { + fatal("translate-c expects exactly 1 source file (found {d})", .{create_module.c_source_files.items.len}); } if (root_src_file == null and arg_mode == .zig_test) { fatal("`zig test` expects a zig source file argument", .{}); } - const root_name = if (provided_name) |n| n else blk: { - if (arg_mode == .zig_test) { - break :blk "test"; - } else if (root_src_file) |file| { - const basename = fs.path.basename(file); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (c_source_files.items.len >= 1) { - const basename = fs.path.basename(c_source_files.items[0].src_path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (link_objects.items.len >= 1) { - const basename = fs.path.basename(link_objects.items[0].path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (emit_bin == .yes) { - const basename = fs.path.basename(emit_bin.yes); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (rc_source_files.items.len >= 1) { - const basename = fs.path.basename(rc_source_files.items[0].src_path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (res_files.items.len >= 1) { - const basename = fs.path.basename(res_files.items[0].path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (show_builtin) { - break :blk "builtin"; - } else if (arg_mode == .run) { - fatal("`zig run` expects at least one positional argument", .{}); - // TODO once the attempt to unwrap error: LinkingWithoutZigSourceUnimplemented - // is solved, remove the above fatal() and uncomment the `break` below. - //break :blk "run"; - } else { - fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{}); - } - }; - - var target_parse_options: std.Target.Query.ParseOptions = .{ - .arch_os_abi = target_arch_os_abi, - .cpu_features = target_mcpu, - .dynamic_linker = target_dynamic_linker, - .object_format = target_ofmt, - }; - - // Before passing the mcpu string in for parsing, we convert any -m flags that were - // passed in via zig cc to zig-style. - if (llvm_m_args.items.len != 0) { - // If this returns null, we let it fall through to the case below which will - // run the full parse function and do proper error handling. - if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| { - var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa); - defer llvm_to_zig_name.deinit(); - - for (cpu_arch.allFeaturesList()) |feature| { - const llvm_name = feature.llvm_name orelse continue; - try llvm_to_zig_name.put(llvm_name, feature.name); - } - - var mcpu_buffer = std.ArrayList(u8).init(gpa); - defer mcpu_buffer.deinit(); - - try mcpu_buffer.appendSlice(target_mcpu orelse "baseline"); - - for (llvm_m_args.items) |llvm_m_arg| { - if (mem.startsWith(u8, llvm_m_arg, "mno-")) { - const llvm_name = llvm_m_arg["mno-".len..]; - const zig_name = llvm_to_zig_name.get(llvm_name) orelse { - fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{ - @tagName(cpu_arch), llvm_name, - }); - }; - try mcpu_buffer.append('-'); - try mcpu_buffer.appendSlice(zig_name); - } else if (mem.startsWith(u8, llvm_m_arg, "m")) { - const llvm_name = llvm_m_arg["m".len..]; - const zig_name = llvm_to_zig_name.get(llvm_name) orelse { - fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{ - @tagName(cpu_arch), llvm_name, - }); - }; - try mcpu_buffer.append('+'); - try mcpu_buffer.appendSlice(zig_name); - } else { - unreachable; - } - } - - const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items); - std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu}); - target_parse_options.cpu_features = adjusted_target_mcpu; - } - } - - const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options); - const target = try std.zig.system.resolveTargetQuery(target_query); - - if (target.os.tag != .freestanding) { - if (ensure_libc_on_non_freestanding) - link_libc = true; - if (ensure_libcpp_on_non_freestanding) - link_libcpp = true; - } - - if (linker_force_entry) |force| { - if (!force) { - entry = null; - } else if (entry == null and output_mode == .Exe) { - entry = switch (target.ofmt) { - .coff => "wWinMainCRTStartup", - .macho => "_main", - .elf, .plan9 => "_start", - .wasm => defaultWasmEntryName(wasi_exec_model), - else => |tag| fatal("No default entry point available for output format {s}", .{@tagName(tag)}), - }; - } - } else if (entry == null and target.isWasm() and output_mode == .Exe) { - // For WebAssembly the compiler defaults to setting the entry name when no flags are set. - entry = defaultWasmEntryName(wasi_exec_model); - } - - if (target.ofmt == .coff) { - // Now that we know the target supports resources, - // we can add the res files as link objects. - for (res_files.items) |res_file| { - try link_objects.append(res_file); - } - } else { - if (manifest_file != null) { - fatal("manifest file is not allowed unless the target object format is coff (Windows/UEFI)", .{}); - } - if (rc_source_files.items.len != 0) { - fatal("rc files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); - } - if (res_files.items.len != 0) { - fatal("res files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); - } - } - - if (target.cpu.arch.isWasm()) blk: { - if (single_threaded == null) { - single_threaded = true; - } - if (link_mode) |mode| { - if (mode == .Dynamic) { - if (linker_export_memory != null and linker_export_memory.?) { - fatal("flags '-dynamic' and '--export-memory' are incompatible", .{}); - } - // User did not supply `--export-memory` which is incompatible with -dynamic, therefore - // set the flag to false to ensure it does not get enabled by default. - linker_export_memory = false; - } - } - if (wasi_exec_model != null and wasi_exec_model.? == .reactor) { - if (entry) |entry_name| { - if (!mem.eql(u8, "_initialize", entry_name)) { - fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name}); - } - } - } - if (linker_shared_memory) { - if (output_mode == .Obj) { - fatal("shared memory is not allowed in object files", .{}); - } - - if (!target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.atomics)) or - !target.cpu.features.isEnabled(@intFromEnum(std.Target.wasm.Feature.bulk_memory))) - { - fatal("'atomics' and 'bulk-memory' features must be enabled to use shared memory", .{}); - } - break :blk; - } - - // Single-threaded is the default for WebAssembly, so only when the user specified `-fno_single-threaded` - // can they enable multithreaded WebAssembly builds. - const is_single_threaded = single_threaded.?; - if (!is_single_threaded) { - fatal("'-fno-single-threaded' requires the linker feature shared-memory to be enabled using '--shared-memory'", .{}); + if (root_src_file) |unresolved_src_path| { + if (create_module.modules.count() != 0) { + fatal("main module provided both by '--mod {s} {}{s}' and by positional argument '{s}'", .{ + create_module.modules.keys()[0], + create_module.modules.values()[0].paths.root, + create_module.modules.values()[0].paths.root_src_path, + unresolved_src_path, + }); } - } - if (use_lld) |opt| { - if (opt and target.isDarwin()) { - fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{}); - } - } + // See duplicate logic: ModCreationGlobalFlags + create_module.opts.have_zcu = true; + if (mod_opts.single_threaded == false) + create_module.opts.any_non_single_threaded = true; + if (mod_opts.sanitize_thread == true) + create_module.opts.any_sanitize_thread = true; + if (mod_opts.unwind_tables == true) + create_module.opts.any_unwind_tables = true; - if (want_lto) |opt| { - if (opt and target.isDarwin()) { - fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{}); - } + const src_path = try introspect.resolvePath(arena, unresolved_src_path); + try create_module.modules.put(arena, "main", .{ + .paths = .{ + .root = .{ + .root_dir = Cache.Directory.cwd(), + .sub_path = fs.path.dirname(src_path) orelse "", + }, + .root_src_path = fs.path.basename(src_path), + }, + .cc_argv = try clang_argv.toOwnedSlice(arena), + .inherited = mod_opts, + .target_arch_os_abi = target_arch_os_abi, + .target_mcpu = target_mcpu, + .deps = try deps.toOwnedSlice(arena), + .resolved = null, + .c_source_files_start = c_source_files_owner_index, + .c_source_files_end = create_module.c_source_files.items.len, + .rc_source_files_start = rc_source_files_owner_index, + .rc_source_files_end = create_module.rc_source_files.items.len, + }); + cssan.reset(); + mod_opts = .{}; + target_arch_os_abi = null; + target_mcpu = null; + c_source_files_owner_index = create_module.c_source_files.items.len; + rc_source_files_owner_index = create_module.rc_source_files.items.len; } - if (comptime builtin.target.isDarwin()) { - // If we want to link against frameworks, we need system headers. - if (framework_dirs.items.len > 0 or frameworks.count() > 0) - want_native_include_dirs = true; + if (c_source_files_owner_index != create_module.c_source_files.items.len) { + fatal("C source file '{s}' has no parent module", .{ + create_module.c_source_files.items[c_source_files_owner_index].src_path, + }); } - // Resolve the library path arguments with respect to sysroot. - var lib_dirs = std.ArrayList([]const u8).init(arena); - if (sysroot) |root| { - for (lib_dir_args.items) |dir| { - if (fs.path.isAbsolute(dir)) { - const stripped_dir = dir[fs.path.diskDesignator(dir).len..]; - const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); - try lib_dirs.append(full_path); - } - try lib_dirs.append(dir); - } - } else { - lib_dirs = lib_dir_args; + if (rc_source_files_owner_index != create_module.rc_source_files.items.len) { + fatal("resource file '{s}' has no parent module", .{ + create_module.rc_source_files.items[rc_source_files_owner_index].src_path, + }); } - lib_dir_args = undefined; // From here we use lib_dirs instead. const self_exe_path: ?[]const u8 = if (!process.can_spawn) null @@ -2757,87 +2620,185 @@ fn buildOutputType( }; defer zig_lib_directory.handle.close(); - // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. - // We need to know whether the set of system libraries contains anything besides these - // to decide whether to trigger native path detection logic. - var external_system_libs: std.MultiArrayList(struct { - name: []const u8, - info: SystemLib, - }) = .{}; + var global_cache_directory: Compilation.Directory = l: { + if (override_global_cache_dir) |p| { + break :l .{ + .handle = try fs.cwd().makeOpenPath(p, .{}), + .path = p, + }; + } + if (builtin.os.tag == .wasi) { + break :l getWasiPreopen("/cache"); + } + const p = try introspect.resolveGlobalCacheDir(arena); + break :l .{ + .handle = try fs.cwd().makeOpenPath(p, .{}), + .path = p, + }; + }; + defer global_cache_directory.handle.close(); - var resolved_system_libs: std.MultiArrayList(struct { - name: []const u8, - lib: Compilation.SystemLib, - }) = .{}; + 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; + create_module.opts.emit_bin = emit_bin != .no; + create_module.opts.c_source_files_len = create_module.c_source_files.items.len; - var libc_installation: ?LibCInstallation = null; - if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { - fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); - }; + const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory); + for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { + if (cli_mod.resolved == null) + fatal("module '{s}' declared but not used", .{key}); } - for (system_libs.keys(), system_libs.values()) |lib_name, info| { - if (target.is_libc_lib_name(lib_name)) { - link_libc = true; - continue; - } - if (target.is_libcpp_lib_name(lib_name)) { - link_libcpp = true; - continue; - } - switch (target_util.classifyCompilerRtLibName(target, lib_name)) { - .none => {}, - .only_libunwind, .both => { - link_libunwind = true; - continue; - }, - .only_compiler_rt => { - warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); - continue; + // When you're testing std, the main module is std. In that case, + // we'll just set the std module to the main one, since avoiding + // the errors caused by duplicating it is more effort than it's + // worth. + const main_mod_is_std = m: { + const std_path = try fs.path.resolve(arena, &.{ + zig_lib_directory.path orelse ".", "std", "std.zig", + }); + const main_path = try fs.path.resolve(arena, &.{ + main_mod.root.root_dir.path orelse ".", + main_mod.root.sub_path, + main_mod.root_src_path, + }); + break :m mem.eql(u8, main_path, std_path); + }; + + const std_mod = m: { + if (main_mod_is_std) break :m main_mod; + if (create_module.modules.get("std")) |cli_mod| break :m cli_mod.resolved.?; + + break :m try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = zig_lib_directory, + .sub_path = "std", + }, + .root_src_path = "std.zig", }, - } + .fully_qualified_name = "std", + .cc_argv = &.{}, + .inherited = .{}, + .global = create_module.resolved_options, + .parent = main_mod, + .builtin_mod = main_mod.getBuiltinDependency(), + }); + }; - if (target.isMinGW()) { - const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| { - fatal("failed to check zig installation for DLL import libs: {s}", .{ - @errorName(err), - }); - }; - if (exists) { - try resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = true, - .weak = false, - .path = null, + const root_mod = if (arg_mode == .zig_test) root_mod: { + const test_mod = if (test_runner_path) |test_runner| test_mod: { + const test_mod = try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = Cache.Directory.cwd(), + .sub_path = fs.path.dirname(test_runner) orelse "", }, - }); - continue; - } + .root_src_path = fs.path.basename(test_runner), + }, + .fully_qualified_name = "root", + .cc_argv = &.{}, + .inherited = .{}, + .global = create_module.resolved_options, + .parent = main_mod, + .builtin_mod = main_mod.getBuiltinDependency(), + }); + test_mod.deps = try main_mod.deps.clone(arena); + break :test_mod test_mod; + } else try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = zig_lib_directory, + }, + .root_src_path = "test_runner.zig", + }, + .fully_qualified_name = "root", + .cc_argv = &.{}, + .inherited = .{}, + .global = create_module.resolved_options, + .parent = main_mod, + .builtin_mod = main_mod.getBuiltinDependency(), + }); + + break :root_mod test_mod; + } else main_mod; + + const target = main_mod.resolved_target.result; + + if (target.ofmt != .coff) { + if (manifest_file != null) { + fatal("manifest file is not allowed unless the target object format is coff (Windows/UEFI)", .{}); + } + if (create_module.rc_source_files.items.len != 0) { + fatal("rc files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); } + if (contains_res_file) { + fatal("res files are not allowed unless the target object format is coff (Windows/UEFI)", .{}); + } + } - if (fs.path.isAbsolute(lib_name)) { - fatal("cannot use absolute path as a system library: {s}", .{lib_name}); + const root_name = if (provided_name) |n| n else blk: { + if (arg_mode == .zig_test) { + break :blk "test"; + } else if (root_src_file) |file| { + const basename = fs.path.basename(file); + break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; + } else if (create_module.c_source_files.items.len >= 1) { + const basename = fs.path.basename(create_module.c_source_files.items[0].src_path); + break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; + } else if (link_objects.items.len >= 1) { + const basename = fs.path.basename(link_objects.items[0].path); + break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; + } else if (emit_bin == .yes) { + const basename = fs.path.basename(emit_bin.yes); + break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; + } else if (create_module.rc_source_files.items.len >= 1) { + const basename = fs.path.basename(create_module.rc_source_files.items[0].src_path); + break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; + } else if (show_builtin) { + break :blk "builtin"; + } else if (arg_mode == .run) { + fatal("`zig run` expects at least one positional argument", .{}); + // TODO once the attempt to unwrap error: LinkingWithoutZigSourceUnimplemented + // is solved, remove the above fatal() and uncomment the `break` below. + //break :blk "run"; + } else { + fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{}); } + }; - if (target.os.tag == .wasi) { - if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { - try wasi_emulated_libs.append(crt_file); - continue; + // Resolve the library path arguments with respect to sysroot. + var lib_dirs: std.ArrayListUnmanaged([]const u8) = .{}; + if (sysroot) |root| { + try lib_dirs.ensureUnusedCapacity(arena, lib_dir_args.items.len * 2); + for (lib_dir_args.items) |dir| { + if (fs.path.isAbsolute(dir)) { + const stripped_dir = dir[fs.path.diskDesignator(dir).len..]; + const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); + lib_dirs.appendAssumeCapacity(full_path); } + lib_dirs.appendAssumeCapacity(dir); } + } else { + lib_dirs = lib_dir_args; + } + lib_dir_args = undefined; // From here we use lib_dirs instead. - try external_system_libs.append(arena, .{ - .name = lib_name, - .info = info, - }); + if (main_mod.resolved_target.is_native_os and target.isDarwin()) { + // If we want to link against frameworks, we need system headers. + if (framework_dirs.items.len > 0 or frameworks.count() > 0) + want_native_include_dirs = true; } - // After this point, external_system_libs is used instead of system_libs. // Trigger native system library path detection if necessary. - if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and - (external_system_libs.len != 0 or want_native_include_dirs)) + if (sysroot == null and + main_mod.resolved_target.is_native_os and + main_mod.resolved_target.is_native_abi and + (create_module.external_system_libs.len != 0 or want_native_include_dirs)) { const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| { fatal("unable to detect native system paths: {s}", .{@errorName(err)}); @@ -2846,20 +2807,27 @@ fn buildOutputType( warn("{s}", .{warning}); } - try clang_argv.ensureUnusedCapacity(paths.include_dirs.items.len * 2); + try clang_argv.ensureUnusedCapacity(arena, paths.include_dirs.items.len * 2); for (paths.include_dirs.items) |include_dir| { clang_argv.appendAssumeCapacity("-isystem"); clang_argv.appendAssumeCapacity(include_dir); } - try framework_dirs.appendSlice(paths.framework_dirs.items); - try lib_dirs.appendSlice(paths.lib_dirs.items); - try rpath_list.appendSlice(paths.rpaths.items); + try framework_dirs.appendSlice(arena, paths.framework_dirs.items); + try lib_dirs.appendSlice(arena, paths.lib_dirs.items); + try rpath_list.appendSlice(arena, paths.rpaths.items); + } + + var libc_installation: ?LibCInstallation = null; + if (libc_paths_file) |paths_file| { + libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { + fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); + }; } if (builtin.target.os.tag == .windows and target.abi == .msvc and - external_system_libs.len != 0) + create_module.external_system_libs.len != 0) { if (libc_installation == null) { libc_installation = try LibCInstallation.findNative(.{ @@ -2868,7 +2836,10 @@ fn buildOutputType( .target = target, }); - try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? }); + try lib_dirs.appendSlice(arena, &.{ + libc_installation.?.msvc_lib_dir.?, + libc_installation.?.kernel32_lib_dir.?, + }); } } @@ -2888,7 +2859,7 @@ fn buildOutputType( preferred_mode: std.builtin.LinkMode, }).init(arena); - syslib: for (external_system_libs.items(.name), external_system_libs.items(.info)) |lib_name, info| { + syslib: for (create_module.external_system_libs.items(.name), create_module.external_system_libs.items(.info)) |lib_name, info| { // Checked in the first pass above while looking for libc libraries. assert(!fs.path.isAbsolute(lib_name)); @@ -2908,8 +2879,8 @@ fn buildOutputType( )) { const path = try arena.dupe(u8, test_path.items); switch (info.preferred_mode) { - .Static => try link_objects.append(.{ .path = path }), - .Dynamic => try resolved_system_libs.append(arena, .{ + .Static => try link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ .name = lib_name, .lib = .{ .needed = info.needed, @@ -2942,8 +2913,8 @@ fn buildOutputType( )) { const path = try arena.dupe(u8, test_path.items); switch (info.fallbackMode()) { - .Static => try link_objects.append(.{ .path = path }), - .Dynamic => try resolved_system_libs.append(arena, .{ + .Static => try link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ .name = lib_name, .lib = .{ .needed = info.needed, @@ -2976,8 +2947,8 @@ fn buildOutputType( )) { const path = try arena.dupe(u8, test_path.items); switch (info.preferred_mode) { - .Static => try link_objects.append(.{ .path = path }), - .Dynamic => try resolved_system_libs.append(arena, .{ + .Static => try link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ .name = lib_name, .lib = .{ .needed = info.needed, @@ -3000,8 +2971,8 @@ fn buildOutputType( )) { const path = try arena.dupe(u8, test_path.items); switch (info.fallbackMode()) { - .Static => try link_objects.append(.{ .path = path }), - .Dynamic => try resolved_system_libs.append(arena, .{ + .Static => try link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ .name = lib_name, .lib = .{ .needed = info.needed, @@ -3035,7 +3006,8 @@ fn buildOutputType( process.exit(1); } } - // After this point, resolved_system_libs is used instead of external_system_libs. + // After this point, create_module.resolved_system_libs is used instead of + // create_module.external_system_libs. // We now repeat part of the process for frameworks. var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena); @@ -3090,10 +3062,10 @@ fn buildOutputType( } // After this point, resolved_frameworks is used instead of frameworks. - if (output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) { - const total_obj_count = c_source_files.items.len + + if (create_module.opts.output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) { + const total_obj_count = create_module.c_source_files.items.len + @intFromBool(root_src_file != null) + - rc_source_files.items.len + + create_module.rc_source_files.items.len + link_objects.items.len; if (total_obj_count > 1) { fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)}); @@ -3141,8 +3113,8 @@ fn buildOutputType( .basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, - .output_mode = output_mode, - .link_mode = link_mode, + .output_mode = create_module.opts.output_mode, + .link_mode = create_module.opts.link_mode, .version = optional_version, }), }, @@ -3260,9 +3232,9 @@ fn buildOutputType( }; defer emit_docs_resolved.deinit(); - const is_exe_or_dyn_lib = switch (output_mode) { + const is_exe_or_dyn_lib = switch (create_module.opts.output_mode) { .Obj => false, - .Lib => (link_mode orelse .Static) == .Dynamic, + .Lib => (create_module.opts.link_mode orelse .Static) == .Dynamic, .Exe => true, }; // Note that cmake when targeting Windows will try to execute @@ -3294,76 +3266,10 @@ fn buildOutputType( }; defer emit_implib_resolved.deinit(); - const main_mod: ?*Package.Module = if (root_src_file) |unresolved_src_path| blk: { - const src_path = try introspect.resolvePath(arena, unresolved_src_path); - if (main_mod_path) |unresolved_main_mod_path| { - const p = try introspect.resolvePath(arena, unresolved_main_mod_path); - break :blk try Package.Module.create(arena, .{ - .root = .{ - .root_dir = Cache.Directory.cwd(), - .sub_path = p, - }, - .root_src_path = if (p.len == 0) - src_path - else - try fs.path.relative(arena, p, src_path), - .fully_qualified_name = "root", - }); - } else { - break :blk try Package.Module.create(arena, .{ - .root = .{ - .root_dir = Cache.Directory.cwd(), - .sub_path = fs.path.dirname(src_path) orelse "", - }, - .root_src_path = fs.path.basename(src_path), - .fully_qualified_name = "root", - }); - } - } else null; - - // Transfer packages added with --deps to the root package - if (main_mod) |mod| { - var it = ModuleDepIterator.init(root_deps_str orelse ""); - while (it.next()) |dep| { - if (dep.expose.len == 0) { - fatal("root module depends on '{s}' with a blank name", .{dep.name}); - } - - for ([_][]const u8{ "std", "root", "builtin" }) |name| { - if (mem.eql(u8, dep.expose, name)) { - fatal("unable to add module '{s}' under name '{s}': conflicts with builtin module", .{ dep.name, dep.expose }); - } - } - - const dep_mod = modules.get(dep.name) orelse - fatal("root module depends on module '{s}' which does not exist", .{dep.name}); - - try mod.deps.put(arena, dep.expose, dep_mod.mod); - } - } - var thread_pool: ThreadPool = undefined; try thread_pool.init(.{ .allocator = gpa }); defer thread_pool.deinit(); - var global_cache_directory: Compilation.Directory = l: { - if (override_global_cache_dir) |p| { - break :l .{ - .handle = try fs.cwd().makeOpenPath(p, .{}), - .path = p, - }; - } - if (builtin.os.tag == .wasi) { - break :l getWasiPreopen("/cache"); - } - const p = try introspect.resolveGlobalCacheDir(arena); - break :l .{ - .handle = try fs.cwd().makeOpenPath(p, .{}), - .path = p, - }; - }; - defer global_cache_directory.handle.close(); - var cleanup_local_cache_dir: ?fs.Dir = null; defer if (cleanup_local_cache_dir) |*dir| dir.close(); @@ -3379,37 +3285,37 @@ fn buildOutputType( if (arg_mode == .run) { break :l global_cache_directory; } - if (main_mod != null) { - // search upwards from cwd until we find directory with build.zig - const cwd_path = try process.getCwdAlloc(arena); - const zig_cache = "zig-cache"; - var dirname: []const u8 = cwd_path; - while (true) { - const joined_path = try fs.path.join(arena, &.{ - dirname, Package.build_zig_basename, - }); - if (fs.cwd().access(joined_path, .{})) |_| { - const cache_dir_path = try fs.path.join(arena, &.{ dirname, zig_cache }); - const dir = try fs.cwd().makeOpenPath(cache_dir_path, .{}); - cleanup_local_cache_dir = dir; - break :l .{ .handle = dir, .path = cache_dir_path }; - } else |err| switch (err) { - error.FileNotFound => { - dirname = fs.path.dirname(dirname) orelse { - break :l global_cache_directory; - }; - continue; - }, - else => break :l global_cache_directory, - } + + // search upwards from cwd until we find directory with build.zig + const cwd_path = try process.getCwdAlloc(arena); + const zig_cache = "zig-cache"; + var dirname: []const u8 = cwd_path; + while (true) { + const joined_path = try fs.path.join(arena, &.{ + dirname, Package.build_zig_basename, + }); + if (fs.cwd().access(joined_path, .{})) |_| { + const cache_dir_path = try fs.path.join(arena, &.{ dirname, zig_cache }); + const dir = try fs.cwd().makeOpenPath(cache_dir_path, .{}); + cleanup_local_cache_dir = dir; + break :l .{ .handle = dir, .path = cache_dir_path }; + } else |err| switch (err) { + error.FileNotFound => { + dirname = fs.path.dirname(dirname) orelse { + break :l global_cache_directory; + }; + continue; + }, + else => break :l global_cache_directory, } } + // Otherwise we really don't have a reasonable place to put the local cache directory, // so we utilize the global one. break :l global_cache_directory; }; - for (c_source_files.items) |*src| { + for (create_module.c_source_files.items) |*src| { if (!mem.eql(u8, src.src_path, "-")) continue; const ext = src.ext orelse @@ -3452,13 +3358,14 @@ fn buildOutputType( .zig_lib_directory = zig_lib_directory, .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, + .thread_pool = &thread_pool, + .self_exe_path = self_exe_path, + .config = create_module.resolved_options, .root_name = root_name, - .target = target, - .is_native_os = target_query.isNativeOs(), - .is_native_abi = target_query.isNativeAbi(), .sysroot = sysroot, - .output_mode = output_mode, .main_mod = main_mod, + .root_mod = root_mod, + .std_mod = std_mod, .emit_bin = emit_bin_loc, .emit_h = emit_h_resolved.data, .emit_asm = emit_asm_resolved.data, @@ -3466,43 +3373,22 @@ fn buildOutputType( .emit_llvm_bc = emit_llvm_bc_resolved.data, .emit_docs = emit_docs_resolved.data, .emit_implib = emit_implib_resolved.data, - .link_mode = link_mode, .dll_export_fns = dll_export_fns, - .optimize_mode = optimize_mode, .keep_source_files_loaded = false, - .clang_argv = clang_argv.items, .lib_dirs = lib_dirs.items, .rpath_list = rpath_list.items, .symbol_wrap_set = symbol_wrap_set, - .c_source_files = c_source_files.items, - .rc_source_files = rc_source_files.items, + .c_source_files = create_module.c_source_files.items, + .rc_source_files = create_module.rc_source_files.items, .manifest_file = manifest_file, .rc_includes = rc_includes, .link_objects = link_objects.items, .framework_dirs = framework_dirs.items, .frameworks = resolved_frameworks.items, - .system_lib_names = resolved_system_libs.items(.name), - .system_lib_infos = resolved_system_libs.items(.lib), - .wasi_emulated_libs = wasi_emulated_libs.items, - .link_libc = link_libc, - .link_libcpp = link_libcpp, - .link_libunwind = link_libunwind, - .want_pic = want_pic, - .want_pie = want_pie, - .want_lto = want_lto, - .want_unwind_tables = want_unwind_tables, - .want_sanitize_c = want_sanitize_c, - .want_stack_check = want_stack_check, - .want_stack_protector = want_stack_protector, - .want_red_zone = want_red_zone, - .omit_frame_pointer = omit_frame_pointer, - .want_valgrind = want_valgrind, - .want_tsan = want_tsan, + .system_lib_names = create_module.resolved_system_libs.items(.name), + .system_lib_infos = create_module.resolved_system_libs.items(.lib), + .wasi_emulated_libs = create_module.wasi_emulated_libs.items, .want_compiler_rt = want_compiler_rt, - .use_llvm = use_llvm, - .use_lib_llvm = use_lib_llvm, - .use_lld = use_lld, - .use_clang = use_clang, .hash_style = hash_style, .rdynamic = rdynamic, .linker_script = linker_script, @@ -3513,14 +3399,11 @@ fn buildOutputType( .linker_gc_sections = linker_gc_sections, .linker_allow_shlib_undefined = linker_allow_shlib_undefined, .linker_bind_global_refs_locally = linker_bind_global_refs_locally, - .linker_import_memory = linker_import_memory, - .linker_export_memory = linker_export_memory, .linker_import_symbols = linker_import_symbols, .linker_import_table = linker_import_table, .linker_export_table = linker_export_table, .linker_initial_memory = linker_initial_memory, .linker_max_memory = linker_max_memory, - .linker_shared_memory = linker_shared_memory, .linker_print_gc_sections = linker_print_gc_sections, .linker_print_icf_sections = linker_print_icf_sections, .linker_print_map = linker_print_map, @@ -3546,18 +3429,13 @@ fn buildOutputType( .minor_subsystem_version = minor_subsystem_version, .link_eh_frame_hdr = link_eh_frame_hdr, .link_emit_relocs = link_emit_relocs, - .entry = entry, .force_undefined_symbols = force_undefined_symbols, .stack_size_override = stack_size_override, .image_base_override = image_base_override, - .strip = strip, .formatted_panics = formatted_panics, - .single_threaded = single_threaded, .function_sections = function_sections, .data_sections = data_sections, .no_builtin = no_builtin, - .self_exe_path = self_exe_path, - .thread_pool = &thread_pool, .clang_passthrough_mode = clang_passthrough_mode, .clang_preprocessor_mode = clang_preprocessor_mode, .version = optional_version, @@ -3571,21 +3449,17 @@ fn buildOutputType( .verbose_llvm_bc = verbose_llvm_bc, .verbose_cimport = verbose_cimport, .verbose_llvm_cpu_features = verbose_llvm_cpu_features, - .machine_code_model = machine_code_model, .color = color, .time_report = time_report, .stack_report = stack_report, - .is_test = arg_mode == .zig_test, .each_lib_rpath = each_lib_rpath, .build_id = build_id, - .test_evented_io = test_evented_io, .test_filter = test_filter, .test_name_prefix = test_name_prefix, .test_runner_path = test_runner_path, .disable_lld_caching = !output_to_cache, .subsystem = subsystem, .dwarf_format = dwarf_format, - .wasi_exec_model = wasi_exec_model, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, .install_name = install_name, @@ -3595,7 +3469,6 @@ fn buildOutputType( .headerpad_max_install_names = headerpad_max_install_names, .dead_strip_dylibs = dead_strip_dylibs, .reference_trace = reference_trace, - .error_tracing = error_tracing, .pdb_out_path = pdb_out_path, .error_limit = error_limit, .want_structured_cfg = want_structured_cfg, @@ -3702,7 +3575,7 @@ fn buildOutputType( try test_exec_args.appendSlice(&.{ "-I", p }); } - if (link_libc) { + if (create_module.resolved_options.link_libc) { try test_exec_args.append("-lc"); } else if (target.os.tag == .windows) { try test_exec_args.appendSlice(&.{ @@ -3711,14 +3584,15 @@ fn buildOutputType( }); } - if (!mem.eql(u8, target_arch_os_abi, "native")) { + const first_cli_mod = create_module.modules.values()[0]; + if (first_cli_mod.target_arch_os_abi) |triple| { try test_exec_args.append("-target"); - try test_exec_args.append(target_arch_os_abi); + try test_exec_args.append(triple); } - if (target_mcpu) |mcpu| { + if (first_cli_mod.target_mcpu) |mcpu| { try test_exec_args.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu})); } - if (target_dynamic_linker) |dl| { + if (create_module.dynamic_linker) |dl| { try test_exec_args.append("--dynamic-linker"); try test_exec_args.append(dl); } @@ -3742,7 +3616,7 @@ fn buildOutputType( &comp_destroyed, all_args, runtime_args_start, - link_libc, + create_module.resolved_options.link_libc, ); } @@ -3750,6 +3624,243 @@ fn buildOutputType( return cleanExit(); } +const CreateModule = struct { + global_cache_directory: Cache.Directory, + modules: std.StringArrayHashMapUnmanaged(CliModule), + opts: Compilation.Config.Options, + dynamic_linker: ?[]const u8, + object_format: ?[]const u8, + /// undefined until createModule() for the root module is called. + resolved_options: Compilation.Config, + + /// This one is used while collecting CLI options. The set of libs is used + /// directly after computing the target and used to compute link_libc, + /// link_libcpp, and then the libraries are filtered into + /// `external_system_libs` and `resolved_system_libs`. + system_libs: std.StringArrayHashMapUnmanaged(SystemLib), + external_system_libs: std.MultiArrayList(struct { + name: []const u8, + info: SystemLib, + }), + resolved_system_libs: std.MultiArrayList(struct { + name: []const u8, + lib: Compilation.SystemLib, + }), + wasi_emulated_libs: std.ArrayListUnmanaged(wasi_libc.CRTFile), + + c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), + rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), + + // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. + // This array is populated by zig cc frontend and then has to be converted to zig-style + // CPU features. + llvm_m_args: std.ArrayListUnmanaged([]const u8), +}; + +fn createModule( + gpa: Allocator, + arena: Allocator, + create_module: *CreateModule, + index: usize, + parent: ?*Package.Module, + zig_lib_directory: Cache.Directory, +) Allocator.Error!*Package.Module { + const cli_mod = &create_module.modules.values()[index]; + if (cli_mod.resolved) |m| return m; + + const name = create_module.modules.keys()[index]; + + cli_mod.inherited.resolved_target = t: { + // If the target is not overridden, use the parent's target. Of course, + // if this is the root module then we need to proceed to resolve the + // target. + if (cli_mod.target_arch_os_abi == null and + cli_mod.target_mcpu == null and + create_module.dynamic_linker == null and + create_module.object_format == null) + { + if (parent) |p| break :t p.resolved_target; + } + + var target_parse_options: std.Target.Query.ParseOptions = .{ + .arch_os_abi = cli_mod.target_arch_os_abi orelse "native", + .cpu_features = cli_mod.target_mcpu, + .dynamic_linker = create_module.dynamic_linker, + .object_format = create_module.object_format, + }; + + // Before passing the mcpu string in for parsing, we convert any -m flags that were + // passed in via zig cc to zig-style. + if (create_module.llvm_m_args.items.len != 0) { + // If this returns null, we let it fall through to the case below which will + // run the full parse function and do proper error handling. + if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| { + var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa); + defer llvm_to_zig_name.deinit(); + + for (cpu_arch.allFeaturesList()) |feature| { + const llvm_name = feature.llvm_name orelse continue; + try llvm_to_zig_name.put(llvm_name, feature.name); + } + + var mcpu_buffer = std.ArrayList(u8).init(gpa); + defer mcpu_buffer.deinit(); + + try mcpu_buffer.appendSlice(cli_mod.target_mcpu orelse "baseline"); + + for (create_module.llvm_m_args.items) |llvm_m_arg| { + if (mem.startsWith(u8, llvm_m_arg, "mno-")) { + const llvm_name = llvm_m_arg["mno-".len..]; + const zig_name = llvm_to_zig_name.get(llvm_name) orelse { + fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{ + @tagName(cpu_arch), llvm_name, + }); + }; + try mcpu_buffer.append('-'); + try mcpu_buffer.appendSlice(zig_name); + } else if (mem.startsWith(u8, llvm_m_arg, "m")) { + const llvm_name = llvm_m_arg["m".len..]; + const zig_name = llvm_to_zig_name.get(llvm_name) orelse { + fatal("target architecture {s} has no LLVM CPU feature named '{s}'", .{ + @tagName(cpu_arch), llvm_name, + }); + }; + try mcpu_buffer.append('+'); + try mcpu_buffer.appendSlice(zig_name); + } else { + unreachable; + } + } + + const adjusted_target_mcpu = try arena.dupe(u8, mcpu_buffer.items); + std.log.debug("adjusted target_mcpu: {s}", .{adjusted_target_mcpu}); + target_parse_options.cpu_features = adjusted_target_mcpu; + } + } + + const target_query = parseTargetQueryOrReportFatalError(arena, target_parse_options); + const target = resolveTargetQueryOrFatal(target_query); + break :t .{ + .result = target, + .is_native_os = target_query.isNativeOs(), + .is_native_abi = target_query.isNativeAbi(), + }; + }; + + if (parent == null) { + // This block is for initializing the fields of + // `Compilation.Config.Options` that require knowledge of the + // target (which was just now resolved for the root module above). + const resolved_target = cli_mod.inherited.resolved_target.?; + create_module.opts.resolved_target = resolved_target; + create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode; + const target = resolved_target.result; + + // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. + // We need to know whether the set of system libraries contains anything besides these + // to decide whether to trigger native path detection logic. + for (create_module.system_libs.keys(), create_module.system_libs.values()) |lib_name, info| { + if (target.is_libc_lib_name(lib_name)) { + create_module.opts.link_libc = true; + continue; + } + if (target.is_libcpp_lib_name(lib_name)) { + create_module.opts.link_libcpp = true; + continue; + } + switch (target_util.classifyCompilerRtLibName(target, lib_name)) { + .none => {}, + .only_libunwind, .both => { + create_module.opts.link_libunwind = true; + continue; + }, + .only_compiler_rt => { + warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); + continue; + }, + } + + if (target.isMinGW()) { + const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| { + fatal("failed to check zig installation for DLL import libs: {s}", .{ + @errorName(err), + }); + }; + if (exists) { + try create_module.resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = true, + .weak = false, + .path = null, + }, + }); + continue; + } + } + + if (fs.path.isAbsolute(lib_name)) { + fatal("cannot use absolute path as a system library: {s}", .{lib_name}); + } + + if (target.os.tag == .wasi) { + if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { + try create_module.wasi_emulated_libs.append(arena, crt_file); + continue; + } + } + + try create_module.external_system_libs.append(arena, .{ + .name = lib_name, + .info = info, + }); + } + // After this point, external_system_libs is used instead of system_libs. + + create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) { + else => fatal("unable to resolve compilation options: {s}", .{@errorName(err)}), + }; + } + + const mod = Package.Module.create(arena, .{ + .global_cache_directory = create_module.global_cache_directory, + .paths = cli_mod.paths, + .fully_qualified_name = name, + + .cc_argv = cli_mod.cc_argv, + .inherited = cli_mod.inherited, + .global = create_module.resolved_options, + .parent = parent, + .builtin_mod = null, + }) catch |err| switch (err) { + error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}), + error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}), + error.BackendRequiresSingleThreaded => fatal("unable to create module '{s}': the selected machine code backend is limited to single-threaded applications", .{name}), + error.TargetRequiresPic => fatal("unable to create module '{s}': the selected target requires position independent code", .{name}), + error.PieRequiresPic => fatal("unable to create module '{s}': making a Position Independent Executable requires enabling Position Independent Code", .{name}), + error.DynamicLinkingRequiresPic => fatal("unable to create module '{s}': dynamic linking requires enabling Position Independent Code", .{name}), + error.TargetHasNoRedZone => fatal("unable to create module '{s}': the selected target does not have a red zone", .{name}), + error.StackCheckUnsupportedByTarget => fatal("unable to create module '{s}': the selected target does not support stack checking", .{name}), + error.StackProtectorUnsupportedByTarget => fatal("unable to create module '{s}': the selected target does not support stack protection", .{name}), + error.StackProtectorUnavailableWithoutLibC => fatal("unable to create module '{s}': enabling stack protection requires libc", .{name}), + error.OutOfMemory => return error.OutOfMemory, + }; + cli_mod.resolved = mod; + + for (create_module.c_source_files.items[cli_mod.c_source_files_start..cli_mod.c_source_files_end]) |*item| item.owner = mod; + + for (create_module.rc_source_files.items[cli_mod.rc_source_files_start..cli_mod.rc_source_files_end]) |*item| item.owner = mod; + + for (cli_mod.deps) |dep| { + const dep_index = create_module.modules.getIndex(dep.key) orelse + fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key }); + const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory); + try mod.deps.put(arena, dep.key, dep_mod); + } + + return mod; +} + fn saveState(comp: *Compilation, debug_incremental: bool) void { if (debug_incremental) { comp.saveState() catch |err| { @@ -3984,36 +4095,10 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { } } -const ModuleDepIterator = struct { - split: mem.SplitIterator(u8, .scalar), - - fn init(deps_str: []const u8) ModuleDepIterator { - return .{ .split = mem.splitScalar(u8, deps_str, ',') }; - } - - const Dependency = struct { - expose: []const u8, - name: []const u8, - }; - - fn next(it: *ModuleDepIterator) ?Dependency { - if (it.split.buffer.len == 0) return null; // don't return "" for the first iteration on "" - const str = it.split.next() orelse return null; - if (mem.indexOfScalar(u8, str, '=')) |i| { - return .{ - .expose = str[0..i], - .name = str[i + 1 ..], - }; - } else { - return .{ .expose = str, .name = str }; - } - } -}; - fn parseTargetQueryOrReportFatalError( allocator: Allocator, opts: std.Target.Query.ParseOptions, -) !std.Target.Query { +) std.Target.Query { var opts_with_diags = opts; var diags: std.Target.Query.ParseOptions.Diagnostics = .{}; if (opts_with_diags.diagnostics == null) { @@ -4057,7 +4142,9 @@ fn parseTargetQueryOrReportFatalError( } fatal("unknown object format: '{s}'", .{opts.object_format.?}); }, - else => |e| return e, + else => |e| fatal("unable to parse target query '{s}': {s}", .{ + opts.arch_os_abi, @errorName(e), + }), }; } @@ -4667,7 +4754,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: .os_tag = .windows, .abi = .msvc, }; - const target = try std.zig.system.resolveTargetQuery(target_query); + const target = resolveTargetQueryOrFatal(target_query); const is_native_abi = target_query.isNativeAbi(); const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| { if (cur_includes == .any) { @@ -4695,7 +4782,7 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: .os_tag = .windows, .abi = .gnu, }; - const target = try std.zig.system.resolveTargetQuery(target_query); + const target = resolveTargetQueryOrFatal(target_query); const is_native_abi = target_query.isNativeAbi(); const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null); return .{ @@ -4757,10 +4844,10 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } } - const target_query = try parseTargetQueryOrReportFatalError(gpa, .{ + const target_query = parseTargetQueryOrReportFatalError(gpa, .{ .arch_os_abi = target_arch_os_abi, }); - const target = try std.zig.system.resolveTargetQuery(target_query); + const target = resolveTargetQueryOrFatal(target_query); if (print_includes) { var arena_state = std.heap.ArenaAllocator.init(gpa); @@ -5024,7 +5111,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi if (!build_options.enable_logging) { warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); } else { - try log_scopes.append(gpa, args[i]); + try log_scopes.append(arena, args[i]); } continue; } else if (mem.eql(u8, arg, "--debug-compile-errors")) { @@ -5115,7 +5202,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi gimmeMoreOfThoseSweetSweetFileDescriptors(); const target_query: std.Target.Query = .{}; - const target = try std.zig.system.resolveTargetQuery(target_query); + const target = resolveTargetQueryOrFatal(target_query); const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", @@ -5130,29 +5217,80 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi try thread_pool.init(.{ .allocator = gpa }); defer thread_pool.deinit(); - var main_mod: Package.Module = if (override_build_runner) |build_runner_path| - .{ + const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{ + .root = .{ + .root_dir = Cache.Directory.cwd(), + .sub_path = fs.path.dirname(runner) orelse "", + }, + .root_src_path = fs.path.basename(runner), + } else .{ + .root = .{ .root_dir = zig_lib_directory }, + .root_src_path = "build_runner.zig", + }; + + const config = try Compilation.Config.resolve(.{ + .output_mode = .Exe, + .resolved_target = .{ + .result = target, + .is_native_os = true, + .is_native_abi = true, + }, + .have_zcu = true, + .emit_bin = true, + .is_test = false, + }); + + const root_mod = try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = main_mod_paths, + .fully_qualified_name = "root", + .cc_argv = &.{}, + .inherited = .{}, + .global = config, + .parent = null, + .builtin_mod = null, + }); + + const builtin_mod = root_mod.getBuiltinDependency(); + const std_mod = try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = .{ .root = .{ - .root_dir = Cache.Directory.cwd(), - .sub_path = fs.path.dirname(build_runner_path) orelse "", + .root_dir = zig_lib_directory, + .sub_path = "std", }, - .root_src_path = fs.path.basename(build_runner_path), - .fully_qualified_name = "root", - } - else - .{ - .root = .{ .root_dir = zig_lib_directory }, - .root_src_path = "build_runner.zig", - .fully_qualified_name = "root", - }; + .root_src_path = "std.zig", + }, + .fully_qualified_name = "std", + .cc_argv = &.{}, + .inherited = .{}, + .global = config, + .parent = root_mod, + .builtin_mod = builtin_mod, + }); - var build_mod: Package.Module = .{ - .root = .{ .root_dir = build_root.directory }, - .root_src_path = build_root.build_zig_basename, + const build_mod = try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = .{ .root_dir = build_root.directory }, + .root_src_path = build_root.build_zig_basename, + }, .fully_qualified_name = "root.@build", - }; + .cc_argv = &.{}, + .inherited = .{}, + .global = config, + .parent = root_mod, + .builtin_mod = builtin_mod, + }); if (build_options.only_core_functionality) { - try createEmptyDependenciesModule(arena, &main_mod, local_cache_directory); + try createEmptyDependenciesModule( + arena, + root_mod, + global_cache_directory, + local_cache_directory, + builtin_mod, + config, + ); } else { var http_client: std.http.Client = .{ .allocator = gpa }; defer http_client.deinit(); @@ -5196,7 +5334,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .has_build_zig = true, .oom_flag = false, - .module = &build_mod, + .module = build_mod, }; job_queue.all_fetches.appendAssumeCapacity(&fetch); @@ -5225,8 +5363,11 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi const deps_mod = try createDependenciesModule( arena, source_buf.items, - &main_mod, + root_mod, + global_cache_directory, local_cache_directory, + builtin_mod, + config, ); { @@ -5242,13 +5383,21 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi if (!f.has_build_zig) continue; const m = try Package.Module.create(arena, .{ - .root = try f.package_root.clone(arena), - .root_src_path = Package.build_zig_basename, + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = try f.package_root.clone(arena), + .root_src_path = Package.build_zig_basename, + }, .fully_qualified_name = try std.fmt.allocPrint( arena, "root.@dependencies.{s}", .{&hash}, ), + .cc_argv = &.{}, + .inherited = .{}, + .global = config, + .parent = root_mod, + .builtin_mod = builtin_mod, }); const hash_cloned = try arena.dupe(u8, &hash); deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m); @@ -5276,21 +5425,19 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi } } - try main_mod.deps.put(arena, "@build", &build_mod); + try root_mod.deps.put(arena, "@build", build_mod); const comp = Compilation.create(gpa, .{ .zig_lib_directory = zig_lib_directory, .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, .root_name = "build", - .target = target, - .is_native_os = target_query.isNativeOs(), - .is_native_abi = target_query.isNativeAbi(), - .output_mode = .Exe, - .main_mod = &main_mod, + .config = config, + .root_mod = root_mod, + .main_mod = build_mod, + .std_mod = std_mod, .emit_bin = emit_bin, .emit_h = null, - .optimize_mode = .Debug, .self_exe_path = self_exe_path, .thread_pool = &thread_pool, .verbose_cc = verbose_cc, @@ -5514,7 +5661,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void .root_decl = .none, }; - file.mod = try Package.Module.create(arena, .{ + file.mod = try Package.Module.createLimited(arena, .{ .root = Package.Path.cwd(), .root_src_path = file.sub_file_path, .fully_qualified_name = "root", @@ -5724,7 +5871,7 @@ fn fmtPathFile( .root_decl = .none, }; - file.mod = try Package.Module.create(fmt.arena, .{ + file.mod = try Package.Module.createLimited(fmt.arena, .{ .root = Package.Path.cwd(), .root_src_path = file.sub_file_path, .fully_qualified_name = "root", @@ -5804,15 +5951,13 @@ pub fn putAstErrorsIntoBundle( .tree = tree, .tree_loaded = true, .zir = undefined, - .mod = undefined, + .mod = try Package.Module.createLimited(gpa, .{ + .root = Package.Path.cwd(), + .root_src_path = path, + .fully_qualified_name = "root", + }), .root_decl = .none, }; - - file.mod = try Package.Module.create(gpa, .{ - .root = Package.Path.cwd(), - .root_src_path = file.sub_file_path, - .fully_qualified_name = "root", - }); defer gpa.destroy(file.mod); file.zir = try AstGen.generate(gpa, file.tree); @@ -6373,7 +6518,7 @@ pub fn cmdAstCheck( file.stat.size = source.len; } - file.mod = try Package.Module.create(arena, .{ + file.mod = try Package.Module.createLimited(arena, .{ .root = Package.Path.cwd(), .root_src_path = file.sub_file_path, .fully_qualified_name = "root", @@ -6546,7 +6691,7 @@ pub fn cmdChangelist( .root_decl = .none, }; - file.mod = try Package.Module.create(arena, .{ + file.mod = try Package.Module.createLimited(arena, .{ .root = Package.Path.cwd(), .root_src_path = file.sub_file_path, .fully_qualified_name = "root", @@ -6669,7 +6814,7 @@ fn warnAboutForeignBinaries( link_libc: bool, ) !void { const host_query: std.Target.Query = .{}; - const host_target = try std.zig.system.resolveTargetQuery(host_query); + const host_target = resolveTargetQueryOrFatal(host_query); switch (std.zig.system.getExternalExecutor(host_target, target, .{ .link_libc = link_libc })) { .native => return, @@ -6809,18 +6954,22 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem { /// Silently ignore superfluous search dirs. /// Warn when a dir is added to multiple searchlists. const ClangSearchSanitizer = struct { - argv: *std.ArrayList([]const u8), - map: std.StringHashMap(Membership), + map: std.StringHashMapUnmanaged(Membership) = .{}, - fn init(gpa: Allocator, argv: *std.ArrayList([]const u8)) @This() { - return .{ - .argv = argv, - .map = std.StringHashMap(Membership).init(gpa), - }; + fn reset(self: *@This()) void { + self.map.clearRetainingCapacity(); } - fn addIncludePath(self: *@This(), group: Group, arg: []const u8, dir: []const u8, joined: bool) !void { - const gopr = try self.map.getOrPut(dir); + fn addIncludePath( + self: *@This(), + ally: Allocator, + argv: *std.ArrayListUnmanaged([]const u8), + group: Group, + arg: []const u8, + dir: []const u8, + joined: bool, + ) !void { + const gopr = try self.map.getOrPut(ally, dir); const m = gopr.value_ptr; if (!gopr.found_existing) { // init empty membership @@ -6867,8 +7016,9 @@ const ClangSearchSanitizer = struct { if (m.iwithsysroot) warn(wtxt, .{ dir, "iframeworkwithsysroot", "iwithsysroot" }); }, } - try self.argv.append(arg); - if (!joined) try self.argv.append(dir); + try argv.ensureUnusedCapacity(ally, 2); + argv.appendAssumeCapacity(arg); + if (!joined) argv.appendAssumeCapacity(dir); } const Group = enum { I, isystem, iwithsysroot, idirafter, iframework, iframeworkwithsysroot }; @@ -7244,11 +7394,22 @@ fn cmdFetch( fn createEmptyDependenciesModule( arena: Allocator, main_mod: *Package.Module, + global_cache_directory: Cache.Directory, local_cache_directory: Cache.Directory, + builtin_mod: *Package.Module, + global_options: Compilation.Config, ) !void { var source = std.ArrayList(u8).init(arena); try Package.Fetch.JobQueue.createEmptyDependenciesSource(&source); - _ = try createDependenciesModule(arena, source.items, main_mod, local_cache_directory); + _ = try createDependenciesModule( + arena, + source.items, + main_mod, + global_cache_directory, + local_cache_directory, + builtin_mod, + global_options, + ); } /// Creates the dependencies.zig file and corresponding `Package.Module` for the @@ -7257,7 +7418,10 @@ fn createDependenciesModule( arena: Allocator, source: []const u8, main_mod: *Package.Module, + global_cache_directory: Cache.Directory, local_cache_directory: Cache.Directory, + builtin_mod: *Package.Module, + global_options: Compilation.Config, ) !*Package.Module { // Atomically create the file in a directory named after the hash of its contents. const basename = "dependencies.zig"; @@ -7283,25 +7447,25 @@ fn createDependenciesModule( ); const deps_mod = try Package.Module.create(arena, .{ - .root = .{ - .root_dir = local_cache_directory, - .sub_path = o_dir_sub_path, + .global_cache_directory = global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = local_cache_directory, + .sub_path = o_dir_sub_path, + }, + .root_src_path = basename, }, - .root_src_path = basename, .fully_qualified_name = "root.@dependencies", + .parent = main_mod, + .builtin_mod = builtin_mod, + .cc_argv = &.{}, + .inherited = .{}, + .global = global_options, }); try main_mod.deps.put(arena, "@dependencies", deps_mod); return deps_mod; } -fn defaultWasmEntryName(exec_model: ?std.builtin.WasiExecModel) []const u8 { - const model = exec_model orelse .command; - if (model == .reactor) { - return "_initialize"; - } - return "_start"; -} - const BuildRoot = struct { directory: Cache.Directory, build_zig_basename: []const u8, @@ -7509,3 +7673,18 @@ fn findTemplates(gpa: Allocator, arena: Allocator) Templates { .buffer = std.ArrayList(u8).init(gpa), }; } + +fn parseOptimizeMode(s: []const u8) std.builtin.OptimizeMode { + return std.meta.stringToEnum(std.builtin.OptimizeMode, s) orelse + fatal("unrecognized optimization mode: '{s}'", .{s}); +} + +fn parseWasiExecModel(s: []const u8) std.builtin.WasiExecModel { + return std.meta.stringToEnum(std.builtin.WasiExecModel, s) orelse + fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{s}); +} + +fn resolveTargetQueryOrFatal(target_query: std.Target.Query) std.Target { + return std.zig.system.resolveTargetQuery(target_query) catch |err| + fatal("unable to resolve target: {s}", .{@errorName(err)}); +} diff --git a/src/target.zig b/src/target.zig index 624a67d043f0..f610e55fb04c 100644 --- a/src/target.zig +++ b/src/target.zig @@ -3,6 +3,8 @@ const Type = @import("type.zig").Type; const AddressSpace = std.builtin.AddressSpace; const Alignment = @import("InternPool.zig").Alignment; +pub const default_stack_protector_buffer_size = 4; + pub const ArchOsAbi = struct { arch: std.Target.Cpu.Arch, os: std.Target.Os.Tag, @@ -204,11 +206,18 @@ pub fn supports_fpic(target: std.Target) bool { return target.os.tag != .windows and target.os.tag != .uefi; } -pub fn isSingleThreaded(target: std.Target) bool { +pub fn alwaysSingleThreaded(target: std.Target) bool { _ = target; return false; } +pub fn defaultSingleThreaded(target: std.Target) bool { + return switch (target.cpu.arch) { + .wasm32, .wasm64 => true, + else => false, + }; +} + /// Valgrind supports more, but Zig does not support them yet. pub fn hasValgrindSupport(target: std.Target) bool { switch (target.cpu.arch) { @@ -375,12 +384,17 @@ pub fn classifyCompilerRtLibName(target: std.Target, name: []const u8) CompilerR } pub fn hasDebugInfo(target: std.Target) bool { - if (target.cpu.arch.isNvptx()) { - // TODO: not sure how to test "ptx >= 7.5" with featureset - return std.Target.nvptx.featureSetHas(target.cpu.features, .ptx75); - } - - return true; + return switch (target.cpu.arch) { + .nvptx, .nvptx64 => std.Target.nvptx.featureSetHas(target.cpu.features, .ptx75) or + std.Target.nvptx.featureSetHas(target.cpu.features, .ptx76) or + std.Target.nvptx.featureSetHas(target.cpu.features, .ptx77) or + std.Target.nvptx.featureSetHas(target.cpu.features, .ptx78) or + std.Target.nvptx.featureSetHas(target.cpu.features, .ptx80) or + std.Target.nvptx.featureSetHas(target.cpu.features, .ptx81), + .wasm32, .wasm64 => false, + .bpfel, .bpfeb => false, + else => true, + }; } pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.OptimizeMode { @@ -619,3 +633,36 @@ pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConve else => false, }; } + +pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBackend { + if (use_llvm) return .stage2_llvm; + if (target.ofmt == .c) return .stage2_c; + return switch (target.cpu.arch) { + .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm, + .arm, .armeb, .thumb, .thumbeb => .stage2_arm, + .x86_64 => .stage2_x86_64, + .x86 => .stage2_x86, + .aarch64, .aarch64_be, .aarch64_32 => .stage2_aarch64, + .riscv64 => .stage2_riscv64, + .sparc64 => .stage2_sparc64, + .spirv64 => .stage2_spirv64, + else => .other, + }; +} + +pub fn defaultEntrySymbolName( + target: std.Target, + /// May be `undefined` when `target` is not WASI. + wasi_exec_model: std.builtin.WasiExecModel, +) ?[]const u8 { + return switch (target.ofmt) { + .coff => "wWinMainCRTStartup", + .macho => "_main", + .elf, .plan9 => "_start", + .wasm => switch (wasi_exec_model) { + .reactor => "_initialize", + .command => "_start", + }, + else => null, + }; +} From 2bef0715c740024c515dce73d267ead5af49d1a9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 21:16:49 -0700 Subject: [PATCH 024/133] move a large chunk of linker logic away from "options" These options are only supposed to be provided to the initialization functions, resolved, and then computed values stored in the appropriate place (base struct or the object-format-specific structs). Many more to go... --- src/Compilation.zig | 94 +++-- src/Compilation/Config.zig | 36 +- src/codegen/llvm.zig | 74 ++-- src/link.zig | 133 ++++--- src/link/C.zig | 54 +-- src/link/Coff.zig | 25 +- src/link/Coff/lld.zig | 32 +- src/link/Elf.zig | 322 +++++++++-------- src/link/Elf/ZigObject.zig | 101 +++--- src/link/MachO.zig | 145 +++++--- src/link/MachO/zld.zig | 159 ++++---- src/link/NvPtx.zig | 48 ++- src/link/Plan9.zig | 152 ++++---- src/link/SpirV.zig | 59 +-- src/link/Wasm.zig | 719 ++++++++++++++++++++----------------- src/main.zig | 44 ++- src/musl.zig | 2 +- src/target.zig | 8 + 18 files changed, 1245 insertions(+), 962 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index ca43e2da079f..b7cf3c52765c 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -69,6 +69,8 @@ root_name: [:0]const u8, cache_mode: CacheMode, include_compiler_rt: bool, objects: []Compilation.LinkObject, +/// Needed only for passing -F args to clang. +framework_dirs: []const []const u8, /// These are *always* dynamically linked. Static libraries will be /// provided as positional arguments. system_libs: std.StringArrayHashMapUnmanaged(SystemLib), @@ -133,6 +135,7 @@ verbose_llvm_ir: ?[]const u8, verbose_llvm_bc: ?[]const u8, verbose_cimport: bool, verbose_llvm_cpu_features: bool, +verbose_link: bool, disable_c_depfile: bool, time_report: bool, stack_report: bool, @@ -220,6 +223,8 @@ emit_llvm_bc: ?EmitLoc, work_queue_wait_group: WaitGroup = .{}, astgen_wait_group: WaitGroup = .{}, +llvm_opt_bisect_limit: c_int, + pub const Emit = struct { /// Where the output will go. directory: Directory, @@ -340,7 +345,7 @@ const Job = union(enum) { /// one of WASI libc static objects wasi_libc_crt_file: wasi_libc.CRTFile, - /// The value is the index into `link.File.Options.system_libs`. + /// The value is the index into `system_libs`. windows_import_lib: usize, }; @@ -819,6 +824,20 @@ pub const cache_helpers = struct { addEmitLoc(hh, optional_emit_loc orelse return); } + pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?link.File.DebugFormat) void { + hh.add(x != null); + addDebugFormat(hh, x orelse return); + } + + pub fn addDebugFormat(hh: *Cache.HashHelper, x: link.File.DebugFormat) void { + const tag: @typeInfo(link.File.DebugFormat).Union.tag_type.? = x; + hh.add(tag); + switch (x) { + .strip, .code_view => {}, + .dwarf => |f| hh.add(f), + } + } + pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void { _ = try self.addFile(c_source.src_path, null); // Hash the extra flags, with special care to call addFile for file parameters. @@ -846,7 +865,7 @@ pub const ClangPreprocessorMode = enum { stdout, }; -pub const Framework = link.Framework; +pub const Framework = link.File.MachO.Framework; pub const SystemLib = link.SystemLib; pub const CacheMode = link.CacheMode; @@ -952,7 +971,7 @@ pub const InitOptions = struct { linker_print_gc_sections: bool = false, linker_print_icf_sections: bool = false, linker_print_map: bool = false, - linker_opt_bisect_limit: i32 = -1, + llvm_opt_bisect_limit: i32 = -1, each_lib_rpath: ?bool = null, build_id: ?std.zig.BuildId = null, disable_c_depfile: bool = false, @@ -994,7 +1013,7 @@ pub const InitOptions = struct { hash_style: link.HashStyle = .both, entry: ?[]const u8 = null, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, - stack_size_override: ?u64 = null, + stack_size: ?u64 = null, image_base_override: ?u64 = null, version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, @@ -1007,7 +1026,7 @@ pub const InitOptions = struct { test_name_prefix: ?[]const u8 = null, test_runner_path: ?[]const u8 = null, subsystem: ?std.Target.SubSystem = null, - dwarf_format: ?std.dwarf.Format = null, + debug_format: ?link.File.DebugFormat = null, /// (Zig compiler development) Enable dumping linker's state as JSON. enable_link_snapshots: bool = false, /// (Darwin) Install name of the dylib @@ -1297,7 +1316,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.config.link_libcpp); cache.hash.add(options.config.link_libunwind); cache.hash.add(output_mode); - cache.hash.addOptional(options.dwarf_format); + cache_helpers.addOptionalDebugFormat(&cache.hash, options.debug_format); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); @@ -1596,6 +1615,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .verbose_llvm_bc = options.verbose_llvm_bc, .verbose_cimport = options.verbose_cimport, .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, + .verbose_link = options.verbose_link, .disable_c_depfile = options.disable_c_depfile, .owned_link_dir = owned_link_dir, .color = options.color, @@ -1617,6 +1637,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .libc_installation = libc_dirs.libc_installation, .include_compiler_rt = include_compiler_rt, .objects = options.link_objects, + .framework_dirs = options.framework_dirs, + .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit, }; if (bin_file_emit) |emit| { @@ -1636,7 +1658,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .z_max_page_size = options.linker_z_max_page_size, .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, .frameworks = options.frameworks, - .framework_dirs = options.framework_dirs, .wasi_emulated_libs = options.wasi_emulated_libs, .lib_dirs = options.lib_dirs, .rpath_list = options.rpath_list, @@ -1659,13 +1680,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .print_gc_sections = options.linker_print_gc_sections, .print_icf_sections = options.linker_print_icf_sections, .print_map = options.linker_print_map, - .opt_bisect_limit = options.linker_opt_bisect_limit, .tsaware = options.linker_tsaware, .nxcompat = options.linker_nxcompat, .dynamicbase = options.linker_dynamicbase, .major_subsystem_version = options.major_subsystem_version, .minor_subsystem_version = options.minor_subsystem_version, - .stack_size_override = options.stack_size_override, + .stack_size = options.stack_size, .image_base_override = options.image_base_override, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, @@ -1674,7 +1694,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .rdynamic = options.rdynamic, .soname = options.soname, .compatibility_version = options.compatibility_version, - .verbose_link = options.verbose_link, .dll_export_fns = dll_export_fns, .skip_linker_dependencies = options.skip_linker_dependencies, .parent_compilation_link_libc = options.parent_compilation_link_libc, @@ -1682,7 +1701,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .build_id = build_id, .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, .subsystem = options.subsystem, - .dwarf_format = options.dwarf_format, + .debug_format = options.debug_format, .hash_style = options.hash_style, .enable_link_snapshots = options.enable_link_snapshots, .install_name = options.install_name, @@ -1826,7 +1845,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // When linking mingw-w64 there are some import libs we always need. for (mingw.always_link_libs) |name| { - try comp.bin_file.options.system_libs.put(comp.gpa, name, .{ + try comp.system_libs.put(comp.gpa, name, .{ .needed = false, .weak = false, .path = null, @@ -1835,7 +1854,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } // Generate Windows import libs. if (target.os.tag == .windows) { - const count = comp.bin_file.options.system_libs.count(); + const count = comp.system_libs.count(); try comp.work_queue.ensureUnusedCapacity(count); for (0..count) |i| { comp.work_queue.writeItemAssumeCapacity(.{ .windows_import_lib = i }); @@ -2450,7 +2469,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); - man.hash.addOptional(comp.bin_file.options.stack_size_override); + man.hash.add(comp.bin_file.stack_size); man.hash.addOptional(comp.bin_file.options.image_base_override); man.hash.addOptional(comp.bin_file.options.gc_sections); man.hash.add(comp.bin_file.options.eh_frame_hdr); @@ -2460,7 +2479,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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.options.build_id); + man.hash.add(comp.bin_file.build_id); man.hash.add(comp.bin_file.options.skip_linker_dependencies); man.hash.add(comp.bin_file.options.z_nodelete); man.hash.add(comp.bin_file.options.z_notext); @@ -2488,9 +2507,9 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } man.hash.addOptionalBytes(comp.bin_file.options.soname); man.hash.addOptional(comp.bin_file.options.version); - try link.hashAddSystemLibs(man, comp.bin_file.options.system_libs); + try link.hashAddSystemLibs(man, comp.system_libs); man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys()); - man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined); + man.hash.addOptional(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); @@ -2505,7 +2524,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptional(comp.bin_file.options.global_base); // Mach-O specific stuff - man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); + man.hash.addListOfBytes(comp.framework_dirs); try link.hashAddFrameworks(man, comp.bin_file.options.frameworks); try man.addOptionalFile(comp.bin_file.options.entitlements); man.hash.addOptional(comp.bin_file.options.pagezero_size); @@ -3561,7 +3580,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v const named_frame = tracy.namedFrame("windows_import_lib"); defer named_frame.end(); - const link_lib = comp.bin_file.options.system_libs.keys()[index]; + const link_lib = comp.system_libs.keys()[index]; mingw.buildImportLib(comp, link_lib) catch |err| { // TODO Surface more error details. comp.lockAndSetMiscFailure( @@ -4964,7 +4983,7 @@ pub fn addCCArgs( try argv.appendSlice(&.{ "-iframework", framework_dir }); } - for (comp.bin_file.options.framework_dirs) |framework_dir| { + for (comp.framework_dirs) |framework_dir| { try argv.appendSlice(&.{ "-F", framework_dir }); } @@ -5219,22 +5238,21 @@ pub fn addCCArgs( }, } - if (!comp.bin_file.options.strip) { - switch (target.ofmt) { - .coff => { - // -g is required here because -gcodeview doesn't trigger debug info - // generation, it only changes the type of information generated. - try argv.appendSlice(&.{ "-g", "-gcodeview" }); - }, - .elf, .macho => { - try argv.append("-gdwarf-4"); - if (comp.bin_file.options.dwarf_format) |f| switch (f) { - .@"32" => try argv.append("-gdwarf32"), - .@"64" => try argv.append("-gdwarf64"), - }; - }, - else => try argv.append("-g"), - } + try argv.ensureUnusedCapacity(2); + switch (comp.bin_file.debug_format) { + .strip => {}, + .code_view => { + // -g is required here because -gcodeview doesn't trigger debug info + // generation, it only changes the type of information generated. + argv.appendSliceAssumeCapacity(&.{ "-g", "-gcodeview" }); + }, + .dwarf => |f| { + argv.appendAssumeCapacity("-gdwarf-4"); + switch (f) { + .@"32" => argv.appendAssumeCapacity("-gdwarf32"), + .@"64" => argv.appendAssumeCapacity("-gdwarf64"), + } + }, } if (target_util.llvmMachineAbi(target)) |mabi| { @@ -6306,7 +6324,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { // This happens when an `extern "foo"` function is referenced. // If we haven't seen this library yet and we're targeting Windows, we need // to queue up a work item to produce the DLL import library for this. - const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name); + const gop = try comp.system_libs.getOrPut(comp.gpa, lib_name); if (!gop.found_existing and comp.getTarget().os.tag == .windows) { gop.value_ptr.* = .{ .needed = true, @@ -6314,7 +6332,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { .path = null, }; try comp.work_queue.writeItem(.{ - .windows_import_lib = comp.bin_file.options.system_libs.count() - 1, + .windows_import_lib = comp.system_libs.count() - 1, }); } } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 0b9c70fc4244..fe33a18c0a66 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -137,7 +137,11 @@ pub fn resolve(options: Options) !Config { const use_llvm = b: { // If emitting to LLVM bitcode object format, must use LLVM backend. if (options.emit_llvm_ir or options.emit_llvm_bc) { - if (options.use_llvm == false) return error.EmittingLlvmModuleRequiresLlvmBackend; + if (options.use_llvm == false) + return error.EmittingLlvmModuleRequiresLlvmBackend; + if (!target_util.hasLlvmSupport(target, target.ofmt)) + return error.LlvmLacksTargetSupport; + break :b true; } @@ -147,6 +151,12 @@ pub fn resolve(options: Options) !Config { break :b false; } + // If Zig does not support the target, then we can't use it. + if (target_util.zigBackend(target, false) == .other) { + if (options.use_llvm == false) return error.ZigLacksTargetSupport; + break :b true; + } + if (options.use_llvm) |x| break :b x; // If we have no zig code to compile, no need for LLVM. @@ -166,16 +176,23 @@ pub fn resolve(options: Options) !Config { break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target); }; - if (!use_lib_llvm and use_llvm and options.emit_bin) { - // Explicit request to use LLVM to produce an object file, but without - // using LLVM libraries. Impossible. - return error.EmittingBinaryRequiresLlvmLibrary; + if (options.emit_bin) { + if (!use_lib_llvm and use_llvm) { + // Explicit request to use LLVM to produce an object file, but without + // using LLVM libraries. Impossible. + return error.EmittingBinaryRequiresLlvmLibrary; + } + + if (target_util.zigBackend(target, use_llvm) == .other) { + // There is no compiler backend available for this target. + return error.ZigLacksTargetSupport; + } } // Make a decision on whether to use LLD or our own linker. const use_lld = b: { - if (target.isDarwin()) { - if (options.use_lld == true) return error.LldIncompatibleOs; + if (!target_util.hasLldSupport(target.ofmt)) { + if (options.use_lld == true) return error.LldIncompatibleObjectFormat; break :b false; } @@ -184,11 +201,6 @@ pub fn resolve(options: Options) !Config { break :b false; } - if (target.ofmt == .c) { - if (options.use_lld == true) return error.LldIncompatibleObjectFormat; - break :b false; - } - if (options.lto == true) { if (options.use_lld == false) return error.LtoRequiresLld; break :b true; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index cf6f38a53ea8..57e5770d89eb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -854,15 +854,21 @@ pub const Object = struct { pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object { - const gpa = options.comp.gpa; - const llvm_target_triple = try targetTriple(arena, options.target); + if (build_options.only_c) unreachable; + const comp = options.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; + const llvm_target_triple = try targetTriple(arena, target); + const strip = comp.root_mod.strip; + const optimize_mode = comp.root_mod.optimize_mode; + const pic = comp.root_mod.pic; var builder = try Builder.init(.{ .allocator = gpa, - .use_lib_llvm = options.use_lib_llvm, - .strip = options.strip or !options.use_lib_llvm, // TODO - .name = options.root_name, - .target = options.target, + .use_lib_llvm = comp.config.use_lib_llvm, + .strip = strip or !comp.config.use_lib_llvm, // TODO + .name = comp.root_name, + .target = target, .triple = llvm_target_triple, }); errdefer builder.deinit(); @@ -870,10 +876,18 @@ pub const Object = struct { var target_machine: if (build_options.have_llvm) *llvm.TargetMachine else void = undefined; var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined; if (builder.useLibLlvm()) { - if (!options.strip) { - switch (options.target.ofmt) { - .coff => builder.llvm.module.?.addModuleCodeViewFlag(), - else => builder.llvm.module.?.addModuleDebugInfoFlag(options.dwarf_format == std.dwarf.Format.@"64"), + debug_info: { + const debug_format = options.debug_format orelse b: { + if (strip) break :b .strip; + break :b switch (target.ofmt) { + .coff => .code_view, + else => .{ .dwarf = .@"32" }, + }; + }; + switch (debug_format) { + .strip => break :debug_info, + .code_view => builder.llvm.module.?.addModuleCodeViewFlag(), + .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"), } builder.llvm.di_builder = builder.llvm.module.?.createDIBuilder(true); @@ -892,8 +906,8 @@ pub const Object = struct { // TODO: the only concern I have with this is WASI as either host or target, should // we leave the paths as relative then? const compile_unit_dir_z = blk: { - if (options.module) |mod| m: { - const d = try mod.root_mod.root.joinStringZ(arena, ""); + if (comp.module) |zcu| m: { + const d = try zcu.root_mod.root.joinStringZ(arena, ""); if (d.len == 0) break :m; if (std.fs.path.isAbsolute(d)) break :blk d; break :blk std.fs.realpathAlloc(arena, d) catch d; @@ -903,9 +917,9 @@ pub const Object = struct { builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( DW.LANG.C99, - builder.llvm.di_builder.?.createFile(options.root_name, compile_unit_dir_z), + builder.llvm.di_builder.?.createFile(comp.root_name, compile_unit_dir_z), producer.slice(&builder).?, - options.optimize_mode != .Debug, + optimize_mode != .Debug, "", // flags 0, // runtime version "", // split name @@ -914,19 +928,19 @@ pub const Object = struct { ); } - const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) + const opt_level: llvm.CodeGenOptLevel = if (optimize_mode == .Debug) .None else .Aggressive; - const reloc_mode: llvm.RelocMode = if (options.pic) + const reloc_mode: llvm.RelocMode = if (pic) .PIC - else if (options.link_mode == .Dynamic) + else if (comp.config.link_mode == .Dynamic) llvm.RelocMode.DynamicNoPIC else .Static; - const code_model: llvm.CodeModel = switch (options.machine_code_model) { + const code_model: llvm.CodeModel = switch (comp.root_mod.code_model) { .default => .Default, .tiny => .Tiny, .small => .Small, @@ -941,15 +955,15 @@ pub const Object = struct { target_machine = llvm.TargetMachine.create( builder.llvm.target.?, builder.target_triple.slice(&builder).?, - if (options.target.cpu.model.llvm_name) |s| s.ptr else null, - options.llvm_cpu_features, + if (target.cpu.model.llvm_name) |s| s.ptr else null, + comp.root_mod.resolved_target.llvm_cpu_features.?, opt_level, reloc_mode, code_model, - options.function_sections, - options.data_sections, + options.function_sections orelse false, + options.data_sections orelse false, float_abi, - if (target_util.llvmMachineAbi(options.target)) |s| s.ptr else null, + if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, ); errdefer target_machine.dispose(); @@ -958,15 +972,15 @@ pub const Object = struct { builder.llvm.module.?.setModuleDataLayout(target_data); - if (options.pic) builder.llvm.module.?.setModulePICLevel(); - if (options.pie) builder.llvm.module.?.setModulePIELevel(); + if (pic) builder.llvm.module.?.setModulePICLevel(); + if (comp.config.pie) builder.llvm.module.?.setModulePIELevel(); if (code_model != .Default) builder.llvm.module.?.setModuleCodeModel(code_model); - if (options.opt_bisect_limit >= 0) { - builder.llvm.context.setOptBisectLimit(std.math.lossyCast(c_int, options.opt_bisect_limit)); + if (comp.llvm_opt_bisect_limit >= 0) { + builder.llvm.context.setOptBisectLimit(comp.llvm_opt_bisect_limit); } - builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = options.target }}); + builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }}); if (std.debug.runtime_safety) { const rep = target_data.stringRep(); defer llvm.disposeMessage(rep); @@ -981,13 +995,13 @@ pub const Object = struct { obj.* = .{ .gpa = gpa, .builder = builder, - .module = options.module.?, + .module = comp.module.?, .di_map = .{}, .di_builder = if (builder.useLibLlvm()) builder.llvm.di_builder else null, // TODO .di_compile_unit = if (builder.useLibLlvm()) builder.llvm.di_compile_unit else null, .target_machine = target_machine, .target_data = target_data, - .target = options.target, + .target = target, .decl_map = .{}, .anon_decl_map = .{}, .named_enum_map = .{}, diff --git a/src/link.zig b/src/link.zig index 46dab1b6edbf..9685cea39154 100644 --- a/src/link.zig +++ b/src/link.zig @@ -32,13 +32,6 @@ pub const SystemLib = struct { path: ?[]const u8, }; -/// When adding a new field, remember to update `hashAddFrameworks`. -pub const Framework = struct { - needed: bool = false, - weak: bool = false, - path: []const u8, -}; - pub const SortSection = enum { name, alignment }; pub const CacheMode = enum { incremental, whole }; @@ -56,14 +49,6 @@ pub fn hashAddSystemLibs( } } -pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { - for (hm) |value| { - man.hash.add(value.needed); - man.hash.add(value.weak); - _ = try man.addFile(value.path, null); - } -} - pub const producer_string = if (builtin.is_test) "zig test" else "zig " ++ build_options.version; pub const HashStyle = enum { sysv, gnu, both }; @@ -81,6 +66,19 @@ pub const File = struct { /// When linking with LLD, this linker code will output an object file only at /// this location, and then this path can be placed on the LLD linker line. intermediary_basename: ?[]const u8 = null, + disable_lld_caching: bool, + gc_sections: bool, + build_id: std.zig.BuildId, + rpath_list: []const []const u8, + /// List of symbols forced as undefined in the symbol table + /// thus forcing their resolution by the linker. + /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. + force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), + allow_shlib_undefined: bool, + stack_size: u64, + debug_format: DebugFormat, + function_sections: bool, + data_sections: bool, /// Prevents other processes from clobbering files in the output directory /// of this linking operation. @@ -88,6 +86,12 @@ pub const File = struct { child_pid: ?std.ChildProcess.Id = null, + pub const DebugFormat = union(enum) { + strip, + dwarf: std.dwarf.Format, + code_view, + }; + pub const OpenOptions = struct { comp: *Compilation, emit: Compilation.Emit, @@ -97,7 +101,7 @@ pub const File = struct { /// Virtual address of the entry point procedure relative to image base. entry_addr: ?u64, - stack_size_override: ?u64, + stack_size: ?u64, image_base_override: ?u64, function_sections: bool, data_sections: bool, @@ -128,7 +132,6 @@ pub const File = struct { max_memory: ?u64, export_symbol_names: []const []const u8, global_base: ?u64, - verbose_link: bool, dll_export_fns: bool, skip_linker_dependencies: bool, parent_compilation_link_libc: bool, @@ -139,7 +142,7 @@ pub const File = struct { sort_section: ?SortSection, major_subsystem_version: ?u32, minor_subsystem_version: ?u32, - gc_sections: ?bool = null, + gc_sections: ?bool, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, version_script: ?[]const u8, @@ -147,11 +150,7 @@ pub const File = struct { print_gc_sections: bool, print_icf_sections: bool, print_map: bool, - opt_bisect_limit: i32, - /// List of symbols forced as undefined in the symbol table - /// thus forcing their resolution by the linker. - /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), /// Use a wrapper function for symbol. Any undefined reference to symbol /// will be resolved to __wrap_symbol. Any undefined reference to @@ -163,7 +162,7 @@ pub const File = struct { compatibility_version: ?std.SemanticVersion, - dwarf_format: ?std.dwarf.Format, + debug_format: ?DebugFormat, // TODO: remove this. libraries are resolved by the frontend. lib_dirs: []const []const u8, @@ -184,8 +183,7 @@ pub const File = struct { headerpad_max_install_names: bool, /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols dead_strip_dylibs: bool, - framework_dirs: []const []const u8, - frameworks: []const Framework, + frameworks: []const MachO.Framework, darwin_sdk_layout: ?MachO.SdkLayout, /// (Windows) PDB source path prefix to instruct the linker how to resolve relative @@ -228,7 +226,7 @@ pub const File = struct { .coff, .elf, .macho, .plan9, .wasm => { if (build_options.only_c) unreachable; if (base.file != null) return; - const emit = base.options.emit orelse return; + const emit = base.emit; if (base.child_pid) |pid| { if (builtin.os.tag == .windows) { base.cast(Coff).?.ptraceAttach(pid) catch |err| { @@ -256,10 +254,13 @@ pub const File = struct { } } } + const use_lld = build_options.have_llvm and base.comp.config.use_lld; + const output_mode = base.comp.config.output_mode; + const link_mode = base.comp.config.link_mode; base.file = try emit.directory.handle.createFile(emit.sub_path, .{ .truncate = false, .read = true, - .mode = determineMode(base.options), + .mode = determineMode(use_lld, output_mode, link_mode), }); }, .c, .spirv, .nvptx => {}, @@ -267,9 +268,13 @@ pub const File = struct { } pub fn makeExecutable(base: *File) !void { - switch (base.options.output_mode) { + const output_mode = base.comp.config.output_mode; + const link_mode = base.comp.config.link_mode; + const use_lld = build_options.have_llvm and base.comp.config.use_lld; + + switch (output_mode) { .Obj => return, - .Lib => switch (base.options.link_mode) { + .Lib => switch (link_mode) { .Static => return, .Dynamic => {}, }, @@ -278,7 +283,6 @@ pub const File = struct { switch (base.tag) { .elf => if (base.file) |f| { if (build_options.only_c) unreachable; - const use_lld = build_options.have_llvm and base.options.use_lld; if (base.intermediary_basename != null and use_lld) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. @@ -596,7 +600,7 @@ pub const File = struct { return @fieldParentPtr(C, "base", base).flush(comp, prog_node); } if (comp.clang_preprocessor_mode == .yes) { - const emit = base.options.emit orelse return; // -fno-emit-bin + const emit = base.emit; // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) // Until then, we do `lld -r -o output.o input.o` even though the output is the same // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file @@ -610,8 +614,10 @@ pub const File = struct { return; } - const use_lld = build_options.have_llvm and base.options.use_lld; - if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static) { + const use_lld = build_options.have_llvm and base.comp.config.use_lld; + const output_mode = base.comp.config.output_mode; + const link_mode = base.comp.config.link_mode; + if (use_lld and output_mode == .Lib and link_mode == .Static) { return base.linkAsArchive(comp, prog_node); } switch (base.tag) { @@ -845,8 +851,6 @@ pub const File = struct { } pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { - const emit = base.options.emit orelse return; - const tracy = trace(@src()); defer tracy.end(); @@ -854,22 +858,23 @@ pub const File = struct { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const directory = emit.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path}); + const directory = base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); const full_out_path_z = try arena.dupeZ(u8, full_out_path); + const opt_zcu = base.comp.module; // If there is no Zig code to compile, then we should skip flushing the output file // because it will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (base.options.module != null) blk: { + const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { try base.flushModule(comp, prog_node); const dirname = fs.path.dirname(full_out_path_z) orelse "."; break :blk try fs.path.join(arena, &.{ dirname, base.intermediary_basename.? }); } else null; - log.debug("module_obj_path={s}", .{if (module_obj_path) |s| s else "(null)"}); + log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"}); - const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt) + const compiler_rt_path: ?[]const u8 = if (base.comp.include_compiler_rt) comp.compiler_rt_obj.?.full_object_path else null; @@ -881,17 +886,19 @@ pub const File = struct { const id_symlink_basename = "llvm-ar.id"; var man: Cache.Manifest = undefined; - defer if (!base.options.disable_lld_caching) man.deinit(); + defer if (!base.disable_lld_caching) man.deinit(); + + const objects = base.comp.objects; var digest: [Cache.hex_digest_len]u8 = undefined; - if (!base.options.disable_lld_caching) { + if (!base.disable_lld_caching) { man = comp.cache_parent.obtain(); // We are about to obtain this lock, so here we give other processes a chance first. base.releaseLock(); - for (base.options.objects) |obj| { + for (objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); man.hash.add(obj.loption); @@ -904,7 +911,7 @@ pub const File = struct { _ = try man.addFile(key.status.success.res_path, null); } } - try man.addOptionalFile(module_obj_path); + try man.addOptionalFile(zcu_obj_path); try man.addOptionalFile(compiler_rt_path); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. @@ -934,11 +941,11 @@ pub const File = struct { } const win32_resource_table_len = if (build_options.only_core_functionality) 0 else comp.win32_resource_table.count(); - const num_object_files = base.options.objects.len + comp.c_object_table.count() + win32_resource_table_len + 2; + const num_object_files = objects.len + comp.c_object_table.count() + win32_resource_table_len + 2; var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files); defer object_files.deinit(); - for (base.options.objects) |obj| { + for (objects) |obj| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj.path)); } for (comp.c_object_table.keys()) |key| { @@ -949,14 +956,14 @@ pub const File = struct { object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path)); } } - if (module_obj_path) |p| { + if (zcu_obj_path) |p| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); } if (compiler_rt_path) |p| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); } - if (base.options.verbose_link) { + if (comp.verbose_link) { std.debug.print("ar rcs {s}", .{full_out_path_z}); for (object_files.items) |arg| { std.debug.print(" {s}", .{arg}); @@ -972,7 +979,7 @@ pub const File = struct { const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag); if (bad) return error.UnableToWriteArchive; - if (!base.options.disable_lld_caching) { + if (!base.disable_lld_caching) { Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { log.warn("failed to save archive hash digest file: {s}", .{@errorName(err)}); }; @@ -1090,6 +1097,34 @@ pub const File = struct { } } + pub fn isStatic(self: File) bool { + return self.base.options.link_mode == .Static; + } + + pub fn isObject(self: File) bool { + const output_mode = self.comp.config.output_mode; + return output_mode == .Obj; + } + + pub fn isExe(self: File) bool { + const output_mode = self.comp.config.output_mode; + return output_mode == .Exe; + } + + pub fn isStaticLib(self: File) bool { + const output_mode = self.comp.config.output_mode; + return output_mode == .Lib and self.isStatic(); + } + + pub fn isRelocatable(self: File) bool { + return self.isObject() or self.isStaticLib(); + } + + pub fn isDynLib(self: File) bool { + const output_mode = self.comp.config.output_mode; + return output_mode == .Lib and !self.isStatic(); + } + pub const C = @import("link/C.zig"); pub const Coff = @import("link/Coff.zig"); pub const Plan9 = @import("link/Plan9.zig"); diff --git a/src/link/C.zig b/src/link/C.zig index 85d13bf7ec4c..4e40addcf7ec 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator; const fs = std.fs; const C = @This(); +const build_options = @import("build_options"); const Module = @import("../Module.zig"); const InternPool = @import("../InternPool.zig"); const Alignment = InternPool.Alignment; @@ -91,28 +92,40 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { }; } -pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C { +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { assert(options.target.ofmt == .c); + const optimize_mode = options.comp.root_mod.optimize_mode; + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; - if (options.use_llvm) return error.LLVMHasNoCBackend; - if (options.use_lld) return error.LLDHasNoCBackend; + // These are caught by `Compilation.Config.resolve`. + assert(!use_lld); + assert(!use_llvm); - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + const emit = options.emit; + + const file = try emit.directory.handle.createFile(emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, .mode = link.determineMode(options), }); errdefer file.close(); - const c_file = try gpa.create(C); - errdefer gpa.destroy(c_file); + const c_file = try arena.create(C); c_file.* = .{ .base = .{ .tag = .c, - .options = options, + .comp = options.comp, + .emit = emit, + .gc_sections = options.gc_sections orelse optimize_mode != .Debug, + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = file, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, }, }; @@ -120,7 +133,7 @@ pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C } pub fn deinit(self: *C) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; for (self.decl_table.values()) |*db| { db.deinit(gpa); @@ -141,7 +154,7 @@ pub fn deinit(self: *C) void { } pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; if (self.decl_table.fetchSwapRemove(decl_index)) |kv| { var decl_block = kv.value; decl_block.deinit(gpa); @@ -155,7 +168,7 @@ pub fn updateFunc( air: Air, liveness: Liveness, ) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const func = module.funcInfo(func_index); const decl_index = func.owner_decl; @@ -223,7 +236,7 @@ pub fn updateFunc( } fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const anon_decl = self.anon_decls.keys()[i]; const fwd_decl = &self.fwd_decl_buf; @@ -285,7 +298,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const gop = try self.decl_table.getOrPut(gpa, decl_index); if (!gop.found_existing) { @@ -352,7 +365,8 @@ pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void } fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { - var defines = std.ArrayList(u8).init(self.base.allocator); + const gpa = self.base.comp.gpa; + var defines = std.ArrayList(u8).init(gpa); errdefer defines.deinit(); const writer = defines.writer(); switch (target.abi) { @@ -371,7 +385,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo sub_prog_node.activate(); defer sub_prog_node.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const module = self.base.options.module.?; { @@ -520,7 +534,7 @@ fn flushCTypes( pass: codegen.DeclGen.Pass, decl_ctypes: codegen.CType.Store, ) FlushDeclError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl_ctypes_len = decl_ctypes.count(); @@ -601,7 +615,7 @@ fn flushCTypes( } fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const fwd_decl = &self.lazy_fwd_decl_buf; const code = &self.lazy_code_buf; @@ -643,7 +657,7 @@ fn flushLazyFn( ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMap.Entry, ) FlushDeclError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const fwd_decl = &self.lazy_fwd_decl_buf; const code = &self.lazy_code_buf; @@ -683,7 +697,7 @@ fn flushLazyFn( } fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); var it = lazy_fns.iterator(); @@ -702,7 +716,7 @@ fn flushDeclBlock( export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), extern_symbol_name: InternPool.OptionalNullTerminatedString, ) FlushDeclError!void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; try self.flushLazyFns(f, decl_block.lazy_fns); try f.all_buffers.ensureUnusedCapacity(gpa, 1); fwd_decl: { diff --git a/src/link/Coff.zig b/src/link/Coff.zig index e477aeffcf48..2541d62eac6c 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -232,7 +232,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { errdefer self.base.destroy(); const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; + const use_llvm = options.comp.config.use_llvm; if (use_lld and use_llvm) { // LLVM emits the object file; LLD links it into the final product. @@ -353,6 +353,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { const target = options.comp.root_mod.resolved_target.result; + const optimize_mode = options.comp.root_mod.optimize_mode; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -367,14 +368,24 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { .tag = .coff, .comp = options.comp, .emit = options.emit, + .stack_size = options.stack_size orelse 16777216, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .code_view, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .ptr_width = ptr_width, .page_size = page_size, .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory), }; - const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; + const use_llvm = options.comp.config.use_llvm; if (use_llvm and options.comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -1494,8 +1505,6 @@ pub fn updateExports( if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - if (self.base.options.emit == null) return; - const gpa = self.base.comp.gpa; const metadata = switch (exported) { @@ -1645,13 +1654,7 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void { } pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (self.base.options.emit == null) { - if (self.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); - } - return; - } - const use_lld = build_options.have_llvm and self.base.options.use_lld; + const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; if (use_lld) { return lld.linkWithLLD(self, comp, prog_node); } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 573a85e167f9..4d4dd840cfaa 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -25,8 +25,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); + const directory = self.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. @@ -50,6 +50,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; const target = self.base.options.target; + const optimize_mode = self.base.comp.root_mod.optimize_mode; // See link/Elf.zig for comments on how this mechanism works. const id_symlink_basename = "lld.id"; @@ -79,7 +80,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } try man.addOptionalFile(module_obj_path); man.hash.addOptionalBytes(self.base.options.entry); - man.hash.addOptional(self.base.options.stack_size_override); + man.hash.add(self.base.stack_size); man.hash.addOptional(self.base.options.image_base_override); man.hash.addListOfBytes(self.base.options.lib_dirs); man.hash.add(self.base.options.skip_linker_dependencies); @@ -93,14 +94,14 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } } - try link.hashAddSystemLibs(&man, self.base.options.system_libs); + try link.hashAddSystemLibs(&man, self.base.comp.system_libs); man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys()); man.hash.addOptional(self.base.options.subsystem); man.hash.add(self.base.options.is_test); man.hash.add(self.base.options.tsaware); man.hash.add(self.base.options.nxcompat); man.hash.add(self.base.options.dynamicbase); - man.hash.addOptional(self.base.options.allow_shlib_undefined); + man.hash.addOptional(self.base.allow_shlib_undefined); // strip does not need to go into the linker hash because it is part of the hash namespace man.hash.addOptional(self.base.options.major_subsystem_version); man.hash.addOptional(self.base.options.minor_subsystem_version); @@ -185,15 +186,14 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor })); } if (self.base.options.lto) { - switch (self.base.options.optimize_mode) { + switch (optimize_mode) { .Debug => {}, .ReleaseSmall => try argv.append("-OPT:lldlto=2"), .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), } } if (self.base.options.output_mode == .Exe) { - const stack_size = self.base.options.stack_size_override orelse 16777216; - try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size})); + try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } if (self.base.options.image_base_override) |image_base| { try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base})); @@ -232,10 +232,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (!self.base.options.dynamicbase) { try argv.append("-dynamicbase:NO"); } - if (self.base.options.allow_shlib_undefined) |allow_shlib_undefined| { - if (allow_shlib_undefined) { - try argv.append("-FORCE:UNRESOLVED"); - } + if (self.base.allow_shlib_undefined) { + try argv.append("-FORCE:UNRESOLVED"); } try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); @@ -419,7 +417,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib")); for (mingw.always_link_libs) |name| { - if (!self.base.options.system_libs.contains(name)) { + if (!self.base.comp.system_libs.contains(name)) { const lib_basename = try allocPrint(arena, "{s}.lib", .{name}); try argv.append(try comp.get_libc_crt_file(arena, lib_basename)); } @@ -429,7 +427,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .Dynamic => "", .Static => "lib", }; - const d_str = switch (self.base.options.optimize_mode) { + const d_str = switch (optimize_mode) { .Debug => "d", else => "", }; @@ -489,8 +487,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); } - try argv.ensureUnusedCapacity(self.base.options.system_libs.count()); - for (self.base.options.system_libs.keys()) |key| { + try argv.ensureUnusedCapacity(self.base.comp.system_libs.count()); + for (self.base.comp.system_libs.keys()) |key| { const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); if (comp.crt_files.get(lib_basename)) |crt_file| { argv.appendAssumeCapacity(crt_file.full_object_path); @@ -516,7 +514,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod return error.DllImportLibraryNotFound; } - if (self.base.options.verbose_link) { + if (self.base.comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ef25c63e3221..2bab459582ec 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -206,7 +206,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { assert(target.ofmt == .elf); const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = build_options.have_llvm and options.comp.config.use_llvm; + const use_llvm = options.comp.config.use_llvm; + const opt_zcu = options.comp.module; + const output_mode = options.comp.config.output_mode; + const link_mode = options.comp.config.link_mode; const self = try createEmpty(arena, options); errdefer self.base.destroy(); @@ -216,8 +219,8 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { return self; } - const is_obj = options.output_mode == .Obj; - const is_obj_or_ar = is_obj or (options.output_mode == .Lib and options.link_mode == .Static); + const is_obj = output_mode == .Obj; + const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static); const sub_path = if (!use_lld) options.emit.sub_path else p: { // Open a temporary object file, not the final output file because we @@ -229,10 +232,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { break :p o_file_path; }; - self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{ + self.base.file = try options.emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); const gpa = options.comp.gpa; @@ -292,24 +295,34 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { }); } - if (options.module != null and !options.use_llvm) { - const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); - self.files.set(index, .{ .zig_object = .{ - .index = index, - .path = try std.fmt.allocPrint(arena, "{s}.o", .{std.fs.path.stem( - options.module.?.main_mod.root_src_path, - )}), - } }); - self.zig_object_index = index; - try self.zigObjectPtr().?.init(self); - try self.initMetadata(); + if (opt_zcu) |zcu| { + if (!use_llvm) { + const index: File.Index = @intCast(try self.files.addOne(gpa)); + self.files.set(index, .{ .zig_object = .{ + .index = index, + .path = try std.fmt.allocPrint(arena, "{s}.o", .{std.fs.path.stem( + zcu.main_mod.root_src_path, + )}), + } }); + self.zig_object_index = index; + try self.zigObjectPtr().?.init(self); + try self.initMetadata(.{ + .symbol_count_hint = options.symbol_count_hint, + .program_code_size_hint = options.program_code_size_hint, + }); + } } return self; } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { + const use_llvm = options.comp.config.use_llvm; + const optimize_mode = options.comp.root_mod.optimize_mode; const target = options.comp.root_mod.resolved_target.result; + const output_mode = options.comp.config.output_mode; + const link_mode = options.comp.config.link_mode; + const is_native_os = options.comp.root_mod.resolved_target.is_native_os; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -322,7 +335,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .sparc64 => 0x2000, else => 0x1000, }; - const is_dyn_lib = options.output_mode == .Lib and options.link_mode == .Dynamic; + const is_dyn_lib = output_mode == .Lib and link_mode == .Dynamic; const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or options.rdynamic) elf.VER_NDX_GLOBAL else @@ -333,13 +346,23 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .tag = .elf, .comp = options.comp, .emit = options.emit, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .ptr_width = ptr_width, .page_size = page_size, .default_sym_version = default_sym_version, }; - if (options.use_llvm and options.comp.config.have_zcu) { + if (use_llvm and options.comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -504,8 +527,13 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { return start; } +pub const InitMetadataOptions = struct { + symbol_count_hint: u64, + program_code_size_hint: u64, +}; + /// TODO move to ZigObject -pub fn initMetadata(self: *Elf) !void { +pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { const gpa = self.base.comp.gpa; const ptr_size = self.ptrWidthBytes(); const target = self.base.comp.root_mod.resolved_target.result; @@ -515,7 +543,7 @@ pub fn initMetadata(self: *Elf) !void { const fillSection = struct { fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void { - if (elf_file.isRelocatable()) { + if (elf_file.base.isRelocatable()) { const off = elf_file.findFreeSpace(size, shdr.sh_addralign); shdr.sh_offset = off; shdr.sh_size = size; @@ -530,9 +558,9 @@ pub fn initMetadata(self: *Elf) !void { comptime assert(number_of_zig_segments == 5); - if (!self.isRelocatable()) { + if (!self.base.isRelocatable()) { if (self.phdr_zig_load_re_index == null) { - const filesz = self.base.options.program_code_size_hint; + const filesz = options.program_code_size_hint; const off = self.findFreeSpace(filesz, self.page_size); self.phdr_zig_load_re_index = try self.addPhdr(.{ .type = elf.PT_LOAD, @@ -549,7 +577,7 @@ pub fn initMetadata(self: *Elf) !void { // We really only need ptr alignment but since we are using PROGBITS, linux requires // page align. const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); - const filesz = @as(u64, ptr_size) * self.base.options.symbol_count_hint; + const filesz = @as(u64, ptr_size) * options.symbol_count_hint; const off = self.findFreeSpace(filesz, alignment); self.phdr_zig_got_index = try self.addPhdr(.{ .type = elf.PT_LOAD, @@ -613,8 +641,8 @@ pub fn initMetadata(self: *Elf) !void { .offset = std.math.maxInt(u64), }); const shdr = &self.shdrs.items[self.zig_text_section_index.?]; - fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index); - if (self.isRelocatable()) { + fillSection(self, shdr, options.program_code_size_hint, self.phdr_zig_load_re_index); + if (self.base.isRelocatable()) { const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?); try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{ .shndx = rela_shndx, @@ -630,7 +658,7 @@ pub fn initMetadata(self: *Elf) !void { try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); } - if (self.zig_got_section_index == null and !self.isRelocatable()) { + if (self.zig_got_section_index == null and !self.base.isRelocatable()) { self.zig_got_section_index = try self.addSection(.{ .name = ".got.zig", .type = elf.SHT_PROGBITS, @@ -661,7 +689,7 @@ pub fn initMetadata(self: *Elf) !void { }); const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); - if (self.isRelocatable()) { + if (self.base.isRelocatable()) { const rela_shndx = try self.addRelaShdr( ".rela.data.rel.ro.zig", self.zig_data_rel_ro_section_index.?, @@ -690,7 +718,7 @@ pub fn initMetadata(self: *Elf) !void { }); const shdr = &self.shdrs.items[self.zig_data_section_index.?]; fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); - if (self.isRelocatable()) { + if (self.base.isRelocatable()) { const rela_shndx = try self.addRelaShdr( ".rela.data.zig", self.zig_data_section_index.?, @@ -930,13 +958,7 @@ pub fn markDirty(self: *Elf, shdr_index: u16) void { } pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (self.base.options.emit == null) { - if (self.llvm_object) |llvm_object| { - try llvm_object.flushModule(comp, prog_node); - } - return; - } - const use_lld = build_options.have_llvm and self.base.options.use_lld; + const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; if (use_lld) { return self.linkWithLLD(comp, prog_node); } @@ -950,7 +972,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (self.llvm_object) |llvm_object| { try llvm_object.flushModule(comp, prog_node); - const use_lld = build_options.have_llvm and self.base.options.use_lld; + const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; if (use_lld) return; } @@ -959,13 +981,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node sub_prog_node.activate(); defer sub_prog_node.end(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); const target = self.base.comp.root_mod.resolved_target.result; - const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); + const link_mode = self.base.comp.config.link_mode; + const directory = self.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); @@ -973,10 +996,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node break :blk path; } } else null; - const gc_sections = self.base.options.gc_sections orelse false; + const gc_sections = self.base.gc_sections; // --verbose-link - if (self.base.options.verbose_link) try self.dumpArgv(comp); + if (self.base.comp.verbose_link) try self.dumpArgv(comp); const csu = try CsuObjects.init(arena, self.base.options, comp); const compiler_rt_path: ?[]const u8 = blk: { @@ -986,8 +1009,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }; if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); - if (self.isStaticLib()) return self.flushStaticLib(comp, module_obj_path); - if (self.isObject()) return self.flushObject(comp, module_obj_path); + if (self.base.isStaticLib()) return self.flushStaticLib(comp, module_obj_path); + if (self.base.isObject()) return self.flushObject(comp, module_obj_path); // Here we will parse input positional and library files (if referenced). // This will roughly match in any linker backend we support. @@ -1011,7 +1034,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (module_obj_path) |path| try positionals.append(.{ .path = path }); // rpaths - var rpath_table = std.StringArrayHashMap(void).init(self.base.allocator); + var rpath_table = std.StringArrayHashMap(void).init(gpa); defer rpath_table.deinit(); for (self.base.options.rpath_list) |rpath| { @@ -1019,10 +1042,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } if (self.base.options.each_lib_rpath) { - var test_path = std.ArrayList(u8).init(self.base.allocator); + var test_path = std.ArrayList(u8).init(gpa); defer test_path.deinit(); for (self.base.options.lib_dirs) |lib_dir_path| { - for (self.base.options.system_libs.keys()) |link_lib| { + for (self.base.comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; _ = try rpath_table.put(lib_dir_path, {}); @@ -1064,8 +1087,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node var system_libs = std.ArrayList(SystemLib).init(arena); - try system_libs.ensureUnusedCapacity(self.base.options.system_libs.values().len); - for (self.base.options.system_libs.values()) |lib_info| { + try system_libs.ensureUnusedCapacity(self.base.comp.system_libs.values().len); + for (self.base.comp.system_libs.values()) |lib_info| { system_libs.appendAssumeCapacity(.{ .needed = lib_info.needed, .path = lib_info.path.? }); } @@ -1127,7 +1150,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node .path = try comp.get_libc_crt_file(arena, "libc_nonshared.a"), }); } else if (target.isMusl()) { - const path = try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { + const path = try comp.get_libc_crt_file(arena, switch (link_mode) { .Static => "libc.a", .Dynamic => "libc.so", }); @@ -1224,7 +1247,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (self.entry_index == null) { const entry: ?[]const u8 = entry: { if (self.base.options.entry) |entry| break :entry entry; - if (!self.isDynLib()) break :entry "_start"; + if (!self.base.isDynLib()) break :entry "_start"; break :entry null; }; self.entry_index = if (entry) |name| self.globalByName(name) else null; @@ -1301,7 +1324,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node try self.writeAtoms(); try self.writeSyntheticSections(); - if (self.entry_index == null and self.isExe()) { + if (self.entry_index == null and self.base.isExe()) { log.debug("flushing. no_entry_point_found = true", .{}); self.error_flags.no_entry_point_found = true; } else { @@ -1531,13 +1554,15 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) /// --verbose-link output fn dumpArgv(self: *Elf, comp: *Compilation) !void { - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = self.base.comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); const target = self.base.comp.root_mod.resolved_target.result; - const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); + const link_mode = self.base.comp.config.link_mode; + const directory = self.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); @@ -1545,7 +1570,6 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { break :blk path; } } else null; - const gc_sections = self.base.options.gc_sections orelse false; const csu = try CsuObjects.init(arena, self.base.options, comp); const compiler_rt_path: ?[]const u8 = blk: { @@ -1558,20 +1582,20 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("zig"); - if (self.isStaticLib()) { + if (self.base.isStaticLib()) { try argv.append("ar"); } else { try argv.append("ld"); } - if (self.isObject()) { + if (self.base.isObject()) { try argv.append("-r"); } try argv.append("-o"); try argv.append(full_out_path); - if (self.isRelocatable()) { + if (self.base.isRelocatable()) { for (self.base.options.objects) |obj| { try argv.append(obj.path); } @@ -1591,7 +1615,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } - if (self.isDynLib()) { + if (self.base.isDynLib()) { if (self.base.options.soname) |name| { try argv.append("-soname"); try argv.append(name); @@ -1624,16 +1648,16 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } - if (self.base.options.stack_size_override) |ss| { - try argv.append("-z"); - try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{ss})); - } + try argv.appendSlice(&.{ + "-z", + try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), + }); if (self.base.options.image_base_override) |image_base| { try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); } - if (gc_sections) { + if (self.base.gc_sections) { try argv.append("--gc-sections"); } @@ -1666,11 +1690,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { if (self.isStatic()) { try argv.append("-static"); - } else if (self.isDynLib()) { + } else if (self.base.isDynLib()) { try argv.append("-shared"); } - if (self.base.options.pie and self.isExe()) { + if (self.base.options.pie and self.base.isExe()) { try argv.append("-pie"); } @@ -1741,11 +1765,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { // Shared libraries. // Worst-case, we need an --as-needed argument for every lib, as well // as one before and one after. - try argv.ensureUnusedCapacity(self.base.options.system_libs.keys().len * 2 + 2); + try argv.ensureUnusedCapacity(self.base.comp.system_libs.keys().len * 2 + 2); argv.appendAssumeCapacity("--as-needed"); var as_needed = true; - for (self.base.options.system_libs.values()) |lib_info| { + for (self.base.comp.system_libs.values()) |lib_info| { const lib_as_needed = !lib_info.needed; switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { 0b00, 0b11 => {}, @@ -1780,7 +1804,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { // libc dep if (self.base.options.link_libc) { if (self.base.options.libc_installation != null) { - const needs_grouping = self.base.options.link_mode == .Static; + const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); if (needs_grouping) try argv.append("--end-group"); @@ -1793,7 +1817,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); } else if (target.isMusl()) { - try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { + try argv.append(try comp.get_libc_crt_file(arena, switch (link_mode) { .Static => "libc.a", .Dynamic => "libc.so", })); @@ -2006,6 +2030,7 @@ fn accessLibPath( lib_name: []const u8, link_mode: ?std.builtin.LinkMode, ) !bool { + const gpa = self.base.comp.gpa; const sep = fs.path.sep_str; const target = self.base.comp.root_mod.resolved_target.result; test_path.clearRetainingCapacity(); @@ -2021,7 +2046,7 @@ fn accessLibPath( suffix, }); if (checked_paths) |cpaths| { - try cpaths.append(try self.base.allocator.dupe(u8, test_path.items)); + try cpaths.append(try gpa.dupe(u8, test_path.items)); } fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => return false, @@ -2150,7 +2175,7 @@ fn markImportsExports(self: *Elf) void { } if (file_ptr.index() == file_index) { global.flags.@"export" = true; - if (elf_file.isDynLib() and vis != .PROTECTED) { + if (elf_file.base.isDynLib() and vis != .PROTECTED) { global.flags.import = true; } } @@ -2158,7 +2183,7 @@ fn markImportsExports(self: *Elf) void { } }.mark; - if (!self.isDynLib()) { + if (!self.base.isDynLib()) { for (self.shared_objects.items) |index| { for (self.file(index).?.globals()) |global_index| { const global = self.symbol(global_index); @@ -2274,12 +2299,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = self.base.comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); + const directory = self.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. @@ -2298,16 +2324,15 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_obj = self.base.options.output_mode == .Obj; - const is_lib = self.base.options.output_mode == .Lib; - const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; - const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; + const output_mode = self.base.comp.config.output_mode; + const is_obj = output_mode == .Obj; + const is_lib = output_mode == .Lib; + const link_mode = self.base.comp.config.link_mode; + const is_dyn_lib = link_mode == .Dynamic and is_lib; + const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; const have_dynamic_linker = self.base.options.link_libc and - self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; + link_mode == .Dynamic and is_exe_or_dyn_lib; const target = self.base.comp.root_mod.resolved_target.result; - const gc_sections = self.base.options.gc_sections orelse !is_obj; - const stack_size = self.base.options.stack_size_override orelse 16777216; - const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; @@ -2354,7 +2379,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // installation sources because they are always a product of the compiler version + target information. man.hash.addOptionalBytes(self.base.options.entry); man.hash.addOptional(self.base.options.image_base_override); - man.hash.add(gc_sections); + man.hash.add(self.base.gc_sections); man.hash.addOptional(self.base.options.sort_section); man.hash.add(self.base.options.eh_frame_hdr); man.hash.add(self.base.options.emit_relocs); @@ -2362,9 +2387,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addListOfBytes(self.base.options.lib_dirs); man.hash.addListOfBytes(self.base.options.rpath_list); man.hash.add(self.base.options.each_lib_rpath); - if (self.base.options.output_mode == .Exe) { - man.hash.add(stack_size); - man.hash.add(self.base.options.build_id); + if (output_mode == .Exe) { + man.hash.add(self.base.stack_size); + man.hash.add(self.base.build_id); } man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys()); man.hash.add(self.base.options.skip_linker_dependencies); @@ -2390,9 +2415,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } man.hash.addOptionalBytes(self.base.options.soname); man.hash.addOptional(self.base.options.version); - try link.hashAddSystemLibs(&man, self.base.options.system_libs); + try link.hashAddSystemLibs(&man, self.base.comp.system_libs); man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys()); - man.hash.add(allow_shlib_undefined); + man.hash.add(self.base.allow_shlib_undefined); man.hash.add(self.base.options.bind_global_refs_locally); man.hash.add(self.base.options.compress_debug_sections); man.hash.add(self.base.options.tsan); @@ -2432,7 +2457,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // copy when generating relocatables. Normally, we would expect `lld -r` to work. // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails // before even generating the relocatable. - if (self.base.options.output_mode == .Obj and + if (output_mode == .Obj and (self.base.options.lto or target.isBpfFreestanding())) { // In this case we must do a simple file copy @@ -2459,7 +2484,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } else { // Create an LLD command line and invoke it. - var argv = std.ArrayList([]const u8).init(self.base.allocator); + var argv = std.ArrayList([]const u8).init(gpa); defer argv.deinit(); // We will invoke ourselves as a child process to gain access to LLD. // This is necessary because LLD does not behave properly as a library - @@ -2503,15 +2528,17 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .both => {}, // this is the default } - if (self.base.options.output_mode == .Exe) { - try argv.append("-z"); - try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size})); + if (output_mode == .Exe) { + try argv.appendSlice(&.{ + "-z", + try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), + }); - switch (self.base.options.build_id) { + switch (self.base.build_id) { .none => {}, .fast, .uuid, .sha1, .md5 => { try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{ - @tagName(self.base.options.build_id), + @tagName(self.base.build_id), })); }, .hexstring => |hs| { @@ -2536,7 +2563,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(arg); } - if (gc_sections) { + if (self.base.gc_sections) { try argv.append("--gc-sections"); } @@ -2615,7 +2642,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(arg); } - if (self.base.options.link_mode == .Static) { + if (link_mode == .Static) { if (target.cpu.arch.isArmOrThumb()) { try argv.append("-Bstatic"); } else { @@ -2625,7 +2652,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-shared"); } - if (self.base.options.pie and self.base.options.output_mode == .Exe) { + if (self.base.options.pie and output_mode == .Exe) { try argv.append("-pie"); } @@ -2648,7 +2675,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v if (csu.crtbegin) |v| try argv.append(v); // rpaths - var rpath_table = std.StringHashMap(void).init(self.base.allocator); + var rpath_table = std.StringHashMap(void).init(gpa); defer rpath_table.deinit(); for (self.base.options.rpath_list) |rpath| { if ((try rpath_table.fetchPut(rpath, {})) == null) { @@ -2664,7 +2691,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v if (self.base.options.each_lib_rpath) { var test_path = std.ArrayList(u8).init(arena); for (self.base.options.lib_dirs) |lib_dir_path| { - for (self.base.options.system_libs.keys()) |link_lib| { + for (self.base.comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) { @@ -2763,8 +2790,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // Shared libraries. if (is_exe_or_dyn_lib) { - const system_libs = self.base.options.system_libs.keys(); - const system_libs_values = self.base.options.system_libs.values(); + const system_libs = self.base.comp.system_libs.keys(); + const system_libs_values = self.base.comp.system_libs.values(); // Worst-case, we need an --as-needed argument for every lib, as well // as one before and one after. @@ -2813,7 +2840,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v self.error_flags.missing_libc = false; if (self.base.options.link_libc) { if (self.base.options.libc_installation != null) { - const needs_grouping = self.base.options.link_mode == .Static; + const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); if (needs_grouping) try argv.append("--end-group"); @@ -2826,7 +2853,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); } else if (target.isMusl()) { - try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { + try argv.append(try comp.get_libc_crt_file(arena, switch (link_mode) { .Static => "libc.a", .Dynamic => "libc.so", })); @@ -2847,7 +2874,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v if (csu.crtend) |v| try argv.append(v); if (csu.crtn) |v| try argv.append(v); - if (allow_shlib_undefined) { + if (self.base.allow_shlib_undefined) { try argv.append("--allow-shlib-undefined"); } @@ -2861,7 +2888,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-Bsymbolic"); } - if (self.base.options.verbose_link) { + if (self.base.comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } @@ -3087,10 +3114,12 @@ fn writeElfHeader(self: *Elf) !void { assert(index == 16); - const elf_type: elf.ET = switch (self.base.options.output_mode) { + const output_mode = self.base.comp.config.output_mode; + const link_mode = self.base.comp.config.link_mode; + const elf_type: elf.ET = switch (output_mode) { .Exe => if (self.base.options.pie) .DYN else .EXEC, .Obj => .REL, - .Lib => switch (self.base.options.link_mode) { + .Lib => switch (link_mode) { .Static => @as(elf.ET, .REL), .Dynamic => .DYN, }, @@ -3216,7 +3245,6 @@ pub fn updateExports( @panic("Attempted to compile for object format that was disabled by build configuration"); } if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - if (self.base.options.emit == null) return; return self.zigObjectPtr().?.updateExports(self, mod, exported, exports); } @@ -3280,6 +3308,8 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { } fn allocateLinkerDefinedSymbols(self: *Elf) void { + const link_mode = self.base.comp.config.link_mode; + // _DYNAMIC if (self.dynamic_section_index) |shndx| { const shdr = &self.shdrs.items[shndx]; @@ -3362,7 +3392,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { // __rela_iplt_start, __rela_iplt_end if (self.rela_dyn_section_index) |shndx| blk: { - if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk; + if (link_mode != .Static or self.base.options.pie) break :blk; const shdr = &self.shdrs.items[shndx]; const end_addr = shdr.sh_addr + shdr.sh_size; const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); @@ -3531,7 +3561,7 @@ fn initSyntheticSections(self: *Elf) !void { }); } - if (self.isDynLib() or self.shared_objects.items.len > 0 or self.base.options.pie) { + if (self.base.isDynLib() or self.shared_objects.items.len > 0 or self.base.options.pie) { self.dynstrtab_section_index = try self.addSection(.{ .name = ".dynstr", .flags = elf.SHF_ALLOC, @@ -3716,7 +3746,7 @@ fn initSpecialPhdrs(self: *Elf) !void { self.phdr_gnu_stack_index = try self.addPhdr(.{ .type = elf.PT_GNU_STACK, .flags = elf.PF_W | elf.PF_R, - .memsz = self.base.options.stack_size_override orelse 0, + .memsz = self.base.stack_size, .@"align" = 1, }); @@ -3822,7 +3852,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { try self.dynamic.addNeeded(shared_object, self); } - if (self.isDynLib()) { + if (self.base.isDynLib()) { if (self.base.options.soname) |soname| { try self.dynamic.setSoname(soname, self); } @@ -3837,8 +3867,9 @@ fn sortDynamicSymtab(self: *Elf) void { } fn setVersionSymtab(self: *Elf) !void { + const gpa = self.base.comp.gpa; if (self.versym_section_index == null) return; - try self.versym.resize(self.base.allocator, self.dynsym.count()); + try self.versym.resize(gpa, self.dynsym.count()); self.versym.items[0] = elf.VER_NDX_LOCAL; for (self.dynsym.entries.items, 1..) |entry, i| { const sym = self.symbol(entry.symbol_index); @@ -5597,38 +5628,14 @@ const CsuObjects = struct { }; pub fn calcImageBase(self: Elf) u64 { - if (self.isDynLib()) return 0; - if (self.isExe() and self.base.options.pie) return 0; + if (self.base.isDynLib()) return 0; + if (self.base.isExe() and self.base.options.pie) return 0; return self.base.options.image_base_override orelse switch (self.ptr_width) { .p32 => 0x1000, .p64 => 0x1000000, }; } -pub fn isStatic(self: Elf) bool { - return self.base.options.link_mode == .Static; -} - -pub fn isObject(self: Elf) bool { - return self.base.options.output_mode == .Obj; -} - -pub fn isExe(self: Elf) bool { - return self.base.options.output_mode == .Exe; -} - -pub fn isStaticLib(self: Elf) bool { - return self.base.options.output_mode == .Lib and self.isStatic(); -} - -pub fn isRelocatable(self: Elf) bool { - return self.isObject() or self.isStaticLib(); -} - -pub fn isDynLib(self: Elf) bool { - return self.base.options.output_mode == .Lib and !self.isStatic(); -} - pub fn isZigSection(self: Elf, shndx: u16) bool { inline for (&[_]?u16{ self.zig_text_section_index, @@ -5668,8 +5675,9 @@ fn addPhdr(self: *Elf, opts: struct { filesz: u64 = 0, memsz: u64 = 0, }) error{OutOfMemory}!u16 { + const gpa = self.base.comp.gpa; const index = @as(u16, @intCast(self.phdrs.items.len)); - try self.phdrs.append(self.base.allocator, .{ + try self.phdrs.append(gpa, .{ .p_type = opts.type, .p_flags = opts.flags, .p_offset = opts.offset, @@ -5818,8 +5826,9 @@ pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom { } pub fn addAtom(self: *Elf) !Atom.Index { + const gpa = self.base.comp.gpa; const index = @as(Atom.Index, @intCast(self.atoms.items.len)); - const atom_ptr = try self.atoms.addOne(self.base.allocator); + const atom_ptr = try self.atoms.addOne(gpa); atom_ptr.* = .{ .atom_index = index }; return index; } @@ -5841,7 +5850,8 @@ pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol { } pub fn addSymbol(self: *Elf) !Symbol.Index { - try self.symbols.ensureUnusedCapacity(self.base.allocator, 1); + const gpa = self.base.comp.gpa; + try self.symbols.ensureUnusedCapacity(gpa, 1); const index = blk: { if (self.symbols_free_list.popOrNull()) |index| { log.debug(" (reusing symbol index {d})", .{index}); @@ -5858,8 +5868,9 @@ pub fn addSymbol(self: *Elf) !Symbol.Index { } pub fn addSymbolExtra(self: *Elf, extra: Symbol.Extra) !u32 { + const gpa = self.base.comp.gpa; const fields = @typeInfo(Symbol.Extra).Struct.fields; - try self.symbols_extra.ensureUnusedCapacity(self.base.allocator, fields.len); + try self.symbols_extra.ensureUnusedCapacity(gpa, fields.len); return self.addSymbolExtraAssumeCapacity(extra); } @@ -5959,8 +5970,9 @@ pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateC } pub fn addComdatGroup(self: *Elf) !ComdatGroup.Index { + const gpa = self.base.comp.gpa; const index = @as(ComdatGroup.Index, @intCast(self.comdat_groups.items.len)); - _ = try self.comdat_groups.addOne(self.base.allocator); + _ = try self.comdat_groups.addOne(gpa); return index; } @@ -6023,14 +6035,16 @@ const ErrorWithNotes = struct { }; pub fn addErrorWithNotes(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { - try self.misc_errors.ensureUnusedCapacity(self.base.allocator, 1); + const gpa = self.base.comp.gpa; + try self.misc_errors.ensureUnusedCapacity(gpa, 1); return self.addErrorWithNotesAssumeCapacity(note_count); } fn addErrorWithNotesAssumeCapacity(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { + const gpa = self.base.comp.gpa; const index = self.misc_errors.items.len; const err = self.misc_errors.addOneAssumeCapacity(); - err.* = .{ .msg = undefined, .notes = try self.base.allocator.alloc(link.File.ErrorMsg, note_count) }; + err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; return .{ .index = index }; } @@ -6040,9 +6054,10 @@ pub fn getShString(self: Elf, off: u32) [:0]const u8 { } pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { + const gpa = self.base.comp.gpa; const off = @as(u32, @intCast(self.shstrtab.items.len)); - try self.shstrtab.ensureUnusedCapacity(self.base.allocator, name.len + 1); - self.shstrtab.writer(self.base.allocator).print("{s}\x00", .{name}) catch unreachable; + try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1); + self.shstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; return off; } @@ -6052,9 +6067,10 @@ pub fn getDynString(self: Elf, off: u32) [:0]const u8 { } pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { + const gpa = self.base.comp.gpa; const off = @as(u32, @intCast(self.dynstrtab.items.len)); - try self.dynstrtab.ensureUnusedCapacity(self.base.allocator, name.len + 1); - self.dynstrtab.writer(self.base.allocator).print("{s}\x00", .{name}) catch unreachable; + try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1); + self.dynstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; return off; } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 7a1fa2143577..15ae3bb94301 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -76,7 +76,7 @@ pub const symbol_mask: u32 = 0x7fffffff; pub const SHN_ATOM: u16 = 0x100; pub fn init(self: *ZigObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; try self.atoms.append(gpa, 0); // null input section try self.relocs.append(gpa, .{}); // null relocs section @@ -96,7 +96,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { esym.st_shndx = elf.SHN_ABS; symbol_ptr.esym_index = esym_index; - if (!elf_file.base.options.strip) { + if (elf_file.base.debug_format != .strip) { self.dwarf = Dwarf.init(gpa, &elf_file.base, .dwarf32); } } @@ -155,13 +155,13 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void { // Handle any lazy symbols that were emitted by incremental compilation. if (self.lazy_syms.getPtr(.none)) |metadata| { - const module = elf_file.base.options.module.?; + const zcu = elf_file.base.comp.module.?; // Most lazy symbols can be updated on first use, but // anyerror needs to wait for everything to be flushed. if (metadata.text_state != .unused) self.updateLazySymbol( elf_file, - link.File.LazySymbol.initDecl(.code, null, module), + link.File.LazySymbol.initDecl(.code, null, zcu), metadata.text_symbol_index, ) catch |err| return switch (err) { error.CodegenFail => error.FlushFailure, @@ -169,7 +169,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void { }; if (metadata.rodata_state != .unused) self.updateLazySymbol( elf_file, - link.File.LazySymbol.initDecl(.const_data, null, module), + link.File.LazySymbol.initDecl(.const_data, null, zcu), metadata.rodata_symbol_index, ) catch |err| return switch (err) { error.CodegenFail => error.FlushFailure, @@ -182,7 +182,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void { } if (self.dwarf) |*dw| { - try dw.flushModule(elf_file.base.options.module.?); + const zcu = elf_file.base.comp.module.?; + try dw.flushModule(zcu); // TODO I need to re-think how to handle ZigObject's debug sections AND debug sections // extracted from input object files correctly. @@ -195,7 +196,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void { const text_shdr = elf_file.shdrs.items[elf_file.zig_text_section_index.?]; const low_pc = text_shdr.sh_addr; const high_pc = text_shdr.sh_addr + text_shdr.sh_size; - try dw.writeDbgInfoHeader(elf_file.base.options.module.?, low_pc, high_pc); + try dw.writeDbgInfoHeader(zcu, low_pc, high_pc); self.debug_info_header_dirty = false; } @@ -268,7 +269,7 @@ pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index { } pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const atom_index = try elf_file.addAtom(); const symbol_index = try elf_file.addSymbol(); const esym_index = try self.addLocalEsym(gpa); @@ -411,6 +412,7 @@ pub fn allocateTlvAtoms(self: ZigObject, elf_file: *Elf) void { } pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { + const gpa = elf_file.base.comp.gpa; for (self.atoms.items) |atom_index| { const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; @@ -421,7 +423,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { // Perhaps it would make sense to save the code until flushModule where we // would free all of generated code? const code = try self.codeAlloc(elf_file, atom_index); - defer elf_file.base.allocator.free(code); + defer gpa.free(code); try atom.scanRelocs(elf_file, code, undefs); } else try atom.scanRelocs(elf_file, null, undefs); } @@ -447,7 +449,7 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void { /// We need this so that we can write to an archive. /// TODO implement writing ZigObject data directly to a buffer instead. pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const shsize: u64 = switch (elf_file.ptr_width) { .p32 => @sizeOf(elf.Elf32_Shdr), .p64 => @sizeOf(elf.Elf64_Shdr), @@ -465,7 +467,7 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { } pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len); @@ -508,7 +510,7 @@ pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void { const out_shdr = elf_file.shdrs.items[out_shndx]; if (out_shdr.sh_type == elf.SHT_NOBITS) continue; - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const sec = elf_file.output_rela_sections.getPtr(out_shndx).?; try sec.atom_list.append(gpa, atom_index); } @@ -602,7 +604,7 @@ pub fn asFile(self: *ZigObject) File { /// Returns atom's code. /// Caller owns the memory. pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const atom = elf_file.atom(atom_index).?; assert(atom.file_index == self.index); const shdr = &elf_file.shdrs.items[atom.outputShndx().?]; @@ -668,8 +670,8 @@ pub fn lowerAnonDecl( explicit_alignment: InternPool.Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const decl_alignment = switch (explicit_alignment) { .none => ty.abiAlignment(mod), @@ -716,8 +718,8 @@ pub fn getOrCreateMetadataForLazySymbol( elf_file: *Elf, lazy_sym: link.File.LazySymbol, ) !Symbol.Index { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const gop = try self.lazy_syms.getOrPut(gpa, lazy_sym.getDecl(mod)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -752,25 +754,28 @@ pub fn getOrCreateMetadataForLazySymbol( } fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.DeclIndex) void { + const gpa = elf_file.base.comp.gpa; const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return; for (unnamed_consts.items) |sym_index| { self.freeDeclMetadata(elf_file, sym_index); } - unnamed_consts.clearAndFree(elf_file.base.allocator); + unnamed_consts.clearAndFree(gpa); } fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void { _ = self; + const gpa = elf_file.base.comp.gpa; const sym = elf_file.symbol(sym_index); sym.atom(elf_file).?.free(elf_file); log.debug("adding %{d} to local symbols free list", .{sym_index}); - elf_file.symbols_free_list.append(elf_file.base.allocator, sym_index) catch {}; + elf_file.symbols_free_list.append(gpa, sym_index) catch {}; elf_file.symbols.items[sym_index] = .{}; // TODO free GOT entry here } pub fn freeDecl(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.DeclIndex) void { - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("freeDecl {*}", .{decl}); @@ -780,7 +785,7 @@ pub fn freeDecl(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.DeclInd const sym_index = kv.value.symbol_index; self.freeDeclMetadata(elf_file, sym_index); self.freeUnnamedConsts(elf_file, decl_index); - kv.value.exports.deinit(elf_file.base.allocator); + kv.value.exports.deinit(gpa); } if (self.dwarf) |*dw| { @@ -793,15 +798,16 @@ pub fn getOrCreateMetadataForDecl( elf_file: *Elf, decl_index: InternPool.DeclIndex, ) !Symbol.Index { - const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index); + const gpa = elf_file.base.comp.gpa; + const gop = try self.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { - const single_threaded = elf_file.base.options.single_threaded; + const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; const symbol_index = try self.addAtom(elf_file); - const mod = elf_file.base.options.module.?; + const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); const sym = elf_file.symbol(symbol_index); if (decl.getOwnedVariable(mod)) |variable| { - if (variable.is_threadlocal and !single_threaded) { + if (variable.is_threadlocal and any_non_single_threaded) { sym.flags.is_tls = true; } } @@ -820,13 +826,13 @@ fn getDeclShdrIndex( code: []const u8, ) error{OutOfMemory}!u16 { _ = self; - const mod = elf_file.base.options.module.?; - const single_threaded = elf_file.base.options.single_threaded; + const mod = elf_file.base.comp.module.?; + const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; const shdr_index = switch (decl.ty.zigTypeTag(mod)) { .Fn => elf_file.zig_text_section_index.?, else => blk: { if (decl.getOwnedVariable(mod)) |variable| { - if (variable.is_threadlocal and !single_threaded) { + if (variable.is_threadlocal and any_non_single_threaded) { const is_all_zeroes = for (code) |byte| { if (byte != 0) break false; } else true; @@ -846,9 +852,12 @@ fn getDeclShdrIndex( } if (variable.is_const) break :blk elf_file.zig_data_rel_ro_section_index.?; if (Value.fromInterned(variable.init).isUndefDeep(mod)) { - const mode = elf_file.base.options.optimize_mode; - if (mode == .Debug or mode == .ReleaseSafe) break :blk elf_file.zig_data_section_index.?; - break :blk elf_file.zig_bss_section_index.?; + // TODO: get the optimize_mode from the Module that owns the decl instead + // of using the root module here. + break :blk switch (elf_file.base.comp.root_mod.optimize_mode) { + .Debug, .ReleaseSafe => elf_file.zig_data_section_index.?, + .ReleaseFast, .ReleaseSmall => elf_file.zig_bss_section_index.?, + }; } // TODO I blatantly copied the logic from the Wasm linker, but is there a less // intrusive check for all zeroes than this? @@ -873,8 +882,8 @@ fn updateDeclCode( code: []const u8, stt_bits: u8, ) !void { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); @@ -971,8 +980,8 @@ fn updateTlv( shndx: u16, code: []const u8, ) !void { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); @@ -1026,6 +1035,7 @@ pub fn updateFunc( const tracy = trace(@src()); defer tracy.end(); + const gpa = elf_file.base.comp.gpa; const func = mod.funcInfo(func_index); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); @@ -1034,7 +1044,7 @@ pub fn updateFunc( self.freeUnnamedConsts(elf_file, decl_index); elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); - var code_buffer = std.ArrayList(u8).init(elf_file.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null; @@ -1117,7 +1127,8 @@ pub fn updateDecl( const sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); elf_file.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); - var code_buffer = std.ArrayList(u8).init(elf_file.base.allocator); + const gpa = elf_file.base.comp.gpa; + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null; @@ -1179,8 +1190,8 @@ fn updateLazySymbol( sym: link.File.LazySymbol, symbol_index: Symbol.Index, ) !void { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; var required_alignment: InternPool.Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1261,8 +1272,8 @@ pub fn lowerUnnamedConst( typed_value: TypedValue, decl_index: InternPool.DeclIndex, ) !u32 { - const gpa = elf_file.base.allocator; - const mod = elf_file.base.options.module.?; + const gpa = elf_file.base.comp.gpa; + const mod = elf_file.base.comp.module.?; const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; @@ -1308,7 +1319,7 @@ fn lowerConst( output_section_index: u16, src_loc: Module.SrcLoc, ) !LowerConstResult { - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); @@ -1364,7 +1375,7 @@ pub fn updateExports( const tracy = trace(@src()); defer tracy.end(); - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { _ = try self.getOrCreateMetadataForDecl(elf_file, decl_index); @@ -1467,7 +1478,7 @@ pub fn deleteDeclExport( name: InternPool.NullTerminatedString, ) void { const metadata = self.decls.getPtr(decl_index) orelse return; - const mod = elf_file.base.options.module.?; + const mod = elf_file.base.comp.module.?; const exp_name = mod.intern_pool.stringToSlice(name); const esym_index = metadata.@"export"(self, exp_name) orelse return; log.debug("deleting export '{s}'", .{exp_name}); @@ -1485,7 +1496,7 @@ pub fn deleteDeclExport( pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { _ = lib_name; - const gpa = elf_file.base.allocator; + const gpa = elf_file.base.comp.gpa; const off = try self.strtab.insert(gpa, name); const lookup_gop = try self.globals_lookup.getOrPut(gpa, off); if (!lookup_gop.found_existing) { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index f61e78c2331a..3af98aa42af0 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -144,6 +144,35 @@ tlv_table: TlvSymbolTable = .{}, hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, darwin_sdk_layout: ?SdkLayout, +/// Size of the __PAGEZERO segment. +pagezero_vmsize: u64, +/// Minimum space for future expansion of the load commands. +headerpad_size: u32, +/// Set enough space as if all paths were MATPATHLEN. +headerpad_max_install_names: bool, +/// Remove dylibs that are unreachable by the entry point or exported symbols. +dead_strip_dylibs: bool, +frameworks: []const Framework, +/// Install name for the dylib. +/// TODO: unify with soname +install_name: ?[]const u8, +/// Path to entitlements file. +entitlements: ?[]const u8, + +/// When adding a new field, remember to update `hashAddFrameworks`. +pub const Framework = struct { + needed: bool = false, + weak: bool = false, + path: []const u8, +}; + +pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { + for (hm) |value| { + man.hash.add(value.needed); + man.hash.add(value.weak); + _ = try man.addFile(value.path, null); + } +} /// The filesystem layout of darwin SDK elements. pub const SdkLayout = enum { @@ -156,12 +185,14 @@ pub const SdkLayout = enum { pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { if (build_options.only_c) unreachable; const target = options.comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; assert(target.ofmt == .macho); const gpa = options.comp.gpa; const emit = options.emit; const mode: Mode = mode: { - if (options.use_llvm or options.module == null or options.cache_mode == .whole) + if (use_llvm or options.module == null or options.cache_mode == .whole) break :mode .zld; break :mode .incremental; }; @@ -192,7 +223,11 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { const file = try emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode( + use_lld, + options.comp.config.output_mode, + options.comp.config.link_mode, + ), }); self.base.file = file; @@ -242,21 +277,37 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { const self = try arena.create(MachO); + const optimize_mode = options.comp.root_mod.optimize_mode; + const use_llvm = options.comp.config.use_llvm; self.* = .{ .base = .{ .tag = .macho, .comp = options.comp, .emit = options.emit, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, - .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole) + .mode = if (use_llvm or options.module == null or options.cache_mode == .whole) .zld else .incremental, + .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, + .headerpad_size = options.headerpad_size orelse default_headerpad_size, + .headerpad_max_install_names = options.headerpad_max_install_names, + .dead_strip_dylibs = options.dead_strip_dylibs, }; - if (options.use_llvm and options.module != null) { + if (use_llvm and options.module != null) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -267,8 +318,9 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { const gpa = self.base.comp.gpa; + const output_mode = self.base.comp.config.output_mode; - if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) { + if (output_mode == .Lib and self.base.options.link_mode == .Static) { if (build_options.have_llvm) { return self.base.linkAsArchive(comp, prog_node); } else { @@ -303,6 +355,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No sub_prog_node.activate(); defer sub_prog_node.end(); + const output_mode = self.base.comp.config.output_mode; const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; if (self.lazy_syms.getPtr(.none)) |metadata| { @@ -335,7 +388,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No } var libs = std.StringArrayHashMap(link.SystemLib).init(arena); - try self.resolveLibSystem(arena, comp, &.{}, &libs); + try self.resolveLibSystem(arena, comp, &libs); const id_symlink_basename = "link.id"; @@ -446,7 +499,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try self.createDyldPrivateAtom(); try self.writeStubHelperPreamble(); - if (self.base.options.output_mode == .Exe and self.getEntryPoint() != null) { + if (output_mode == .Exe and self.getEntryPoint() != null) { const global = self.getEntryPoint().?; if (self.getSymbol(global).undf()) { // We do one additional check here in case the entry point was found in one of the dylibs. @@ -517,8 +570,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No // The most important here is to have the correct vm and filesize of the __LINKEDIT segment // where the code signature goes into. var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch)); - codesig.code_directory.ident = self.base.options.emit.?.sub_path; - if (self.base.options.entitlements) |path| { + codesig.code_directory.ident = self.base.emit.sub_path; + if (self.entitlements) |path| { try codesig.addEntitlements(gpa, path); } try self.writeCodeSignaturePadding(&codesig); @@ -536,7 +589,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try lc_writer.writeStruct(self.dysymtab_cmd); try load_commands.writeDylinkerLC(lc_writer); - switch (self.base.options.output_mode) { + switch (output_mode) { .Exe => blk: { const seg_id = self.header_segment_cmd_index.?; const seg = self.segments.items[seg_id]; @@ -552,7 +605,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try lc_writer.writeStruct(macho.entry_point_command{ .entryoff = @as(u32, @intCast(addr - seg.vmaddr)), - .stacksize = self.base.options.stack_size_override orelse 0, + .stacksize = self.base.stack_size, }); }, .Lib => if (self.base.options.link_mode == .Dynamic) { @@ -591,7 +644,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No if (codesig) |*csig| { try self.writeCodeSignature(comp, csig); // code signing always comes last - const emit = self.base.options.emit.?; + const emit = self.base.emit; try invalidateKernelCache(emit.directory.handle, emit.sub_path); } @@ -642,34 +695,20 @@ pub fn resolveLibSystem( self: *MachO, arena: Allocator, comp: *Compilation, - search_dirs: []const []const u8, out_libs: anytype, ) !void { - const gpa = self.base.comp.gpa; - var tmp_arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer tmp_arena_allocator.deinit(); - const tmp_arena = tmp_arena_allocator.allocator(); - - var test_path = std.ArrayList(u8).init(tmp_arena); - var checked_paths = std.ArrayList([]const u8).init(tmp_arena); + var test_path = std.ArrayList(u8).init(arena); + var checked_paths = std.ArrayList([]const u8).init(arena); success: { - for (search_dirs) |dir| if (try accessLibPath( - tmp_arena, - &test_path, - &checked_paths, - dir, - "libSystem", - )) break :success; - if (self.base.options.darwin_sdk_layout) |sdk_layout| switch (sdk_layout) { .sdk => { - const dir = try fs.path.join(tmp_arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" }); - if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success; + const dir = try fs.path.join(arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" }); + if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success; }, .vendored => { - const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" }); - if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success; + const dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "darwin" }); + if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success; }, }; @@ -1082,7 +1121,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts, ctx: *ParseErr try self.dylibs.append(gpa, dylib); const should_link_dylib_even_if_unreachable = blk: { - if (self.base.options.dead_strip_dylibs and !dylib_options.needed) break :blk false; + if (self.dead_strip_dylibs and !dylib_options.needed) break :blk false; break :blk !(dylib_options.dependent or self.referenced_dylibs.contains(gop.value_ptr.*)); }; @@ -1597,7 +1636,8 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S } pub fn createMhExecuteHeaderSymbol(self: *MachO) !void { - if (self.base.options.output_mode != .Exe) return; + const output_mode = self.base.comp.config.output_mode; + if (output_mode != .Exe) return; const gpa = self.base.comp.gpa; const sym_index = try self.allocateSymbol(); @@ -1647,10 +1687,11 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { } pub fn resolveSymbols(self: *MachO) !void { + const output_mode = self.base.comp.config.output_mode; // We add the specified entrypoint as the first unresolved symbols so that // we search for it in libraries should there be no object files specified // on the linker line. - if (self.base.options.output_mode == .Exe) { + if (output_mode == .Exe) { const entry_name = self.base.options.entry orelse load_commands.default_entry_point; _ = try self.addUndefined(entry_name, .{}); } @@ -1867,9 +1908,10 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { } fn resolveSymbolsAtLoading(self: *MachO) !void { - const is_lib = self.base.options.output_mode == .Lib; + const output_mode = self.base.comp.config.output_mode; + const is_lib = output_mode == .Lib; const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; - const allow_undef = is_dyn_lib and (self.base.options.allow_shlib_undefined orelse false); + const allow_undef = is_dyn_lib and self.base.allow_shlib_undefined; var next_sym: usize = 0; while (next_sym < self.unresolved.count()) { @@ -2674,12 +2716,12 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 { const val = decl.val; const mod = self.base.options.module.?; const zig_ty = ty.zigTypeTag(mod); - const mode = self.base.options.optimize_mode; - const single_threaded = self.base.options.single_threaded; + const any_non_single_threaded = self.base.comp.config.any_non_single_threaded; + const optimize_mode = self.base.comp.root_mod.optimize_mode; const sect_id: u8 = blk: { // TODO finish and audit this function if (val.isUndefDeep(mod)) { - if (mode == .ReleaseFast or mode == .ReleaseSmall) { + if (optimize_mode == .ReleaseFast or optimize_mode == .ReleaseSmall) { @panic("TODO __DATA,__bss"); } else { break :blk self.data_section_index.?; @@ -2687,7 +2729,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 { } if (val.getVariable(mod)) |variable| { - if (variable.is_threadlocal and !single_threaded) { + if (variable.is_threadlocal and any_non_single_threaded) { break :blk self.thread_data_section_index.?; } break :blk self.data_section_index.?; @@ -2796,8 +2838,6 @@ pub fn updateExports( if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - if (self.base.options.emit == null) return; - const tracy = trace(@src()); defer tracy.end(); @@ -3093,7 +3133,7 @@ fn populateMissingMetadata(self: *MachO) !void { if (self.header_segment_cmd_index == null) { // The first __TEXT segment is immovable and covers MachO header and load commands. self.header_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); - const ideal_size = @max(self.base.options.headerpad_size orelse 0, default_headerpad_size); + const ideal_size = self.headerpad_size; const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), getPageSize(cpu_arch)); log.debug("found __TEXT segment (header-only) free space 0x{x} to 0x{x}", .{ 0, needed_size }); @@ -3222,13 +3262,13 @@ fn populateMissingMetadata(self: *MachO) !void { } fn calcPagezeroSize(self: *MachO) u64 { - const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize; + const output_mode = self.base.comp.config.output_mode; const page_size = getPageSize(self.base.options.target.cpu.arch); - const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, page_size); - if (self.base.options.output_mode == .Lib) return 0; + const aligned_pagezero_vmsize = mem.alignBackward(u64, self.pagezero_vmsize, page_size); + if (output_mode == .Lib) return 0; if (aligned_pagezero_vmsize == 0) return 0; - if (aligned_pagezero_vmsize != pagezero_vmsize) { - log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize}); + if (aligned_pagezero_vmsize != self.pagezero_vmsize) { + log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{self.pagezero_vmsize}); log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize}); } return aligned_pagezero_vmsize; @@ -4685,6 +4725,7 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { } pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *CodeSignature) !void { + const output_mode = self.base.comp.config.output_mode; const seg_id = self.header_segment_cmd_index.?; const seg = self.segments.items[seg_id]; const offset = self.codesig_cmd.dataoff; @@ -4698,7 +4739,7 @@ pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *Cod .exec_seg_base = seg.fileoff, .exec_seg_limit = seg.filesize, .file_size = offset, - .output_mode = self.base.options.output_mode, + .output_mode = output_mode, }, buffer.writer()); assert(buffer.items.len == code_sig.size()); @@ -4712,6 +4753,8 @@ pub fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *Cod /// Writes Mach-O file header. pub fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void { + const output_mode = self.base.comp.config.output_mode; + var header: macho.mach_header_64 = .{}; header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL; @@ -4727,7 +4770,7 @@ pub fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void { else => unreachable, } - switch (self.base.options.output_mode) { + switch (output_mode) { .Exe => { header.filetype = macho.MH_EXECUTE; }, diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index e627b91f11da..41c387c2444d 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -6,20 +6,21 @@ pub fn linkWithZld( const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.allocator; - const options = &macho_file.base.options; - const target = options.target; + const gpa = macho_file.base.comp.gpa; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const emit = macho_file.base.emit; var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const directory = options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{options.emit.?.sub_path}); + const directory = emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{emit.?.sub_path}); + const opt_zcu = macho_file.base.comp.module; // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (options.module != null) blk: { + const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { try macho_file.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -34,22 +35,24 @@ pub fn linkWithZld( sub_prog_node.context.refresh(); defer sub_prog_node.end(); + const output_mode = macho_file.base.comp.config.output_mode; + const link_mode = macho_file.base.comp.config.link_mode; const cpu_arch = target.cpu.arch; - const is_lib = options.output_mode == .Lib; - const is_dyn_lib = options.link_mode == .Dynamic and is_lib; - const is_exe_or_dyn_lib = is_dyn_lib or options.output_mode == .Exe; - const stack_size = options.stack_size_override orelse 0; - const is_debug_build = options.optimize_mode == .Debug; - const gc_sections = options.gc_sections orelse !is_debug_build; + const is_lib = output_mode == .Lib; + const is_dyn_lib = link_mode == .Dynamic and is_lib; + const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; + const stack_size = macho_file.base.stack_size; const id_symlink_basename = "zld.id"; var man: Cache.Manifest = undefined; - defer if (!options.disable_lld_caching) man.deinit(); + defer if (!macho_file.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - if (!options.disable_lld_caching) { + const objects = macho_file.base.comp.objects; + + if (!macho_file.base.disable_lld_caching) { man = comp.cache_parent.obtain(); // We are about to obtain this lock, so here we give other processes a chance first. @@ -57,7 +60,7 @@ pub fn linkWithZld( comptime assert(Compilation.link_hash_implementation_version == 10); - for (options.objects) |obj| { + for (objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); } @@ -68,24 +71,22 @@ pub fn linkWithZld( // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.add(stack_size); - man.hash.addOptional(options.pagezero_size); - man.hash.addOptional(options.headerpad_size); - man.hash.add(options.headerpad_max_install_names); - man.hash.add(gc_sections); - man.hash.add(options.dead_strip_dylibs); - man.hash.add(options.strip); - man.hash.addListOfBytes(options.lib_dirs); - man.hash.addListOfBytes(options.framework_dirs); - try link.hashAddFrameworks(&man, options.frameworks); - man.hash.addListOfBytes(options.rpath_list); + man.hash.addOptional(macho_file.pagezero_vmsize); + man.hash.addOptional(macho_file.headerpad_size); + man.hash.add(macho_file.headerpad_max_install_names); + man.hash.add(macho_file.base.gc_sections); + man.hash.add(macho_file.dead_strip_dylibs); + man.hash.add(macho_file.base.comp.root_mod.strip); + try MachO.hashAddFrameworks(&man, macho_file.frameworks); + man.hash.addListOfBytes(macho_file.rpath_list); if (is_dyn_lib) { - man.hash.addOptionalBytes(options.install_name); - man.hash.addOptional(options.version); + man.hash.addOptionalBytes(macho_file.install_name); + man.hash.addOptional(comp.version); } - try link.hashAddSystemLibs(&man, options.system_libs); - man.hash.addOptionalBytes(options.sysroot); - man.hash.addListOfBytes(options.force_undefined_symbols.keys()); - try man.addOptionalFile(options.entitlements); + try link.hashAddSystemLibs(&man, comp.system_libs); + man.hash.addOptionalBytes(comp.sysroot); + man.hash.addListOfBytes(macho_file.base.force_undefined_symbols.keys()); + try man.addOptionalFile(macho_file.entitlements); // We don't actually care whether it's a cache hit or miss; we just // need the digest and the lock. @@ -125,13 +126,13 @@ pub fn linkWithZld( }; } - if (options.output_mode == .Obj) { + if (output_mode == .Obj) { // LLD's MachO driver does not support the equivalent of `-r` so we do a simple file copy // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { - if (options.objects.len != 0) { - break :blk options.objects[0].path; + if (objects.len != 0) { + break :blk objects[0].path; } if (comp.c_object_table.count() != 0) @@ -150,7 +151,7 @@ pub fn linkWithZld( try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); } } else { - const sub_path = options.emit.?.sub_path; + const sub_path = emit.?.sub_path; const old_file = macho_file.base.file; // TODO is this needed at all? defer macho_file.base.file = old_file; @@ -158,7 +159,7 @@ pub fn linkWithZld( const file = try directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, - .mode = link.determineMode(options.*), + .mode = link.File.determineMode(false, output_mode, link_mode), }); defer file.close(); macho_file.base.file = file; @@ -175,8 +176,8 @@ pub fn linkWithZld( // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList(Compilation.LinkObject).init(arena); - try positionals.ensureUnusedCapacity(options.objects.len); - positionals.appendSliceAssumeCapacity(options.objects); + try positionals.ensureUnusedCapacity(objects.len); + positionals.appendSliceAssumeCapacity(objects); for (comp.c_object_table.keys()) |key| { try positionals.append(.{ .path = key.status.success.object_path }); @@ -190,7 +191,7 @@ pub fn linkWithZld( if (comp.compiler_rt_obj) |obj| try positionals.append(.{ .path = obj.full_object_path }); // libc++ dep - if (options.link_libcpp) { + if (comp.config.link_libcpp) { try positionals.ensureUnusedCapacity(2); positionals.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }); positionals.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path }); @@ -199,23 +200,23 @@ pub fn linkWithZld( var libs = std.StringArrayHashMap(link.SystemLib).init(arena); { - const vals = options.system_libs.values(); + const vals = comp.system_libs.values(); try libs.ensureUnusedCapacity(vals.len); for (vals) |v| libs.putAssumeCapacity(v.path.?, v); } { - try libs.ensureUnusedCapacity(options.frameworks.len); - for (options.frameworks) |v| libs.putAssumeCapacity(v.path, .{ + try libs.ensureUnusedCapacity(macho_file.frameworks.len); + for (macho_file.frameworks) |v| libs.putAssumeCapacity(v.path, .{ .needed = v.needed, .weak = v.weak, .path = v.path, }); } - try macho_file.resolveLibSystem(arena, comp, options.lib_dirs, &libs); + try macho_file.resolveLibSystem(arena, comp, &libs); - if (options.verbose_link) { + if (comp.verbose_link) { var argv = std.ArrayList([]const u8).init(arena); try argv.append("zig"); @@ -228,14 +229,14 @@ pub fn linkWithZld( if (is_dyn_lib) { try argv.append("-dylib"); - if (options.install_name) |install_name| { + if (macho_file.install_name) |install_name| { try argv.append("-install_name"); try argv.append(install_name); } } { - const platform = Platform.fromTarget(options.target); + const platform = Platform.fromTarget(target); try argv.append("-platform_version"); try argv.append(@tagName(platform.os_tag)); try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); @@ -248,44 +249,39 @@ pub fn linkWithZld( } } - if (options.sysroot) |syslibroot| { + if (macho_file.sysroot) |syslibroot| { try argv.append("-syslibroot"); try argv.append(syslibroot); } - for (options.rpath_list) |rpath| { + for (macho_file.rpath_list) |rpath| { try argv.append("-rpath"); try argv.append(rpath); } - if (options.pagezero_size) |pagezero_size| { - try argv.append("-pagezero_size"); - try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size})); - } - - if (options.headerpad_size) |headerpad_size| { - try argv.append("-headerpad_size"); - try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{headerpad_size})); - } + try argv.appendSlice(&.{ + "-pagezero_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.pagezero_size}), + "-headerpad_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.headerpad_size}), + }); - if (options.headerpad_max_install_names) { + if (macho_file.headerpad_max_install_names) { try argv.append("-headerpad_max_install_names"); } - if (gc_sections) { + if (macho_file.base.gc_sections) { try argv.append("-dead_strip"); } - if (options.dead_strip_dylibs) { + if (macho_file.dead_strip_dylibs) { try argv.append("-dead_strip_dylibs"); } - if (options.entry) |entry| { + if (comp.config.entry) |entry| { try argv.append("-e"); try argv.append(entry); } - for (options.objects) |obj| { + for (objects) |obj| { if (obj.must_link) { try argv.append("-force_load"); } @@ -303,7 +299,7 @@ pub fn linkWithZld( if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); if (comp.compiler_rt_obj) |obj| try argv.append(obj.full_object_path); - if (options.link_libcpp) { + if (comp.config.link_libcpp) { try argv.append(comp.libcxxabi_static_lib.?.full_object_path); try argv.append(comp.libcxx_static_lib.?.full_object_path); } @@ -313,8 +309,8 @@ pub fn linkWithZld( try argv.append("-lSystem"); - for (options.system_libs.keys()) |l_name| { - const info = options.system_libs.get(l_name).?; + for (comp.system_libs.keys()) |l_name| { + const info = comp.system_libs.get(l_name).?; const arg = if (info.needed) try std.fmt.allocPrint(arena, "-needed-l{s}", .{l_name}) else if (info.weak) @@ -324,11 +320,7 @@ pub fn linkWithZld( try argv.append(arg); } - for (options.lib_dirs) |lib_dir| { - try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir})); - } - - for (options.frameworks) |framework| { + for (macho_file.frameworks) |framework| { const name = std.fs.path.stem(framework.path); const arg = if (framework.needed) try std.fmt.allocPrint(arena, "-needed_framework {s}", .{name}) @@ -339,11 +331,7 @@ pub fn linkWithZld( try argv.append(arg); } - for (options.framework_dirs) |framework_dir| { - try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir})); - } - - if (is_dyn_lib and (options.allow_shlib_undefined orelse false)) { + if (is_dyn_lib and macho_file.base.allow_shlib_undefined) { try argv.append("-undefined"); try argv.append("dynamic_lookup"); } @@ -412,7 +400,7 @@ pub fn linkWithZld( }; } - if (gc_sections) { + if (macho_file.base.gc_sections) { try dead_strip.gcAtoms(macho_file); } @@ -519,7 +507,7 @@ pub fn linkWithZld( // where the code signature goes into. var codesig = CodeSignature.init(MachO.getPageSize(cpu_arch)); codesig.code_directory.ident = fs.path.basename(full_out_path); - if (options.entitlements) |path| { + if (macho_file.entitlements) |path| { try codesig.addEntitlements(gpa, path); } try macho_file.writeCodeSignaturePadding(&codesig); @@ -539,7 +527,7 @@ pub fn linkWithZld( try lc_writer.writeStruct(macho_file.dysymtab_cmd); try load_commands.writeDylinkerLC(lc_writer); - switch (macho_file.base.options.output_mode) { + switch (output_mode) { .Exe => blk: { const seg_id = macho_file.header_segment_cmd_index.?; const seg = macho_file.segments.items[seg_id]; @@ -555,10 +543,10 @@ pub fn linkWithZld( try lc_writer.writeStruct(macho.entry_point_command{ .entryoff = @as(u32, @intCast(addr - seg.vmaddr)), - .stacksize = macho_file.base.options.stack_size_override orelse 0, + .stacksize = macho_file.base.stack_size, }); }, - .Lib => if (macho_file.base.options.link_mode == .Dynamic) { + .Lib => if (link_mode == .Dynamic) { try load_commands.writeDylibIdLC(gpa, &macho_file.base.options, lc_writer); }, else => {}, @@ -598,11 +586,11 @@ pub fn linkWithZld( if (codesig) |*csig| { try macho_file.writeCodeSignature(comp, csig); // code signing always comes last - try MachO.invalidateKernelCache(directory.handle, macho_file.base.options.emit.?.sub_path); + try MachO.invalidateKernelCache(directory.handle, macho_file.base.emit.sub_path); } } - if (!options.disable_lld_caching) { + if (!macho_file.base.disable_lld_caching) { // Update the file with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { @@ -622,12 +610,11 @@ pub fn linkWithZld( fn createSegments(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; - const pagezero_vmsize = macho_file.base.options.pagezero_size orelse MachO.default_pagezero_vmsize; const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); - const aligned_pagezero_vmsize = mem.alignBackward(u64, pagezero_vmsize, page_size); + const aligned_pagezero_vmsize = mem.alignBackward(u64, macho_file.pagezero_vmsize, page_size); if (macho_file.base.options.output_mode != .Lib and aligned_pagezero_vmsize > 0) { - if (aligned_pagezero_vmsize != pagezero_vmsize) { - log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize}); + if (aligned_pagezero_vmsize != macho_file.pagezero_vmsize) { + log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{macho_file.pagezero_vmsize}); log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize}); } macho_file.pagezero_segment_cmd_index = @intCast(macho_file.segments.items.len); diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 606c5f123754..1cfc14cef028 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -24,46 +24,56 @@ const LlvmObject = @import("../codegen/llvm.zig").Object; base: link.File, llvm_object: *LlvmObject, -ptx_file_name: []const u8, -pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { - if (!options.use_llvm) return error.PtxArchNotSupported; +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { + if (build_options.only_c) unreachable; - if (!options.target.cpu.arch.isNvptx()) return error.PtxArchNotSupported; + const target = options.comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; - switch (options.target.os.tag) { + assert(use_llvm); // Caught by Compilation.Config.resolve. + assert(!use_lld); // Caught by Compilation.Config.resolve. + assert(target.cpu.arch.isNvptx()); // Caught by Compilation.Config.resolve. + + switch (target.os.tag) { // TODO: does it also work with nvcl ? .cuda => {}, else => return error.PtxArchNotSupported, } - const llvm_object = try LlvmObject.create(gpa, options); - const nvptx = try gpa.create(NvPtx); + const llvm_object = try LlvmObject.create(arena, options); + const nvptx = try arena.create(NvPtx); nvptx.* = .{ .base = .{ .tag = .nvptx, - .options = options, + .comp = options.comp, + .emit = options.emit, + .gc_sections = options.gc_sections orelse false, + .stack_size = options.stack_size orelse 0, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .llvm_object = llvm_object, - .ptx_file_name = try std.mem.join(gpa, "", &[_][]const u8{ options.root_name, ".ptx" }), }; return nvptx; } -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx { - if (!options.use_llvm) return error.PtxArchNotSupported; - assert(options.target.ofmt == .nvptx); - - log.debug("Opening .ptx target file {s}", .{sub_path}); - return createEmpty(allocator, options); +pub fn open(arena: Allocator, options: link.FileOpenOptions) !*NvPtx { + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .nvptx); + return createEmpty(arena, options); } pub fn deinit(self: *NvPtx) void { - self.llvm_object.destroy(self.base.allocator); - self.base.allocator.free(self.ptx_file_name); + self.llvm_object.deinit(); } pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { @@ -110,7 +120,7 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.No comp.emit_asm = .{ // 'null' means using the default cache dir: zig-cache/o/... .directory = null, - .basename = self.ptx_file_name, + .basename = self.base.emit.sub_path, }; defer { comp.bin_file.options.emit = outfile; diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index b608b291615e..a5bb943ada2c 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -318,12 +318,12 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), }; // a / will always be in a file path - try self.file_segments.put(self.base.allocator, "/", 1); + try self.file_segments.put(gpa, "/", 1); return self; } fn putFn(self: *Plan9, decl_index: InternPool.DeclIndex, out: FnDeclOutput) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope(mod)); @@ -379,6 +379,7 @@ fn putFn(self: *Plan9, decl_index: InternPool.DeclIndex, out: FnDeclOutput) !voi } fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !void { + const gpa = self.base.comp.gpa; const sep = std.fs.path.sep; var it = std.mem.tokenizeScalar(u8, path, sep); while (it.next()) |component| { @@ -386,7 +387,7 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi try a.writer().writeInt(u16, num, .big); } else { self.file_segments_i += 1; - try self.file_segments.put(self.base.allocator, component, self.file_segments_i); + try self.file_segments.put(gpa, component, self.file_segments_i); try a.writer().writeInt(u16, self.file_segments_i, .big); } } @@ -397,6 +398,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: @panic("Attempted to compile for object format that was disabled by build configuration"); } + const gpa = self.base.comp.gpa; const func = mod.funcInfo(func_index); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); @@ -404,10 +406,10 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: const atom_idx = try self.seeDecl(decl_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); var dbg_info_output: DebugInfoOutput = .{ - .dbg_line = std.ArrayList(u8).init(self.base.allocator), + .dbg_line = std.ArrayList(u8).init(gpa), .start_line = null, .end_line = undefined, .pcop_change_index = null, @@ -448,14 +450,15 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: } pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { + const gpa = self.base.comp.gpa; _ = try self.seeDecl(decl_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); - const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl_index); + const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } @@ -465,7 +468,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De const index = unnamed_consts.items.len; // name is freed when the unnamed const is freed - const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl_name, index }); + const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); const sym_index = try self.allocateSymbolIndex(); const new_atom_idx = try self.createAtom(); @@ -498,17 +501,18 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De }, }; // duped_code is freed when the unnamed const is freed - const duped_code = try self.base.allocator.dupe(u8, code); - errdefer self.base.allocator.free(duped_code); + const duped_code = try gpa.dupe(u8, code); + errdefer gpa.free(duped_code); const new_atom = self.getAtomPtr(new_atom_idx); new_atom.* = info; new_atom.code = .{ .code_ptr = duped_code.ptr, .other = .{ .code_len = duped_code.len } }; - try unnamed_consts.append(self.base.allocator, new_atom_idx); + try unnamed_consts.append(gpa, new_atom_idx); // we return the new_atom_idx to codegen return new_atom_idx; } pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) !void { + const gpa = self.base.comp.gpa; const decl = mod.declPtr(decl_index); if (decl.isExtern(mod)) { @@ -517,7 +521,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) } const atom_idx = try self.seeDecl(decl_index); - var code_buffer = std.ArrayList(u8).init(self.base.allocator); + var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; // TODO we need the symbol index for symbol in the table of locals for the containing atom @@ -535,16 +539,17 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) return; }, }; - try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1); - const duped_code = try self.base.allocator.dupe(u8, code); + try self.data_decl_table.ensureUnusedCapacity(gpa, 1); + const duped_code = try gpa.dupe(u8, code); self.getAtomPtr(self.decls.get(decl_index).?.index).code = .{ .code_ptr = null, .other = .{ .decl_index = decl_index } }; if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| { - self.base.allocator.free(old_entry.value); + gpa.free(old_entry.value); } return self.updateFinish(decl_index); } /// called at the end of update{Decl,Func} fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; const decl = mod.declPtr(decl_index); const is_fn = (decl.ty.zigTypeTag(mod) == .Fn); @@ -558,7 +563,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { const sym: aout.Sym = .{ .value = undefined, // the value of stuff gets filled in in flushModule .type = atom.type, - .name = try self.base.allocator.dupe(u8, mod.intern_pool.stringToSlice(decl.name)), + .name = try gpa.dupe(u8, mod.intern_pool.stringToSlice(decl.name)), }; if (atom.sym_index) |s| { @@ -571,10 +576,11 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { } fn allocateSymbolIndex(self: *Plan9) !usize { + const gpa = self.base.comp.gpa; if (self.syms_index_free_list.popOrNull()) |i| { return i; } else { - _ = try self.syms.addOne(self.base.allocator); + _ = try self.syms.addOne(gpa); return self.syms.items.len - 1; } } @@ -589,7 +595,8 @@ fn allocateGotIndex(self: *Plan9) usize { } pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - assert(!self.base.options.use_lld); + const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; + assert(!use_lld); switch (self.base.options.effectiveOutputMode()) { .Exe => {}, @@ -650,7 +657,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No @panic("Attempted to compile for object format that was disabled by build configuration"); } - _ = comp; + const gpa = comp.gpa; + const tracy = trace(@src()); defer tracy.end(); @@ -691,12 +699,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No const atom_count = self.atomCount(); assert(self.got_len == atom_count + self.got_index_free_list.items.len); const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; - var got_table = try self.base.allocator.alloc(u8, got_size); - defer self.base.allocator.free(got_table); + var got_table = try gpa.alloc(u8, got_size); + defer gpa.free(got_table); // + 4 for header, got, symbols, linecountinfo - var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.atomCount() + 4 - self.externCount()); - defer self.base.allocator.free(iovecs); + var iovecs = try gpa.alloc(std.os.iovec_const, self.atomCount() + 4 - self.externCount()); + defer gpa.free(iovecs); const file = self.base.file.?; @@ -709,7 +717,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No var iovecs_i: usize = 1; var text_i: u64 = 0; - var linecountinfo = std.ArrayList(u8).init(self.base.allocator); + var linecountinfo = std.ArrayList(u8).init(gpa); defer linecountinfo.deinit(); // text { @@ -901,10 +909,10 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No } } } - var sym_buf = std.ArrayList(u8).init(self.base.allocator); + var sym_buf = std.ArrayList(u8).init(gpa); try self.writeSyms(&sym_buf); const syms = try sym_buf.toOwnedSlice(); - defer self.base.allocator.free(syms); + defer gpa.free(syms); assert(2 + self.atomCount() - self.externCount() == iovecs_i); // we didn't write all the decls iovecs[iovecs_i] = .{ .iov_base = syms.ptr, .iov_len = syms.len }; iovecs_i += 1; @@ -985,6 +993,7 @@ fn addDeclExports( decl_index: InternPool.DeclIndex, exports: []const *Module.Export, ) !void { + const gpa = self.base.comp.gpa; const metadata = self.decls.getPtr(decl_index).?; const atom = self.getAtom(metadata.index); @@ -994,7 +1003,7 @@ fn addDeclExports( if (exp.opts.section.unwrap()) |section_name| { if (!mod.intern_pool.stringEqlSlice(section_name, ".text") and !mod.intern_pool.stringEqlSlice(section_name, ".data")) { try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( - self.base.allocator, + gpa, mod.declPtr(decl_index).srcLoc(mod), "plan9 does not support extra sections", .{}, @@ -1005,19 +1014,20 @@ fn addDeclExports( const sym = .{ .value = atom.offset.?, .type = atom.type.toGlobal(), - .name = try self.base.allocator.dupe(u8, exp_name), + .name = try gpa.dupe(u8, exp_name), }; if (metadata.getExport(self, exp_name)) |i| { self.syms.items[i] = sym; } else { - try self.syms.append(self.base.allocator, sym); - try metadata.exports.append(self.base.allocator, self.syms.items.len - 1); + try self.syms.append(gpa, sym); + try metadata.exports.append(gpa, self.syms.items.len - 1); } } } pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { + const gpa = self.base.comp.gpa; // TODO audit the lifetimes of decls table entries. It's possible to get // freeDecl without any updateDecl in between. // However that is planned to change, see the TODO comment in Module.zig @@ -1029,17 +1039,17 @@ pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { const symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?; var submap = symidx_and_submap.functions; if (submap.fetchSwapRemove(decl_index)) |removed_entry| { - self.base.allocator.free(removed_entry.value.code); - self.base.allocator.free(removed_entry.value.lineinfo); + gpa.free(removed_entry.value.code); + gpa.free(removed_entry.value.lineinfo); } if (submap.count() == 0) { self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol; - self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {}; - submap.deinit(self.base.allocator); + self.syms_index_free_list.append(gpa, symidx_and_submap.sym_index) catch {}; + submap.deinit(gpa); } } else { if (self.data_decl_table.fetchSwapRemove(decl_index)) |removed_entry| { - self.base.allocator.free(removed_entry.value); + gpa.free(removed_entry.value); } } if (self.decls.fetchRemove(decl_index)) |const_kv| { @@ -1047,35 +1057,36 @@ pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { const atom = self.getAtom(kv.value.index); if (atom.got_index) |i| { // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length - self.got_index_free_list.append(self.base.allocator, i) catch {}; + self.got_index_free_list.append(gpa, i) catch {}; } if (atom.sym_index) |i| { - self.syms_index_free_list.append(self.base.allocator, i) catch {}; + self.syms_index_free_list.append(gpa, i) catch {}; self.syms.items[i] = aout.Sym.undefined_symbol; } - kv.value.exports.deinit(self.base.allocator); + kv.value.exports.deinit(gpa); } self.freeUnnamedConsts(decl_index); { const atom_index = self.decls.get(decl_index).?.index; const relocs = self.relocs.getPtr(atom_index) orelse return; - relocs.clearAndFree(self.base.allocator); + relocs.clearAndFree(gpa); assert(self.relocs.remove(atom_index)); } } fn freeUnnamedConsts(self: *Plan9, decl_index: InternPool.DeclIndex) void { + const gpa = self.base.comp.gpa; const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; for (unnamed_consts.items) |atom_idx| { const atom = self.getAtom(atom_idx); - self.base.allocator.free(self.syms.items[atom.sym_index.?].name); + gpa.free(self.syms.items[atom.sym_index.?].name); self.syms.items[atom.sym_index.?] = aout.Sym.undefined_symbol; - self.syms_index_free_list.append(self.base.allocator, atom.sym_index.?) catch {}; + self.syms_index_free_list.append(gpa, atom.sym_index.?) catch {}; } - unnamed_consts.clearAndFree(self.base.allocator); + unnamed_consts.clearAndFree(gpa); } fn createAtom(self: *Plan9) !Atom.Index { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const index = @as(Atom.Index, @intCast(self.atoms.items.len)); const atom = try self.atoms.addOne(gpa); atom.* = .{ @@ -1089,7 +1100,8 @@ fn createAtom(self: *Plan9) !Atom.Index { } pub fn seeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) !Atom.Index { - const gop = try self.decls.getOrPut(self.base.allocator, decl_index); + const gpa = self.base.comp.gpa; + const gop = try self.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { const index = try self.createAtom(); self.getAtomPtr(index).got_index = self.allocateGotIndex(); @@ -1134,7 +1146,8 @@ pub fn updateExports( } pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index { - const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(self.base.options.module.?)); + const gpa = self.base.comp.gpa; + const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(self.base.options.module.?)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -1160,7 +1173,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.In } fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Index) !void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const mod = self.base.options.module.?; var required_alignment: InternPool.Alignment = .none; @@ -1206,8 +1219,8 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind }, }; // duped_code is freed when the atom is freed - const duped_code = try self.base.allocator.dupe(u8, code); - errdefer self.base.allocator.free(duped_code); + const duped_code = try gpa.dupe(u8, code); + errdefer gpa.free(duped_code); self.getAtomPtr(atom_index).code = .{ .code_ptr = duped_code.ptr, .other = .{ .code_len = duped_code.len }, @@ -1215,13 +1228,13 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind } pub fn deinit(self: *Plan9) void { - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; { var it = self.relocs.valueIterator(); while (it.next()) |relocs| { - relocs.deinit(self.base.allocator); + relocs.deinit(gpa); } - self.relocs.deinit(self.base.allocator); + self.relocs.deinit(gpa); } // free the unnamed consts var it_unc = self.unnamed_const_atoms.iterator(); @@ -1280,24 +1293,36 @@ pub fn deinit(self: *Plan9) void { } } -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 { - if (options.use_llvm) - return error.LLVMBackendDoesNotSupportPlan9; - assert(options.target.ofmt == .plan9); +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { + if (build_options.only_c) unreachable; + + const target = options.comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; - const self = try createEmpty(allocator, options); + assert(!use_llvm); // Caught by Compilation.Config.resolve. + assert(!use_lld); // Caught by Compilation.Config.resolve. + assert(target.ofmt == .plan9); + + const self = try createEmpty(arena, options); errdefer self.base.destroy(); - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{ .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode( + use_lld, + options.comp.config.output_mode, + options.comp.config.link_mode, + ), }); errdefer file.close(); self.base.file = file; - self.bases = defaultBaseAddrs(options.target.cpu.arch); + self.bases = defaultBaseAddrs(target.cpu.arch); + + const gpa = options.comp.gpa; - try self.syms.appendSlice(self.base.allocator, &.{ + try self.syms.appendSlice(gpa, &.{ // we include the global offset table to make it easier for debugging .{ .value = self.getAddr(0, .d), // the global offset table starts at 0 @@ -1490,7 +1515,7 @@ pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.S // be used by more than one function, however, its address is being used so we need // to put it in some location. // ... - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const gop = try self.anon_decls.getOrPut(gpa, decl_val); const mod = self.base.options.module.?; if (!gop.found_existing) { @@ -1538,11 +1563,12 @@ pub fn getAnonDeclVAddr(self: *Plan9, decl_val: InternPool.Index, reloc_info: li } pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void { - const gop = try self.relocs.getOrPut(self.base.allocator, parent_index); + const gpa = self.base.comp.gpa; + const gop = try self.relocs.getOrPut(gpa, parent_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; } - try gop.value_ptr.append(self.base.allocator, reloc); + try gop.value_ptr.append(gpa, reloc); } pub fn getAtom(self: *const Plan9, index: Atom.Index) Atom { diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index ac36a391ecdd..c6bb5f558892 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -47,48 +47,65 @@ base: link.File, object: codegen.Object, -pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { - const self = try gpa.create(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; + + const self = try arena.create(SpirV); self.* = .{ .base = .{ .tag = .spirv, - .options = options, + .comp = options.comp, + .emit = options.emit, + .gc_sections = options.gc_sections orelse false, + .stack_size = options.stack_size orelse 0, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .object = codegen.Object.init(gpa), }; errdefer self.deinit(); - // TODO: Figure out where to put all of these - switch (options.target.cpu.arch) { + switch (target.cpu.arch) { .spirv32, .spirv64 => {}, - else => return error.TODOArchNotSupported, + else => unreachable, // Caught by Compilation.Config.resolve. } - switch (options.target.os.tag) { + switch (target.os.tag) { .opencl, .glsl450, .vulkan => {}, - else => return error.TODOOsNotSupported, + else => unreachable, // Caught by Compilation.Config.resolve. } - if (options.target.abi != .none) { - return error.TODOAbiNotSupported; - } + assert(target.abi != .none); // Caught by Compilation.Config.resolve. return self; } -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*SpirV { - assert(options.target.ofmt == .spirv); +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV { + if (build_options.only_c) unreachable; + + const target = options.comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; - if (options.use_llvm) return error.LLVM_BackendIsTODO_ForSpirV; // TODO: LLVM Doesn't support SpirV at all. - if (options.use_lld) return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all. + assert(!use_llvm); // Caught by Compilation.Config.resolve. + assert(!use_lld); // Caught by Compilation.Config.resolve. + assert(target.ofmt == .spirv); // Caught by Compilation.Config.resolve. - const spirv = try createEmpty(allocator, options); + const spirv = try createEmpty(arena, options); errdefer spirv.base.destroy(); // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true }); + const file = try options.emit.?.directory.handle.createFile(options.emit.sub_path, .{ + .truncate = true, + .read = true, + }); spirv.base.file = file; return spirv; } @@ -150,11 +167,7 @@ pub fn freeDecl(self: *SpirV, decl_index: InternPool.DeclIndex) void { } pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (build_options.have_llvm and self.base.options.use_lld) { - return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all. - } else { - return self.flushModule(comp, prog_node); - } + return self.flushModule(comp, prog_node); } pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 513922f24777..bb0d4447bb86 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -191,6 +191,9 @@ synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{}, /// Map for storing anonymous declarations. Each anonymous decl maps to its Atom's index. anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Atom.Index) = .{}, +import_table: bool, +export_table: bool, + pub const Alignment = types.Alignment; pub const Segment = struct { @@ -363,63 +366,71 @@ pub const StringTable = struct { } }; -pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Wasm { - assert(options.target.ofmt == .wasm); +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { + if (build_options.only_c) unreachable; + const gpa = options.comp.gpa; + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .wasm); - if (options.use_llvm and options.use_lld) { - return createEmpty(allocator, options); - } + const use_lld = build_options.have_llvm and options.comp.config.use_lld; + const use_llvm = options.comp.config.use_llvm; + const output_mode = options.comp.config.output_mode; - const wasm_bin = try createEmpty(allocator, options); - errdefer wasm_bin.base.destroy(); + const wasm = try createEmpty(arena, options); + errdefer wasm.base.destroy(); - // We are not using LLD at this point, so ensure we set the intermediary basename - if (build_options.have_llvm and options.use_llvm and options.module != null) { - // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`, - // we also want to put the intermediary object file in the cache while the - // main emit directory is the cwd. - wasm_bin.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{ - options.emit.?.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), - }); + if (use_lld and use_llvm) { + // LLVM emits the object file; LLD links it into the final product. + return wasm; } + const sub_path = if (!use_lld) options.emit.sub_path else p: { + // Open a temporary object file, not the final output file because we + // want to link with LLD. + const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ + options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + }); + wasm.base.intermediary_basename = o_file_path; + break :p o_file_path; + }; + // TODO: read the file and keep valid parts instead of truncating const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = if (fs.has_executable_bit) - if (options.target.os.tag == .wasi and options.output_mode == .Exe) + if (target.os.tag == .wasi and output_mode == .Exe) fs.File.default_mode | 0b001_000_000 else fs.File.default_mode else 0, }); - wasm_bin.base.file = file; - wasm_bin.name = sub_path; + wasm.base.file = file; + wasm.name = sub_path; // create stack pointer symbol { - const loc = try wasm_bin.createSyntheticSymbol("__stack_pointer", .global); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__stack_pointer", .global); + const symbol = loc.getSymbol(wasm); // For object files we will import the stack pointer symbol - if (options.output_mode == .Obj) { + if (output_mode == .Obj) { symbol.setUndefined(true); - symbol.index = @as(u32, @intCast(wasm_bin.imported_globals_count)); - wasm_bin.imported_globals_count += 1; - try wasm_bin.imports.putNoClobber( - allocator, + symbol.index = @intCast(wasm.imported_globals_count); + wasm.imported_globals_count += 1; + try wasm.imports.putNoClobber( + gpa, loc, .{ - .module_name = try wasm_bin.string_table.put(allocator, wasm_bin.host_name), + .module_name = try wasm.string_table.put(gpa, wasm.host_name), .name = symbol.name, .kind = .{ .global = .{ .valtype = .i32, .mutable = true } }, }, ); } else { - symbol.index = @intCast(wasm_bin.imported_globals_count + wasm_bin.wasm_globals.items.len); + symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); - const global = try wasm_bin.wasm_globals.addOne(allocator); + const global = try wasm.wasm_globals.addOne(gpa); global.* = .{ .global_type = .{ .valtype = .i32, @@ -432,25 +443,25 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option // create indirect function pointer symbol { - const loc = try wasm_bin.createSyntheticSymbol("__indirect_function_table", .table); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__indirect_function_table", .table); + const symbol = loc.getSymbol(wasm); const table: std.wasm.Table = .{ .limits = .{ .flags = 0, .min = 0, .max = undefined }, // will be overwritten during `mapFunctionTable` .reftype = .funcref, }; - if (options.output_mode == .Obj or options.import_table) { + if (output_mode == .Obj or options.import_table) { symbol.setUndefined(true); - symbol.index = @intCast(wasm_bin.imported_tables_count); - wasm_bin.imported_tables_count += 1; - try wasm_bin.imports.put(allocator, loc, .{ - .module_name = try wasm_bin.string_table.put(allocator, wasm_bin.host_name), + symbol.index = @intCast(wasm.imported_tables_count); + wasm.imported_tables_count += 1; + try wasm.imports.put(gpa, loc, .{ + .module_name = try wasm.string_table.put(gpa, wasm.host_name), .name = symbol.name, .kind = .{ .table = table }, }); } else { - symbol.index = @as(u32, @intCast(wasm_bin.imported_tables_count + wasm_bin.tables.items.len)); - try wasm_bin.tables.append(allocator, table); - if (options.export_table) { + symbol.index = @as(u32, @intCast(wasm.imported_tables_count + wasm.tables.items.len)); + try wasm.tables.append(gpa, table); + if (wasm.export_table) { symbol.setFlag(.WASM_SYM_EXPORTED); } else { symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); @@ -460,8 +471,8 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option // create __wasm_call_ctors { - const loc = try wasm_bin.createSyntheticSymbol("__wasm_call_ctors", .function); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__wasm_call_ctors", .function); + const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); // we do not know the function index until after we merged all sections. // Therefore we set `symbol.index` and create its corresponding references @@ -469,67 +480,76 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option } // shared-memory symbols for TLS support - if (wasm_bin.base.options.shared_memory) { + if (wasm.base.options.shared_memory) { { - const loc = try wasm_bin.createSyntheticSymbol("__tls_base", .global); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__tls_base", .global); + const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); - symbol.index = @intCast(wasm_bin.imported_globals_count + wasm_bin.wasm_globals.items.len); - try wasm_bin.wasm_globals.append(wasm_bin.base.allocator, .{ + symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); + try wasm.wasm_globals.append(gpa, .{ .global_type = .{ .valtype = .i32, .mutable = true }, .init = .{ .i32_const = undefined }, }); } { - const loc = try wasm_bin.createSyntheticSymbol("__tls_size", .global); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__tls_size", .global); + const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); - symbol.index = @intCast(wasm_bin.imported_globals_count + wasm_bin.wasm_globals.items.len); - try wasm_bin.wasm_globals.append(wasm_bin.base.allocator, .{ + symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); + try wasm.wasm_globals.append(gpa, .{ .global_type = .{ .valtype = .i32, .mutable = false }, .init = .{ .i32_const = undefined }, }); } { - const loc = try wasm_bin.createSyntheticSymbol("__tls_align", .global); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__tls_align", .global); + const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); - symbol.index = @intCast(wasm_bin.imported_globals_count + wasm_bin.wasm_globals.items.len); - try wasm_bin.wasm_globals.append(wasm_bin.base.allocator, .{ + symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); + try wasm.wasm_globals.append(gpa, .{ .global_type = .{ .valtype = .i32, .mutable = false }, .init = .{ .i32_const = undefined }, }); } { - const loc = try wasm_bin.createSyntheticSymbol("__wasm_init_tls", .function); - const symbol = loc.getSymbol(wasm_bin); + const loc = try wasm.createSyntheticSymbol("__wasm_init_tls", .function); + const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); } } - // if (!options.strip and options.module != null) { - // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, .dwarf32); - // try wasm_bin.initDebugSections(); - // } - - return wasm_bin; + return wasm; } -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { - const wasm = try gpa.create(Wasm); - errdefer gpa.destroy(wasm); +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { + const use_llvm = options.comp.config.use_llvm; + const output_mode = options.comp.config.output_mode; + + const wasm = try arena.create(Wasm); wasm.* = .{ .base = .{ .tag = .wasm, - .options = options, + .comp = options.comp, + .emit = options.emit, + .gc_sections = options.gc_sections orelse (output_mode != .Obj), + .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .name = undefined, + .import_table = options.import_table, + .export_table = options.export_table, }; - if (options.use_llvm) { - wasm.llvm_object = try LlvmObject.create(gpa, options); + if (use_llvm) { + wasm.llvm_object = try LlvmObject.create(arena, options); } return wasm; } @@ -537,22 +557,24 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { /// For a given name, creates a new global synthetic symbol. /// Leaves index undefined and the default flags (0). fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc { - const name_offset = try wasm.string_table.put(wasm.base.allocator, name); + const gpa = wasm.base.comp.gpa; + const name_offset = try wasm.string_table.put(gpa, name); return wasm.createSyntheticSymbolOffset(name_offset, tag); } fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc { const sym_index = @as(u32, @intCast(wasm.symbols.items.len)); const loc: SymbolLoc = .{ .index = sym_index, .file = null }; - try wasm.symbols.append(wasm.base.allocator, .{ + const gpa = wasm.base.comp.gpa; + try wasm.symbols.append(gpa, .{ .name = name_offset, .flags = 0, .tag = tag, .index = undefined, .virtual_address = undefined, }); - try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); - try wasm.globals.put(wasm.base.allocator, name_offset, loc); + try wasm.resolved_symbols.putNoClobber(gpa, loc, {}); + try wasm.globals.put(gpa, name_offset, loc); return loc; } @@ -589,12 +611,13 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { const file = try fs.cwd().openFile(path, .{}); errdefer file.close(); - var object = Object.create(wasm.base.allocator, file, path, null) catch |err| switch (err) { + const gpa = wasm.base.comp.gpa; + var object = Object.create(gpa, file, path, null) catch |err| switch (err) { error.InvalidMagicByte, error.NotObjectFile => return false, else => |e| return e, }; - errdefer object.deinit(wasm.base.allocator); - try wasm.objects.append(wasm.base.allocator, object); + errdefer object.deinit(gpa); + try wasm.objects.append(gpa, object); return true; } @@ -602,7 +625,8 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { /// When the index was not found, a new `Atom` will be created, and its index will be returned. /// The newly created Atom is empty with default fields as specified by `Atom.empty`. pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) !Atom.Index { - const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index); + const gpa = wasm.base.comp.gpa; + const gop = try wasm.decls.getOrPut(gpa, decl_index); if (!gop.found_existing) { const atom_index = try wasm.createAtom(); gop.value_ptr.* = atom_index; @@ -611,18 +635,19 @@ pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) !At const mod = wasm.base.options.module.?; const decl = mod.declPtr(decl_index); const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name); + symbol.name = try wasm.string_table.put(gpa, full_name); } return gop.value_ptr.*; } /// Creates a new empty `Atom` and returns its `Atom.Index` fn createAtom(wasm: *Wasm) !Atom.Index { - const index = @as(Atom.Index, @intCast(wasm.managed_atoms.items.len)); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); + const gpa = wasm.base.comp.gpa; + const index: Atom.Index = @intCast(wasm.managed_atoms.items.len); + const atom = try wasm.managed_atoms.addOne(gpa); atom.* = Atom.empty; atom.sym_index = try wasm.allocateSymbol(); - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, .{ .file = null, .index = atom.sym_index }, index); + try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = atom.sym_index }, index); return index; } @@ -644,6 +669,8 @@ pub inline fn getAtomPtr(wasm: *Wasm, index: Atom.Index) *Atom { /// When false, it will only link with object files that contain symbols that /// are referenced by other object files or Zig code. fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { + const gpa = wasm.base.comp.gpa; + const file = try fs.cwd().openFile(path, .{}); errdefer file.close(); @@ -651,25 +678,25 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { .file = file, .name = path, }; - archive.parse(wasm.base.allocator) catch |err| switch (err) { + archive.parse(gpa) catch |err| switch (err) { error.EndOfStream, error.NotArchive => { - archive.deinit(wasm.base.allocator); + archive.deinit(gpa); return false; }, else => |e| return e, }; if (!force_load) { - errdefer archive.deinit(wasm.base.allocator); - try wasm.archives.append(wasm.base.allocator, archive); + errdefer archive.deinit(gpa); + try wasm.archives.append(gpa, archive); return true; } - defer archive.deinit(wasm.base.allocator); + defer archive.deinit(gpa); // In this case we must force link all embedded object files within the archive // We loop over all symbols, and then group them by offset as the offset // notates where the object file starts. - var offsets = std.AutoArrayHashMap(u32, void).init(wasm.base.allocator); + var offsets = std.AutoArrayHashMap(u32, void).init(gpa); defer offsets.deinit(); for (archive.toc.values()) |symbol_offsets| { for (symbol_offsets.items) |sym_offset| { @@ -678,8 +705,8 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { } for (offsets.keys()) |file_offset| { - const object = try wasm.objects.addOne(wasm.base.allocator); - object.* = try archive.parseObject(wasm.base.allocator, file_offset); + const object = try wasm.objects.addOne(gpa); + object.* = try archive.parseObject(gpa, file_offset); } return true; @@ -695,6 +722,7 @@ fn requiresTLSReloc(wasm: *const Wasm) bool { } fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { + const gpa = wasm.base.comp.gpa; const object: Object = wasm.objects.items[object_index]; log.debug("Resolving symbols in object: '{s}'", .{object.name}); @@ -708,7 +736,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { if (mem.eql(u8, sym_name, "__indirect_function_table")) { continue; } - const sym_name_index = try wasm.string_table.put(wasm.base.allocator, sym_name); + const sym_name_index = try wasm.string_table.put(gpa, sym_name); if (symbol.isLocal()) { if (symbol.isUndefined()) { @@ -716,17 +744,17 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name }); return error.UndefinedLocal; } - try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {}); + try wasm.resolved_symbols.putNoClobber(gpa, location, {}); continue; } - const maybe_existing = try wasm.globals.getOrPut(wasm.base.allocator, sym_name_index); + const maybe_existing = try wasm.globals.getOrPut(gpa, sym_name_index); if (!maybe_existing.found_existing) { maybe_existing.value_ptr.* = location; - try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {}); + try wasm.resolved_symbols.putNoClobber(gpa, location, {}); if (symbol.isUndefined()) { - try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name_index, location); + try wasm.undefs.putNoClobber(gpa, sym_name_index, location); } continue; } @@ -753,7 +781,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { return error.SymbolCollision; } - try wasm.discarded.put(wasm.base.allocator, location, existing_loc); + try wasm.discarded.put(gpa, location, existing_loc); continue; // Do not overwrite defined symbols with undefined symbols } @@ -791,7 +819,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { } // both undefined so skip overwriting existing symbol and discard the new symbol - try wasm.discarded.put(wasm.base.allocator, location, existing_loc); + try wasm.discarded.put(gpa, location, existing_loc); continue; } @@ -822,7 +850,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { // symbol is weak and the new one isn't, in which case we *do* overwrite it. if (existing_sym.isWeak() and symbol.isWeak()) blk: { if (existing_sym.isUndefined() and !symbol.isUndefined()) break :blk; - try wasm.discarded.put(wasm.base.allocator, location, existing_loc); + try wasm.discarded.put(gpa, location, existing_loc); continue; } @@ -830,10 +858,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { log.debug("Overwriting symbol '{s}'", .{sym_name}); log.debug(" old definition in '{s}'", .{existing_file_path}); log.debug(" new definition in '{s}'", .{object.name}); - try wasm.discarded.putNoClobber(wasm.base.allocator, existing_loc, location); + try wasm.discarded.putNoClobber(gpa, existing_loc, location); maybe_existing.value_ptr.* = location; - try wasm.globals.put(wasm.base.allocator, sym_name_index, location); - try wasm.resolved_symbols.put(wasm.base.allocator, location, {}); + try wasm.globals.put(gpa, sym_name_index, location); + try wasm.resolved_symbols.put(gpa, location, {}); assert(wasm.resolved_symbols.swapRemove(existing_loc)); if (existing_sym.isUndefined()) { _ = wasm.undefs.swapRemove(sym_name_index); @@ -842,6 +870,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { } fn resolveSymbolsInArchives(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; if (wasm.archives.items.len == 0) return; log.debug("Resolving symbols in archives", .{}); @@ -860,9 +889,9 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void { // Symbol is found in unparsed object file within current archive. // Parse object and and resolve symbols again before we check remaining // undefined symbols. - const object_file_index = @as(u16, @intCast(wasm.objects.items.len)); - const object = try archive.parseObject(wasm.base.allocator, offset.items[0]); - try wasm.objects.append(wasm.base.allocator, object); + const object_file_index: u16 = @intCast(wasm.objects.items.len); + const object = try archive.parseObject(gpa, offset.items[0]); + try wasm.objects.append(gpa, object); try wasm.resolveSymbolsInObject(object_file_index); // continue loop for any remaining undefined symbols that still exist @@ -880,6 +909,8 @@ fn writeI32Const(writer: anytype, val: u32) !void { } fn setupInitMemoryFunction(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; + // Passive segments are used to avoid memory being reinitialized on each // thread's instantiation. These passive segments are initialized and // dropped in __wasm_init_memory, which is registered as the start function @@ -896,7 +927,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { break :address loc.getSymbol(wasm).virtual_address; } else 0; - var function_body = std.ArrayList(u8).init(wasm.base.allocator); + var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); const writer = function_body.writer(); @@ -1040,6 +1071,8 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { /// Constructs a synthetic function that performs runtime relocations for /// TLS symbols. This function is called by `__wasm_init_tls`. fn setupTLSRelocationsFunction(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; + // When we have TLS GOT entries and shared memory is enabled, // we must perform runtime relocations or else we don't create the function. if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) { @@ -1047,7 +1080,7 @@ fn setupTLSRelocationsFunction(wasm: *Wasm) !void { } // const loc = try wasm.createSyntheticSymbol("__wasm_apply_global_tls_relocs"); - var function_body = std.ArrayList(u8).init(wasm.base.allocator); + var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); const writer = function_body.writer(); @@ -1221,10 +1254,12 @@ fn validateFeatures( /// if one or multiple undefined references exist. When none exist, the symbol will /// not be created, ensuring we don't unneccesarily emit unreferenced symbols. fn resolveLazySymbols(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; + if (wasm.string_table.getOffset("__heap_base")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); - try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); + try wasm.discarded.putNoClobber(gpa, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations. } } @@ -1232,7 +1267,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void { if (wasm.string_table.getOffset("__heap_end")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); - try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); + try wasm.discarded.putNoClobber(gpa, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(loc); } } @@ -1241,12 +1276,12 @@ fn resolveLazySymbols(wasm: *Wasm) !void { if (wasm.string_table.getOffset("__tls_base")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global); - try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); + try wasm.discarded.putNoClobber(gpa, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(kv.value); const symbol = loc.getSymbol(wasm); symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); symbol.index = @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len); - try wasm.wasm_globals.append(wasm.base.allocator, .{ + try wasm.wasm_globals.append(gpa, .{ .global_type = .{ .valtype = .i32, .mutable = true }, .init = .{ .i32_const = undefined }, }); @@ -1256,7 +1291,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void { if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); - try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); + try wasm.discarded.putNoClobber(gpa, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(kv.value); } } @@ -1292,8 +1327,8 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void { } pub fn deinit(wasm: *Wasm) void { - const gpa = wasm.base.allocator; - if (wasm.llvm_object) |llvm_object| llvm_object.destroy(gpa); + const gpa = wasm.base.comp.gpa; + if (wasm.llvm_object) |llvm_object| llvm_object.deinit(); for (wasm.func_types.items) |*func_type| { func_type.deinit(gpa); @@ -1378,7 +1413,9 @@ pub fn deinit(wasm: *Wasm) void { /// Allocates a new symbol and returns its index. /// Will re-use slots when a symbol was freed at an earlier stage. pub fn allocateSymbol(wasm: *Wasm) !u32 { - try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1); + const gpa = wasm.base.comp.gpa; + + try wasm.symbols.ensureUnusedCapacity(gpa, 1); const symbol: Symbol = .{ .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), @@ -1404,6 +1441,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: const tracy = trace(@src()); defer tracy.end(); + const gpa = wasm.base.comp.gpa; const func = mod.funcInfo(func_index); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); @@ -1414,7 +1452,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: // var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl_index) else null; // defer if (decl_state) |*ds| ds.deinit(); - var code_writer = std.ArrayList(u8).init(wasm.base.allocator); + var code_writer = std.ArrayList(u8).init(gpa); defer code_writer.deinit(); // const result = try codegen.generateFunction( // &wasm.base, @@ -1477,6 +1515,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) ! return; } + const gpa = wasm.base.comp.gpa; const atom_index = try wasm.getOrCreateAtomForDecl(decl_index); const atom = wasm.getAtomPtr(atom_index); atom.clear(); @@ -1489,7 +1528,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: InternPool.DeclIndex) ! } const val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; - var code_writer = std.ArrayList(u8).init(wasm.base.allocator); + var code_writer = std.ArrayList(u8).init(gpa); defer code_writer.deinit(); const res = try codegen.generateSymbol( @@ -1528,16 +1567,17 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.De } fn finishUpdateDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex, code: []const u8, symbol_tag: Symbol.Tag) !void { + const gpa = wasm.base.comp.gpa; const mod = wasm.base.options.module.?; const decl = mod.declPtr(decl_index); const atom_index = wasm.decls.get(decl_index).?; const atom = wasm.getAtomPtr(atom_index); const symbol = &wasm.symbols.items[atom.sym_index]; const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name); + symbol.name = try wasm.string_table.put(gpa, full_name); symbol.tag = symbol_tag; - try atom.code.appendSlice(wasm.base.allocator, code); - try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {}); + try atom.code.appendSlice(gpa, code); + try wasm.resolved_symbols.put(gpa, atom.symbolLoc(), {}); atom.size = @intCast(code.len); if (code.len == 0) return; @@ -1591,6 +1631,7 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { /// Returns the symbol index of the local /// The given `decl` is the parent decl whom owns the constant. pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { + const gpa = wasm.base.comp.gpa; const mod = wasm.base.options.module.?; assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions const decl = mod.declPtr(decl_index); @@ -1599,14 +1640,14 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.Dec const parent_atom = wasm.getAtom(parent_atom_index); const local_index = parent_atom.locals.items.len; const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); - const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ + const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{ fqn, local_index, }); - defer wasm.base.allocator.free(name); + defer gpa.free(name); switch (try wasm.lowerConst(name, tv, decl.srcLoc(mod))) { .ok => |atom_index| { - try wasm.getAtomPtr(parent_atom_index).locals.append(wasm.base.allocator, atom_index); + try wasm.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); return wasm.getAtom(atom_index).getSymbolIndex().?; }, .fail => |em| { @@ -1623,24 +1664,25 @@ const LowerConstResult = union(enum) { }; fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { + const gpa = wasm.base.comp.gpa; const mod = wasm.base.options.module.?; // Create and initialize a new local symbol and atom const atom_index = try wasm.createAtom(); - var value_bytes = std.ArrayList(u8).init(wasm.base.allocator); + var value_bytes = std.ArrayList(u8).init(gpa); defer value_bytes.deinit(); const code = code: { const atom = wasm.getAtomPtr(atom_index); atom.alignment = tv.ty.abiAlignment(mod); wasm.symbols.items[atom.sym_index] = .{ - .name = try wasm.string_table.put(wasm.base.allocator, name), + .name = try wasm.string_table.put(gpa, name), .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .tag = .data, .index = undefined, .virtual_address = undefined, }; - try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); + try wasm.resolved_symbols.putNoClobber(gpa, atom.symbolLoc(), {}); const result = try codegen.generateSymbol( &wasm.base, @@ -1663,7 +1705,7 @@ fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.Src const atom = wasm.getAtomPtr(atom_index); atom.size = @intCast(code.len); - try atom.code.appendSlice(wasm.base.allocator, code); + try atom.code.appendSlice(gpa, code); return .{ .ok = atom_index }; } @@ -1673,8 +1715,9 @@ fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.Src /// and then returns the index to it. pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u32 { _ = lib_name; - const name_index = try wasm.string_table.put(wasm.base.allocator, name); - const gop = try wasm.globals.getOrPut(wasm.base.allocator, name_index); + const gpa = wasm.base.comp.gpa; + const name_index = try wasm.string_table.put(gpa, name); + const gop = try wasm.globals.getOrPut(gpa, name_index); if (gop.found_existing) { return gop.value_ptr.*.index; } @@ -1691,14 +1734,14 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3 const sym_index = if (wasm.symbols_free_list.popOrNull()) |index| index else blk: { const index: u32 = @intCast(wasm.symbols.items.len); - try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1); + try wasm.symbols.ensureUnusedCapacity(gpa, 1); wasm.symbols.items.len += 1; break :blk index; }; wasm.symbols.items[sym_index] = symbol; gop.value_ptr.* = .{ .index = sym_index, .file = null }; - try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {}); - try wasm.undefs.putNoClobber(wasm.base.allocator, name_index, gop.value_ptr.*); + try wasm.resolved_symbols.put(gpa, gop.value_ptr.*, {}); + try wasm.undefs.putNoClobber(gpa, name_index, gop.value_ptr.*); return sym_index; } @@ -1709,6 +1752,7 @@ pub fn getDeclVAddr( decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo, ) !u64 { + const gpa = wasm.base.comp.gpa; const mod = wasm.base.options.module.?; const decl = mod.declPtr(decl_index); @@ -1725,17 +1769,17 @@ pub fn getDeclVAddr( // as function pointers are not allowed to be stored inside the data section. // They are instead stored in a function table which are called by index. try wasm.addTableFunction(target_symbol_index); - try atom.relocs.append(wasm.base.allocator, .{ + try atom.relocs.append(gpa, .{ .index = target_symbol_index, - .offset = @as(u32, @intCast(reloc_info.offset)), + .offset = @intCast(reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64, }); } else { - try atom.relocs.append(wasm.base.allocator, .{ + try atom.relocs.append(gpa, .{ .index = target_symbol_index, - .offset = @as(u32, @intCast(reloc_info.offset)), + .offset = @intCast(reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, - .addend = @as(i32, @intCast(reloc_info.addend)), + .addend = @intCast(reloc_info.addend), }); } // we do not know the final address at this point, @@ -1751,7 +1795,8 @@ pub fn lowerAnonDecl( explicit_alignment: Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val); + const gpa = wasm.base.comp.gpa; + const gop = try wasm.anon_decls.getOrPut(gpa, decl_val); if (!gop.found_existing) { const mod = wasm.base.options.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); @@ -1779,6 +1824,7 @@ pub fn lowerAnonDecl( } pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { + const gpa = wasm.base.comp.gpa; const atom_index = wasm.anon_decls.get(decl_val).?; const target_symbol_index = wasm.getAtom(atom_index).getSymbolIndex().?; @@ -1793,17 +1839,17 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin // as function pointers are not allowed to be stored inside the data section. // They are instead stored in a function table which are called by index. try wasm.addTableFunction(target_symbol_index); - try parent_atom.relocs.append(wasm.base.allocator, .{ + try parent_atom.relocs.append(gpa, .{ .index = target_symbol_index, - .offset = @as(u32, @intCast(reloc_info.offset)), + .offset = @intCast(reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64, }); } else { - try parent_atom.relocs.append(wasm.base.allocator, .{ + try parent_atom.relocs.append(gpa, .{ .index = target_symbol_index, - .offset = @as(u32, @intCast(reloc_info.offset)), + .offset = @intCast(reloc_info.offset), .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64, - .addend = @as(i32, @intCast(reloc_info.addend)), + .addend = @intCast(reloc_info.addend), }); } @@ -1840,8 +1886,6 @@ pub fn updateExports( } if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - if (wasm.base.options.emit == null) return; - const decl_index = switch (exported) { .decl_index => |i| i, .value => |val| { @@ -1880,7 +1924,7 @@ pub fn updateExports( }; const exported_atom_index = try wasm.getOrCreateAtomForDecl(exported_decl_index); const exported_atom = wasm.getAtom(exported_atom_index); - const export_name = try wasm.string_table.put(wasm.base.allocator, mod.intern_pool.stringToSlice(exp.opts.name)); + const export_name = try wasm.string_table.put(gpa, mod.intern_pool.stringToSlice(exp.opts.name)); const sym_loc = exported_atom.symbolLoc(); const symbol = sym_loc.getSymbol(wasm); symbol.setGlobal(true); @@ -1915,7 +1959,7 @@ pub fn updateExports( if (!existing_sym.isUndefined()) blk: { if (symbol.isWeak()) { - try wasm.discarded.put(wasm.base.allocator, existing_loc, sym_loc); + try wasm.discarded.put(gpa, existing_loc, sym_loc); continue; // to-be-exported symbol is weak, so we keep the existing symbol } @@ -1939,18 +1983,18 @@ pub fn updateExports( } // in this case the existing symbol must be replaced either because it's weak or undefined. - try wasm.discarded.put(wasm.base.allocator, existing_loc, sym_loc); + try wasm.discarded.put(gpa, existing_loc, sym_loc); _ = wasm.imports.remove(existing_loc); _ = wasm.undefs.swapRemove(existing_sym.name); } // Ensure the symbol will be exported using the given name if (!mod.intern_pool.stringEqlSlice(exp.opts.name, sym_loc.getName(wasm))) { - try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name); + try wasm.export_names.put(gpa, sym_loc, export_name); } try wasm.globals.put( - wasm.base.allocator, + gpa, export_name, sym_loc, ); @@ -1959,18 +2003,19 @@ pub fn updateExports( pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); + const gpa = wasm.base.comp.gpa; const mod = wasm.base.options.module.?; const decl = mod.declPtr(decl_index); const atom_index = wasm.decls.get(decl_index).?; const atom = wasm.getAtomPtr(atom_index); - wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {}; + wasm.symbols_free_list.append(gpa, atom.sym_index) catch {}; _ = wasm.decls.remove(decl_index); wasm.symbols.items[atom.sym_index].tag = .dead; for (atom.locals.items) |local_atom_index| { const local_atom = wasm.getAtom(local_atom_index); const local_symbol = &wasm.symbols.items[local_atom.sym_index]; local_symbol.tag = .dead; // also for any local symbol - wasm.symbols_free_list.append(wasm.base.allocator, local_atom.sym_index) catch {}; + wasm.symbols_free_list.append(gpa, local_atom.sym_index) catch {}; assert(wasm.resolved_symbols.swapRemove(local_atom.symbolLoc())); assert(wasm.symbol_atom.remove(local_atom.symbolLoc())); } @@ -1999,8 +2044,9 @@ pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { /// Appends a new entry to the indirect function table pub fn addTableFunction(wasm: *Wasm, symbol_index: u32) !void { - const index = @as(u32, @intCast(wasm.function_table.count())); - try wasm.function_table.put(wasm.base.allocator, .{ .file = null, .index = symbol_index }, index); + const gpa = wasm.base.comp.gpa; + const index: u32 = @intCast(wasm.function_table.count()); + try wasm.function_table.put(gpa, .{ .file = null, .index = symbol_index }, index); } /// Assigns indexes to all indirect functions. @@ -2019,7 +2065,7 @@ fn mapFunctionTable(wasm: *Wasm) void { } } - if (wasm.base.options.import_table or wasm.base.options.output_mode == .Obj) { + if (wasm.import_table or wasm.base.options.output_mode == .Obj) { const sym_loc = wasm.findGlobalSymbol("__indirect_function_table").?; const import = wasm.imports.getPtr(sym_loc).?; import.kind.table.limits.min = index - 1; // we start at index 1. @@ -2048,6 +2094,7 @@ pub fn addOrUpdateImport( /// is asserted instead. type_index: ?u32, ) !void { + const gpa = wasm.base.comp.gpa; assert(symbol_index != 0); // For the import name, we use the decl's name, rather than the fully qualified name // Also mangle the name when the lib name is set and not equal to "C" so imports with the same @@ -2055,11 +2102,11 @@ pub fn addOrUpdateImport( const mangle_name = lib_name != null and !std.mem.eql(u8, lib_name.?, "c"); const full_name = if (mangle_name) full_name: { - break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? }); + break :full_name try std.fmt.allocPrint(gpa, "{s}|{s}", .{ name, lib_name.? }); } else name; - defer if (mangle_name) wasm.base.allocator.free(full_name); + defer if (mangle_name) gpa.free(full_name); - const decl_name_index = try wasm.string_table.put(wasm.base.allocator, full_name); + const decl_name_index = try wasm.string_table.put(gpa, full_name); const symbol: *Symbol = &wasm.symbols.items[symbol_index]; symbol.setUndefined(true); symbol.setGlobal(true); @@ -2068,12 +2115,12 @@ pub fn addOrUpdateImport( // we specified a specific name for the symbol that does not match the import name symbol.setFlag(.WASM_SYM_EXPLICIT_NAME); } - const global_gop = try wasm.globals.getOrPut(wasm.base.allocator, decl_name_index); + const global_gop = try wasm.globals.getOrPut(gpa, decl_name_index); if (!global_gop.found_existing) { const loc: SymbolLoc = .{ .file = null, .index = symbol_index }; global_gop.value_ptr.* = loc; - try wasm.resolved_symbols.put(wasm.base.allocator, loc, {}); - try wasm.undefs.putNoClobber(wasm.base.allocator, decl_name_index, loc); + try wasm.resolved_symbols.put(gpa, loc, {}); + try wasm.undefs.putNoClobber(gpa, decl_name_index, loc); } else if (global_gop.value_ptr.*.index != symbol_index) { // We are not updating a symbol, but found an existing global // symbol with the same name. This means we always favor the @@ -2081,21 +2128,21 @@ pub fn addOrUpdateImport( // We can also skip storing the import as we will not output // this symbol. return wasm.discarded.put( - wasm.base.allocator, + gpa, .{ .file = null, .index = symbol_index }, global_gop.value_ptr.*, ); } if (type_index) |ty_index| { - const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null }); + const gop = try wasm.imports.getOrPut(gpa, .{ .index = symbol_index, .file = null }); const module_name = if (lib_name) |l_name| blk: { break :blk l_name; } else wasm.host_name; if (!gop.found_existing) { gop.value_ptr.* = .{ - .module_name = try wasm.string_table.put(wasm.base.allocator, module_name), - .name = try wasm.string_table.put(wasm.base.allocator, name), + .module_name = try wasm.string_table.put(gpa, module_name), + .name = try wasm.string_table.put(gpa, name), .kind = .{ .function = ty_index }, }; } @@ -2132,10 +2179,10 @@ const Kind = union(enum) { /// Parses an Atom and inserts its metadata into the corresponding sections. fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { + const gpa = wasm.base.comp.gpa; const atom = wasm.getAtomPtr(atom_index); const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); - const do_garbage_collect = wasm.base.options.gc_sections orelse - (wasm.base.options.output_mode != .Obj); + const do_garbage_collect = wasm.base.gc_sections; if (symbol.isDead() and do_garbage_collect) { // Prevent unreferenced symbols from being parsed. @@ -2147,7 +2194,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { const index: u32 = @intCast(wasm.functions.count() + wasm.imported_functions_count); const type_index = wasm.atom_types.get(atom_index).?; try wasm.functions.putNoClobber( - wasm.base.allocator, + gpa, .{ .file = null, .index = index }, .{ .func = .{ .type_index = type_index }, .sym_index = atom.sym_index }, ); @@ -2156,7 +2203,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { if (wasm.code_section_index == null) { wasm.code_section_index = @intCast(wasm.segments.items.len); - try wasm.segments.append(wasm.base.allocator, .{ + try wasm.segments.append(gpa, .{ .alignment = atom.alignment, .size = atom.size, .offset = 0, @@ -2167,11 +2214,11 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { break :result wasm.code_section_index.?; }, .data => result: { - const segment_name = try std.mem.concat(wasm.base.allocator, u8, &.{ + const segment_name = try std.mem.concat(gpa, u8, &.{ kind.segmentName(), wasm.string_table.get(symbol.name), }); - errdefer wasm.base.allocator.free(segment_name); + errdefer gpa.free(segment_name); const segment_info: types.Segment = .{ .name = segment_name, .alignment = atom.alignment, @@ -2188,14 +2235,14 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { } const should_merge = wasm.base.options.output_mode != .Obj; - const gop = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(should_merge)); + const gop = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(should_merge)); if (gop.found_existing) { const index = gop.value_ptr.*; wasm.segments.items[index].size += atom.size; symbol.index = @intCast(wasm.segment_info.getIndex(index).?); // segment info already exists, so free its memory - wasm.base.allocator.free(segment_name); + gpa.free(segment_name); break :result index; } else { const index: u32 = @intCast(wasm.segments.items.len); @@ -2203,7 +2250,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { if (wasm.base.options.shared_memory) { flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); } - try wasm.segments.append(wasm.base.allocator, .{ + try wasm.segments.append(gpa, .{ .alignment = atom.alignment, .size = 0, .offset = 0, @@ -2212,7 +2259,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { gop.value_ptr.* = index; const info_index: u32 = @intCast(wasm.segment_info.count()); - try wasm.segment_info.put(wasm.base.allocator, index, segment_info); + try wasm.segment_info.put(gpa, index, segment_info); symbol.index = info_index; break :result index; } @@ -2228,6 +2275,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { /// From a given index, append the given `Atom` at the back of the linked list. /// Simply inserts it into the map of atoms when it doesn't exist yet. pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void { + const gpa = wasm.base.comp.gpa; const atom = wasm.getAtomPtr(atom_index); if (wasm.atoms.getPtr(index)) |last_index_ptr| { const last = wasm.getAtomPtr(last_index_ptr.*); @@ -2235,7 +2283,7 @@ pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom_index: Atom.Index) !void atom.prev = last_index_ptr.*; last_index_ptr.* = atom_index; } else { - try wasm.atoms.putNoClobber(wasm.base.allocator, index, atom_index); + try wasm.atoms.putNoClobber(gpa, index, atom_index); } } @@ -2363,12 +2411,13 @@ fn allocateVirtualAddresses(wasm: *Wasm) void { } fn sortDataSegments(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{}; - try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count()); - errdefer new_mapping.deinit(wasm.base.allocator); + try new_mapping.ensureUnusedCapacity(gpa, wasm.data_segments.count()); + errdefer new_mapping.deinit(gpa); - const keys = try wasm.base.allocator.dupe([]const u8, wasm.data_segments.keys()); - defer wasm.base.allocator.free(keys); + const keys = try gpa.dupe([]const u8, wasm.data_segments.keys()); + defer gpa.free(keys); const SortContext = struct { fn sort(_: void, lhs: []const u8, rhs: []const u8) bool { @@ -2388,7 +2437,7 @@ fn sortDataSegments(wasm: *Wasm) !void { const segment_index = wasm.data_segments.get(key).?; new_mapping.putAssumeCapacity(key, segment_index); } - wasm.data_segments.deinit(wasm.base.allocator); + wasm.data_segments.deinit(gpa); wasm.data_segments = new_mapping; } @@ -2401,8 +2450,9 @@ fn sortDataSegments(wasm: *Wasm) !void { /// original functions and their types. We need to know the type to verify it doesn't /// contain any parameters. fn setupInitFunctions(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; for (wasm.objects.items, 0..) |object, file_index| { - try wasm.init_funcs.ensureUnusedCapacity(wasm.base.allocator, object.init_funcs.len); + try wasm.init_funcs.ensureUnusedCapacity(gpa, object.init_funcs.len); for (object.init_funcs) |init_func| { const symbol = object.symtable[init_func.symbol_index]; const ty: std.wasm.Type = if (symbol.isUndefined()) ty: { @@ -2439,6 +2489,7 @@ fn setupInitFunctions(wasm: *Wasm) !void { /// Generates an atom containing the global error set' size. /// This will only be generated if the symbol exists. fn setupErrorsLen(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; const loc = wasm.findGlobalSymbol("__zig_errors_len") orelse return; const errors_len = wasm.base.options.module.?.global_error_set.count(); @@ -2456,19 +2507,19 @@ fn setupErrorsLen(wasm: *Wasm) !void { prev_atom.next = atom.next; atom.prev = null; } - atom.deinit(wasm.base.allocator); + atom.deinit(gpa); break :blk index; } else new_atom: { const atom_index: Atom.Index = @intCast(wasm.managed_atoms.items.len); - try wasm.symbol_atom.put(wasm.base.allocator, loc, atom_index); - try wasm.managed_atoms.append(wasm.base.allocator, undefined); + try wasm.symbol_atom.put(gpa, loc, atom_index); + try wasm.managed_atoms.append(gpa, undefined); break :new_atom atom_index; }; const atom = wasm.getAtomPtr(atom_index); atom.* = Atom.empty; atom.sym_index = loc.index; atom.size = 2; - try atom.code.writer(wasm.base.allocator).writeInt(u16, @intCast(errors_len), .little); + try atom.code.writer(gpa).writeInt(u16, @intCast(errors_len), .little); try wasm.parseAtom(atom_index, .{ .data = .read_only }); } @@ -2480,16 +2531,17 @@ fn setupErrorsLen(wasm: *Wasm) !void { /// references to the function stored in the symbol have been finalized so we end /// up calling the resolved function. fn initializeCallCtorsFunction(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; // No code to emit, so also no ctors to call if (wasm.code_section_index == null) { // Make sure to remove it from the resolved symbols so we do not emit // it within any section. TODO: Remove this once we implement garbage collection. const loc = wasm.findGlobalSymbol("__wasm_call_ctors").?; - std.debug.assert(wasm.resolved_symbols.swapRemove(loc)); + assert(wasm.resolved_symbols.swapRemove(loc)); return; } - var function_body = std.ArrayList(u8).init(wasm.base.allocator); + var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); const writer = function_body.writer(); @@ -2531,6 +2583,7 @@ fn createSyntheticFunction( func_ty: std.wasm.Type, function_body: *std.ArrayList(u8), ) !void { + const gpa = wasm.base.comp.gpa; const loc = wasm.findGlobalSymbol(symbol_name) orelse try wasm.createSyntheticSymbol(symbol_name, .function); const symbol = loc.getSymbol(wasm); @@ -2541,7 +2594,7 @@ fn createSyntheticFunction( // create function with above type const func_index = wasm.imported_functions_count + @as(u32, @intCast(wasm.functions.count())); try wasm.functions.putNoClobber( - wasm.base.allocator, + gpa, .{ .file = null, .index = func_index }, .{ .func = .{ .type_index = ty_index }, .sym_index = loc.index }, ); @@ -2549,7 +2602,7 @@ fn createSyntheticFunction( // create the atom that will be output into the final binary const atom_index = @as(Atom.Index, @intCast(wasm.managed_atoms.items.len)); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); + const atom = try wasm.managed_atoms.addOne(gpa); atom.* = .{ .size = @as(u32, @intCast(function_body.items.len)), .offset = 0, @@ -2562,7 +2615,7 @@ fn createSyntheticFunction( .original_offset = 0, }; try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index); - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); + try wasm.symbol_atom.putNoClobber(gpa, loc, atom_index); // `allocateAtoms` has already been called, set the atom's offset manually. // This is fine to do manually as we insert the atom at the very end. @@ -2582,10 +2635,11 @@ pub fn createFunction( function_body: *std.ArrayList(u8), relocations: *std.ArrayList(Relocation), ) !u32 { + const gpa = wasm.base.comp.gpa; const loc = try wasm.createSyntheticSymbol(symbol_name, .function); - const atom_index = @as(Atom.Index, @intCast(wasm.managed_atoms.items.len)); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); + const atom_index: Atom.Index = @intCast(wasm.managed_atoms.items.len); + const atom = try wasm.managed_atoms.addOne(gpa); atom.* = .{ .size = @intCast(function_body.items.len), .offset = 0, @@ -2607,9 +2661,9 @@ pub fn createFunction( break :idx index; }; try wasm.appendAtomAtIndex(section_index, atom_index); - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); - try wasm.atom_types.put(wasm.base.allocator, atom_index, try wasm.putOrGetFuncType(func_ty)); - try wasm.synthetic_functions.append(wasm.base.allocator, atom_index); + try wasm.symbol_atom.putNoClobber(gpa, loc, atom_index); + try wasm.atom_types.put(gpa, atom_index, try wasm.putOrGetFuncType(func_ty)); + try wasm.synthetic_functions.append(gpa, atom_index); return loc.index; } @@ -2622,9 +2676,11 @@ fn setupStartSection(wasm: *Wasm) !void { } fn initializeTLSFunction(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; + if (!wasm.base.options.shared_memory) return; - var function_body = std.ArrayList(u8).init(wasm.base.allocator); + var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); const writer = function_body.writer(); @@ -2684,6 +2740,7 @@ fn initializeTLSFunction(wasm: *Wasm) !void { } fn setupImports(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; log.debug("Merging imports", .{}); var discarded_it = wasm.discarded.keyIterator(); while (discarded_it.next()) |discarded| { @@ -2718,12 +2775,12 @@ fn setupImports(wasm: *Wasm) !void { // We copy the import to a new import to ensure the names contain references // to the internal string table, rather than of the object file. const new_imp: types.Import = .{ - .module_name = try wasm.string_table.put(wasm.base.allocator, object.string_table.get(import.module_name)), - .name = try wasm.string_table.put(wasm.base.allocator, object.string_table.get(import.name)), + .module_name = try wasm.string_table.put(gpa, object.string_table.get(import.module_name)), + .name = try wasm.string_table.put(gpa, object.string_table.get(import.name)), .kind = import.kind, }; // TODO: De-duplicate imports when they contain the same names and type - try wasm.imports.putNoClobber(wasm.base.allocator, symbol_loc, new_imp); + try wasm.imports.putNoClobber(gpa, symbol_loc, new_imp); } // Assign all indexes of the imports to their representing symbols @@ -2764,7 +2821,9 @@ fn setupImports(wasm: *Wasm) !void { /// Takes the global, function and table section from each linked object file /// and merges it into a single section for each. fn mergeSections(wasm: *Wasm) !void { - var removed_duplicates = std.ArrayList(SymbolLoc).init(wasm.base.allocator); + const gpa = wasm.base.comp.gpa; + + var removed_duplicates = std.ArrayList(SymbolLoc).init(gpa); defer removed_duplicates.deinit(); for (wasm.resolved_symbols.keys()) |sym_loc| { @@ -2791,7 +2850,7 @@ fn mergeSections(wasm: *Wasm) !void { switch (symbol.tag) { .function => { const gop = try wasm.functions.getOrPut( - wasm.base.allocator, + gpa, .{ .file = sym_loc.file, .index = symbol.index }, ); if (gop.found_existing) { @@ -2800,7 +2859,7 @@ fn mergeSections(wasm: *Wasm) !void { // we only emit a single function, instead of duplicates. symbol.unmark(); try wasm.discarded.putNoClobber( - wasm.base.allocator, + gpa, sym_loc, .{ .file = gop.key_ptr.*.file, .index = gop.value_ptr.*.sym_index }, ); @@ -2813,12 +2872,12 @@ fn mergeSections(wasm: *Wasm) !void { .global => { const original_global = object.globals[index]; symbol.index = @as(u32, @intCast(wasm.wasm_globals.items.len)) + wasm.imported_globals_count; - try wasm.wasm_globals.append(wasm.base.allocator, original_global); + try wasm.wasm_globals.append(gpa, original_global); }, .table => { const original_table = object.tables[index]; symbol.index = @as(u32, @intCast(wasm.tables.items.len)) + wasm.imported_tables_count; - try wasm.tables.append(wasm.base.allocator, original_table); + try wasm.tables.append(gpa, original_table); }, else => unreachable, } @@ -2838,10 +2897,11 @@ fn mergeSections(wasm: *Wasm) !void { /// 'types' section, while assigning the type index to the representing /// section (import, export, function). fn mergeTypes(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; // A map to track which functions have already had their // type inserted. If we do this for the same function multiple times, // it will be overwritten with the incorrect type. - var dirty = std.AutoHashMap(u32, void).init(wasm.base.allocator); + var dirty = std.AutoHashMap(u32, void).init(gpa); try dirty.ensureUnusedCapacity(@as(u32, @intCast(wasm.functions.count()))); defer dirty.deinit(); @@ -2873,6 +2933,7 @@ fn mergeTypes(wasm: *Wasm) !void { } fn setupExports(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; if (wasm.base.options.output_mode == .Obj) return; log.debug("Building exports from symbols", .{}); @@ -2903,11 +2964,11 @@ fn setupExports(wasm: *Wasm) !void { const sym_name = sym_loc.getName(wasm); const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: { if (sym_loc.file == null) break :blk symbol.name; - break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); + break :blk try wasm.string_table.put(gpa, sym_name); }; const exp: types.Export = if (symbol.tag == .data) exp: { const global_index = @as(u32, @intCast(wasm.imported_globals_count + wasm.wasm_globals.items.len)); - try wasm.wasm_globals.append(wasm.base.allocator, .{ + try wasm.wasm_globals.append(gpa, .{ .global_type = .{ .valtype = .i32, .mutable = false }, .init = .{ .i32_const = @as(i32, @intCast(symbol.virtual_address)) }, }); @@ -2926,7 +2987,7 @@ fn setupExports(wasm: *Wasm) !void { wasm.string_table.get(exp.name), exp.index, }); - try wasm.exports.append(wasm.base.allocator, exp); + try wasm.exports.append(gpa, exp); } log.debug("Completed building exports. Total count: ({d})", .{wasm.exports.items.len}); @@ -2957,8 +3018,6 @@ fn setupStart(wasm: *Wasm) !void { fn setupMemory(wasm: *Wasm) !void { log.debug("Setting up memory layout", .{}); const page_size = std.wasm.page_size; // 64kb - // Use the user-provided stack size or else we use 1MB by default - const stack_size = wasm.base.options.stack_size_override orelse page_size * 16; const stack_alignment: Alignment = .@"16"; // wasm's stack alignment as specified by tool-convention const heap_alignment: Alignment = .@"16"; // wasm's heap alignment as specified by tool-convention @@ -2974,7 +3033,7 @@ fn setupMemory(wasm: *Wasm) !void { if (place_stack_first and !is_obj) { memory_ptr = stack_alignment.forward(memory_ptr); - memory_ptr += stack_size; + memory_ptr += wasm.base.stack_size; // We always put the stack pointer global at index 0 wasm.wasm_globals.items[0].init.i32_const = @as(i32, @bitCast(@as(u32, @intCast(memory_ptr)))); } @@ -3021,7 +3080,7 @@ fn setupMemory(wasm: *Wasm) !void { if (!place_stack_first and !is_obj) { memory_ptr = stack_alignment.forward(memory_ptr); - memory_ptr += stack_size; + memory_ptr += wasm.base.stack_size; wasm.wasm_globals.items[0].init.i32_const = @as(i32, @bitCast(@as(u32, @intCast(memory_ptr)))); } @@ -3088,29 +3147,30 @@ fn setupMemory(wasm: *Wasm) !void { /// index of the segment within the final data section. When the segment does not yet /// exist, a new one will be initialized and appended. The new index will be returned in that case. pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u32 { + const gpa = wasm.base.comp.gpa; const object: Object = wasm.objects.items[object_index]; const symbol = object.symtable[symbol_index]; - const index = @as(u32, @intCast(wasm.segments.items.len)); + const index: u32 = @intCast(wasm.segments.items.len); switch (symbol.tag) { .data => { const segment_info = object.segment_info[symbol.index]; const merge_segment = wasm.base.options.output_mode != .Obj; - const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment)); + const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment)); if (!result.found_existing) { result.value_ptr.* = index; var flags: u32 = 0; if (wasm.base.options.shared_memory) { flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); } - try wasm.segments.append(wasm.base.allocator, .{ + try wasm.segments.append(gpa, .{ .alignment = .@"1", .size = 0, .offset = 0, .flags = flags, }); - try wasm.segment_info.putNoClobber(wasm.base.allocator, index, .{ - .name = try wasm.base.allocator.dupe(u8, segment_info.name), + try wasm.segment_info.putNoClobber(gpa, index, .{ + .name = try gpa.dupe(u8, segment_info.name), .alignment = segment_info.alignment, .flags = segment_info.flags, }); @@ -3183,7 +3243,8 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u3 /// Appends a new segment with default field values fn appendDummySegment(wasm: *Wasm) !void { - try wasm.segments.append(wasm.base.allocator, .{ + const gpa = wasm.base.comp.gpa; + try wasm.segments.append(gpa, .{ .alignment = .@"1", .size = 0, .offset = 0, @@ -3203,6 +3264,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { // and then return said symbol's index. The final table will be populated // during `flush` when we know all possible error names. + const gpa = wasm.base.comp.gpa; const atom_index = try wasm.createAtom(); const atom = wasm.getAtomPtr(atom_index); const slice_ty = Type.slice_const_u8_sentinel_0; @@ -3210,7 +3272,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { atom.alignment = slice_ty.abiAlignment(mod); const sym_index = atom.sym_index; - const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table"); + const sym_name = try wasm.string_table.put(gpa, "__zig_err_name_table"); const symbol = &wasm.symbols.items[sym_index]; symbol.* = .{ .name = sym_name, @@ -3222,7 +3284,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); symbol.mark(); - try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {}); + try wasm.resolved_symbols.put(gpa, atom.symbolLoc(), {}); log.debug("Error name table was created with symbol index: ({d})", .{sym_index}); wasm.error_table_symbol = sym_index; @@ -3234,6 +3296,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { /// This creates a table that consists of pointers and length to each error name. /// The table is what is being pointed to within the runtime bodies that are generated. fn populateErrorNameTable(wasm: *Wasm) !void { + const gpa = wasm.base.comp.gpa; const symbol_index = wasm.error_table_symbol orelse return; const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?; @@ -3243,7 +3306,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { const names_atom_index = try wasm.createAtom(); const names_atom = wasm.getAtomPtr(names_atom_index); names_atom.alignment = .@"1"; - const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_names"); + const sym_name = try wasm.string_table.put(gpa, "__zig_err_names"); const names_symbol = &wasm.symbols.items[names_atom.sym_index]; names_symbol.* = .{ .name = sym_name, @@ -3269,10 +3332,10 @@ fn populateErrorNameTable(wasm: *Wasm) !void { const slice_ty = Type.slice_const_u8_sentinel_0; const offset = @as(u32, @intCast(atom.code.items.len)); // first we create the data for the slice of the name - try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated - try atom.code.writer(wasm.base.allocator).writeInt(u32, len - 1, .little); + try atom.code.appendNTimes(gpa, 0, 4); // ptr to name, will be relocated + try atom.code.writer(gpa).writeInt(u32, len - 1, .little); // create relocation to the error name - try atom.relocs.append(wasm.base.allocator, .{ + try atom.relocs.append(gpa, .{ .index = names_atom.sym_index, .relocation_type = .R_WASM_MEMORY_ADDR_I32, .offset = offset, @@ -3282,7 +3345,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { addend += len; // as we updated the error name table, we now store the actual name within the names atom - try names_atom.code.ensureUnusedCapacity(wasm.base.allocator, len); + try names_atom.code.ensureUnusedCapacity(gpa, len); names_atom.code.appendSliceAssumeCapacity(error_name); names_atom.code.appendAssumeCapacity(0); @@ -3291,8 +3354,8 @@ fn populateErrorNameTable(wasm: *Wasm) !void { names_atom.size = addend; const name_loc = names_atom.symbolLoc(); - try wasm.resolved_symbols.put(wasm.base.allocator, name_loc, {}); - try wasm.symbol_atom.put(wasm.base.allocator, name_loc, names_atom_index); + try wasm.resolved_symbols.put(gpa, name_loc, {}); + try wasm.symbol_atom.put(gpa, name_loc, names_atom_index); // link the atoms with the rest of the binary so they can be allocated // and relocations will be performed. @@ -3304,7 +3367,8 @@ fn populateErrorNameTable(wasm: *Wasm) !void { /// This initializes the index, appends a new segment, /// and finally, creates a managed `Atom`. pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !Atom.Index { - const new_index = @as(u32, @intCast(wasm.segments.items.len)); + const gpa = wasm.base.comp.gpa; + const new_index: u32 = @intCast(wasm.segments.items.len); index.* = new_index; try wasm.appendDummySegment(); @@ -3312,7 +3376,7 @@ pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) ! const atom = wasm.getAtomPtr(atom_index); wasm.symbols.items[atom.sym_index] = .{ .tag = .section, - .name = try wasm.string_table.put(wasm.base.allocator, name), + .name = try wasm.string_table.put(gpa, name), .index = 0, .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL), }; @@ -3322,8 +3386,10 @@ pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) ! } fn resetState(wasm: *Wasm) void { + const gpa = wasm.base.comp.gpa; + for (wasm.segment_info.values()) |segment_info| { - wasm.base.allocator.free(segment_info.name); + gpa.free(segment_info.name); } var atom_it = wasm.decls.valueIterator(); @@ -3358,16 +3424,12 @@ fn resetState(wasm: *Wasm) void { } pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (wasm.base.options.emit == null) { - if (wasm.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); - } - return; - } + const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld; + const use_llvm = wasm.base.comp.config.use_llvm; - if (build_options.have_llvm and wasm.base.options.use_lld) { + if (use_lld) { return wasm.linkWithLLD(comp, prog_node); - } else if (wasm.base.options.use_llvm and !wasm.base.options.use_lld) { + } else if (use_llvm and !use_lld) { return wasm.linkWithZld(comp, prog_node); } else { return wasm.flushModule(comp, prog_node); @@ -3379,21 +3441,22 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const tracy = trace(@src()); defer tracy.end(); - const gpa = wasm.base.allocator; - const options = wasm.base.options; + const gpa = wasm.base.comp.gpa; // Used for all temporary memory allocated during flushin var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = arena_instance.allocator(); - const directory = options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{options.emit.?.sub_path}); + const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); + const opt_zcu = wasm.base.comp.module; + const use_llvm = wasm.base.comp.config.use_llvm; // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (options.module != null) blk: { - assert(options.use_llvm); // `linkWithZld` should never be called when the Wasm backend is used + const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { + assert(use_llvm); // `linkWithZld` should never be called when the Wasm backend is used try wasm.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -3416,12 +3479,14 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const id_symlink_basename = "zld.id"; var man: Cache.Manifest = undefined; - defer if (!options.disable_lld_caching) man.deinit(); + defer if (!wasm.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; + const objects = wasm.base.comp.objects; + // NOTE: The following section must be maintained to be equal // as the section defined in `linkWithLLD` - if (!options.disable_lld_caching) { + if (!wasm.base.disable_lld_caching) { man = comp.cache_parent.obtain(); // We are about to obtain this lock, so here we give other processes a chance first. @@ -3429,7 +3494,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l comptime assert(Compilation.link_hash_implementation_version == 10); - for (options.objects) |obj| { + for (objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); } @@ -3438,19 +3503,19 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(options.entry); - man.hash.addOptional(options.stack_size_override); - man.hash.add(wasm.base.options.build_id); - man.hash.add(options.import_memory); - man.hash.add(options.import_table); - man.hash.add(options.export_table); - man.hash.addOptional(options.initial_memory); - man.hash.addOptional(options.max_memory); - man.hash.add(options.shared_memory); - man.hash.addOptional(options.global_base); - man.hash.add(options.export_symbol_names.len); + man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.add(wasm.base.stack_size); + man.hash.add(wasm.base.build_id); + man.hash.add(wasm.base.comp.config.import_memory); + man.hash.add(wasm.base.comp.config.shared_memory); + man.hash.add(wasm.import_table); + man.hash.add(wasm.export_table); + man.hash.addOptional(wasm.initial_memory); + man.hash.addOptional(wasm.max_memory); + man.hash.addOptional(wasm.global_base); + man.hash.add(wasm.export_symbol_names.len); // strip does not need to go into the linker hash because it is part of the hash namespace - for (options.export_symbol_names) |symbol_name| { + for (wasm.export_symbol_names) |symbol_name| { man.hash.addBytes(symbol_name); } @@ -3485,30 +3550,36 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList([]const u8).init(arena); - try positionals.ensureUnusedCapacity(options.objects.len); + try positionals.ensureUnusedCapacity(objects.len); + + const target = wasm.base.comp.root_mod.resolved_target.result; + const output_mode = wasm.base.comp.config.output_mode; + const link_mode = wasm.base.comp.config.link_mode; + const link_libc = wasm.base.comp.config.link_libc; + const link_libcpp = wasm.base.comp.config.link_libcpp; + const wasi_exec_model = wasm.base.comp.config.wasi_exec_model; // When the target os is WASI, we allow linking with WASI-LIBC - if (options.target.os.tag == .wasi) { - const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or - (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); + if (target.os.tag == .wasi) { + const is_exe_or_dyn_lib = output_mode == .Exe or + (output_mode == .Lib and link_mode == .Dynamic); if (is_exe_or_dyn_lib) { - const wasi_emulated_libs = wasm.base.options.wasi_emulated_libs; - for (wasi_emulated_libs) |crt_file| { + for (wasm.wasi_emulated_libs) |crt_file| { try positionals.append(try comp.get_libc_crt_file( arena, wasi_libc.emulatedLibCRFileLibName(crt_file), )); } - if (wasm.base.options.link_libc) { + if (link_libc) { try positionals.append(try comp.get_libc_crt_file( arena, - wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model), + wasi_libc.execModelCrtFileFullName(wasi_exec_model), )); try positionals.append(try comp.get_libc_crt_file(arena, "libc.a")); } - if (wasm.base.options.link_libcpp) { + if (link_libcpp) { try positionals.append(comp.libcxx_static_lib.?.full_object_path); try positionals.append(comp.libcxxabi_static_lib.?.full_object_path); } @@ -3519,7 +3590,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try positionals.append(path); } - for (options.objects) |object| { + for (objects) |object| { try positionals.append(object.path); } @@ -3562,7 +3633,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try wasm.setupExports(); try wasm.writeToFile(enabled_features, emit_features_count, arena); - if (!wasm.base.options.disable_lld_caching) { + if (!wasm.base.disable_lld_caching) { // Update the file with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { @@ -3594,15 +3665,18 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try wasm.populateErrorNameTable(); // Used for all temporary memory allocated during flushin - var arena_instance = std.heap.ArenaAllocator.init(wasm.base.allocator); + const gpa = wasm.base.comp.gpa; + var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = arena_instance.allocator(); + const objects = wasm.base.comp.objects; + // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList([]const u8).init(arena); - try positionals.ensureUnusedCapacity(wasm.base.options.objects.len); + try positionals.ensureUnusedCapacity(objects.len); - for (wasm.base.options.objects) |object| { + for (objects) |object| { positionals.appendAssumeCapacity(object.path); } @@ -3711,6 +3785,10 @@ fn writeToFile( feature_count: u32, arena: Allocator, ) !void { + const gpa = wasm.base.comp.gpa; + const use_llvm = wasm.base.comp.config.use_llvm; + const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld; + // Size of each section header const header_size = 5 + 1; // The amount of sections that will be written @@ -3719,9 +3797,9 @@ fn writeToFile( var code_section_index: ?u32 = null; // Index of the data section. Used to tell relocation table where the section lives. var data_section_index: ?u32 = null; - const is_obj = wasm.base.options.output_mode == .Obj or (!wasm.base.options.use_llvm and wasm.base.options.use_lld); + const is_obj = wasm.base.options.output_mode == .Obj or (!use_llvm and use_lld); - var binary_bytes = std.ArrayList(u8).init(wasm.base.allocator); + var binary_bytes = std.ArrayList(u8).init(gpa); defer binary_bytes.deinit(); const binary_writer = binary_bytes.writer(); @@ -3774,8 +3852,8 @@ fn writeToFile( if (import_memory) { const mem_name = if (is_obj) "__linear_memory" else "memory"; const mem_imp: types.Import = .{ - .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name), - .name = try wasm.string_table.put(wasm.base.allocator, mem_name), + .module_name = try wasm.string_table.put(gpa, wasm.host_name), + .name = try wasm.string_table.put(gpa, mem_name), .kind = .{ .memory = wasm.memories.limits }, }; try wasm.emitImport(binary_writer, mem_imp); @@ -3955,7 +4033,7 @@ fn writeToFile( var atom_index = wasm.atoms.get(code_index).?; // The code section must be sorted in line with the function order. - var sorted_atoms = try std.ArrayList(*const Atom).initCapacity(wasm.base.allocator, wasm.functions.count()); + var sorted_atoms = try std.ArrayList(*const Atom).initCapacity(gpa, wasm.functions.count()); defer sorted_atoms.deinit(); while (true) { @@ -3966,7 +4044,7 @@ fn writeToFile( sorted_atoms.appendAssumeCapacity(atom); // found more code atoms than functions atom_index = atom.prev orelse break; } - std.debug.assert(wasm.functions.count() == sorted_atoms.items.len); + assert(wasm.functions.count() == sorted_atoms.items.len); const atom_sort_fn = struct { fn sort(ctx: *const Wasm, lhs: *const Atom, rhs: *const Atom) bool { @@ -4086,7 +4164,7 @@ fn writeToFile( if (!wasm.base.options.strip) { // The build id must be computed on the main sections only, // so we have to do it now, before the debug sections. - switch (wasm.base.options.build_id) { + switch (wasm.base.build_id) { .none => {}, .fast => { var id: [16]u8 = undefined; @@ -4121,7 +4199,7 @@ fn writeToFile( // try dwarf.writeDbgLineHeader(); // } - var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator); + var debug_bytes = std.ArrayList(u8).init(gpa); defer debug_bytes.deinit(); const DebugSection = struct { @@ -4362,8 +4440,10 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem } fn emitNameSubsection(wasm: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void { + const gpa = wasm.base.comp.gpa; + // We must emit subsection size, so first write to a temporary list - var section_list = std.ArrayList(u8).init(wasm.base.allocator); + var section_list = std.ArrayList(u8).init(gpa); defer section_list.deinit(); const sub_writer = section_list.writer(); @@ -4445,12 +4525,13 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(wasm.base.allocator); + const gpa = wasm.base.comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const directory = wasm.base.options.emit.?.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.options.emit.?.sub_path}); + const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. + const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. @@ -4481,11 +4562,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const id_symlink_basename = "lld.id"; var man: Cache.Manifest = undefined; - defer if (!wasm.base.options.disable_lld_caching) man.deinit(); + defer if (!wasm.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - if (!wasm.base.options.disable_lld_caching) { + if (!wasm.base.disable_lld_caching) { man = comp.cache_parent.obtain(); // We are about to obtain this lock, so here we give other processes a chance first. @@ -4502,13 +4583,13 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(wasm.base.options.entry); - man.hash.addOptional(wasm.base.options.stack_size_override); - man.hash.add(wasm.base.options.build_id); + man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.add(wasm.base.stack_size); + man.hash.add(wasm.base.build_id); man.hash.add(wasm.base.options.import_memory); man.hash.add(wasm.base.options.export_memory); - man.hash.add(wasm.base.options.import_table); - man.hash.add(wasm.base.options.export_table); + man.hash.add(wasm.import_table); + man.hash.add(wasm.export_table); man.hash.addOptional(wasm.base.options.initial_memory); man.hash.addOptional(wasm.base.options.max_memory); man.hash.add(wasm.base.options.shared_memory); @@ -4573,7 +4654,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } } else { // Create an LLD command line and invoke it. - var argv = std.ArrayList([]const u8).init(wasm.base.allocator); + var argv = std.ArrayList([]const u8).init(gpa); defer argv.deinit(); // We will invoke ourselves as a child process to gain access to LLD. // This is necessary because LLD does not behave properly as a library - @@ -4598,22 +4679,20 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--export-memory"); } - if (wasm.base.options.import_table) { - assert(!wasm.base.options.export_table); + if (wasm.import_table) { + assert(!wasm.export_table); try argv.append("--import-table"); } - if (wasm.base.options.export_table) { - assert(!wasm.base.options.import_table); + if (wasm.export_table) { + assert(!wasm.import_table); try argv.append("--export-table"); } - if (wasm.base.options.gc_sections) |gc| { - // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly - // specified it as garbage collection is enabled by default. - if (!gc) { - try argv.append("--no-gc-sections"); - } + // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly + // specified it as garbage collection is enabled by default. + if (!wasm.base.gc_sections) { + try argv.append("--no-gc-sections"); } if (wasm.base.options.strip) { @@ -4662,12 +4741,10 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--no-entry"); } - // Increase the default stack size to a more reasonable value of 1MB instead of - // the default of 1 Wasm page being 64KB, unless overridden by the user. - try argv.append("-z"); - const stack_size = wasm.base.options.stack_size_override orelse std.wasm.page_size * 16; - const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); - try argv.append(arg); + try argv.appendSlice(&.{ + "-z", + try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}), + }); if (wasm.base.options.import_symbols) { try argv.append("--allow-undefined"); @@ -4681,7 +4758,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } // XXX - TODO: add when wasm-ld supports --build-id. - // if (wasm.base.options.build_id) { + // if (wasm.base.build_id) { // try argv.append("--build-id=tree"); // } @@ -4695,8 +4772,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); if (is_exe_or_dyn_lib) { - const wasi_emulated_libs = wasm.base.options.wasi_emulated_libs; - for (wasi_emulated_libs) |crt_file| { + for (wasm.wasi_emulated_libs) |crt_file| { try argv.append(try comp.get_libc_crt_file( arena, wasi_libc.emulatedLibCRFileLibName(crt_file), @@ -4753,7 +4829,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.options.verbose_link) { + if (wasm.base.comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } @@ -4838,7 +4914,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } } - if (!wasm.base.options.disable_lld_caching) { + if (!wasm.base.disable_lld_caching) { // Update the file with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { @@ -5113,14 +5189,15 @@ pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { if (wasm.getTypeIndex(func_type)) |index| { return index; } + const gpa = wasm.base.comp.gpa; // functype does not exist. - const index = @as(u32, @intCast(wasm.func_types.items.len)); - const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params); - errdefer wasm.base.allocator.free(params); - const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns); - errdefer wasm.base.allocator.free(returns); - try wasm.func_types.append(wasm.base.allocator, .{ + const index: u32 = @intCast(wasm.func_types.items.len); + const params = try gpa.dupe(std.wasm.Valtype, func_type.params); + errdefer gpa.free(params); + const returns = try gpa.dupe(std.wasm.Valtype, func_type.returns); + errdefer gpa.free(returns); + try wasm.func_types.append(gpa, .{ .params = params, .returns = returns, }); @@ -5131,9 +5208,10 @@ pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 { /// Asserts declaration has an associated `Atom`. /// Returns the index into the list of types. pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: std.wasm.Type) !u32 { + const gpa = wasm.base.comp.gpa; const atom_index = wasm.decls.get(decl_index).?; const index = try wasm.putOrGetFuncType(func_type); - try wasm.atom_types.put(wasm.base.allocator, atom_index, index); + try wasm.atom_types.put(gpa, atom_index, index); return index; } @@ -5142,8 +5220,7 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s fn markReferences(wasm: *Wasm) !void { const tracy = trace(@src()); defer tracy.end(); - const do_garbage_collect = wasm.base.options.gc_sections orelse - (wasm.base.options.output_mode != .Obj); + const do_garbage_collect = wasm.base.gc_sections; for (wasm.resolved_symbols.keys()) |sym_loc| { const sym = sym_loc.getSymbol(wasm); diff --git a/src/main.zig b/src/main.zig index 5685ddad27b2..4f701398ca01 100644 --- a/src/main.zig +++ b/src/main.zig @@ -842,7 +842,7 @@ fn buildOutputType( var linker_print_gc_sections: bool = false; var linker_print_icf_sections: bool = false; var linker_print_map: bool = false; - var linker_opt_bisect_limit: i32 = -1; + var llvm_opt_bisect_limit: c_int = -1; var linker_z_nocopyreloc = false; var linker_z_nodelete = false; var linker_z_notext = false; @@ -859,7 +859,7 @@ fn buildOutputType( var linker_module_definition_file: ?[]const u8 = null; var test_no_exec = false; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; - var stack_size_override: ?u64 = null; + var stack_size: ?u64 = null; var image_base_override: ?u64 = null; var link_eh_frame_hdr = false; var link_emit_relocs = false; @@ -892,7 +892,7 @@ fn buildOutputType( var contains_res_file: bool = false; var reference_trace: ?u32 = null; var pdb_out_path: ?[]const u8 = null; - var dwarf_format: ?std.dwarf.Format = 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. @@ -1129,10 +1129,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--force_undefined")) { try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack")) { - const next_arg = args_iter.nextOrFatal(); - stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { - fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) }); - }; + stack_size = parseStackSize(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { const next_arg = args_iter.nextOrFatal(); image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { @@ -1487,9 +1484,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-strip")) { mod_opts.strip = false; } else if (mem.eql(u8, arg, "-gdwarf32")) { - dwarf_format = .@"32"; + debug_format = .{ .dwarf = .@"32" }; } else if (mem.eql(u8, arg, "-gdwarf64")) { - dwarf_format = .@"64"; + debug_format = .{ .dwarf = .@"64" }; } else if (mem.eql(u8, arg, "-fformatted-panics")) { formatted_panics = true; } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { @@ -1511,7 +1508,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-builtin")) { no_builtin = true; } else if (mem.startsWith(u8, arg, "-fopt-bisect-limit=")) { - linker_opt_bisect_limit = std.math.lossyCast(i32, parseIntSuffix(arg, "-fopt-bisect-limit=".len)); + const next_arg = arg["-fopt-bisect-limit=".len..]; + llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err| + fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { link_eh_frame_hdr = true; } else if (mem.eql(u8, arg, "--dynamicbase")) { @@ -1994,11 +1993,11 @@ fn buildOutputType( }, .gdwarf32 => { mod_opts.strip = false; - dwarf_format = .@"32"; + debug_format = .{ .dwarf = .@"32" }; }, .gdwarf64 => { mod_opts.strip = false; - dwarf_format = .@"64"; + debug_format = .{ .dwarf = .@"64" }; }, .sanitize => { if (mem.eql(u8, it.only_arg, "undefined")) { @@ -2257,10 +2256,7 @@ fn buildOutputType( } else if (mem.eql(u8, z_arg, "norelro")) { linker_z_relro = false; } else if (mem.startsWith(u8, z_arg, "stack-size=")) { - const next_arg = z_arg["stack-size=".len..]; - stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { - fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) }); - }; + stack_size = parseStackSize(z_arg["stack-size=".len..]); } else if (mem.startsWith(u8, z_arg, "common-page-size=")) { linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len); } else if (mem.startsWith(u8, z_arg, "max-page-size=")) { @@ -2285,10 +2281,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-u")) { try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { - const stack_size = linker_args_it.nextOrFatal(); - stack_size_override = std.fmt.parseUnsigned(u64, stack_size, 0) catch |err| { - fatal("unable to parse stack size override '{s}': {s}", .{ stack_size, @errorName(err) }); - }; + stack_size = parseStackSize(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { const image_base = linker_args_it.nextOrFatal(); image_base_override = std.fmt.parseUnsigned(u64, image_base, 0) catch |err| { @@ -3407,7 +3400,7 @@ fn buildOutputType( .linker_print_gc_sections = linker_print_gc_sections, .linker_print_icf_sections = linker_print_icf_sections, .linker_print_map = linker_print_map, - .linker_opt_bisect_limit = linker_opt_bisect_limit, + .llvm_opt_bisect_limit = llvm_opt_bisect_limit, .linker_global_base = linker_global_base, .linker_export_symbol_names = linker_export_symbol_names.items, .linker_z_nocopyreloc = linker_z_nocopyreloc, @@ -3430,7 +3423,7 @@ fn buildOutputType( .link_eh_frame_hdr = link_eh_frame_hdr, .link_emit_relocs = link_emit_relocs, .force_undefined_symbols = force_undefined_symbols, - .stack_size_override = stack_size_override, + .stack_size = stack_size, .image_base_override = image_base_override, .formatted_panics = formatted_panics, .function_sections = function_sections, @@ -3459,7 +3452,7 @@ fn buildOutputType( .test_runner_path = test_runner_path, .disable_lld_caching = !output_to_cache, .subsystem = subsystem, - .dwarf_format = dwarf_format, + .debug_format = debug_format, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, .install_name = install_name, @@ -7688,3 +7681,8 @@ fn resolveTargetQueryOrFatal(target_query: std.Target.Query) std.Target { return std.zig.system.resolveTargetQuery(target_query) catch |err| fatal("unable to resolve target: {s}", .{@errorName(err)}); } + +fn parseStackSize(s: []const u8) u64 { + return std.fmt.parseUnsigned(u64, s, 0) catch |err| + fatal("unable to parse stack size '{s}': {s}", .{ s, @errorName(err) }); +} diff --git a/src/musl.zig b/src/musl.zig index bbb3c145bb1b..47b8c8d6b553 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -226,7 +226,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .is_native_abi = false, .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_llvm_ir = comp.verbose_llvm_ir, .verbose_cimport = comp.verbose_cimport, diff --git a/src/target.zig b/src/target.zig index f610e55fb04c..04c25a5f0c60 100644 --- a/src/target.zig +++ b/src/target.zig @@ -323,6 +323,14 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { }; } +/// The set of targets that Zig supports using LLD to link for. +pub fn hasLldSupport(ofmt: std.Target.ObjectFormat) bool { + return switch (ofmt) { + .elf, .coff, .wasm => true, + else => false, + }; +} + /// The set of targets that our own self-hosted backends have robust support for. /// Used to select between LLVM backend and self-hosted backend when compiling in /// debug mode. A given target should only return true here if it is passing greater From 2be36c5b8d7d22c2ffc20b88e497da7e6612de5c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 21:21:01 -0700 Subject: [PATCH 025/133] linker: update references to module --- src/arch/wasm/CodeGen.zig | 236 +++++++++++++++++++------------------- src/arch/wasm/Emit.zig | 2 +- src/link/C.zig | 8 +- src/link/Coff.zig | 20 ++-- src/link/Coff/lld.zig | 6 +- src/link/Elf.zig | 2 +- src/link/MachO.zig | 22 ++-- src/link/Plan9.zig | 30 ++--- src/link/SpirV.zig | 2 +- src/link/Wasm.zig | 30 ++--- 10 files changed, 179 insertions(+), 179 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index a9028768f714..aa6c2dea79c0 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -766,7 +766,7 @@ pub fn deinit(func: *CodeGen) void { /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const src = LazySrcLoc.nodeOffset(0); const src_loc = src.toSrcLoc(func.decl, mod); func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args); @@ -791,7 +791,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref); assert(!gop.found_existing); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const val = (try func.air.value(ref, mod)).?; const ty = func.typeOf(ref); if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) { @@ -1101,7 +1101,7 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue { /// Creates one locals for a given `Type`. /// Returns a corresponding `Wvalue` with `local` as active tag fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const valtype = typeToValtype(ty, mod); switch (valtype) { .i32 => if (func.free_locals_i32.popOrNull()) |index| { @@ -1133,7 +1133,7 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue { /// Ensures a new local will be created. This is useful when it's useful /// to use a zero-initialized local. fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; try func.locals.append(func.gpa, genValtype(ty, mod)); const initial_index = func.local_index; func.local_index += 1; @@ -1237,7 +1237,7 @@ pub fn generate( } fn genFunc(func: *CodeGen) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(func.decl.ty).?; var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), mod); @@ -1348,7 +1348,7 @@ const CallWValues = struct { }; fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(fn_ty).?; const cc = fn_info.cc; @@ -1417,7 +1417,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: return func.lowerToStack(value); } - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_classes = abi.classifyType(ty, mod); assert(ty_classes[0] != .none); switch (ty.zigTypeTag(mod)) { @@ -1516,7 +1516,7 @@ fn restoreStackPointer(func: *CodeGen) !void { /// /// Asserts Type has codegenbits fn allocStack(func: *CodeGen, ty: Type) !WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(ty.hasRuntimeBitsIgnoreComptime(mod)); if (func.initial_stack_value == .none) { try func.initializeStack(); @@ -1542,7 +1542,7 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue { /// This is different from allocStack where this will use the pointer's alignment /// if it is set, to ensure the stack alignment will be set correctly. fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ptr_ty = func.typeOfIndex(inst); const pointee_ty = ptr_ty.childType(mod); @@ -2072,7 +2072,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; for (body) |inst| { @@ -2093,7 +2093,7 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void { } fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try func.resolveInst(un_op); const fn_info = mod.typeToFunc(func.decl.ty).?; @@ -2136,7 +2136,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const child_type = func.typeOfIndex(inst).childType(mod); const result = result: { @@ -2156,7 +2156,7 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try func.resolveInst(un_op); const ret_ty = func.typeOf(un_op).childType(mod); @@ -2183,7 +2183,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const args = @as([]const Air.Inst.Ref, @ptrCast(func.air.extra[extra.end..][0..extra.data.args_len])); const ty = func.typeOf(pl_op.operand); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const fn_ty = switch (ty.zigTypeTag(mod)) { .Fn => ty, @@ -2295,7 +2295,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (safety) { // TODO if the value is undef, write 0xaa bytes to dest } else { @@ -2349,7 +2349,7 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { assert(!(lhs != .stack and rhs == .stack)); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const abi_size = ty.abiSize(mod); switch (ty.zigTypeTag(mod)) { .ErrorUnion => { @@ -2428,7 +2428,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE }, else => if (abi_size > 8) { return func.fail("TODO: `store` for type `{}` with abisize `{d}`", .{ - ty.fmt(func.bin_file.base.options.module.?), + ty.fmt(func.bin_file.base.comp.module.?), abi_size, }); }, @@ -2456,7 +2456,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE } fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); const ty = ty_op.ty.toType(); @@ -2499,7 +2499,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { /// Loads an operand from the linear memory section. /// NOTE: Leaves the value on the stack. fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; // load local's value from memory by its stack position try func.emitWValue(operand); @@ -2536,7 +2536,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu } fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const arg_index = func.arg_index; const arg = func.args[arg_index]; const cc = mod.typeToFunc(func.decl.ty).?.cc; @@ -2555,7 +2555,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { if (arg_ty.zigTypeTag(mod) != .Int and arg_ty.zigTypeTag(mod) != .Float) { return func.fail( "TODO: Implement C-ABI argument for type '{}'", - .{arg_ty.fmt(func.bin_file.base.options.module.?)}, + .{arg_ty.fmt(func.bin_file.base.comp.module.?)}, ); } const result = try func.allocStack(arg_ty); @@ -2582,7 +2582,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try func.resolveInst(bin_op.lhs); const rhs = try func.resolveInst(bin_op.rhs); @@ -2619,7 +2619,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { /// Performs a binary operation on the given `WValue`'s /// NOTE: THis leaves the value on top of the stack. fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(!(lhs != .stack and rhs == .stack)); if (ty.isAnyFloat()) { @@ -2633,7 +2633,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! } else { return func.fail( "TODO: Implement binary operation for type: {}", - .{ty.fmt(func.bin_file.base.options.module.?)}, + .{ty.fmt(func.bin_file.base.comp.module.?)}, ); } } @@ -2652,7 +2652,7 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! } fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const int_info = ty.intInfo(mod); if (int_info.bits > 128) { return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{}); @@ -2788,7 +2788,7 @@ const FloatOp = enum { }; fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); const ty = func.typeOf(ty_op.operand); @@ -2873,7 +2873,7 @@ fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError } fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (ty.zigTypeTag(mod) == .Vector) { return func.fail("TODO: Implement floatOps for vectors", .{}); } @@ -2979,7 +2979,7 @@ fn floatNeg(func: *CodeGen, ty: Type, arg: WValue) InnerError!WValue { } fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try func.resolveInst(bin_op.lhs); @@ -3030,7 +3030,7 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr /// Asserts `Type` is <= 128 bits. /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack. fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(ty.abiSize(mod) <= 16); const bitsize = @as(u16, @intCast(ty.bitSize(mod))); const wasm_bits = toWasmBits(bitsize) orelse { @@ -3069,7 +3069,7 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { } fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ptr = mod.intern_pool.indexToKey(ptr_val.ip_index).ptr; switch (ptr.addr) { .decl => |decl_index| { @@ -3132,7 +3132,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue } fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const decl = mod.declPtr(decl_index); try mod.markDeclAlive(decl); const ptr_ty = try mod.singleMutPtrType(decl.ty); @@ -3144,7 +3144,7 @@ fn lowerAnonDeclRef( anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, offset: u32, ) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const decl_val = anon_decl.val; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); @@ -3172,7 +3172,7 @@ fn lowerAnonDeclRef( } fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (tv.ty.isSlice(mod)) { return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) }; } @@ -3225,7 +3225,7 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo( /// This function is intended to assert that `isByRef` returns `false` for `ty`. /// However such an assertion fails on the behavior tests currently. fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; // TODO: enable this assertion //assert(!isByRef(ty, mod)); const ip = &mod.intern_pool; @@ -3394,7 +3394,7 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue { } fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; switch (ty.zigTypeTag(mod)) { .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa }, @@ -3436,7 +3436,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { /// It's illegal to provide a value with a type that cannot be represented /// as an integer value. fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; switch (val.ip_index) { .none => {}, @@ -3472,7 +3472,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 { } fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const block_ty = ty_pl.ty.toType(); const wasm_block_ty = genBlockType(block_ty, mod); @@ -3593,7 +3593,7 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In /// NOTE: This leaves the result on top of the stack, rather than a new local. fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue { assert(!(lhs != .stack and rhs == .stack)); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (ty.zigTypeTag(mod) == .Optional and !ty.optionalReprIsPayload(mod)) { const payload_ty = ty.optionalChild(mod); if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { @@ -3711,7 +3711,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const errors_len = WValue{ .memory = sym_index }; try func.emitWValue(operand); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const err_int_ty = try mod.errorIntType(); const errors_len_val = try func.load(errors_len, err_int_ty, 0); const result = try func.cmp(.stack, errors_len_val, err_int_ty, .lt); @@ -3720,7 +3720,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br; const block = func.blocks.get(br.block_inst).?; @@ -3747,7 +3747,7 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const operand = try func.resolveInst(ty_op.operand); const operand_ty = func.typeOf(ty_op.operand); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const result = result: { if (operand_ty.zigTypeTag(mod) == .Bool) { @@ -3818,7 +3818,7 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand); break :result try bitcast_result.toLocal(func, wanted_ty); } - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (isByRef(given_ty, mod) and !isByRef(wanted_ty, mod)) { const loaded_memory = try func.load(operand, wanted_ty, 0); break :result try loaded_memory.toLocal(func, wanted_ty); @@ -3834,7 +3834,7 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand; if (wanted_ty.ip_index == .f16_type or given_ty.ip_index == .f16_type) return operand; @@ -3852,7 +3852,7 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn } fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.StructField, ty_pl.payload); @@ -3864,7 +3864,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const struct_ptr = try func.resolveInst(ty_op.operand); const struct_ptr_ty = func.typeOf(ty_op.operand); @@ -3883,7 +3883,7 @@ fn structFieldPtr( struct_ty: Type, index: u32, ) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const result_ty = func.typeOfIndex(inst); const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod); @@ -3914,7 +3914,7 @@ fn structFieldPtr( } fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_field = func.air.extraData(Air.StructField, ty_pl.payload).data; @@ -4013,7 +4013,7 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; // result type is always 'noreturn' const blocktype = wasm.block_empty; const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; @@ -4193,7 +4193,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try func.resolveInst(un_op); const err_union_ty = func.typeOf(un_op); @@ -4228,7 +4228,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro } fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -4256,7 +4256,7 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo } fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -4280,7 +4280,7 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) } fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -4310,7 +4310,7 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void } fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -4342,7 +4342,7 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ty = ty_op.ty.toType(); const operand = try func.resolveInst(ty_op.operand); const operand_ty = func.typeOf(ty_op.operand); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (ty.zigTypeTag(mod) == .Vector or operand_ty.zigTypeTag(mod) == .Vector) { return func.fail("todo Wasm intcast for vectors", .{}); } @@ -4365,7 +4365,7 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { /// Asserts type's bitsize <= 128 /// NOTE: May leave the result on the top of the stack. fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const given_bitsize = @as(u16, @intCast(given.bitSize(mod))); const wanted_bitsize = @as(u16, @intCast(wanted.bitSize(mod))); assert(given_bitsize <= 128); @@ -4433,7 +4433,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro } fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: enum { value, ptr }) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try func.resolveInst(un_op); @@ -4447,7 +4447,7 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: /// For a given type and operand, checks if it's considered `null`. /// NOTE: Leaves the result on the stack fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; try func.emitWValue(operand); const payload_ty = optional_ty.optionalChild(mod); if (!optional_ty.optionalReprIsPayload(mod)) { @@ -4475,7 +4475,7 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod } fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const opt_ty = func.typeOf(ty_op.operand); const payload_ty = func.typeOfIndex(inst); @@ -4498,7 +4498,7 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); const opt_ty = func.typeOf(ty_op.operand).childType(mod); @@ -4515,7 +4515,7 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); const opt_ty = func.typeOf(ty_op.operand).childType(mod); @@ -4543,7 +4543,7 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const payload_ty = func.typeOf(ty_op.operand); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const result = result: { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { @@ -4600,7 +4600,7 @@ fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const slice_ty = func.typeOf(bin_op.lhs); @@ -4630,7 +4630,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4683,7 +4683,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { /// Truncates a given operand to a given type, discarding any overflown bits. /// NOTE: Resulting value is left on the stack. fn trunc(func: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const given_bits = @as(u16, @intCast(given_ty.bitSize(mod))); if (toWasmBits(given_bits) == null) { return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits}); @@ -4707,7 +4707,7 @@ fn airIntFromBool(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -4730,7 +4730,7 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try func.resolveInst(un_op); const ptr_ty = func.typeOf(un_op); @@ -4745,7 +4745,7 @@ fn airIntFromPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = func.typeOf(bin_op.lhs); @@ -4782,7 +4782,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4812,7 +4812,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4840,7 +4840,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { } fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (safety) { // TODO if the value is undef, write 0xaa bytes to dest } else { @@ -4873,7 +4873,7 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void /// this to wasm's memset instruction. When the feature is not present, /// we implement it manually. fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const abi_size = @as(u32, @intCast(elem_ty.abiSize(mod))); // When bulk_memory is enabled, we lower it to wasm's memset instruction. @@ -4962,7 +4962,7 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue } fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const array_ty = func.typeOf(bin_op.lhs); @@ -5031,7 +5031,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -5076,7 +5076,7 @@ fn airIntFromFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -5122,7 +5122,7 @@ fn airFloatFromInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); const ty = func.typeOfIndex(inst); @@ -5201,7 +5201,7 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const inst_ty = func.typeOfIndex(inst); const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data; @@ -5270,7 +5270,7 @@ fn airReduce(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const result_ty = func.typeOfIndex(inst); @@ -5400,7 +5400,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ip = &mod.intern_pool; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data; @@ -5499,7 +5499,7 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void { } fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(operand_ty.hasRuntimeBitsIgnoreComptime(mod)); assert(op == .eq or op == .neq); const payload_ty = operand_ty.optionalChild(mod); @@ -5535,7 +5535,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: /// NOTE: Leaves the result of the comparison on top of the stack. /// TODO: Lower this to compiler_rt call when bitsize > 128 fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(operand_ty.abiSize(mod) >= 16); assert(!(lhs != .stack and rhs == .stack)); if (operand_ty.bitSize(mod) > 128) { @@ -5577,7 +5577,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std } fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const un_ty = func.typeOf(bin_op.lhs).childType(mod); const tag_ty = func.typeOf(bin_op.rhs); @@ -5601,7 +5601,7 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const un_ty = func.typeOf(ty_op.operand); @@ -5706,7 +5706,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro } fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const err_set_ty = func.typeOf(ty_op.operand).childType(mod); @@ -5732,7 +5732,7 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi } fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; @@ -5753,7 +5753,7 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (ptr_ty.isSlice(mod)) { return func.slicePtr(ptr); } else { @@ -5762,7 +5762,7 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue } fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dst = try func.resolveInst(bin_op.lhs); const dst_ty = func.typeOf(bin_op.lhs); @@ -5802,7 +5802,7 @@ fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -5863,7 +5863,7 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { // to make a copy of the ptr+value but can point towards them directly. const error_table_symbol = try func.bin_file.getErrorTableSymbol(); const name_ty = Type.slice_const_u8_sentinel_0; - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const abi_size = name_ty.abiSize(mod); const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation @@ -5903,7 +5903,7 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro const lhs_op = try func.resolveInst(extra.lhs); const rhs_op = try func.resolveInst(extra.rhs); const lhs_ty = func.typeOf(extra.lhs); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (lhs_ty.zigTypeTag(mod) == .Vector) { return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); @@ -5975,7 +5975,7 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro } fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; assert(op == .add or op == .sub); const int_info = ty.intInfo(mod); const is_signed = int_info.signedness == .signed; @@ -6040,7 +6040,7 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, } fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.Bin, ty_pl.payload).data; @@ -6103,7 +6103,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const lhs = try func.resolveInst(extra.lhs); const rhs = try func.resolveInst(extra.rhs); const lhs_ty = func.typeOf(extra.lhs); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (lhs_ty.zigTypeTag(mod) == .Vector) { return func.fail("TODO: Implement overflow arithmetic for vectors", .{}); @@ -6273,7 +6273,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { assert(op == .max or op == .min); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const target = mod.getTarget(); const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -6317,7 +6317,7 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { } fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data; @@ -6351,7 +6351,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ty = func.typeOf(ty_op.operand); @@ -6404,7 +6404,7 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ty = func.typeOf(ty_op.operand); @@ -6471,7 +6471,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void { if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{}); - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const ty = func.typeOf(pl_op.operand); const operand = try func.resolveInst(pl_op.operand); @@ -6517,7 +6517,7 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.TryPtr, ty_pl.payload); const err_union_ptr = try func.resolveInst(extra.data.ptr); @@ -6535,7 +6535,7 @@ fn lowerTry( err_union_ty: Type, operand_is_ptr: bool, ) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; if (operand_is_ptr) { return func.fail("TODO: lowerTry for pointers", .{}); } @@ -6584,7 +6584,7 @@ fn lowerTry( } fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ty = func.typeOfIndex(inst); @@ -6655,7 +6655,7 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = func.typeOfIndex(inst); @@ -6670,7 +6670,7 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = func.typeOfIndex(inst); @@ -6693,7 +6693,7 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty = func.typeOfIndex(inst); const lhs = try func.resolveInst(bin_op.lhs); const rhs = try func.resolveInst(bin_op.rhs); @@ -6806,7 +6806,7 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const int_bits = ty.intInfo(mod).bits; const wasm_bits = toWasmBits(int_bits) orelse { return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits}); @@ -6836,7 +6836,7 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty = func.typeOfIndex(inst); const lhs = try func.resolveInst(bin_op.lhs); const rhs = try func.resolveInst(bin_op.rhs); @@ -6883,7 +6883,7 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { /// The result will be sign extended to 32 bits if N <= 32 or 64 bits if N <= 64. /// Support for integers wider than 64 bits has not yet been implemented. fn signExtendInt(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const int_bits = ty.intInfo(mod).bits; const wasm_bits = toWasmBits(int_bits) orelse { return func.fail("TODO: signExtendInt for signed integers larger than '{d}' bits", .{int_bits}); @@ -6919,7 +6919,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { assert(op == .add or op == .sub); const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty = func.typeOfIndex(inst); const lhs = try func.resolveInst(bin_op.lhs); const rhs = try func.resolveInst(bin_op.rhs); @@ -6967,7 +6967,7 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { } fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op: Op) InnerError!WValue { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const int_info = ty.intInfo(mod); const wasm_bits = toWasmBits(int_info.bits).?; const is_wasm_bits = wasm_bits == int_info.bits; @@ -7034,7 +7034,7 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty = func.typeOfIndex(inst); const int_info = ty.intInfo(mod); const is_signed = int_info.signedness == .signed; @@ -7155,7 +7155,7 @@ fn callIntrinsic( }; // Always pass over C-ABI - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; var func_type = try genFunctype(func.gpa, .C, param_types, return_type, mod); defer func_type.deinit(func.gpa); const func_type_index = try func.bin_file.putOrGetFuncType(func_type); @@ -7208,7 +7208,7 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const enum_decl_index = enum_ty.getOwnerDecl(mod); var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); @@ -7364,7 +7364,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { } fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -7449,7 +7449,7 @@ inline fn useAtomicFeature(func: *const CodeGen) bool { } fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data; @@ -7522,7 +7522,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const atomic_load = func.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const ptr = try func.resolveInst(atomic_load.ptr); const ty = func.typeOfIndex(inst); @@ -7549,7 +7549,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data; @@ -7735,7 +7735,7 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr = try func.resolveInst(bin_op.lhs); @@ -7774,11 +7774,11 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn typeOf(func: *CodeGen, inst: Air.Inst.Ref) Type { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; return func.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(func: *CodeGen, inst: Air.Inst.Index) Type { - const mod = func.bin_file.base.options.module.?; + const mod = func.bin_file.base.comp.module.?; return func.air.typeOfIndex(inst, &mod.intern_pool); } diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index d1b7114b1255..dbd85116a0d1 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -254,7 +254,7 @@ fn offset(self: Emit) u32 { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); std.debug.assert(emit.error_msg == null); - const mod = emit.bin_file.base.options.module.?; + const mod = emit.bin_file.base.comp.module.?; emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.base.allocator, mod.declPtr(emit.decl_index).srcLoc(mod), format, args); return error.EmitFail; } diff --git a/src/link/C.zig b/src/link/C.zig index 4e40addcf7ec..e6827947ae41 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -386,7 +386,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo defer sub_prog_node.end(); const gpa = self.base.comp.gpa; - const module = self.base.options.module.?; + const module = self.base.comp.module.?; { var i: usize = 0; @@ -535,7 +535,7 @@ fn flushCTypes( decl_ctypes: codegen.CType.Store, ) FlushDeclError!void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl_ctypes_len = decl_ctypes.count(); f.ctypes_map.clearRetainingCapacity(); @@ -623,7 +623,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { var object = codegen.Object{ .dg = .{ .gpa = gpa, - .module = self.base.options.module.?, + .module = self.base.comp.module.?, .error_msg = null, .pass = .flush, .is_naked_fn = false, @@ -665,7 +665,7 @@ fn flushLazyFn( var object = codegen.Object{ .dg = .{ .gpa = gpa, - .module = self.base.options.module.?, + .module = self.base.comp.module.?, .error_msg = null, .pass = .flush, .is_naked_fn = false, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 2541d62eac6c..134d00feb079 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1118,7 +1118,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); if (!gop.found_existing) { @@ -1249,7 +1249,7 @@ fn updateLazySymbolAtom( section_index: u16, ) !void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; var required_alignment: InternPool.Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1310,7 +1310,7 @@ fn updateLazySymbolAtom( pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -1347,9 +1347,9 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: InternPool.DeclIndex) !At } fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { - const decl = self.base.options.module.?.declPtr(decl_index); + const decl = self.base.comp.module.?.declPtr(decl_index); const ty = decl.ty; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const zig_ty = ty.zigTypeTag(mod); const val = decl.val; const index: u16 = blk: { @@ -1373,7 +1373,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: InternPool.DeclIndex) u16 { } fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, complex_type: coff.ComplexType) !void { - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); @@ -1443,7 +1443,7 @@ pub fn freeDecl(self: *Coff, decl_index: InternPool.DeclIndex) void { if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("freeDecl {*}", .{decl}); @@ -1599,7 +1599,7 @@ pub fn deleteDeclExport( ) void { if (self.llvm_object) |_| return; const metadata = self.decls.getPtr(decl_index) orelse return; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const name = mod.intern_pool.stringToSlice(name_ip); const sym_index = metadata.getExportPtr(self, name) orelse return; @@ -1678,7 +1678,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const gpa = self.base.comp.gpa; - const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; if (self.lazy_syms.getPtr(.none)) |metadata| { // Most lazy symbols can be updated on first use, but @@ -1818,7 +1818,7 @@ pub fn lowerAnonDecl( src_loc: Module.SrcLoc, ) !codegen.Result { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const decl_alignment = switch (explicit_alignment) { .none => ty.abiAlignment(mod), diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 4d4dd840cfaa..45a6f9c14c94 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -30,7 +30,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (self.base.options.module != null) blk: { + const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: { try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -289,7 +289,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.base.options.subsystem) |explicit| break :blk explicit; switch (target.os.tag) { .windows => { - if (self.base.options.module) |module| { + if (self.base.comp.module) |module| { if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib) break :blk null; if (module.stage1_flags.have_c_main or self.base.options.is_test or @@ -450,7 +450,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } else { try argv.append("-NODEFAULTLIB"); if (!is_lib and self.base.options.entry == null) { - if (self.base.options.module) |module| { + if (self.base.comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); } else { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 2bab459582ec..7db9b06fbc86 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2309,7 +2309,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (self.base.options.module != null) blk: { + const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: { try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 3af98aa42af0..3b36b73fa306 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -356,7 +356,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No defer sub_prog_node.end(); const output_mode = self.base.comp.config.output_mode; - const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; if (self.lazy_syms.getPtr(.none)) |metadata| { // Most lazy symbols can be updated on first use, but @@ -2333,7 +2333,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; @@ -2504,7 +2504,7 @@ fn updateLazySymbolAtom( section_index: u8, ) !void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; var required_alignment: Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -2568,7 +2568,7 @@ fn updateLazySymbolAtom( } pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index { - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const gpa = self.base.comp.gpa; const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(mod)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); @@ -2600,7 +2600,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In } fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void { - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; // Lowering a TLV on macOS involves two stages: // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss) // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars @@ -2711,10 +2711,10 @@ pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: InternPool.DeclIndex) !A } fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 { - const decl = self.base.options.module.?.declPtr(decl_index); + const decl = self.base.comp.module.?.declPtr(decl_index); const ty = decl.ty; const val = decl.val; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const zig_ty = ty.zigTypeTag(mod); const any_non_single_threaded = self.base.comp.config.any_non_single_threaded; const optimize_mode = self.base.comp.root_mod.optimize_mode; @@ -2751,7 +2751,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: InternPool.DeclIndex) u8 { fn updateDeclCode(self: *MachO, decl_index: InternPool.DeclIndex, code: []u8) !u64 { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const required_alignment = decl.getAlignment(mod); @@ -2967,7 +2967,7 @@ pub fn deleteDeclExport( const metadata = self.decls.getPtr(decl_index) orelse return; const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)}); defer gpa.free(exp_name); const sym_index = metadata.getExportPtr(self, exp_name) orelse return; @@ -3006,7 +3006,7 @@ fn freeUnnamedConsts(self: *MachO, decl_index: InternPool.DeclIndex) void { pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("freeDecl {*}", .{decl}); @@ -3049,7 +3049,7 @@ pub fn lowerAnonDecl( src_loc: Module.SrcLoc, ) !codegen.Result { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const decl_alignment = switch (explicit_alignment) { .none => ty.abiAlignment(mod), diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index a5bb943ada2c..ece949b01ef9 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -174,7 +174,7 @@ pub const Atom = struct { return .{ .code_ptr = slice.ptr, .other = .{ .code_len = slice.len } }; } fn getCode(self: CodePtr, plan9: *const Plan9) []u8 { - const mod = plan9.base.options.module.?; + const mod = plan9.base.comp.module.?; return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: { const decl_index = self.other.decl_index; const decl = mod.declPtr(decl_index); @@ -324,7 +324,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { fn putFn(self: *Plan9, decl_index: InternPool.DeclIndex, out: FnDeclOutput) !void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope(mod)); if (fn_map_res.found_existing) { @@ -455,7 +455,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De var code_buffer = std.ArrayList(u8).init(gpa); defer code_buffer.deinit(); - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); @@ -550,7 +550,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) /// called at the end of update{Decl,Func} fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const is_fn = (decl.ty.zigTypeTag(mod) == .Fn); const sym_t: aout.Sym.Type = if (is_fn) .t else .d; @@ -670,7 +670,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No defer assert(self.hdr.entry != 0x0); - const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const mod = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; // finish up the lazy syms if (self.lazy_syms.getPtr(.none)) |metadata| { @@ -1032,7 +1032,7 @@ pub fn freeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) void { // freeDecl without any updateDecl in between. // However that is planned to change, see the TODO comment in Module.zig // in the deleteUnusedDecl function. - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const is_fn = decl.val.isFuncBody(mod); if (is_fn) { @@ -1112,7 +1112,7 @@ pub fn seeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) !Atom.Index { } const atom_idx = gop.value_ptr.index; // handle externs here because they might not get updateDecl called on them - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const name = mod.intern_pool.stringToSlice(decl.name); if (decl.isExtern(mod)) { @@ -1147,7 +1147,7 @@ pub fn updateExports( pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index { const gpa = self.base.comp.gpa; - const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(self.base.options.module.?)); + const gop = try self.lazy_syms.getOrPut(gpa, sym.getDecl(self.base.comp.module.?)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -1166,7 +1166,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.In _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self); _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self); // anyerror needs to be deferred until flushModule - if (sym.getDecl(self.base.options.module.?) != .none) { + if (sym.getDecl(self.base.comp.module.?) != .none) { try self.updateLazySymbolAtom(sym, atom); } return atom; @@ -1174,7 +1174,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.In fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Index) !void { const gpa = self.base.comp.gpa; - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; var required_alignment: InternPool.Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1348,7 +1348,7 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void { } pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const ip = &mod.intern_pool; const writer = buf.writer(); // write __GOT @@ -1374,7 +1374,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { const atom = self.getAtom(decl_metadata.index); const sym = self.syms.items[atom.sym_index.?]; try self.writeSym(writer, sym); - if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { + if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| { try self.writeSym(writer, self.syms.items[exp_i]); }; @@ -1421,7 +1421,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { const atom = self.getAtom(decl_metadata.index); const sym = self.syms.items[atom.sym_index.?]; try self.writeSym(writer, sym); - if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { + if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| { const s = self.syms.items[exp_i]; if (mem.eql(u8, s.name, "_start")) @@ -1464,7 +1464,7 @@ pub fn getDeclVAddr( decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo, ) !u64 { - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("getDeclVAddr for {s}", .{mod.intern_pool.stringToSlice(decl.name)}); if (decl.isExtern(mod)) { @@ -1517,7 +1517,7 @@ pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.S // ... const gpa = self.base.comp.gpa; const gop = try self.anon_decls.getOrPut(gpa, decl_val); - const mod = self.base.options.module.?; + const mod = self.base.comp.module.?; if (!gop.found_existing) { const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const val = Value.fromInterned(decl_val); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index c6bb5f558892..414ebcf98787 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -196,7 +196,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No defer error_info.deinit(); try error_info.appendSlice("zig_errors"); - const module = self.base.options.module.?; + const module = self.base.comp.module.?; for (module.global_error_set.keys()) |name_nts| { const name = module.intern_pool.stringToSlice(name_nts); // Errors can contain pretty much any character - to encode them in a string we must escape diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index bb0d4447bb86..c9bd90eacfb1 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -632,7 +632,7 @@ pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) !At gop.value_ptr.* = atom_index; const atom = wasm.getAtom(atom_index); const symbol = atom.symbolLoc().getSymbol(wasm); - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const decl = mod.declPtr(decl_index); const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); symbol.name = try wasm.string_table.put(gpa, full_name); @@ -1568,7 +1568,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: InternPool.De fn finishUpdateDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex, code: []const u8, symbol_tag: Symbol.Tag) !void { const gpa = wasm.base.comp.gpa; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const decl = mod.declPtr(decl_index); const atom_index = wasm.decls.get(decl_index).?; const atom = wasm.getAtomPtr(atom_index); @@ -1632,7 +1632,7 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { /// The given `decl` is the parent decl whom owns the constant. pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { const gpa = wasm.base.comp.gpa; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions const decl = mod.declPtr(decl_index); @@ -1665,7 +1665,7 @@ const LowerConstResult = union(enum) { fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { const gpa = wasm.base.comp.gpa; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; // Create and initialize a new local symbol and atom const atom_index = try wasm.createAtom(); @@ -1753,7 +1753,7 @@ pub fn getDeclVAddr( reloc_info: link.File.RelocInfo, ) !u64 { const gpa = wasm.base.comp.gpa; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const decl = mod.declPtr(decl_index); const target_atom_index = try wasm.getOrCreateAtomForDecl(decl_index); @@ -1798,7 +1798,7 @@ pub fn lowerAnonDecl( const gpa = wasm.base.comp.gpa; const gop = try wasm.anon_decls.getOrPut(gpa, decl_val); if (!gop.found_existing) { - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const tv: TypedValue = .{ .ty = ty, .val = Value.fromInterned(decl_val) }; var name_buf: [32]u8 = undefined; @@ -1831,7 +1831,7 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin const parent_atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; const parent_atom = wasm.getAtomPtr(parent_atom_index); const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); if (ty.zigTypeTag(mod) == .Fn) { assert(reloc_info.addend == 0); // addend not allowed for function relocations @@ -2004,7 +2004,7 @@ pub fn updateExports( pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); const gpa = wasm.base.comp.gpa; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; const decl = mod.declPtr(decl_index); const atom_index = wasm.decls.get(decl_index).?; const atom = wasm.getAtomPtr(atom_index); @@ -2492,7 +2492,7 @@ fn setupErrorsLen(wasm: *Wasm) !void { const gpa = wasm.base.comp.gpa; const loc = wasm.findGlobalSymbol("__zig_errors_len") orelse return; - const errors_len = wasm.base.options.module.?.global_error_set.count(); + const errors_len = wasm.base.comp.module.?.global_error_set.count(); // overwrite existing atom if it already exists (maybe the error set has increased) // if not, allcoate a new atom. const atom_index = if (wasm.symbol_atom.get(loc)) |index| blk: { @@ -3268,7 +3268,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { const atom_index = try wasm.createAtom(); const atom = wasm.getAtomPtr(atom_index); const slice_ty = Type.slice_const_u8_sentinel_0; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; atom.alignment = slice_ty.abiAlignment(mod); const sym_index = atom.sym_index; @@ -3322,7 +3322,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { // Addend for each relocation to the table var addend: u32 = 0; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; for (mod.global_error_set.keys()) |error_name_nts| { const atom = wasm.getAtomPtr(atom_index); @@ -3708,7 +3708,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try wasm.markReferences(); try wasm.setupErrorsLen(); try wasm.setupImports(); - if (wasm.base.options.module) |mod| { + if (wasm.base.comp.module) |mod| { var decl_it = wasm.decls.iterator(); while (decl_it.next()) |entry| { const decl = mod.declPtr(entry.key_ptr.*); @@ -3759,7 +3759,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } if (wasm.dwarf) |*dwarf| { - try dwarf.flushModule(wasm.base.options.module.?); + try dwarf.flushModule(wasm.base.comp.module.?); } } @@ -4190,7 +4190,7 @@ fn writeToFile( } // if (wasm.dwarf) |*dwarf| { - // const mod = wasm.base.options.module.?; + // const mod = wasm.base.comp.module.?; // try dwarf.writeDbgAbbrev(); // // for debug info and ranges, the address is always 0, // // as locations are always offsets relative to 'code' section. @@ -4535,7 +4535,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (wasm.base.options.module != null) blk: { + const module_obj_path: ?[]const u8 = if (wasm.base.comp.module != null) blk: { try wasm.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { From 6ec6c077957c8d1f96d83299b35f6c84a34b07e6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 21:22:16 -0700 Subject: [PATCH 026/133] linker: update output_mode references --- src/link/Coff.zig | 8 ++++---- src/link/Coff/lld.zig | 8 ++++---- src/link/Elf/Atom.zig | 2 +- src/link/MachO/dead_strip.zig | 2 +- src/link/MachO/zld.zig | 4 ++-- src/link/Wasm.zig | 32 ++++++++++++++++---------------- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 134d00feb079..4a6679b1bad8 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1658,7 +1658,7 @@ pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) lin if (use_lld) { return lld.linkWithLLD(self, comp, prog_node); } - switch (self.base.options.output_mode) { + switch (self.base.comp.config.output_mode) { .Exe, .Obj => return self.flushModule(comp, prog_node), .Lib => return error.TODOImplementWritingLibFiles, } @@ -1779,7 +1779,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try self.writeDataDirectoriesHeaders(); try self.writeSectionHeaders(); - if (self.entry_addr == null and self.base.options.output_mode == .Exe) { + if (self.entry_addr == null and self.base.comp.config.output_mode == .Exe) { log.debug("flushing. no_entry_point_found = true\n", .{}); self.error_flags.no_entry_point_found = true; } else { @@ -2218,7 +2218,7 @@ fn writeHeader(self: *Coff) !void { .p32 => flags.@"32BIT_MACHINE" = 1, .p64 => flags.LARGE_ADDRESS_AWARE = 1, } - if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic) { + if (self.base.comp.config.output_mode == .Lib and self.base.options.link_mode == .Dynamic) { flags.DLL = 1; } @@ -2451,7 +2451,7 @@ pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { } pub fn getImageBase(self: Coff) u64 { - const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { + const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.comp.config.output_mode) { .Exe => switch (self.base.options.target.cpu.arch) { .aarch64 => @as(u64, 0x140000000), .x86_64, .x86 => 0x400000, diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 45a6f9c14c94..4d2b569d56a6 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -45,9 +45,9 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_lib = self.base.options.output_mode == .Lib; + const is_lib = self.base.comp.config.output_mode == .Lib; const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; - const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; + const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; const target = self.base.options.target; const optimize_mode = self.base.comp.root_mod.optimize_mode; @@ -136,7 +136,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod }; } - if (self.base.options.output_mode == .Obj) { + if (self.base.comp.config.output_mode == .Obj) { // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. @@ -192,7 +192,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), } } - if (self.base.options.output_mode == .Exe) { + if (self.base.comp.config.output_mode == .Exe) { try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } if (self.base.options.image_base_override) |image_base| { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index ec12f177212d..b3d7b51d3e05 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -658,7 +658,7 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { fn outputType(elf_file: *Elf) u2 { assert(!elf_file.isRelocatable()); - return switch (elf_file.base.options.output_mode) { + return switch (elf_file.base.comp.config.output_mode) { .Obj => unreachable, .Lib => 0, .Exe => if (elf_file.base.options.pie) 1 else 2, diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index dda82385e185..21f9154b4506 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -33,7 +33,7 @@ fn addRoot(macho_file: *MachO, roots: *AtomTable, file: u32, sym_loc: SymbolWith fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void { log.debug("collecting roots", .{}); - switch (macho_file.base.options.output_mode) { + switch (macho_file.base.comp.config.output_mode) { .Exe => { // Add entrypoint as GC root if (macho_file.getEntryPoint()) |global| { diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 41c387c2444d..e0aa82f2430d 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -407,7 +407,7 @@ pub fn linkWithZld( try macho_file.createDyldPrivateAtom(); try macho_file.createTentativeDefAtoms(); - if (macho_file.base.options.output_mode == .Exe) { + if (macho_file.base.comp.config.output_mode == .Exe) { const global = macho_file.getEntryPoint().?; if (macho_file.getSymbol(global).undf()) { // We do one additional check here in case the entry point was found in one of the dylibs. @@ -612,7 +612,7 @@ fn createSegments(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); const aligned_pagezero_vmsize = mem.alignBackward(u64, macho_file.pagezero_vmsize, page_size); - if (macho_file.base.options.output_mode != .Lib and aligned_pagezero_vmsize > 0) { + if (macho_file.base.comp.config.output_mode != .Lib and aligned_pagezero_vmsize > 0) { if (aligned_pagezero_vmsize != macho_file.pagezero_vmsize) { log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{macho_file.pagezero_vmsize}); log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize}); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index c9bd90eacfb1..84b5c792aaff 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1305,7 +1305,7 @@ pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc { } fn checkUndefinedSymbols(wasm: *const Wasm) !void { - if (wasm.base.options.output_mode == .Obj) return; + if (wasm.base.comp.config.output_mode == .Obj) return; if (wasm.base.options.import_symbols) return; var found_undefined_symbols = false; @@ -2065,7 +2065,7 @@ fn mapFunctionTable(wasm: *Wasm) void { } } - if (wasm.import_table or wasm.base.options.output_mode == .Obj) { + if (wasm.import_table or wasm.base.comp.config.output_mode == .Obj) { const sym_loc = wasm.findGlobalSymbol("__indirect_function_table").?; const import = wasm.imports.getPtr(sym_loc).?; import.kind.table.limits.min = index - 1; // we start at index 1. @@ -2230,11 +2230,11 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { // we set the entire region of it to zeroes. // We do not have to do this when exporting the memory (the default) because the runtime // will do it for us, and we do not emit the bss segment at all. - if ((wasm.base.options.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) { + if ((wasm.base.comp.config.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) { @memset(atom.code.items, 0); } - const should_merge = wasm.base.options.output_mode != .Obj; + const should_merge = wasm.base.comp.config.output_mode != .Obj; const gop = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(should_merge)); if (gop.found_existing) { const index = gop.value_ptr.*; @@ -2392,7 +2392,7 @@ fn allocateVirtualAddresses(wasm: *Wasm) void { }; const atom = wasm.getAtom(atom_index); - const merge_segment = wasm.base.options.output_mode != .Obj; + const merge_segment = wasm.base.comp.config.output_mode != .Obj; const segment_info = if (atom.file) |object_index| blk: { break :blk wasm.objects.items[object_index].segment_info; } else wasm.segment_info.values(); @@ -2934,7 +2934,7 @@ fn mergeTypes(wasm: *Wasm) !void { fn setupExports(wasm: *Wasm) !void { const gpa = wasm.base.comp.gpa; - if (wasm.base.options.output_mode == .Obj) return; + if (wasm.base.comp.config.output_mode == .Obj) return; log.debug("Building exports from symbols", .{}); const force_exp_names = wasm.base.options.export_symbol_names; @@ -3009,7 +3009,7 @@ fn setupStart(wasm: *Wasm) !void { } // Ensure the symbol is exported so host environment can access it - if (wasm.base.options.output_mode != .Obj) { + if (wasm.base.comp.config.output_mode != .Obj) { symbol.setFlag(.WASM_SYM_EXPORTED); } } @@ -3029,7 +3029,7 @@ fn setupMemory(wasm: *Wasm) !void { break :blk base; } else 0; - const is_obj = wasm.base.options.output_mode == .Obj; + const is_obj = wasm.base.comp.config.output_mode == .Obj; if (place_stack_first and !is_obj) { memory_ptr = stack_alignment.forward(memory_ptr); @@ -3155,7 +3155,7 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u3 switch (symbol.tag) { .data => { const segment_info = object.segment_info[symbol.index]; - const merge_segment = wasm.base.options.output_mode != .Obj; + const merge_segment = wasm.base.comp.config.output_mode != .Obj; const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment)); if (!result.found_existing) { result.value_ptr.* = index; @@ -3797,7 +3797,7 @@ fn writeToFile( var code_section_index: ?u32 = null; // Index of the data section. Used to tell relocation table where the section lives. var data_section_index: ?u32 = null; - const is_obj = wasm.base.options.output_mode == .Obj or (!use_llvm and use_lld); + const is_obj = wasm.base.comp.config.output_mode == .Obj or (!use_llvm and use_lld); var binary_bytes = std.ArrayList(u8).init(gpa); defer binary_bytes.deinit(); @@ -4550,7 +4550,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_obj = wasm.base.options.output_mode == .Obj; + const is_obj = wasm.base.comp.config.output_mode == .Obj; const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; @@ -4750,7 +4750,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--allow-undefined"); } - if (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { + if (wasm.base.comp.config.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { try argv.append("--shared"); } if (wasm.base.options.pie) { @@ -4769,8 +4769,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } if (target.os.tag == .wasi) { - const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or - (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); + const is_exe_or_dyn_lib = wasm.base.comp.config.output_mode == .Exe or + (wasm.base.comp.config.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); if (is_exe_or_dyn_lib) { for (wasm.wasi_emulated_libs) |crt_file| { try argv.append(try comp.get_libc_crt_file( @@ -4818,7 +4818,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.options.output_mode != .Obj and + if (wasm.base.comp.config.output_mode != .Obj and !wasm.base.options.skip_linker_dependencies and !wasm.base.options.link_libc) { @@ -4904,7 +4904,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // it, and then can react to that in the same way as trying to run an ELF file // from a foreign CPU architecture. if (fs.has_executable_bit and target.os.tag == .wasi and - wasm.base.options.output_mode == .Exe) + wasm.base.comp.config.output_mode == .Exe) { // TODO: what's our strategy for reporting linker errors from this function? // report a nice error here with the file path if it fails instead of From b5e2af49a0469c7f96ebabb8e796585d53382e7d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 21:23:12 -0700 Subject: [PATCH 027/133] linker: update link_mode references --- src/link.zig | 2 +- src/link/Coff.zig | 2 +- src/link/Coff/lld.zig | 6 +++--- src/link/MachO.zig | 6 +++--- src/link/Wasm.zig | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/link.zig b/src/link.zig index 9685cea39154..fd8d84f765c5 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1098,7 +1098,7 @@ pub const File = struct { } pub fn isStatic(self: File) bool { - return self.base.options.link_mode == .Static; + return self.base.comp.config.link_mode == .Static; } pub fn isObject(self: File) bool { diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 4a6679b1bad8..789b9fe773a8 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -2218,7 +2218,7 @@ fn writeHeader(self: *Coff) !void { .p32 => flags.@"32BIT_MACHINE" = 1, .p64 => flags.LARGE_ADDRESS_AWARE = 1, } - if (self.base.comp.config.output_mode == .Lib and self.base.options.link_mode == .Dynamic) { + if (self.base.comp.config.output_mode == .Lib and self.base.comp.config.link_mode == .Dynamic) { flags.DLL = 1; } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 4d2b569d56a6..369d837ae6e5 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -46,7 +46,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod defer sub_prog_node.end(); const is_lib = self.base.comp.config.output_mode == .Lib; - const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; + const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; const target = self.base.options.target; @@ -423,7 +423,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } } else { - const lib_str = switch (self.base.options.link_mode) { + const lib_str = switch (self.base.comp.config.link_mode) { .Dynamic => "", .Static => "lib", }; @@ -431,7 +431,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .Debug => "d", else => "", }; - switch (self.base.options.link_mode) { + switch (self.base.comp.config.link_mode) { .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})), .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})), } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 3b36b73fa306..eb5b5bce0d7d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -320,7 +320,7 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li const gpa = self.base.comp.gpa; const output_mode = self.base.comp.config.output_mode; - if (output_mode == .Lib and self.base.options.link_mode == .Static) { + if (output_mode == .Lib and self.base.comp.config.link_mode == .Static) { if (build_options.have_llvm) { return self.base.linkAsArchive(comp, prog_node); } else { @@ -608,7 +608,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No .stacksize = self.base.stack_size, }); }, - .Lib => if (self.base.options.link_mode == .Dynamic) { + .Lib => if (self.base.comp.config.link_mode == .Dynamic) { try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer); }, else => {}, @@ -1910,7 +1910,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { fn resolveSymbolsAtLoading(self: *MachO) !void { const output_mode = self.base.comp.config.output_mode; const is_lib = output_mode == .Lib; - const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; + const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; const allow_undef = is_dyn_lib and self.base.allow_shlib_undefined; var next_sym: usize = 0; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 84b5c792aaff..28eeaedba45a 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4750,7 +4750,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--allow-undefined"); } - if (wasm.base.comp.config.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { + if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) { try argv.append("--shared"); } if (wasm.base.options.pie) { @@ -4770,7 +4770,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! if (target.os.tag == .wasi) { const is_exe_or_dyn_lib = wasm.base.comp.config.output_mode == .Exe or - (wasm.base.comp.config.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic); + (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic); if (is_exe_or_dyn_lib) { for (wasm.wasi_emulated_libs) |crt_file| { try argv.append(try comp.get_libc_crt_file( From 98da660e453789f578c04e641286bdf8ff84bcd4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 21:35:51 -0700 Subject: [PATCH 028/133] linker: update options references of CsuObjects --- src/link/Coff/lld.zig | 6 ++-- src/link/Elf.zig | 68 +++++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 369d837ae6e5..297900fae5d2 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -85,8 +85,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man.hash.addListOfBytes(self.base.options.lib_dirs); man.hash.add(self.base.options.skip_linker_dependencies); if (self.base.options.link_libc) { - man.hash.add(self.base.options.libc_installation != null); - if (self.base.options.libc_installation) |libc_installation| { + man.hash.add(self.base.comp.libc_installation != null); + if (self.base.comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); if (target.abi == .msvc) { man.hash.addBytes(libc_installation.msvc_lib_dir.?); @@ -244,7 +244,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } if (self.base.options.link_libc) { - if (self.base.options.libc_installation) |libc_installation| { + if (self.base.comp.libc_installation) |libc_installation| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?})); if (target.abi == .msvc) { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 7db9b06fbc86..1ddbece4e1ba 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1001,7 +1001,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // --verbose-link if (self.base.comp.verbose_link) try self.dumpArgv(comp); - const csu = try CsuObjects.init(arena, self.base.options, comp); + const csu = try CsuObjects.init(arena, comp); const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; @@ -1021,8 +1021,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (csu.crti) |v| try positionals.append(.{ .path = v }); if (csu.crtbegin) |v| try positionals.append(.{ .path = v }); - try positionals.ensureUnusedCapacity(self.base.options.objects.len); - positionals.appendSliceAssumeCapacity(self.base.options.objects); + try positionals.ensureUnusedCapacity(self.base.comp.objects.len); + positionals.appendSliceAssumeCapacity(self.base.comp.objects); // This is a set of object files emitted by clang in a single `build-exe` invocation. // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up @@ -1051,7 +1051,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node _ = try rpath_table.put(lib_dir_path, {}); } } - for (self.base.options.objects) |obj| { + for (self.base.comp.objects) |obj| { if (Compilation.classifyFileExt(obj.path) == .shared_library) { const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; if (obj.loption) continue; @@ -1061,7 +1061,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // TSAN - if (self.base.options.tsan) { + if (self.base.comp.config.any_sanitize_thread) { try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path }); } @@ -1093,21 +1093,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // libc++ dep - if (self.base.options.link_libcpp) { + if (self.base.comp.config.link_libcpp) { try system_libs.ensureUnusedCapacity(2); system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }); system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path }); } // libunwind dep - if (self.base.options.link_libunwind) { + if (self.base.comp.config.link_libunwind) { try system_libs.append(.{ .path = comp.libunwind_static_lib.?.full_object_path }); } // libc dep self.error_flags.missing_libc = false; - if (self.base.options.link_libc) { - if (self.base.options.libc_installation) |lc| { + if (self.base.comp.config.link_libc) { + if (self.base.comp.libc_installation) |lc| { const flags = target_util.libcFullLinkFlags(target); try system_libs.ensureUnusedCapacity(flags.len); @@ -1246,7 +1246,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Look for entry address in objects if not set by the incremental compiler. if (self.entry_index == null) { const entry: ?[]const u8 = entry: { - if (self.base.options.entry) |entry| break :entry entry; + if (self.base.comp.config.entry) |entry| break :entry entry; if (!self.base.isDynLib()) break :entry "_start"; break :entry null; }; @@ -1571,7 +1571,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } else null; - const csu = try CsuObjects.init(arena, self.base.options, comp); + const csu = try CsuObjects.init(arena, comp); const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; @@ -1713,7 +1713,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } if (self.base.options.link_libc) { - if (self.base.options.libc_installation) |libc_installation| { + if (self.base.comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); } @@ -1803,7 +1803,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { // libc dep if (self.base.options.link_libc) { - if (self.base.options.libc_installation != null) { + if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); @@ -2405,8 +2405,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.add(self.base.options.hash_style); // strip does not need to go into the linker hash because it is part of the hash namespace if (self.base.options.link_libc) { - man.hash.add(self.base.options.libc_installation != null); - if (self.base.options.libc_installation) |libc_installation| { + man.hash.add(self.base.comp.libc_installation != null); + if (self.base.comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); } if (have_dynamic_linker) { @@ -2669,7 +2669,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(full_out_path); // csu prelude - const csu = try CsuObjects.init(arena, self.base.options, comp); + const csu = try CsuObjects.init(arena, comp); if (csu.crt0) |v| try argv.append(v); if (csu.crti) |v| try argv.append(v); if (csu.crtbegin) |v| try argv.append(v); @@ -2719,7 +2719,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } if (self.base.options.link_libc) { - if (self.base.options.libc_installation) |libc_installation| { + if (self.base.comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); } @@ -2839,7 +2839,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // libc dep self.error_flags.missing_libc = false; if (self.base.options.link_libc) { - if (self.base.options.libc_installation != null) { + if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); @@ -5444,9 +5444,11 @@ const CsuObjects = struct { crtend: ?[]const u8 = null, crtn: ?[]const u8 = null, - fn init(arena: mem.Allocator, link_options: link.Options, comp: *const Compilation) !CsuObjects { + const InitArgs = struct {}; + + fn init(arena: Allocator, comp: *const Compilation) !CsuObjects { // crt objects are only required for libc. - if (!link_options.link_libc) return CsuObjects{}; + if (!comp.config.link_libc) return .{}; var result: CsuObjects = .{}; @@ -5457,19 +5459,21 @@ const CsuObjects = struct { dynamic_pie, static_exe, static_pie, - } = switch (link_options.output_mode) { + } = switch (comp.config.output_mode) { .Obj => return CsuObjects{}, - .Lib => switch (link_options.link_mode) { + .Lib => switch (comp.config.link_mode) { .Dynamic => .dynamic_lib, .Static => return CsuObjects{}, }, - .Exe => switch (link_options.link_mode) { - .Dynamic => if (link_options.pie) .dynamic_pie else .dynamic_exe, - .Static => if (link_options.pie) .static_pie else .static_exe, + .Exe => switch (comp.config.link_mode) { + .Dynamic => if (comp.config.pie) .dynamic_pie else .dynamic_exe, + .Static => if (comp.config.pie) .static_pie else .static_exe, }, }; - if (link_options.target.isAndroid()) { + const target = comp.root_mod.resolved_target.result; + + if (target.isAndroid()) { switch (mode) { // zig fmt: off .dynamic_lib => result.set( null, null, "crtbegin_so.o", "crtend_so.o", null ), @@ -5480,7 +5484,7 @@ const CsuObjects = struct { // zig fmt: on } } else { - switch (link_options.target.os.tag) { + switch (target.os.tag) { .linux => { switch (mode) { // zig fmt: off @@ -5491,7 +5495,7 @@ const CsuObjects = struct { .static_pie => result.set( "rcrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), // zig fmt: on } - if (link_options.libc_installation) |_| { + if (comp.libc_installation) |_| { // hosted-glibc provides crtbegin/end objects in platform/compiler-specific dirs // and they are not known at comptime. For now null-out crtbegin/end objects; // there is no feature loss, zig has never linked those objects in before. @@ -5499,7 +5503,7 @@ const CsuObjects = struct { result.crtend = null; } else { // Bundled glibc only has Scrt1.o . - if (result.crt0 != null and link_options.target.isGnuLibC()) result.crt0 = "Scrt1.o"; + if (result.crt0 != null and target.isGnuLibC()) result.crt0 = "Scrt1.o"; } }, .dragonfly => switch (mode) { @@ -5561,16 +5565,16 @@ const CsuObjects = struct { } // Convert each object to a full pathname. - if (link_options.libc_installation) |lci| { + if (comp.libc_installation) |lci| { const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; - switch (link_options.target.os.tag) { + switch (target.os.tag) { .dragonfly => { if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); var gccv: []const u8 = undefined; - if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4, .patch = 0 }) orelse true) { + if (target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4, .patch = 0 }) orelse true) { gccv = "gcc80"; } else { gccv = "gcc54"; From 5a6a1f8a8ad1475d328c998824981c7b310987d2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Dec 2023 22:10:39 -0700 Subject: [PATCH 029/133] linker: update target references --- src/arch/wasm/Emit.zig | 3 +- src/link/Coff.zig | 11 ++- src/link/Coff/Relocation.zig | 3 +- src/link/Coff/lld.zig | 2 +- src/link/Elf/Object.zig | 3 +- src/link/Elf/SharedObject.zig | 3 +- src/link/Elf/synthetic_sections.zig | 6 +- src/link/MachO.zig | 126 +++++++++++++++++----------- src/link/MachO/Atom.zig | 28 ++++--- src/link/MachO/DebugSymbols.zig | 14 +++- src/link/MachO/Object.zig | 33 ++++---- src/link/MachO/Relocation.zig | 6 +- src/link/MachO/UnwindInfo.zig | 29 ++++--- src/link/MachO/dead_strip.zig | 62 +++++++------- src/link/MachO/eh_frame.zig | 35 ++++---- src/link/MachO/load_commands.zig | 6 +- src/link/MachO/zld.zig | 29 ++++--- src/link/Plan9.zig | 55 ++++++------ src/link/Wasm.zig | 11 ++- 19 files changed, 274 insertions(+), 191 deletions(-) diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index dbd85116a0d1..990eb359e883 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -406,7 +406,8 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { const extra_index = emit.mir.instructions.items(.data)[inst].payload; const mem = emit.mir.extraData(Mir.Memory, extra_index).data; const mem_offset = emit.offset() + 1; - const is_wasm32 = emit.bin_file.base.options.target.cpu.arch == .wasm32; + const target = emit.bin_file.comp.root_mod.resolved_target.result; + const is_wasm32 = target.cpu.arch == .wasm32; if (is_wasm32) { try emit.code.append(std.wasm.opcode(.i32_const)); var buf: [5]u8 = undefined; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 789b9fe773a8..d99460d333cf 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1467,6 +1467,7 @@ pub fn updateExports( } const ip = &mod.intern_pool; + const target = self.base.comp.root_mod.resolved_target.result; if (self.base.options.use_llvm) { // Even in the case of LLVM, we need to notice certain exported symbols in order to @@ -1478,7 +1479,7 @@ pub fn updateExports( }; const exported_decl = mod.declPtr(exported_decl_index); if (exported_decl.getOwnedFunction(mod) == null) continue; - const winapi_cc = switch (self.base.options.target.cpu.arch) { + const winapi_cc = switch (target.cpu.arch) { .x86 => std.builtin.CallingConvention.Stdcall, else => std.builtin.CallingConvention.C, }; @@ -1487,7 +1488,7 @@ pub fn updateExports( self.base.options.link_libc) { mod.stage1_flags.have_c_main = true; - } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) { + } else if (decl_cc == winapi_cc and target.os.tag == .windows) { if (ip.stringEqlSlice(exp.opts.name, "WinMain")) { mod.stage1_flags.have_winmain = true; } else if (ip.stringEqlSlice(exp.opts.name, "wWinMain")) { @@ -2200,6 +2201,7 @@ fn writeDataDirectoriesHeaders(self: *Coff) !void { } fn writeHeader(self: *Coff) !void { + const target = self.base.comp.root_mod.resolved_target.result; const gpa = self.base.comp.gpa; var buffer = std.ArrayList(u8).init(gpa); defer buffer.deinit(); @@ -2225,7 +2227,7 @@ fn writeHeader(self: *Coff) !void { const timestamp = std.time.timestamp(); const size_of_optional_header = @as(u16, @intCast(self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize())); var coff_header = coff.CoffHeader{ - .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch), + .machine = coff.MachineType.fromTargetCpuArch(target.cpu.arch), .number_of_sections = @as(u16, @intCast(self.sections.slice().len)), // TODO what if we prune a section .time_date_stamp = @as(u32, @truncate(@as(u64, @bitCast(timestamp)))), .pointer_to_symbol_table = self.strtab_offset orelse 0, @@ -2451,8 +2453,9 @@ pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { } pub fn getImageBase(self: Coff) u64 { + const target = self.base.comp.root_mod.resolved_target.result; const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.comp.config.output_mode) { - .Exe => switch (self.base.options.target.cpu.arch) { + .Exe => switch (target.cpu.arch) { .aarch64 => @as(u64, 0x140000000), .x86_64, .x86 => 0x400000, else => unreachable, // unsupported target architecture diff --git a/src/link/Coff/Relocation.zig b/src/link/Coff/Relocation.zig index 84cfcdc18a88..b25427fedaa8 100644 --- a/src/link/Coff/Relocation.zig +++ b/src/link/Coff/Relocation.zig @@ -107,7 +107,8 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, image_base: .ptr_width = coff_file.ptr_width, }; - switch (coff_file.base.options.target.cpu.arch) { + const target = coff_file.base.comp.root_mod.resolved_target.result; + switch (target.cpu.arch) { .aarch64 => self.resolveAarch64(ctx), .x86, .x86_64 => self.resolveX86(ctx), else => unreachable, // unhandled target architecture diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 297900fae5d2..918a7004c1a2 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -49,7 +49,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; - const target = self.base.options.target; + const target = self.base.comp.root_mod.resolved_target.result; const optimize_mode = self.base.comp.root_mod.optimize_mode; // See link/Elf.zig for comments on how this mechanism works. diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 6b0cc66c33e3..347f96d45117 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -54,7 +54,8 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { self.header = try reader.readStruct(elf.Elf64_Ehdr); - if (elf_file.base.options.target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { + const target = elf_file.base.comp.root_mod.resolved_target.result; + if (target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { try elf_file.reportParseError2( self.index, "invalid cpu architecture: {s}", diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 2a39477805ba..6675f4994146 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -53,7 +53,8 @@ pub fn parse(self: *SharedObject, elf_file: *Elf) !void { self.header = try reader.readStruct(elf.Elf64_Ehdr); - if (elf_file.base.options.target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { + const target = elf_file.base.comp.root_mod.resolved_target.result; + if (target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { try elf_file.reportParseError2( self.index, "invalid cpu architecture: {s}", diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 25a9975f01e4..1e7f2f4f9f2a 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -287,7 +287,8 @@ pub const ZigGotSection = struct { zig_got.flags.dirty = false; } const entry_size: u16 = elf_file.archPtrWidthBytes(); - const endian = elf_file.base.options.target.cpu.arch.endian(); + const target = elf_file.base.comp.root_mod.resolved_target.result; + const endian = target.cpu.arch.endian(); const off = zig_got.entryOffset(index, elf_file); const vaddr = zig_got.entryAddress(index, elf_file); const entry = zig_got.entries.items[index]; @@ -1575,7 +1576,8 @@ pub const ComdatGroupSection = struct { fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void { const entry_size = elf_file.archPtrWidthBytes(); - const endian = elf_file.base.options.target.cpu.arch.endian(); + const target = elf_file.base.comp.root_mod.resolved_target.result; + const endian = target.cpu.arch.endian(); switch (entry_size) { 2 => try writer.writeInt(u16, @intCast(value), endian), 4 => try writer.writeInt(u32, @intCast(value), endian), diff --git a/src/link/MachO.zig b/src/link/MachO.zig index eb5b5bce0d7d..c1d7eef6526d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -143,7 +143,7 @@ tlv_table: TlvSymbolTable = .{}, /// Hot-code swapping state. hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, -darwin_sdk_layout: ?SdkLayout, +sdk_layout: ?SdkLayout, /// Size of the __PAGEZERO segment. pagezero_vmsize: u64, /// Minimum space for future expansion of the load commands. @@ -184,20 +184,21 @@ pub const SdkLayout = enum { pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; + const comp = options.comp; + const target = comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; assert(target.ofmt == .macho); - const gpa = options.comp.gpa; + const gpa = comp.gpa; const emit = options.emit; const mode: Mode = mode: { - if (use_llvm or options.module == null or options.cache_mode == .whole) + if (use_llvm or comp.module == null or comp.cache_mode == .whole) break :mode .zld; break :mode .incremental; }; const sub_path = if (mode == .zld) blk: { - if (options.module == null) { + if (comp.module == null) { // No point in opening a file, we would not write anything to it. // Initialize with empty. return createEmpty(arena, options); @@ -225,13 +226,13 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { .read = true, .mode = link.File.determineMode( use_lld, - options.comp.config.output_mode, - options.comp.config.link_mode, + comp.config.output_mode, + comp.config.link_mode, ), }); self.base.file = file; - if (!options.strip and options.module != null) { + if (self.base.debug_format != .strip and comp.module != null) { // Create dSYM bundle. log.debug("creating {s}.dSYM bundle", .{sub_path}); @@ -276,14 +277,15 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { - const self = try arena.create(MachO); - const optimize_mode = options.comp.root_mod.optimize_mode; - const use_llvm = options.comp.config.use_llvm; + const comp = options.comp; + const optimize_mode = comp.root_mod.optimize_mode; + const use_llvm = comp.config.use_llvm; + const self = try arena.create(MachO); self.* = .{ .base = .{ .tag = .macho, - .comp = options.comp, + .comp = comp, .emit = options.emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), .stack_size = options.stack_size orelse 16777216, @@ -297,7 +299,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { .function_sections = options.function_sections, .data_sections = options.data_sections, }, - .mode = if (use_llvm or options.module == null or options.cache_mode == .whole) + .mode = if (use_llvm or comp.module == null or comp.cache_mode == .whole) .zld else .incremental, @@ -305,9 +307,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { .headerpad_size = options.headerpad_size orelse default_headerpad_size, .headerpad_max_install_names = options.headerpad_max_install_names, .dead_strip_dylibs = options.dead_strip_dylibs, + .sdk_layout = options.darwin_sdk_layout, + .frameworks = options.frameworks, + .install_name = options.install_name, + .entitlements = options.entitlements, }; - if (use_llvm and options.module != null) { + if (use_llvm and comp.module != null) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -357,6 +363,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No const output_mode = self.base.comp.config.output_mode; const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const target = self.base.comp.root_mod.resolved_target.result; if (self.lazy_syms.getPtr(.none)) |metadata| { // Most lazy symbols can be updated on first use, but @@ -569,7 +576,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No // written out to the file. // The most important here is to have the correct vm and filesize of the __LINKEDIT segment // where the code signature goes into. - var codesig = CodeSignature.init(getPageSize(self.base.options.target.cpu.arch)); + var codesig = CodeSignature.init(getPageSize(target.cpu.arch)); codesig.code_directory.ident = self.base.emit.sub_path; if (self.entitlements) |path| { try codesig.addEntitlements(gpa, path); @@ -619,7 +626,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No .version = 0, }); { - const platform = Platform.fromTarget(self.base.options.target); + const platform = Platform.fromTarget(target); const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); @@ -701,7 +708,7 @@ pub fn resolveLibSystem( var checked_paths = std.ArrayList([]const u8).init(arena); success: { - if (self.base.options.darwin_sdk_layout) |sdk_layout| switch (sdk_layout) { + if (self.sdk_layout) |sdk_layout| switch (sdk_layout) { .sdk => { const dir = try fs.path.join(arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" }); if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success; @@ -817,6 +824,7 @@ fn parseObject( defer tracy.end(); const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; const mtime: u64 = mtime: { const stat = file.stat() catch break :mtime 0; break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000))); @@ -839,8 +847,8 @@ fn parseObject( else => unreachable, }; const detected_platform = object.getPlatform(); - const this_cpu_arch = self.base.options.target.cpu.arch; - const this_platform = Platform.fromTarget(self.base.options.target); + const this_cpu_arch = target.cpu.arch; + const this_platform = Platform.fromTarget(target); if (this_cpu_arch != detected_cpu_arch or (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) @@ -867,8 +875,10 @@ pub fn parseLibrary( const tracy = trace(@src()); defer tracy.end(); + const target = self.base.comp.root_mod.resolved_target.result; + if (fat.isFatLibrary(file)) { - const offset = try self.parseFatLibrary(file, self.base.options.target.cpu.arch, ctx); + const offset = try self.parseFatLibrary(file, target.cpu.arch, ctx); try file.seekTo(offset); if (Archive.isArchive(file, offset)) { @@ -934,6 +944,7 @@ fn parseArchive( ctx: *ParseErrorCtx, ) ParseError!void { const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; // We take ownership of the file so that we can store it for the duration of symbol resolution. // TODO we shouldn't need to do that and could pre-parse the archive like we do for zld/ELF? @@ -963,8 +974,8 @@ fn parseArchive( else => unreachable, }; const detected_platform = object.getPlatform(); - const this_cpu_arch = self.base.options.target.cpu.arch; - const this_platform = Platform.fromTarget(self.base.options.target); + const this_cpu_arch = target.cpu.arch; + const this_platform = Platform.fromTarget(target); if (this_cpu_arch != detected_cpu_arch or (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) @@ -1015,6 +1026,7 @@ fn parseDylib( ctx: *ParseErrorCtx, ) ParseError!void { const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; const file_stat = try file.stat(); const file_size = math.cast(usize, file_stat.size - offset) orelse return error.Overflow; @@ -1038,8 +1050,8 @@ fn parseDylib( else => unreachable, }; const detected_platform = dylib.getPlatform(contents); - const this_cpu_arch = self.base.options.target.cpu.arch; - const this_platform = Platform.fromTarget(self.base.options.target); + const this_cpu_arch = target.cpu.arch; + const this_platform = Platform.fromTarget(target); if (this_cpu_arch != detected_cpu_arch or (detected_platform != null and !detected_platform.?.eqlTarget(this_platform))) @@ -1061,6 +1073,8 @@ fn parseLibStub( ctx: *ParseErrorCtx, ) ParseError!void { const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; + var lib_stub = try LibStub.loadFromFile(gpa, file); defer lib_stub.deinit(); @@ -1068,7 +1082,7 @@ fn parseLibStub( // Verify target { - var matcher = try Dylib.TargetMatcher.init(gpa, self.base.options.target); + var matcher = try Dylib.TargetMatcher.init(gpa, target); defer matcher.deinit(); const first_tbd = lib_stub.inner[0]; @@ -1091,7 +1105,7 @@ fn parseLibStub( try dylib.parseFromStub( gpa, - self.base.options.target, + target, lib_stub, @intCast(self.dylibs.items.len), // TODO defer it till later dependent_libs, @@ -1236,7 +1250,8 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { fn writeToMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void { const segment = self.segments.items[segment_index]; - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const nwritten = if (!segment.isWriteable()) try task.writeMemProtected(addr, code, cpu_arch) else @@ -1280,7 +1295,8 @@ fn writeStubHelperPreamble(self: *MachO) !void { if (self.stub_helper_preamble_allocated) return; const gpa = self.base.comp.gpa; - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const size = stubs.stubHelperPreambleSize(cpu_arch); var buf = try std.ArrayList(u8).initCapacity(gpa, size); @@ -1306,11 +1322,12 @@ fn writeStubHelperPreamble(self: *MachO) !void { } fn writeStubTableEntry(self: *MachO, index: usize) !void { + const target = self.base.comp.root_mod.resolved_target.result; const stubs_sect_id = self.stubs_section_index.?; const stub_helper_sect_id = self.stub_helper_section_index.?; const laptr_sect_id = self.la_symbol_ptr_section_index.?; - const cpu_arch = self.base.options.target.cpu.arch; + const cpu_arch = target.cpu.arch; const stub_entry_size = stubs.stubSize(cpu_arch); const stub_helper_entry_size = stubs.stubHelperSize(cpu_arch); const stub_helper_preamble_size = stubs.stubHelperPreambleSize(cpu_arch); @@ -2243,7 +2260,7 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, - .reserved2 = stubs.stubSize(self.base.options.target.cpu.arch), + .reserved2 = stubs.stubSize(target.cpu.arch), }); self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ .flags = macho.S_REGULAR | @@ -3116,7 +3133,8 @@ fn populateMissingMetadata(self: *MachO) !void { assert(self.mode == .incremental); const gpa = self.base.comp.gpa; - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const pagezero_vmsize = self.calcPagezeroSize(); if (self.pagezero_segment_cmd_index == null) { @@ -3263,7 +3281,8 @@ fn populateMissingMetadata(self: *MachO) !void { fn calcPagezeroSize(self: *MachO) u64 { const output_mode = self.base.comp.config.output_mode; - const page_size = getPageSize(self.base.options.target.cpu.arch); + const target = self.base.comp.root_mod.resolved_target.result; + const page_size = getPageSize(target.cpu.arch); const aligned_pagezero_vmsize = mem.alignBackward(u64, self.pagezero_vmsize, page_size); if (output_mode == .Lib) return 0; if (aligned_pagezero_vmsize == 0) return 0; @@ -3305,7 +3324,8 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts reserved2: u32 = 0, }) !u8 { const gpa = self.base.comp.gpa; - const page_size = getPageSize(self.base.options.target.cpu.arch); + const target = self.base.comp.root_mod.resolved_target.result; + const page_size = getPageSize(target.cpu.arch); // In incremental context, we create one section per segment pairing. This way, // we can move the segment in raw file as we please. const segment_id = @as(u8, @intCast(self.segments.items.len)); @@ -3360,7 +3380,8 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { const segment = &self.segments.items[segment_index]; const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id]; const sect_capacity = self.allocatedSize(header.offset); - const page_size = getPageSize(self.base.options.target.cpu.arch); + const target = self.base.comp.root_mod.resolved_target.result; + const page_size = getPageSize(target.cpu.arch); if (needed_size > sect_capacity) { const new_offset = self.findFreeSpace(needed_size, page_size); @@ -3400,7 +3421,8 @@ fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { } fn growSectionVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void { - const page_size = getPageSize(self.base.options.target.cpu.arch); + const target = self.base.comp.root_mod.resolved_target.result; + const page_size = getPageSize(target.cpu.arch); const header = &self.sections.items(.header)[sect_id]; const segment = self.getSegmentPtr(sect_id); const increased_size = padToIdeal(needed_size); @@ -3611,7 +3633,8 @@ pub fn writeSegmentHeaders(self: *MachO, writer: anytype) !void { } pub fn writeLinkeditSegmentData(self: *MachO) !void { - const page_size = getPageSize(self.base.options.target.cpu.arch); + const target = self.base.comp.root_mod.resolved_target.result; + const page_size = getPageSize(target.cpu.arch); const seg = self.getLinkeditSegmentPtr(); seg.filesize = 0; seg.vmsize = 0; @@ -3698,7 +3721,8 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { } // Finally, unpack the rest. - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; for (self.objects.items) |*object| { for (object.atoms.items) |atom_index| { const atom = self.getAtom(atom_index); @@ -3744,14 +3768,14 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void { }, else => unreachable, } - const target = Atom.parseRelocTarget(self, .{ + const reloc_target = Atom.parseRelocTarget(self, .{ .object_id = atom.getFile().?, .rel = rel, .code = code, .base_offset = ctx.base_offset, .base_addr = ctx.base_addr, }); - const target_sym = self.getSymbol(target); + const target_sym = self.getSymbol(reloc_target); if (target_sym.undf()) continue; const base_offset = @as(i32, @intCast(sym.n_value - segment.vmaddr)); @@ -3853,7 +3877,8 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void { } // Finally, unpack the rest. - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; for (self.objects.items) |*object| { for (object.atoms.items) |atom_index| { const atom = self.getAtom(atom_index); @@ -4072,7 +4097,8 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: anytype) !void { const header = self.sections.items(.header)[stub_helper_section_index]; - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const preamble_size = stubs.stubHelperPreambleSize(cpu_arch); const stub_size = stubs.stubHelperSize(cpu_arch); const stub_offset = stubs.stubOffsetInStubHelper(cpu_arch); @@ -4708,13 +4734,14 @@ pub fn writeUuid(self: *MachO, comp: *const Compilation, uuid_cmd_offset: u32, h } pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { + const target = self.base.comp.root_mod.resolved_target.result; const seg = self.getLinkeditSegmentPtr(); // Code signature data has to be 16-bytes aligned for Apple tools to recognize the file // https://github.com/opensource-apple/cctools/blob/fdb4825f303fd5c0751be524babd32958181b3ed/libstuff/checkout.c#L271 const offset = mem.alignForward(u64, seg.fileoff + seg.filesize, 16); const needed_size = code_sig.estimateSize(offset); seg.filesize = offset + needed_size - seg.fileoff; - seg.vmsize = mem.alignForward(u64, seg.filesize, getPageSize(self.base.options.target.cpu.arch)); + seg.vmsize = mem.alignForward(u64, seg.filesize, getPageSize(target.cpu.arch)); log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); // Pad out the space. We need to do this to calculate valid hashes for everything in the file // except for code signature data. @@ -4758,7 +4785,8 @@ pub fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void { var header: macho.mach_header_64 = .{}; header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL; - switch (self.base.options.target.cpu.arch) { + const target = self.base.comp.root_mod.resolved_target.result; + switch (target.cpu.arch) { .aarch64 => { header.cputype = macho.CPU_TYPE_ARM64; header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; @@ -5123,9 +5151,10 @@ pub fn getTlvPtrEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 { } pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 { + const target = self.base.comp.root_mod.resolved_target.result; const index = self.stub_table.lookup.get(sym_with_loc) orelse return null; const header = self.sections.items(.header)[self.stubs_section_index.?]; - return header.addr + stubs.stubSize(self.base.options.target.cpu.arch) * index; + return header.addr + stubs.stubSize(target.cpu.arch) * index; } /// Returns symbol location corresponding to the set entrypoint if any. @@ -5234,8 +5263,9 @@ pub fn handleAndReportParseError( err: ParseError, ctx: *const ParseErrorCtx, ) error{OutOfMemory}!void { + const target = self.base.comp.root_mod.resolved_target.result; const gpa = self.base.comp.gpa; - const cpu_arch = self.base.options.target.cpu.arch; + const cpu_arch = target.cpu.arch; switch (err) { error.DylibAlreadyExists => {}, error.IncompatibleDylibVersion => { @@ -5270,7 +5300,7 @@ pub fn handleAndReportParseError( error.InvalidTarget => try self.reportParseError( path, "invalid target: expected '{}', but found '{s}'", - .{ Platform.fromTarget(self.base.options.target).fmtTarget(cpu_arch), targets_string.items }, + .{ Platform.fromTarget(target).fmtTarget(cpu_arch), targets_string.items }, ), error.InvalidTargetFatLibrary => try self.reportParseError( path, diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 290c67c45e2e..02639953593d 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -387,7 +387,8 @@ pub fn calcInnerSymbolOffset(macho_file: *MachO, atom_index: Index, sym_index: u } pub fn scanAtomRelocs(macho_file: *MachO, atom_index: Index, relocs: []align(1) const macho.relocation_info) !void { - const arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const arch = target.cpu.arch; const atom = macho_file.getAtom(atom_index); assert(atom.getFile() != null); // synthetic atoms do not have relocs @@ -434,6 +435,7 @@ pub fn parseRelocTarget(macho_file: *MachO, ctx: struct { const tracy = trace(@src()); defer tracy.end(); + const target = macho_file.base.comp.root_mod.resolved_target.result; const object = &macho_file.objects.items[ctx.object_id]; log.debug("parsing reloc target in object({d}) '{s}' ", .{ ctx.object_id, object.name }); @@ -447,7 +449,7 @@ pub fn parseRelocTarget(macho_file: *MachO, ctx: struct { else mem.readInt(u32, ctx.code[rel_offset..][0..4], .little); } else blk: { - assert(macho_file.base.options.target.cpu.arch == .x86_64); + assert(target.cpu.arch == .x86_64); const correction: u3 = switch (@as(macho.reloc_type_x86_64, @enumFromInt(ctx.rel.r_type))) { .X86_64_RELOC_SIGNED => 0, .X86_64_RELOC_SIGNED_1 => 1, @@ -467,18 +469,18 @@ pub fn parseRelocTarget(macho_file: *MachO, ctx: struct { const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = ctx.object_id + 1 }; const sym = macho_file.getSymbol(sym_loc); - const target = if (sym.sect() and !sym.ext()) + const reloc_target = if (sym.sect() and !sym.ext()) sym_loc else if (object.getGlobal(sym_index)) |global_index| macho_file.globals.items[global_index] else sym_loc; log.debug(" | target %{d} ('{s}') in object({?d})", .{ - target.sym_index, - macho_file.getSymbolName(target), - target.getFile(), + reloc_target.sym_index, + macho_file.getSymbolName(reloc_target), + reloc_target.getFile(), }); - return target; + return reloc_target; } pub fn getRelocTargetAtomIndex(macho_file: *MachO, target: SymbolWithLoc) ?Index { @@ -599,7 +601,8 @@ pub fn resolveRelocs( atom_code: []u8, atom_relocs: []align(1) const macho.relocation_info, ) !void { - const arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const arch = target.cpu.arch; const atom = macho_file.getAtom(atom_index); assert(atom.getFile() != null); // synthetic atoms do not have relocs @@ -1192,7 +1195,8 @@ pub fn getAtomRelocs(macho_file: *MachO, atom_index: Index) []const macho.reloca } pub fn relocRequiresGot(macho_file: *MachO, rel: macho.relocation_info) bool { - switch (macho_file.base.options.target.cpu.arch) { + const target = macho_file.base.comp.root_mod.resolved_target.result; + switch (target.cpu.arch) { .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { .ARM64_RELOC_GOT_LOAD_PAGE21, .ARM64_RELOC_GOT_LOAD_PAGEOFF12, @@ -1211,7 +1215,8 @@ pub fn relocRequiresGot(macho_file: *MachO, rel: macho.relocation_info) bool { } pub fn relocIsTlv(macho_file: *MachO, rel: macho.relocation_info) bool { - switch (macho_file.base.options.target.cpu.arch) { + const target = macho_file.base.comp.root_mod.resolved_target.result; + switch (target.cpu.arch) { .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { .ARM64_RELOC_TLVP_LOAD_PAGE21, .ARM64_RELOC_TLVP_LOAD_PAGEOFF12, @@ -1227,7 +1232,8 @@ pub fn relocIsTlv(macho_file: *MachO, rel: macho.relocation_info) bool { } pub fn relocIsStub(macho_file: *MachO, rel: macho.relocation_info) bool { - switch (macho_file.base.options.target.cpu.arch) { + const target = macho_file.base.comp.root_mod.resolved_target.result; + switch (target.cpu.arch) { .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { .ARM64_RELOC_BRANCH26 => return true, else => return false, diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index f204093290e3..2e7f8e49af73 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -39,10 +39,12 @@ pub const Reloc = struct { /// You must call this function *after* `MachO.populateMissingMetadata()` /// has been called to get a viable debug symbols output. pub fn populateMissingMetadata(self: *DebugSymbols, macho_file: *MachO) !void { + const target = macho_file.base.comp.root_mod.resolved_target.result; + if (self.dwarf_segment_cmd_index == null) { self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); - const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); + const page_size = MachO.getPageSize(target.cpu.arch); const off = @as(u64, @intCast(page_size)); const ideal_size: u16 = 200 + 128 + 160 + 250; const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), page_size); @@ -332,7 +334,8 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { file_size = @max(file_size, header.offset + header.size); } - const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); + const target = macho_file.base.comp.root_mod.resolved_target.result; + const page_size = MachO.getPageSize(target.cpu.arch); const aligned_size = mem.alignForward(u64, file_size, page_size); dwarf_segment.vmaddr = base_vmaddr; dwarf_segment.filesize = aligned_size; @@ -394,10 +397,12 @@ fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) } fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void { + const target = macho_file.base.comp.root_mod.resolved_target.result; + var header: macho.mach_header_64 = .{}; header.filetype = macho.MH_DSYM; - switch (macho_file.base.options.target.cpu.arch) { + switch (target.cpu.arch) { .aarch64 => { header.cputype = macho.CPU_TYPE_ARM64; header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; @@ -435,7 +440,8 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { try self.writeSymtab(macho_file); try self.writeStrtab(); - const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); + const target = macho_file.base.comp.root_mod.resolved_target.result; + const page_size = MachO.getPageSize(target.cpu.arch); const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; const aligned_size = mem.alignForward(u64, seg.filesize, page_size); seg.vmsize = aligned_size; diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 0c68d706446f..5185b933860e 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -355,6 +355,7 @@ pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) SplitIn /// into subsections where each subsection then represents an Atom. pub fn splitRegularSections(self: *Object, macho_file: *MachO, object_id: u32) !void { const gpa = macho_file.base.allocator; + const target = macho_file.base.comp.root_mod.resolved_target.result; const sections = self.getSourceSections(); for (sections, 0..) |sect, id| { @@ -448,7 +449,7 @@ pub fn splitRegularSections(self: *Object, macho_file: *MachO, object_id: u32) ! try self.parseRelocs(gpa, section.id); - const cpu_arch = macho_file.base.options.target.cpu.arch; + const cpu_arch = target.cpu.arch; const sect_loc = filterSymbolsBySection(symtab[sect_sym_index..], sect_id + 1); const sect_start_index = sect_sym_index + sect_loc.index; @@ -676,7 +677,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void macho_file.eh_frame_section_index = try macho_file.initSection("__TEXT", "__eh_frame", .{}); } - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; try self.parseRelocs(gpa, sect_id); const relocs = self.getRelocs(sect_id); @@ -704,7 +706,7 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void }); if (record.tag == .fde) { - const target = blk: { + const reloc_target = blk: { switch (cpu_arch) { .aarch64 => { assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed @@ -714,13 +716,13 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type)) == .ARM64_RELOC_UNSIGNED) break rel; } else unreachable; - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = it.data[offset..], .base_offset = @as(i32, @intCast(offset)), }); - break :blk target; + break :blk reloc_target; }, .x86_64 => { const target_address = record.getTargetSymbolAddress(.{ @@ -728,16 +730,16 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void .base_offset = offset, }); const target_sym_index = self.getSymbolByAddress(target_address, null); - const target = if (self.getGlobal(target_sym_index)) |global_index| + const reloc_target = if (self.getGlobal(target_sym_index)) |global_index| macho_file.globals.items[global_index] else SymbolWithLoc{ .sym_index = target_sym_index, .file = object_id + 1 }; - break :blk target; + break :blk reloc_target; }, else => unreachable, } }; - if (target.getFile() != object_id) { + if (reloc_target.getFile() != object_id) { log.debug("FDE at offset {x} marked DEAD", .{offset}); self.eh_frame_relocs_lookup.getPtr(offset).?.dead = true; } else { @@ -746,12 +748,12 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void // very problematic when using Zig's @export feature to re-export symbols under // additional names. For that reason, we need to ensure we record aliases here // too so that we can tie them with their matching unwind records and vice versa. - const aliases = self.getSymbolAliases(target.sym_index); + const aliases = self.getSymbolAliases(reloc_target.sym_index); var i: u32 = 0; while (i < aliases.len) : (i += 1) { const actual_target = SymbolWithLoc{ .sym_index = i + aliases.start, - .file = target.file, + .file = reloc_target.file, }; log.debug("FDE at offset {x} tracks {s}", .{ offset, @@ -766,7 +768,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void { const gpa = macho_file.base.allocator; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const sect_id = self.unwind_info_sect_id orelse { // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`, // we will try fully synthesising unwind info records to somewhat match Apple ld's @@ -818,13 +821,13 @@ fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void { // Find function symbol that this record describes const rel = relocs[rel_pos.start..][rel_pos.len - 1]; - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(offset)), }); - if (target.getFile() != object_id) { + if (reloc_target.getFile() != object_id) { log.debug("unwind record {d} marked DEAD", .{record_id}); self.unwind_relocs_lookup[record_id].dead = true; } else { @@ -833,12 +836,12 @@ fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void { // very problematic when using Zig's @export feature to re-export symbols under // additional names. For that reason, we need to ensure we record aliases here // too so that we can tie them with their matching unwind records and vice versa. - const aliases = self.getSymbolAliases(target.sym_index); + const aliases = self.getSymbolAliases(reloc_target.sym_index); var i: u32 = 0; while (i < aliases.len) : (i += 1) { const actual_target = SymbolWithLoc{ .sym_index = i + aliases.start, - .file = target.file, + .file = reloc_target.file, }; log.debug("unwind record {d} tracks {s}", .{ record_id, diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index 74be9eb0d561..85c19c7608f3 100644 --- a/src/link/MachO/Relocation.zig +++ b/src/link/MachO/Relocation.zig @@ -58,11 +58,12 @@ pub fn isStubTrampoline(self: Relocation, macho_file: *MachO) bool { } pub fn getTargetBaseAddress(self: Relocation, macho_file: *MachO) ?u64 { + const target = macho_file.base.comp.root_mod.resolved_target.result; if (self.isStubTrampoline(macho_file)) { const index = macho_file.stub_table.lookup.get(self.target) orelse return null; const header = macho_file.sections.items(.header)[macho_file.stubs_section_index.?]; return header.addr + - index * @import("stubs.zig").stubSize(macho_file.base.options.target.cpu.arch); + index * @import("stubs.zig").stubSize(target.cpu.arch); } switch (self.type) { .got, .got_page, .got_pageoff => { @@ -84,7 +85,8 @@ pub fn getTargetBaseAddress(self: Relocation, macho_file: *MachO) ?u64 { } pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, code: []u8) void { - const arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const arch = target.cpu.arch; const atom = macho_file.getAtom(atom_index); const source_sym = atom.getSymbol(macho_file); const source_addr = source_sym.n_value + self.offset; diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index be6c9dbb3453..7223b5555f7e 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -184,7 +184,8 @@ pub fn deinit(info: *UnwindInfo) void { pub fn scanRelocs(macho_file: *MachO) !void { if (macho_file.unwind_info_section_index == null) return; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; for (macho_file.objects.items, 0..) |*object, object_id| { const unwind_records = object.getUnwindRecords(); for (object.exec_atoms.items) |atom_index| { @@ -196,13 +197,13 @@ pub fn scanRelocs(macho_file: *MachO) !void { if (!UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) { if (getPersonalityFunctionReloc(macho_file, @as(u32, @intCast(object_id)), record_id)) |rel| { // Personality function; add GOT pointer. - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = @as(u32, @intCast(object_id)), .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))), }); - try macho_file.addGotEntry(target); + try macho_file.addGotEntry(reloc_target); } } } @@ -213,7 +214,8 @@ pub fn scanRelocs(macho_file: *MachO) !void { pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void { if (macho_file.unwind_info_section_index == null) return; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; var records = std.ArrayList(macho.compact_unwind_entry).init(info.gpa); defer records.deinit(); @@ -247,15 +249,15 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void { @as(u32, @intCast(object_id)), record_id, )) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = @as(u32, @intCast(object_id)), .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))), }); - const personality_index = info.getPersonalityFunction(target) orelse inner: { + const personality_index = info.getPersonalityFunction(reloc_target) orelse inner: { const personality_index = info.personalities_count; - info.personalities[personality_index] = target; + info.personalities[personality_index] = reloc_target; info.personalities_count += 1; break :inner personality_index; }; @@ -265,13 +267,13 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void { } if (getLsdaReloc(macho_file, @as(u32, @intCast(object_id)), record_id)) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = @as(u32, @intCast(object_id)), .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))), }); - record.lsda = @as(u64, @bitCast(target)); + record.lsda = @as(u64, @bitCast(reloc_target)); } } break :blk record; @@ -557,13 +559,14 @@ pub fn write(info: *UnwindInfo, macho_file: *MachO) !void { const text_sect = macho_file.sections.items(.header)[text_sect_id]; var personalities: [max_personalities]u32 = undefined; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; log.debug("Personalities:", .{}); - for (info.personalities[0..info.personalities_count], 0..) |target, i| { - const addr = macho_file.getGotEntryAddress(target).?; + for (info.personalities[0..info.personalities_count], 0..) |reloc_target, i| { + const addr = macho_file.getGotEntryAddress(reloc_target).?; personalities[i] = @as(u32, @intCast(addr - seg.vmaddr)); - log.debug(" {d}: 0x{x} ({s})", .{ i, personalities[i], macho_file.getSymbolName(target) }); + log.debug(" {d}: 0x{x} ({s})", .{ i, personalities[i], macho_file.getSymbolName(reloc_target) }); } for (info.records.items) |*rec| { diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index 21f9154b4506..51a43351ba03 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -118,7 +118,8 @@ fn markLive(macho_file: *MachO, atom_index: Atom.Index, alive: *AtomTable) void alive.putAssumeCapacityNoClobber(atom_index, {}); - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const sym = macho_file.getSymbol(atom.getSymbolWithLoc()); const header = macho_file.sections.items(.header)[sym.n_sect - 1]; @@ -129,7 +130,7 @@ fn markLive(macho_file: *MachO, atom_index: Atom.Index, alive: *AtomTable) void const ctx = Atom.getRelocContext(macho_file, atom_index); for (relocs) |rel| { - const target = switch (cpu_arch) { + const reloc_target = switch (cpu_arch) { .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { .ARM64_RELOC_ADDEND => continue, else => Atom.parseRelocTarget(macho_file, .{ @@ -149,19 +150,19 @@ fn markLive(macho_file: *MachO, atom_index: Atom.Index, alive: *AtomTable) void }), else => unreachable, }; - const target_sym = macho_file.getSymbol(target); + const target_sym = macho_file.getSymbol(reloc_target); if (target_sym.undf()) continue; - if (target.getFile() == null) { - const target_sym_name = macho_file.getSymbolName(target); + if (reloc_target.getFile() == null) { + const target_sym_name = macho_file.getSymbolName(reloc_target); if (mem.eql(u8, "__mh_execute_header", target_sym_name)) continue; if (mem.eql(u8, "___dso_handle", target_sym_name)) continue; unreachable; // referenced symbol not found } - const object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = object.getAtomIndexForSymbol(target.sym_index).?; + const object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = object.getAtomIndexForSymbol(reloc_target.sym_index).?; log.debug(" following ATOM({d}, %{d}, {?d})", .{ target_atom_index, macho_file.getAtom(target_atom_index).sym_index, @@ -178,7 +179,8 @@ fn refersLive(macho_file: *MachO, atom_index: Atom.Index, alive: AtomTable) bool log.debug("refersLive(ATOM({d}, %{d}, {?d}))", .{ atom_index, sym_loc.sym_index, sym_loc.getFile() }); - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const sym = macho_file.getSymbol(sym_loc); const header = macho_file.sections.items(.header)[sym.n_sect - 1]; @@ -189,7 +191,7 @@ fn refersLive(macho_file: *MachO, atom_index: Atom.Index, alive: AtomTable) bool const ctx = Atom.getRelocContext(macho_file, atom_index); for (relocs) |rel| { - const target = switch (cpu_arch) { + const reloc_target = switch (cpu_arch) { .aarch64 => switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { .ARM64_RELOC_ADDEND => continue, else => Atom.parseRelocTarget(macho_file, .{ @@ -210,9 +212,9 @@ fn refersLive(macho_file: *MachO, atom_index: Atom.Index, alive: AtomTable) bool else => unreachable, }; - const object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = object.getAtomIndexForSymbol(target.sym_index) orelse { - log.debug("atom for symbol '{s}' not found; skipping...", .{macho_file.getSymbolName(target)}); + const object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = object.getAtomIndexForSymbol(reloc_target.sym_index) orelse { + log.debug("atom for symbol '{s}' not found; skipping...", .{macho_file.getSymbolName(reloc_target)}); continue; }; if (alive.contains(target_atom_index)) { @@ -271,7 +273,8 @@ fn mark(macho_file: *MachO, roots: AtomTable, alive: *AtomTable) void { fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) void { const object = &macho_file.objects.items[object_id]; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const unwind_records = object.getUnwindRecords(); @@ -310,29 +313,29 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) void markEhFrameRecords(macho_file, object_id, atom_index, alive); } else { if (UnwindInfo.getPersonalityFunctionReloc(macho_file, object_id, record_id)) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))), }); - const target_sym = macho_file.getSymbol(target); + const target_sym = macho_file.getSymbol(reloc_target); if (!target_sym.undf()) { - const target_object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; + const target_object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = target_object.getAtomIndexForSymbol(reloc_target.sym_index).?; markLive(macho_file, target_atom_index, alive); } } if (UnwindInfo.getLsdaReloc(macho_file, object_id, record_id)) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = mem.asBytes(&record), .base_offset = @as(i32, @intCast(record_id * @sizeOf(macho.compact_unwind_entry))), }); - const target_object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; + const target_object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = target_object.getAtomIndexForSymbol(reloc_target.sym_index).?; markLive(macho_file, target_atom_index, alive); } } @@ -341,7 +344,8 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) void } fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index, alive: *AtomTable) void { - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const object = &macho_file.objects.items[object_id]; var it = object.getEhFrameRecordsIterator(); var inner_syms_it = Atom.getInnerSymbolsIterator(macho_file, atom_index); @@ -361,16 +365,16 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index // Mark FDE references which should include any referenced LSDA record const relocs = eh_frame.getRelocs(macho_file, object_id, fde_offset); for (relocs) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = fde.data, .base_offset = @as(i32, @intCast(fde_offset)) + 4, }); - const target_sym = macho_file.getSymbol(target); + const target_sym = macho_file.getSymbol(reloc_target); if (!target_sym.undf()) blk: { - const target_object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index) orelse + const target_object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = target_object.getAtomIndexForSymbol(reloc_target.sym_index) orelse break :blk; markLive(macho_file, target_atom_index, alive); } @@ -394,11 +398,11 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index // Mark CIE references which should include any referenced personalities // that are defined locally. - if (cie.getPersonalityPointerReloc(macho_file, object_id, cie_offset)) |target| { - const target_sym = macho_file.getSymbol(target); + if (cie.getPersonalityPointerReloc(macho_file, object_id, cie_offset)) |reloc_target| { + const target_sym = macho_file.getSymbol(reloc_target); if (!target_sym.undf()) { - const target_object = macho_file.objects.items[target.getFile().?]; - const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; + const target_object = macho_file.objects.items[reloc_target.getFile().?]; + const target_atom_index = target_object.getAtomIndexForSymbol(reloc_target.sym_index).?; markLive(macho_file, target_atom_index, alive); } } diff --git a/src/link/MachO/eh_frame.zig b/src/link/MachO/eh_frame.zig index 0f021a569cc1..8223c830e00d 100644 --- a/src/link/MachO/eh_frame.zig +++ b/src/link/MachO/eh_frame.zig @@ -35,7 +35,8 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) error sect.@"align" = 3; sect.size = 0; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const gpa = macho_file.base.allocator; var size: u32 = 0; @@ -86,7 +87,8 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void { const seg_id = macho_file.sections.items(.segment_index)[sect_id]; const seg = macho_file.segments.items[seg_id]; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const gpa = macho_file.base.allocator; var eh_records = std.AutoArrayHashMap(u32, EhFrameRecord(true)).init(gpa); @@ -109,11 +111,11 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void { for (object.exec_atoms.items) |atom_index| { var inner_syms_it = Atom.getInnerSymbolsIterator(macho_file, atom_index); - while (inner_syms_it.next()) |target| { - const fde_record_offset = object.eh_frame_records_lookup.get(target) orelse continue; + while (inner_syms_it.next()) |reloc_target| { + const fde_record_offset = object.eh_frame_records_lookup.get(reloc_target) orelse continue; if (object.eh_frame_relocs_lookup.get(fde_record_offset).?.dead) continue; - const record_id = unwind_info.records_lookup.get(target) orelse continue; + const record_id = unwind_info.records_lookup.get(reloc_target) orelse continue; const record = &unwind_info.records.items[record_id]; // TODO skip this check if no __compact_unwind is present @@ -153,7 +155,7 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void { .aarch64 => {}, // relocs take care of LSDA pointers .x86_64 => { // We need to relocate target symbol address ourselves. - const atom_sym = macho_file.getSymbol(target); + const atom_sym = macho_file.getSymbol(reloc_target); try fde_record.setTargetSymbolAddress(atom_sym.n_value, .{ .base_addr = sect.addr, .base_offset = eh_frame_offset, @@ -278,7 +280,8 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { object_id: u32, source_offset: u32, ) ?SymbolWithLoc { - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const relocs = getRelocs(macho_file, object_id, source_offset); for (relocs) |rel| { switch (cpu_arch) { @@ -301,13 +304,13 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { }, else => unreachable, } - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = rec.data, .base_offset = @as(i32, @intCast(source_offset)) + 4, }); - return target; + return reloc_target; } return null; } @@ -319,11 +322,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { }) !void { comptime assert(is_mutable); - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const relocs = getRelocs(macho_file, object_id, ctx.source_offset); for (relocs) |rel| { - const target = Atom.parseRelocTarget(macho_file, .{ + const reloc_target = Atom.parseRelocTarget(macho_file, .{ .object_id = object_id, .rel = rel, .code = rec.data, @@ -340,14 +344,14 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { // Address of the __eh_frame in the source object file }, .ARM64_RELOC_POINTER_TO_GOT => { - const target_addr = macho_file.getGotEntryAddress(target).?; + const target_addr = macho_file.getGotEntryAddress(reloc_target).?; const result = math.cast(i32, @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr))) orelse return error.Overflow; mem.writeInt(i32, rec.data[rel_offset..][0..4], result, .little); }, .ARM64_RELOC_UNSIGNED => { assert(rel.r_extern == 1); - const target_addr = Atom.getRelocTargetAddress(macho_file, target, false); + const target_addr = Atom.getRelocTargetAddress(macho_file, reloc_target, false); const result = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr)); mem.writeInt(i64, rec.data[rel_offset..][0..8], @as(i64, @intCast(result)), .little); }, @@ -358,7 +362,7 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type)); switch (rel_type) { .X86_64_RELOC_GOT => { - const target_addr = macho_file.getGotEntryAddress(target).?; + const target_addr = macho_file.getGotEntryAddress(reloc_target).?; const addend = mem.readInt(i32, rec.data[rel_offset..][0..4], .little); const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); @@ -374,7 +378,8 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type { pub fn getCiePointerSource(rec: Record, object_id: u32, macho_file: *MachO, offset: u32) u32 { assert(rec.tag == .fde); - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const addend = mem.readInt(u32, rec.data[0..4], .little); switch (cpu_arch) { .aarch64 => { diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index f06441573997..be8ac636423c 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -472,11 +472,11 @@ pub fn inferSdkVersion(gpa: Allocator, comp: *const Compilation) ?std.SemanticVe defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const options = comp.bin_file.options; + const macho_file = comp.bin_file.cast(MachO).?; - const sdk_layout = options.darwin_sdk_layout orelse return null; + const sdk_layout = macho_file.sdk_layout orelse return null; const sdk_dir = switch (sdk_layout) { - .sdk => options.sysroot.?, + .sdk => macho_file.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 e0aa82f2430d..8b0aa90f96f1 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -458,7 +458,7 @@ pub fn linkWithZld( } try writeAtoms(macho_file); - if (macho_file.base.options.target.cpu.arch == .aarch64) try writeThunks(macho_file); + if (target.cpu.arch == .aarch64) try writeThunks(macho_file); try writeDyldPrivateAtom(macho_file); if (macho_file.stubs_section_index) |_| { @@ -557,7 +557,7 @@ pub fn linkWithZld( .version = 0, }); { - const platform = Platform.fromTarget(macho_file.base.options.target); + const platform = Platform.fromTarget(target); const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); @@ -610,7 +610,8 @@ pub fn linkWithZld( fn createSegments(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; - const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); + const target = macho_file.base.comp.root_mod.resolved_target.result; + const page_size = MachO.getPageSize(target.cpu.arch); const aligned_pagezero_vmsize = mem.alignBackward(u64, macho_file.pagezero_vmsize, page_size); if (macho_file.base.comp.config.output_mode != .Lib and aligned_pagezero_vmsize > 0) { if (aligned_pagezero_vmsize != macho_file.pagezero_vmsize) { @@ -755,7 +756,8 @@ fn writeDyldPrivateAtom(macho_file: *MachO) !void { } fn writeThunks(macho_file: *MachO) !void { - assert(macho_file.base.options.target.cpu.arch == .aarch64); + const target = macho_file.base.comp.root_mod.resolved_target.result; + assert(target.cpu.arch == .aarch64); const gpa = macho_file.base.allocator; const sect_id = macho_file.text_section_index orelse return; @@ -791,7 +793,8 @@ fn writePointerEntries(macho_file: *MachO, sect_id: u8, table: anytype) !void { fn writeStubs(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const stubs_header = macho_file.sections.items(.header)[macho_file.stubs_section_index.?]; const la_symbol_ptr_header = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_section_index.?]; @@ -813,7 +816,8 @@ fn writeStubs(macho_file: *MachO) !void { fn writeStubHelpers(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const stub_helper_header = macho_file.sections.items(.header)[macho_file.stub_helper_section_index.?]; const capacity = math.cast(usize, stub_helper_header.size) orelse return error.Overflow; @@ -856,7 +860,8 @@ fn writeStubHelpers(macho_file: *MachO) !void { fn writeLaSymbolPtrs(macho_file: *MachO) !void { const gpa = macho_file.base.allocator; - const cpu_arch = macho_file.base.options.target.cpu.arch; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; const la_symbol_ptr_header = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_section_index.?]; const stub_helper_header = macho_file.sections.items(.header)[macho_file.stub_helper_section_index.?]; @@ -964,11 +969,12 @@ fn pruneAndSortSections(macho_file: *MachO) !void { } fn calcSectionSizes(macho_file: *MachO) !void { + const target = macho_file.base.comp.root_mod.resolved_target.result; const slice = macho_file.sections.slice(); for (slice.items(.header), 0..) |*header, sect_id| { if (header.size == 0) continue; if (macho_file.text_section_index) |txt| { - if (txt == sect_id and macho_file.base.options.target.cpu.arch == .aarch64) continue; + if (txt == sect_id and target.cpu.arch == .aarch64) continue; } var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue; @@ -991,7 +997,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { } } - if (macho_file.text_section_index != null and macho_file.base.options.target.cpu.arch == .aarch64) { + if (macho_file.text_section_index != null and target.cpu.arch == .aarch64) { // Create jump/branch range extenders if needed. try thunks.createThunks(macho_file, macho_file.text_section_index.?); } @@ -1043,7 +1049,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { header.@"align" = 3; } - const cpu_arch = macho_file.base.options.target.cpu.arch; + const cpu_arch = target.cpu.arch; if (macho_file.stubs_section_index) |sect_id| { const header = &macho_file.sections.items(.header)[sect_id]; @@ -1093,6 +1099,7 @@ fn getSegmentAllocBase(macho_file: *MachO, segment_index: u8) struct { vmaddr: u } fn allocateSegment(macho_file: *MachO, segment_index: u8, init_size: u64) !void { + const target = macho_file.base.comp.root_mod.resolved_target.result; const segment = &macho_file.segments.items[segment_index]; if (mem.eql(u8, segment.segName(), "__PAGEZERO")) return; // allocated upon creation @@ -1175,7 +1182,7 @@ fn allocateSegment(macho_file: *MachO, segment_index: u8, init_size: u64) !void segment.vmsize = start; } - const page_size = MachO.getPageSize(macho_file.base.options.target.cpu.arch); + const page_size = MachO.getPageSize(target.cpu.arch); segment.filesize = mem.alignForward(u64, segment.filesize, page_size); segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size); } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index ece949b01ef9..247986d76773 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -206,7 +206,8 @@ pub const Atom = struct { // asserts that self.got_index != null pub fn getOffsetTableAddress(self: Atom, plan9: *Plan9) u64 { - const ptr_bytes = @divExact(plan9.base.options.target.ptrBitWidth(), 8); + const target = plan9.base.comp.root_mod.resolved_target.result; + const ptr_bytes = @divExact(target.ptrBitWidth(), 8); const got_addr = plan9.bases.data; const got_index = self.got_index.?; return got_addr + got_index * ptr_bytes; @@ -293,9 +294,11 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { }; } -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { - if (options.use_llvm) - return error.LLVMBackendDoesNotSupportPlan9; +pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { + _ = arena; + const target = options.comp.root_mod.resolved_target.result; + const gpa = options.comp.gpa; + const sixtyfour_bit: bool = switch (options.target.ptrBitWidth()) { 0...32 => false, 33...64 => true, @@ -315,7 +318,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { }, .sixtyfour_bit = sixtyfour_bit, .bases = undefined, - .magic = try aout.magicFromArch(self.base.options.target.cpu.arch), + .magic = try aout.magicFromArch(target.cpu.arch), }; // a / will always be in a file path try self.file_segments.put(gpa, "/", 1); @@ -399,6 +402,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: } const gpa = self.base.comp.gpa; + const target = self.base.comp.root_mod.resolved_target.result; const func = mod.funcInfo(func_index); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); @@ -414,7 +418,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: .end_line = undefined, .pcop_change_index = null, // we have already checked the target in the linker to make sure it is compatable - .pc_quanta = aout.getPCQuant(self.base.options.target.cpu.arch) catch unreachable, + .pc_quanta = aout.getPCQuant(target.cpu.arch) catch unreachable, }; defer dbg_info_output.dbg_line.deinit(); @@ -658,6 +662,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No } const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const tracy = trace(@src()); defer tracy.end(); @@ -749,9 +754,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No atom.offset = off; log.debug("write text decl {*} ({}), lines {d} to {d}.;__GOT+0x{x} vaddr: 0x{x}", .{ decl, decl.name.fmt(&mod.intern_pool), out.start_line + 1, out.end_line, atom.got_index.? * 8, off }); if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[atom.sym_index.?].value = off; if (mod.decl_exports.get(decl_index)) |exports| { @@ -778,9 +783,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No text_i += code.len; text_atom.offset = off; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[text_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[text_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[text_atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[text_atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[text_atom.sym_index.?].value = off; } @@ -791,9 +796,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No const val = self.getAddr(text_i, .t); self.syms.items[etext_atom.sym_index.?].value = val; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[etext_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[etext_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[etext_atom.got_index.? * 8 ..][0..8], val, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[etext_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian()); } } // global offset table is in data @@ -815,9 +820,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No data_i += code.len; atom.offset = off; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[atom.sym_index.?].value = off; if (mod.decl_exports.get(decl_index)) |exports| { @@ -838,9 +843,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No data_i += code.len; atom.offset = off; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[atom.sym_index.?].value = off; } @@ -859,9 +864,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No data_i += code.len; atom.offset = off; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[atom.sym_index.?].value = off; } @@ -879,9 +884,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No data_i += code.len; data_atom.offset = off; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[data_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[data_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[data_atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[data_atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); } self.syms.items[data_atom.sym_index.?].value = off; } @@ -891,9 +896,9 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No const val = self.getAddr(data_i, .b); self.syms.items[edata_atom.sym_index.?].value = val; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[edata_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[edata_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian()); } else { - mem.writeInt(u64, got_table[edata_atom.got_index.? * 8 ..][0..8], val, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[edata_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian()); } } // end symbol (same as edata because native backends don't do .bss yet) @@ -902,10 +907,10 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No const val = self.getAddr(data_i, .b); self.syms.items[end_atom.sym_index.?].value = val; if (!self.sixtyfour_bit) { - mem.writeInt(u32, got_table[end_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), self.base.options.target.cpu.arch.endian()); + mem.writeInt(u32, got_table[end_atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(val)), target.cpu.arch.endian()); } else { log.debug("write end (got_table[0x{x}] = 0x{x})", .{ end_atom.got_index.? * 8, val }); - mem.writeInt(u64, got_table[end_atom.got_index.? * 8 ..][0..8], val, self.base.options.target.cpu.arch.endian()); + mem.writeInt(u64, got_table[end_atom.got_index.? * 8 ..][0..8], val, target.cpu.arch.endian()); } } } @@ -942,7 +947,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No const source_atom = self.getAtom(source_atom_index); const source_atom_symbol = self.syms.items[source_atom.sym_index.?]; const code = source_atom.code.getCode(self); - const endian = self.base.options.target.cpu.arch.endian(); + const endian = target.cpu.arch.endian(); for (kv.value_ptr.items) |reloc| { const offset = reloc.offset; const addend = reloc.addend; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 28eeaedba45a..0a728c7b6b08 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1119,7 +1119,8 @@ fn validateFeatures( to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool, emit_features_count: *u32, ) !void { - const cpu_features = wasm.base.options.target.cpu.features; + const target = wasm.base.comp.root_mod.resolved_target.result; + const cpu_features = target.cpu.features; const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects. const known_features_count = @typeInfo(types.Feature.Tag).Enum.fields.len; @@ -1752,6 +1753,7 @@ pub fn getDeclVAddr( decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo, ) !u64 { + const target = wasm.base.comp.root_mod.resolved_target.result; const gpa = wasm.base.comp.gpa; const mod = wasm.base.comp.module.?; const decl = mod.declPtr(decl_index); @@ -1762,7 +1764,7 @@ pub fn getDeclVAddr( assert(reloc_info.parent_atom_index != 0); const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; const atom = wasm.getAtomPtr(atom_index); - const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; + const is_wasm32 = target.cpu.arch == .wasm32; if (decl.ty.zigTypeTag(mod) == .Fn) { assert(reloc_info.addend == 0); // addend not allowed for function relocations // We found a function pointer, so add it to our table, @@ -1825,12 +1827,13 @@ pub fn lowerAnonDecl( pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { const gpa = wasm.base.comp.gpa; + const target = wasm.base.comp.root_mod.resolved_target.result; const atom_index = wasm.anon_decls.get(decl_val).?; const target_symbol_index = wasm.getAtom(atom_index).getSymbolIndex().?; const parent_atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?; const parent_atom = wasm.getAtomPtr(parent_atom_index); - const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32; + const is_wasm32 = target.cpu.arch == .wasm32; const mod = wasm.base.comp.module.?; const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); if (ty.zigTypeTag(mod) == .Fn) { @@ -4557,7 +4560,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! break :blk null; }; - const target = wasm.base.options.target; + const target = wasm.base.comp.root_mod.resolved_target.result; const id_symlink_basename = "lld.id"; From 43720be04af8ddb8334b210ff936a834fb8871a7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Dec 2023 13:00:13 -0700 Subject: [PATCH 030/133] frontend: fix stack protector option logic Commit 97e23896a9168132b6d36ca22ae1af10dd53d80d regressed this behavior because it made target_util.supportsStackProtector *correctly* notice which zig backend is being used to generate code, while the logic calling that function *incorrectly assumed* that .zig code is being compiled, when in reality it might be only C code being compiled. This commit adjusts the option resolution logic for stack protector so that it takes into account the zig backend only if there is a zig compilation unit. A separate piece of logic checks whether clang supports stack protector for a given target. closes #18009 closes #18114 closes #18254 --- src/Compilation/Config.zig | 6 ++++-- src/Package/Module.zig | 13 ++++++++++++- src/main.zig | 4 ++-- src/target.zig | 7 +++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index fe33a18c0a66..33b9bab40b10 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -31,6 +31,7 @@ shared_memory: bool, is_test: bool, test_evented_io: bool, entry: ?[]const u8, +any_c_source_files: bool, pub const CFrontend = enum { clang, aro }; @@ -48,7 +49,7 @@ pub const Options = struct { any_sanitize_thread: bool = false, any_unwind_tables: bool = false, any_dyn_libs: bool = false, - c_source_files_len: usize = 0, + any_c_source_files: bool = false, emit_llvm_ir: bool = false, emit_llvm_bc: bool = false, link_libc: ?bool = null, @@ -231,7 +232,7 @@ pub fn resolve(options: Options) !Config { } if (options.lto) |x| break :b x; - if (options.c_source_files_len == 0) break :b false; + if (!options.any_c_source_files) break :b false; if (target.cpu.arch.isRISCV()) { // Clang and LLVM currently don't support RISC-V target-abi for LTO. @@ -384,6 +385,7 @@ pub fn resolve(options: Options) !Config { .use_lld = use_lld, .entry = entry, .wasi_exec_model = wasi_exec_model, + .any_c_source_files = options.any_c_source_files, }; } diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 94431856acf0..f1e709185578 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -229,7 +229,18 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { }; const stack_protector: u32 = sp: { - if (!target_util.supportsStackProtector(target, zig_backend)) { + const use_zig_backend = options.global.have_zcu or + (options.global.any_c_source_files and options.global.c_frontend == .aro); + if (use_zig_backend and !target_util.supportsStackProtector(target, zig_backend)) { + if (options.inherited.stack_protector) |x| { + if (x > 0) return error.StackProtectorUnsupportedByTarget; + } + break :sp 0; + } + + if (options.global.any_c_source_files and options.global.c_frontend == .clang and + !target_util.clangSupportsStackProtector(target)) + { if (options.inherited.stack_protector) |x| { if (x > 0) return error.StackProtectorUnsupportedByTarget; } diff --git a/src/main.zig b/src/main.zig index 4f701398ca01..61b9b6ff5618 100644 --- a/src/main.zig +++ b/src/main.zig @@ -949,7 +949,7 @@ fn buildOutputType( // Populated just before the call to `createModule`. .emit_bin = undefined, // Populated just before the call to `createModule`. - .c_source_files_len = undefined, + .any_c_source_files = undefined, }, // Populated in the call to `createModule` for the root module. .resolved_options = undefined, @@ -2635,7 +2635,7 @@ fn buildOutputType( create_module.opts.emit_llvm_ir = emit_llvm_ir != .no; create_module.opts.emit_llvm_bc = emit_llvm_bc != .no; create_module.opts.emit_bin = emit_bin != .no; - create_module.opts.c_source_files_len = create_module.c_source_files.items.len; + create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0; const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory); for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| { diff --git a/src/target.zig b/src/target.zig index 04c25a5f0c60..68777945a9b3 100644 --- a/src/target.zig +++ b/src/target.zig @@ -360,6 +360,13 @@ pub fn supportsStackProtector(target: std.Target, backend: std.builtin.CompilerB }; } +pub fn clangSupportsStackProtector(target: std.Target) bool { + return switch (target.cpu.arch) { + .spirv32, .spirv64 => return false, + else => true, + }; +} + pub fn libcProvidesStackProtector(target: std.Target) bool { return !target.isMinGW() and target.os.tag != .wasi and !target.isSpirV(); } From 9a48a5ab0784ae9744c72cfcc6d7ad9b2cea6a9c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Dec 2023 13:36:33 -0700 Subject: [PATCH 031/133] compiler: update references to single_threaded --- src/Compilation.zig | 10 ++++------ src/Compilation/Config.zig | 6 ++++-- src/arch/wasm/CodeGen.zig | 5 ++++- src/codegen.zig | 4 +++- src/codegen/llvm.zig | 15 +++++++++++---- src/libcxx.zig | 4 ++-- src/libunwind.zig | 2 +- src/link/MachO.zig | 33 ++++++++++++++++++++++----------- 8 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index b7cf3c52765c..4d4eafba65ab 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1871,7 +1871,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { try comp.work_queue.writeItem(.libtsan); } - if (comp.getTarget().isMinGW() and !comp.bin_file.options.single_threaded) { + if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) { // LLD might drop some symbols as unused during LTO and GCing, therefore, // we force mark them for resolution here. @@ -2418,10 +2418,8 @@ 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.bin_file.options.valgrind); - man.hash.add(comp.bin_file.options.single_threaded); - man.hash.add(comp.bin_file.options.use_llvm); - man.hash.add(comp.bin_file.options.use_lib_llvm); + 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); @@ -4922,7 +4920,7 @@ pub fn addCCArgs( try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS"); - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { try argv.append("-D_LIBCPP_HAS_NO_THREADS"); } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 33b9bab40b10..0e379212cce1 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -7,6 +7,8 @@ link_libc: bool, link_libcpp: bool, link_libunwind: bool, any_unwind_tables: bool, +any_c_source_files: bool, +any_non_single_threaded: bool, pie: bool, /// If this is true then linker code is responsible for making an LLVM IR /// Module, outputting it to an object file, and then linking that together @@ -31,7 +33,6 @@ shared_memory: bool, is_test: bool, test_evented_io: bool, entry: ?[]const u8, -any_c_source_files: bool, pub const CFrontend = enum { clang, aro }; @@ -374,6 +375,8 @@ pub fn resolve(options: Options) !Config { .link_libcpp = link_libcpp, .link_libunwind = link_libunwind, .any_unwind_tables = any_unwind_tables, + .any_c_source_files = options.any_c_source_files, + .any_non_single_threaded = options.any_non_single_threaded, .pie = pie, .lto = lto, .import_memory = import_memory, @@ -385,7 +388,6 @@ pub fn resolve(options: Options) !Config { .use_lld = use_lld, .entry = entry, .wasi_exec_model = wasi_exec_model, - .any_c_source_files = options.any_c_source_files, }; } diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index aa6c2dea79c0..e0be273c2631 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -7724,10 +7724,13 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const zcu = func.bin_file.base.comp.module.?; // Only when the atomic feature is enabled, and we're not building // for a single-threaded build, can we emit the `fence` instruction. // In all other cases, we emit no instructions for a fence. - if (func.useAtomicFeature() and !func.bin_file.base.options.single_threaded) { + const func_namespace = zcu.namespacePtr(zcu.declPtr(func.decl).namespace); + const single_threaded = func_namespace.file_scope.mod.single_threaded; + if (func.useAtomicFeature() and !single_threaded) { try func.addAtomicTag(.atomic_fence); } diff --git a/src/codegen.zig b/src/codegen.zig index b464a9f36535..5efde3985cbe 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -942,7 +942,9 @@ fn genDeclRef( try mod.markDeclAlive(decl); - const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded; + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; + const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !single_threaded; const is_extern = decl.isExtern(mod); if (bin_file.cast(link.File.Elf)) |elf_file| { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 57e5770d89eb..a072c6a069f7 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1591,8 +1591,10 @@ pub const Object = struct { var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; + const namespace = mod.namespacePtr(decl.src_namespace); + if (o.di_builder) |dib| { - di_file = try o.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope); + di_file = try o.getDIFile(gpa, namespace.file_scope); const line_number = decl.src_line + 1; const is_internal_linkage = decl.val.getExternFunc(mod) == null and @@ -1623,6 +1625,8 @@ pub const Object = struct { di_scope = subprogram.toScope(); } + const single_threaded = namespace.file_scope.mod.single_threaded; + var fg: FuncGen = .{ .gpa = gpa, .air = air, @@ -1634,7 +1638,7 @@ pub const Object = struct { .arg_index = 0, .func_inst_table = .{}, .blocks = .{}, - .sync_scope = if (mod.comp.bin_file.options.single_threaded) .singlethread else .system, + .sync_scope = if (single_threaded) .singlethread else .system, .di_scope = di_scope, .di_file = di_file, .base_line = dg.decl.src_line, @@ -1788,8 +1792,10 @@ pub const Object = struct { if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); global_index.setUnnamedAddr(.unnamed_addr, &self.builder); if (decl.val.getVariable(mod)) |decl_var| { + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( - if (decl_var.is_threadlocal and !mod.comp.bin_file.options.single_threaded) + if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, @@ -3176,7 +3182,8 @@ pub const Object = struct { variable_index.setLinkage(.external, &o.builder); variable_index.setUnnamedAddr(.default, &o.builder); if (decl.val.getVariable(mod)) |decl_var| { - const single_threaded = mod.comp.bin_file.options.single_threaded; + const decl_namespace = mod.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; variable_index.setThreadLocal( if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, &o.builder, diff --git a/src/libcxx.zig b/src/libcxx.zig index 19c1d25b8c78..8ae7db80f133 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -154,7 +154,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { continue; if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos) continue; - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { if (std.mem.startsWith(u8, cxx_src, "src/support/win32/thread_win32.cpp")) { continue; } @@ -332,7 +332,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { } // WASM targets are single threaded. - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp")) { continue; } diff --git a/src/libunwind.zig b/src/libunwind.zig index f0330a4e5157..876bd7a31fd8 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -67,7 +67,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { if (comp.bin_file.options.optimize_mode == .Debug) { try cflags.append("-D_DEBUG"); } - if (comp.bin_file.options.single_threaded) { + if (!comp.config.any_non_single_threaded) { try cflags.append("-D_LIBUNWIND_HAS_NO_THREADS"); } if (target.cpu.arch.isARM() and target.abi.floatAbi() == .hard) { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index c1d7eef6526d..3da076ba5675 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -267,7 +267,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { }); try self.strtab.buffer.append(gpa, 0); - try self.populateMissingMetadata(); + try self.populateMissingMetadata(.{ + .symbol_count_hint = options.symbol_count_hint, + .program_code_size_hint = options.program_code_size_hint, + }); if (self.d_sym) |*d_sym| { try d_sym.populateMissingMetadata(self); @@ -1704,7 +1707,8 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { } pub fn resolveSymbols(self: *MachO) !void { - const output_mode = self.base.comp.config.output_mode; + const comp = self.base.comp; + const output_mode = comp.config.output_mode; // We add the specified entrypoint as the first unresolved symbols so that // we search for it in libraries should there be no object files specified // on the linker line. @@ -1729,7 +1733,7 @@ pub fn resolveSymbols(self: *MachO) !void { if (self.unresolved.count() > 0 and self.dyld_stub_binder_index == null) { self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder", .{ .add_got = true }); } - if (!self.base.options.single_threaded and self.mode == .incremental) { + if (comp.config.any_non_single_threaded and self.mode == .incremental) { _ = try self.addUndefined("__tlv_bootstrap", .{}); } @@ -2436,7 +2440,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; const decl = mod.declPtr(decl_index); if (decl.val.getExternFunc(mod)) |_| { @@ -2453,7 +2458,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) } const is_threadlocal = if (decl.val.getVariable(mod)) |variable| - variable.is_threadlocal and !self.base.options.single_threaded + variable.is_threadlocal and comp.config.any_non_single_threaded else false; if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index); @@ -3129,11 +3134,17 @@ pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: li return 0; } -fn populateMissingMetadata(self: *MachO) !void { +const PopulateMissingMetadataOptions = struct { + symbol_count_hint: u64, + program_code_size_hint: u64, +}; + +fn populateMissingMetadata(self: *MachO, options: PopulateMissingMetadataOptions) !void { assert(self.mode == .incremental); - const gpa = self.base.comp.gpa; - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const pagezero_vmsize = self.calcPagezeroSize(); @@ -3171,7 +3182,7 @@ fn populateMissingMetadata(self: *MachO) !void { if (self.text_section_index == null) { // Sadly, segments need unique string identfiers for some reason. self.text_section_index = try self.allocateSection("__TEXT1", "__text", .{ - .size = self.base.options.program_code_size_hint, + .size = options.program_code_size_hint, .alignment = switch (cpu_arch) { .x86_64 => 1, .aarch64 => @sizeOf(u32), @@ -3207,7 +3218,7 @@ fn populateMissingMetadata(self: *MachO) !void { if (self.got_section_index == null) { self.got_section_index = try self.allocateSection("__DATA_CONST", "__got", .{ - .size = @sizeOf(u64) * self.base.options.symbol_count_hint, + .size = @sizeOf(u64) * options.symbol_count_hint, .alignment = @alignOf(u64), .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, .prot = macho.PROT.READ | macho.PROT.WRITE, @@ -3245,7 +3256,7 @@ fn populateMissingMetadata(self: *MachO) !void { self.segment_table_dirty = true; } - if (!self.base.options.single_threaded) { + if (comp.config.any_non_single_threaded) { if (self.thread_vars_section_index == null) { self.thread_vars_section_index = try self.allocateSection("__DATA2", "__thread_vars", .{ .size = @sizeOf(u64) * 3, From 3b6cb257dfbcfe7217cdb00819615d1cf1e6b89c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Dec 2023 14:12:45 -0700 Subject: [PATCH 032/133] update image_base references --- src/Compilation.zig | 76 ++++++++++++++++++++++++------------------- src/link.zig | 7 ++-- src/link/C.zig | 12 +++++-- src/link/Coff.zig | 71 +++++++++++++++++++++------------------- src/link/Coff/lld.zig | 6 ++-- src/link/Elf.zig | 53 ++++++++++++++---------------- src/main.zig | 19 +++++------ 7 files changed, 129 insertions(+), 115 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 4d4eafba65ab..2859090edc8f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1014,7 +1014,7 @@ pub const InitOptions = struct { entry: ?[]const u8 = null, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, stack_size: ?u64 = null, - image_base_override: ?u64 = null, + image_base: ?u64 = null, version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation = null, @@ -1686,7 +1686,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .major_subsystem_version = options.major_subsystem_version, .minor_subsystem_version = options.minor_subsystem_version, .stack_size = options.stack_size, - .image_base_override = options.image_base_override, + .image_base = options.image_base, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, .eh_frame_hdr = link_eh_frame_hdr, @@ -2429,7 +2429,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.formatted_panics); man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); - man.hash.addOptional(comp.bin_file.options.want_structured_cfg); + man.hash.add(comp.bin_file.options.want_structured_cfg); } try man.addOptionalFile(comp.bin_file.options.linker_script); @@ -2468,8 +2468,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); man.hash.add(comp.bin_file.stack_size); - man.hash.addOptional(comp.bin_file.options.image_base_override); - man.hash.addOptional(comp.bin_file.options.gc_sections); + 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); @@ -2491,8 +2490,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.bin_file.options.hash_style); man.hash.add(comp.bin_file.options.compress_debug_sections); man.hash.add(comp.bin_file.options.include_compiler_rt); - man.hash.addOptional(comp.bin_file.options.sort_section); - if (comp.bin_file.options.link_libc) { + 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.addOptionalBytes(libc_installation.crt_dir); @@ -2504,39 +2503,50 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptionalBytes(target.dynamic_linker.get()); } man.hash.addOptionalBytes(comp.bin_file.options.soname); - man.hash.addOptional(comp.bin_file.options.version); + 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.addOptional(comp.bin_file.allow_shlib_undefined); + 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); - // WASM specific stuff - man.hash.add(comp.bin_file.options.import_memory); - man.hash.add(comp.bin_file.options.export_memory); - man.hash.addOptional(comp.bin_file.options.initial_memory); - man.hash.addOptional(comp.bin_file.options.max_memory); - man.hash.add(comp.bin_file.options.shared_memory); - man.hash.addOptional(comp.bin_file.options.global_base); - - // Mach-O specific stuff - man.hash.addListOfBytes(comp.framework_dirs); - try link.hashAddFrameworks(man, comp.bin_file.options.frameworks); - try man.addOptionalFile(comp.bin_file.options.entitlements); - man.hash.addOptional(comp.bin_file.options.pagezero_size); - man.hash.addOptional(comp.bin_file.options.headerpad_size); - man.hash.add(comp.bin_file.options.headerpad_max_install_names); - man.hash.add(comp.bin_file.options.dead_strip_dylibs); - - // COFF specific stuff - man.hash.addOptional(comp.bin_file.options.subsystem); - man.hash.add(comp.bin_file.options.tsaware); - man.hash.add(comp.bin_file.options.nxcompat); - man.hash.add(comp.bin_file.options.dynamicbase); - man.hash.addOptional(comp.bin_file.options.major_subsystem_version); - man.hash.addOptional(comp.bin_file.options.minor_subsystem_version); + 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); + }, + } } fn emitOthers(comp: *Compilation) void { diff --git a/src/link.zig b/src/link.zig index fd8d84f765c5..95a32821861d 100644 --- a/src/link.zig +++ b/src/link.zig @@ -102,7 +102,7 @@ pub const File = struct { /// Virtual address of the entry point procedure relative to image base. entry_addr: ?u64, stack_size: ?u64, - image_base_override: ?u64, + image_base: ?u64, function_sections: bool, data_sections: bool, no_builtin: bool, @@ -974,8 +974,9 @@ pub const File = struct { const llvm_bindings = @import("codegen/llvm/bindings.zig"); const Builder = @import("codegen/llvm/Builder.zig"); const llvm = @import("codegen/llvm.zig"); - Builder.initializeLLVMTarget(base.options.target.cpu.arch); - const os_tag = llvm.targetOs(base.options.target.os.tag); + const target = comp.root_mod.resolved_target.result; + Builder.initializeLLVMTarget(target.cpu.arch); + const os_tag = llvm.targetOs(target.os.tag); const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag); if (bad) return error.UnableToWriteArchive; diff --git a/src/link/C.zig b/src/link/C.zig index e6827947ae41..043ca0ce6fd7 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -93,10 +93,13 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { } pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { - assert(options.target.ofmt == .c); + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .c); const optimize_mode = options.comp.root_mod.optimize_mode; const use_lld = build_options.have_llvm and options.comp.config.use_lld; const use_llvm = options.comp.config.use_llvm; + const output_mode = options.comp.config.output_mode; + const link_mode = options.comp.config.link_mode; // These are caught by `Compilation.Config.resolve`. assert(!use_lld); @@ -107,7 +110,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { const file = try emit.directory.handle.createFile(emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, - .mode = link.determineMode(options), + .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); errdefer file.close(); @@ -118,7 +121,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { .tag = .c, .comp = options.comp, .emit = emit, - .gc_sections = options.gc_sections orelse optimize_mode != .Debug, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = file, @@ -126,6 +129,9 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index d99460d333cf..6bb2e6b1f817 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -7,6 +7,7 @@ llvm_object: ?*LlvmObject = null, base: link.File, +image_base: u64, error_flags: link.File.ErrorFlags = .{}, ptr_width: PtrWidth, @@ -352,8 +353,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { - const target = options.comp.root_mod.resolved_target.result; - const optimize_mode = options.comp.root_mod.optimize_mode; + const comp = options.comp; + const target = comp.root_mod.resolved_target.result; + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -366,7 +369,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { self.* = .{ .base = .{ .tag = .coff, - .comp = options.comp, + .comp = comp, .emit = options.emit, .stack_size = options.stack_size orelse 16777216, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), @@ -382,11 +385,25 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { }, .ptr_width = ptr_width, .page_size = page_size, - .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory), + + .data_directories = [1]coff.ImageDataDirectory{.{ + .virtual_address = 0, + .size = 0, + }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, + + .image_base = options.image_base orelse switch (output_mode) { + .Exe => switch (target.cpu.arch) { + .aarch64 => 0x140000000, + .x86_64, .x86 => 0x400000, + else => unreachable, + }, + .Lib => 0x10000000, + .Obj => 0, + }, }; - const use_llvm = options.comp.config.use_llvm; - if (use_llvm and options.comp.config.have_zcu) { + const use_llvm = comp.config.use_llvm; + if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } return self; @@ -833,7 +850,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void { } } - self.resolveRelocs(atom_index, relocs.items, code, self.getImageBase()); + self.resolveRelocs(atom_index, relocs.items, code, self.image_base); try self.base.file.?.pwriteAll(code, file_offset); // Now we can mark the relocs as resolved. @@ -879,17 +896,17 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void { const file_offset = header.pointer_to_raw_data + entry_offset; const vmaddr = header.virtual_address + entry_offset; - log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.getImageBase() }); + log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.image_base }); switch (self.ptr_width) { .p32 => { var buf: [4]u8 = undefined; - mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.getImageBase())), .little); + mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.image_base)), .little); try self.base.file.?.pwriteAll(&buf, file_offset); }, .p64 => { var buf: [8]u8 = undefined; - mem.writeInt(u64, &buf, entry_value + self.getImageBase(), .little); + mem.writeInt(u64, &buf, entry_value + self.image_base, .little); try self.base.file.?.pwriteAll(&buf, file_offset); }, } @@ -1467,9 +1484,10 @@ pub fn updateExports( } const ip = &mod.intern_pool; - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const target = comp.root_mod.resolved_target.result; - if (self.base.options.use_llvm) { + if (comp.config.use_llvm) { // Even in the case of LLVM, we need to notice certain exported symbols in order to // detect the default subsystem. for (exports) |exp| { @@ -1485,7 +1503,7 @@ pub fn updateExports( }; const decl_cc = exported_decl.ty.fnCallingConvention(mod); if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and - self.base.options.link_libc) + comp.config.link_libc) { mod.stage1_flags.have_c_main = true; } else if (decl_cc == winapi_cc and target.os.tag == .windows) { @@ -1506,7 +1524,7 @@ pub fn updateExports( if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -2247,8 +2265,6 @@ fn writeHeader(self: *Coff) !void { const subsystem: coff.Subsystem = .WINDOWS_CUI; const size_of_image: u32 = self.getSizeOfImage(); const size_of_headers: u32 = mem.alignForward(u32, self.getSizeOfHeaders(), default_file_alignment); - const image_base = self.getImageBase(); - const base_of_code = self.sections.get(self.text_section_index.?).header.virtual_address; const base_of_data = self.sections.get(self.data_section_index.?).header.virtual_address; @@ -2279,7 +2295,7 @@ fn writeHeader(self: *Coff) !void { .address_of_entry_point = self.entry_addr orelse 0, .base_of_code = base_of_code, .base_of_data = base_of_data, - .image_base = @as(u32, @intCast(image_base)), + .image_base = @intCast(self.image_base), .section_alignment = self.page_size, .file_alignment = default_file_alignment, .major_operating_system_version = 6, @@ -2313,7 +2329,7 @@ fn writeHeader(self: *Coff) !void { .size_of_uninitialized_data = size_of_uninitialized_data, .address_of_entry_point = self.entry_addr orelse 0, .base_of_code = base_of_code, - .image_base = image_base, + .image_base = self.image_base, .section_alignment = self.page_size, .file_alignment = default_file_alignment, .major_operating_system_version = 6, @@ -2333,7 +2349,7 @@ fn writeHeader(self: *Coff) !void { .size_of_heap_reserve = default_size_of_heap_reserve, .size_of_heap_commit = default_size_of_heap_commit, .loader_flags = 0, - .number_of_rva_and_sizes = @as(u32, @intCast(self.data_directories.len)), + .number_of_rva_and_sizes = @intCast(self.data_directories.len), }; writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; }, @@ -2447,25 +2463,12 @@ inline fn getSizeOfImage(self: Coff) u32 { /// Returns symbol location corresponding to the set entrypoint (if any). pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { - const entry_name = self.base.options.entry orelse "wWinMainCRTStartup"; // TODO this is incomplete + const comp = self.base.comp; + const entry_name = comp.config.entry orelse return null; const global_index = self.resolver.get(entry_name) orelse return null; return self.globals.items[global_index]; } -pub fn getImageBase(self: Coff) u64 { - const target = self.base.comp.root_mod.resolved_target.result; - const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.comp.config.output_mode) { - .Exe => switch (target.cpu.arch) { - .aarch64 => @as(u64, 0x140000000), - .x86_64, .x86 => 0x400000, - else => unreachable, // unsupported target architecture - }, - .Lib => 0x10000000, - .Obj => 0, - }; - return image_base; -} - /// Returns pointer-to-symbol described by `sym_loc` descriptor. pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol { assert(sym_loc.file == null); // TODO linking object files diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 918a7004c1a2..a321d28fb3d6 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -81,7 +81,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try man.addOptionalFile(module_obj_path); man.hash.addOptionalBytes(self.base.options.entry); man.hash.add(self.base.stack_size); - man.hash.addOptional(self.base.options.image_base_override); + man.hash.addOptional(self.image_base); man.hash.addListOfBytes(self.base.options.lib_dirs); man.hash.add(self.base.options.skip_linker_dependencies); if (self.base.options.link_libc) { @@ -195,9 +195,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.base.comp.config.output_mode == .Exe) { try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{self.image_base})); if (target.cpu.arch == .x86) { try argv.append("-MACHINE:X86"); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1ddbece4e1ba..df83878494e1 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,4 +1,5 @@ base: link.File, +image_base: u64, ptr_width: PtrWidth, @@ -264,7 +265,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .p32 => @alignOf(elf.Elf32_Phdr), .p64 => @alignOf(elf.Elf64_Phdr), }; - const image_base = self.calcImageBase(); const ehsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Ehdr), .p64 => @sizeOf(elf.Elf64_Ehdr), @@ -279,7 +279,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .type = elf.PT_PHDR, .flags = elf.PF_R, .@"align" = p_align, - .addr = image_base + ehsize, + .addr = self.image_base + ehsize, .offset = ehsize, .filesz = reserved, .memsz = reserved, @@ -288,7 +288,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .type = elf.PT_LOAD, .flags = elf.PF_R, .@"align" = self.page_size, - .addr = image_base, + .addr = self.image_base, .offset = 0, .filesz = reserved + ehsize, .memsz = reserved + ehsize, @@ -317,12 +317,13 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { - const use_llvm = options.comp.config.use_llvm; - const optimize_mode = options.comp.root_mod.optimize_mode; - const target = options.comp.root_mod.resolved_target.result; - const output_mode = options.comp.config.output_mode; - const link_mode = options.comp.config.link_mode; - const is_native_os = options.comp.root_mod.resolved_target.is_native_os; + const comp = options.comp; + const use_llvm = comp.config.use_llvm; + const optimize_mode = comp.root_mod.optimize_mode; + const target = comp.root_mod.resolved_target.result; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const is_native_os = comp.root_mod.resolved_target.is_native_os; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -344,7 +345,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { self.* = .{ .base = .{ .tag = .elf, - .comp = options.comp, + .comp = comp, .emit = options.emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .stack_size = options.stack_size orelse 16777216, @@ -357,12 +358,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, .function_sections = options.function_sections, .data_sections = options.data_sections, + + .image_base = b: { + if (is_dyn_lib) break :b 0; + if (output_mode == .Exe and comp.config.pie) return 0; + return options.image_base orelse switch (ptr_width) { + .p32 => 0x1000, + .p64 => 0x1000000, + }; + }, }, .ptr_width = ptr_width, .page_size = page_size, .default_sym_version = default_sym_version, }; - if (use_llvm and options.comp.config.have_zcu) { + if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -1653,9 +1663,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), }); - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); if (self.base.gc_sections) { try argv.append("--gc-sections"); @@ -2378,7 +2386,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.addOptionalBytes(self.base.options.entry); - man.hash.addOptional(self.base.options.image_base_override); + man.hash.addOptional(self.image_base); man.hash.add(self.base.gc_sections); man.hash.addOptional(self.base.options.sort_section); man.hash.add(self.base.options.eh_frame_hdr); @@ -2549,9 +2557,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); if (self.base.options.linker_script) |linker_script| { try argv.append("-T"); @@ -3321,7 +3327,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { // __ehdr_start { const symbol_ptr = self.symbol(self.ehdr_start_index.?); - symbol_ptr.value = self.calcImageBase(); + symbol_ptr.value = self.image_base; symbol_ptr.output_section_index = 1; } @@ -5631,15 +5637,6 @@ const CsuObjects = struct { } }; -pub fn calcImageBase(self: Elf) u64 { - if (self.base.isDynLib()) return 0; - if (self.base.isExe() and self.base.options.pie) return 0; - return self.base.options.image_base_override orelse switch (self.ptr_width) { - .p32 => 0x1000, - .p64 => 0x1000000, - }; -} - pub fn isZigSection(self: Elf, shndx: u16) bool { inline for (&[_]?u16{ self.zig_text_section_index, diff --git a/src/main.zig b/src/main.zig index 61b9b6ff5618..499d0f57f9cd 100644 --- a/src/main.zig +++ b/src/main.zig @@ -860,7 +860,7 @@ fn buildOutputType( var test_no_exec = false; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; var stack_size: ?u64 = null; - var image_base_override: ?u64 = null; + var image_base: ?u64 = null; var link_eh_frame_hdr = false; var link_emit_relocs = false; var each_lib_rpath: ?bool = null; @@ -1131,10 +1131,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--stack")) { stack_size = parseStackSize(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { - const next_arg = args_iter.nextOrFatal(); - image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { - fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) }); - }; + image_base = parseImageBase(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--name")) { provided_name = args_iter.nextOrFatal(); if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?))) @@ -2283,10 +2280,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { stack_size = parseStackSize(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { - const image_base = linker_args_it.nextOrFatal(); - image_base_override = std.fmt.parseUnsigned(u64, image_base, 0) catch |err| { - fatal("unable to parse image base override '{s}': {s}", .{ image_base, @errorName(err) }); - }; + image_base = parseImageBase(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { linker_script = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { @@ -3424,7 +3418,7 @@ fn buildOutputType( .link_emit_relocs = link_emit_relocs, .force_undefined_symbols = force_undefined_symbols, .stack_size = stack_size, - .image_base_override = image_base_override, + .image_base = image_base, .formatted_panics = formatted_panics, .function_sections = function_sections, .data_sections = data_sections, @@ -7686,3 +7680,8 @@ fn parseStackSize(s: []const u8) u64 { return std.fmt.parseUnsigned(u64, s, 0) catch |err| fatal("unable to parse stack size '{s}': {s}", .{ s, @errorName(err) }); } + +fn parseImageBase(s: []const u8) u64 { + return std.fmt.parseUnsigned(u64, s, 0) catch |err| + fatal("unable to parse image base '{s}': {s}", .{ s, @errorName(err) }); +} From 0789e91eeb08495c5084067df2b2dab410197364 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Dec 2023 16:25:28 -0700 Subject: [PATCH 033/133] linkers: update references to "options" field --- src/Compilation.zig | 91 +++++---- src/Compilation/Config.zig | 2 +- src/Sema.zig | 27 +-- src/codegen/llvm.zig | 4 +- src/libtsan.zig | 2 +- src/link.zig | 3 +- src/link/Coff/lld.zig | 94 ++++----- src/link/Dwarf.zig | 10 +- src/link/Elf.zig | 295 ++++++++++++++-------------- src/link/Elf/Atom.zig | 13 +- src/link/Elf/Object.zig | 2 +- src/link/Elf/ZigObject.zig | 2 +- src/link/Elf/synthetic_sections.zig | 24 ++- src/link/MachO.zig | 36 ++-- src/link/MachO/DebugSymbols.zig | 7 +- src/link/MachO/dead_strip.zig | 2 +- src/link/MachO/load_commands.zig | 34 ++-- src/link/MachO/zld.zig | 9 +- src/link/NvPtx.zig | 3 +- src/link/Plan9.zig | 32 +-- src/link/SpirV.zig | 3 +- src/link/Wasm.zig | 245 ++++++++++++++--------- 22 files changed, 511 insertions(+), 429 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 2859090edc8f..cedbf5024fb6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -76,6 +76,7 @@ framework_dirs: []const []const u8, system_libs: std.StringArrayHashMapUnmanaged(SystemLib), version: ?std.SemanticVersion, libc_installation: ?*const LibCInstallation, +skip_linker_dependencies: bool, c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = @@ -940,7 +941,7 @@ pub const InitOptions = struct { /// * getpid /// * mman /// * signal - wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{}, + wasi_emulated_libs: []const wasi_libc.CRTFile = &.{}, /// This means that if the output mode is an executable it will be a /// Position Independent Executable. If the output mode is not an /// executable this field is ignored. @@ -1238,7 +1239,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const sysroot = options.sysroot orelse libc_dirs.sysroot; const include_compiler_rt = options.want_compiler_rt orelse - (!options.skip_linker_dependencies and is_exe_or_dyn_lib); + (!comp.skip_linker_dependencies and is_exe_or_dyn_lib); if (include_compiler_rt and output_mode == .Obj) { // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");` @@ -1639,6 +1640,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .objects = options.link_objects, .framework_dirs = options.framework_dirs, .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit, + .skip_linker_dependencies = options.skip_linker_dependencies, }; if (bin_file_emit) |emit| { @@ -1695,7 +1697,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .soname = options.soname, .compatibility_version = options.compatibility_version, .dll_export_fns = dll_export_fns, - .skip_linker_dependencies = options.skip_linker_dependencies, .parent_compilation_link_libc = options.parent_compilation_link_libc, .each_lib_rpath = each_lib_rpath, .build_id = build_id, @@ -1765,9 +1766,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } } - const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null; + const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null; - if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies and target.ofmt != .c) { + if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) { if (target.isDarwin()) { switch (target.abi) { .none, @@ -1808,27 +1809,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .{ .musl_crt_file = .crt1_o }, .{ .musl_crt_file = .scrt1_o }, .{ .musl_crt_file = .rcrt1_o }, - switch (comp.bin_file.options.link_mode) { + switch (comp.config.link_mode) { .Static => .{ .musl_crt_file = .libc_a }, .Dynamic => .{ .musl_crt_file = .libc_so }, }, }); } - if (comp.wantBuildWasiLibcFromSource()) { - if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; - const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs; - try comp.work_queue.ensureUnusedCapacity(wasi_emulated_libs.len + 2); // worst-case we need all components - for (wasi_emulated_libs) |crt_file| { - comp.work_queue.writeItemAssumeCapacity(.{ - .wasi_libc_crt_file = crt_file, - }); + if (comp.bin_file) |lf| { + if (lf.cast(link.File.Wasm)) |wasm| { + if (comp.wantBuildWasiLibcFromSource()) { + if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; + + // worst-case we need all components + try comp.work_queue.ensureUnusedCapacity(wasm.wasi_emulated_libs.len + 2); + + for (wasm.wasi_emulated_libs) |crt_file| { + comp.work_queue.writeItemAssumeCapacity(.{ + .wasi_libc_crt_file = crt_file, + }); + } + comp.work_queue.writeAssumeCapacity(&[_]Job{ + .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) }, + .{ .wasi_libc_crt_file = .libc_a }, + }); + } } - comp.work_queue.writeAssumeCapacity(&[_]Job{ - .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) }, - .{ .wasi_libc_crt_file = .libc_a }, - }); } + if (comp.wantBuildMinGWFromSource()) { if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; @@ -1863,27 +1871,29 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { if (comp.wantBuildLibUnwindFromSource()) { try comp.work_queue.writeItem(.{ .libunwind = {} }); } - if (build_options.have_llvm and is_exe_or_dyn_lib and comp.bin_file.options.link_libcpp) { + if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) { try comp.work_queue.writeItem(.libcxx); try comp.work_queue.writeItem(.libcxxabi); } - if (build_options.have_llvm and comp.bin_file.options.tsan) { + if (build_options.have_llvm and comp.config.any_sanitize_thread) { try comp.work_queue.writeItem(.libtsan); } - if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) { - // LLD might drop some symbols as unused during LTO and GCing, therefore, - // we force mark them for resolution here. + if (comp.bin_file) |lf| { + if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) { + // LLD might drop some symbols as unused during LTO and GCing, therefore, + // we force mark them for resolution here. - const tls_index_sym = switch (comp.getTarget().cpu.arch) { - .x86 => "__tls_index", - else => "_tls_index", - }; + const tls_index_sym = switch (comp.getTarget().cpu.arch) { + .x86 => "__tls_index", + else => "_tls_index", + }; - try comp.bin_file.options.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); + try lf.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); + } } - if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { + if (comp.include_compiler_rt and capable_of_building_compiler_rt) { if (is_exe_or_dyn_lib) { log.debug("queuing a job to build compiler_rt_lib", .{}); comp.job_queued_compiler_rt_lib = true; @@ -1895,8 +1905,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } } - if (!comp.bin_file.options.skip_linker_dependencies and is_exe_or_dyn_lib and - !comp.bin_file.options.link_libc and capable_of_building_zig_libc) + if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and + !comp.config.link_libc and capable_of_building_zig_libc) { try comp.work_queue.writeItem(.{ .zig_libc = {} }); } @@ -2425,7 +2435,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.test_evented_io); man.hash.addOptionalBytes(comp.test_filter); man.hash.addOptionalBytes(comp.test_name_prefix); - man.hash.add(comp.bin_file.options.skip_linker_dependencies); + 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); @@ -2477,7 +2487,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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.bin_file.options.skip_linker_dependencies); + 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); @@ -2489,7 +2499,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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.bin_file.options.include_compiler_rt); + 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); @@ -3836,7 +3846,7 @@ pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest { // Also nothing that applies only to compiling .zig code. man.hash.add(comp.sanitize_c); man.hash.addListOfBytes(comp.clang_argv); - man.hash.add(comp.bin_file.options.link_libcpp); + man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list // based on the zig library directory alone. The zig lib directory file @@ -4909,7 +4919,7 @@ pub fn addCCArgs( try argv.append("-fno-builtin"); } - if (comp.bin_file.options.link_libcpp) { + if (comp.config.link_libcpp) { const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "libcxx", "include", }); @@ -4954,7 +4964,7 @@ pub fn addCCArgs( try argv.append(libunwind_include_path); } - if (comp.bin_file.options.link_libc and target.isGnuLibC()) { + if (comp.config.link_libc and target.isGnuLibC()) { const target_version = target.os.version_range.linux.glibc; const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{ target_version.minor, @@ -5944,7 +5954,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool { .Lib => comp.bin_file.options.link_mode == .Dynamic, .Exe => true, }; - return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and + return comp.config.link_libc and is_exe_or_dyn_lib and comp.bin_file.options.libc_installation == null and comp.bin_file.options.target.ofmt != .c; } @@ -6164,6 +6174,7 @@ fn buildOutputFromZig( .have_zcu = true, .emit_bin = true, .root_optimize_mode = comp.compilerRtOptMode(), + .link_libc = comp.config.link_libc, }); const root_mod = Package.Module.create(.{ @@ -6224,7 +6235,6 @@ fn buildOutputFromZig( .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .skip_linker_dependencies = true, - .link_libc = comp.bin_file.options.link_libc, .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); @@ -6305,7 +6315,6 @@ 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, - .link_libc = comp.bin_file.options.link_libc, .want_structured_cfg = comp.bin_file.options.want_structured_cfg, }); defer sub_compilation.destroy(); @@ -6327,7 +6336,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { // This can happen when the user uses `build-exe foo.obj -lkernel32` and // then when we create a sub-Compilation for zig libc, it also tries to // build kernel32.lib. - if (comp.bin_file.options.skip_linker_dependencies) return; + if (comp.skip_linker_dependencies) return; // This happens when an `extern "foo"` function is referenced. // If we haven't seen this library yet and we're targeting Windows, we need diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 0e379212cce1..aba21e4bfe8d 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -335,7 +335,7 @@ pub fn resolve(options: Options) !Config { break :b .Static; }; - const import_memory = options.import_memory orelse false; + const import_memory = options.import_memory orelse (options.output_mode == .Obj); const export_memory = b: { if (link_mode == .Dynamic) { if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible; diff --git a/src/Sema.zig b/src/Sema.zig index 9d1f65584ed5..910b1cca47cc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5742,7 +5742,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr const msg = try sema.errMsg(&child_block, src, "C import failed", .{}); errdefer msg.destroy(gpa); - if (!comp.bin_file.options.link_libc) + if (!comp.config.link_libc) try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{}); const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index); @@ -9058,7 +9058,7 @@ fn resolveGenericBody( /// Given a library name, examines if the library name should end up in /// `link.File.Options.system_libs` table (for example, libc is always -/// specified via dedicated flag `link.File.Options.link_libc` instead), +/// specified via dedicated flag `link_libc` instead), /// and puts it there if it doesn't exist. /// It also dupes the library name which can then be saved as part of the /// respective `Decl` (either `ExternFn` or `Var`). @@ -9076,7 +9076,7 @@ fn handleExternLibName( const target = mod.getTarget(); log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); if (target.is_libc_lib_name(lib_name)) { - if (!comp.bin_file.options.link_libc) { + if (!comp.config.link_libc) { return sema.fail( block, src_loc, @@ -9087,18 +9087,21 @@ fn handleExternLibName( break :blk; } if (target.is_libcpp_lib_name(lib_name)) { - if (!comp.bin_file.options.link_libcpp) { - return sema.fail( - block, - src_loc, - "dependency on libc++ must be explicitly specified in the build command", - .{}, - ); - } + if (!comp.config.link_libcpp) return sema.fail( + block, + src_loc, + "dependency on libc++ must be explicitly specified in the build command", + .{}, + ); break :blk; } if (mem.eql(u8, lib_name, "unwind")) { - comp.bin_file.options.link_libunwind = true; + if (!comp.config.link_libunwind) return sema.fail( + block, + src_loc, + "dependency on libunwind must be explicitly specified in the build command", + .{}, + ); break :blk; } if (!target.isWasm() and !comp.bin_file.options.pic) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a072c6a069f7..522da0f8c956 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3083,9 +3083,7 @@ pub const Object = struct { if (comp.unwind_tables) { try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); } - if (comp.bin_file.options.skip_linker_dependencies or - comp.bin_file.options.no_builtin) - { + if (comp.skip_linker_dependencies or comp.bin_file.options.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/libtsan.zig b/src/libtsan.zig index 2489eb21afd3..d0af65e4c654 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -119,7 +119,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } - const to_c_or_not_to_c_sources = if (comp.bin_file.options.link_libc) + const to_c_or_not_to_c_sources = if (comp.config.link_libc) &sanitizer_libcdep_sources else &sanitizer_nolibc_sources; diff --git a/src/link.zig b/src/link.zig index 95a32821861d..612c05f82b8a 100644 --- a/src/link.zig +++ b/src/link.zig @@ -133,7 +133,6 @@ pub const File = struct { export_symbol_names: []const []const u8, global_base: ?u64, dll_export_fns: bool, - skip_linker_dependencies: bool, parent_compilation_link_libc: bool, each_lib_rpath: bool, build_id: std.zig.BuildId, @@ -1099,7 +1098,7 @@ pub const File = struct { } pub fn isStatic(self: File) bool { - return self.base.comp.config.link_mode == .Static; + return self.comp.config.link_mode == .Static; } pub fn isObject(self: File) bool { diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index a321d28fb3d6..1719d5fa6703 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -48,7 +48,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const is_lib = self.base.comp.config.output_mode == .Lib; const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; - const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; + const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib; const target = self.base.comp.root_mod.resolved_target.result; const optimize_mode = self.base.comp.root_mod.optimize_mode; @@ -56,17 +56,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const id_symlink_basename = "lld.id"; var man: Cache.Manifest = undefined; - defer if (!self.base.options.disable_lld_caching) man.deinit(); + defer if (!self.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - if (!self.base.options.disable_lld_caching) { + if (!self.base.disable_lld_caching) { man = comp.cache_parent.obtain(); self.base.releaseLock(); comptime assert(Compilation.link_hash_implementation_version == 10); - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); } @@ -79,12 +79,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } try man.addOptionalFile(module_obj_path); - man.hash.addOptionalBytes(self.base.options.entry); + man.hash.addOptionalBytes(comp.config.entry); man.hash.add(self.base.stack_size); man.hash.addOptional(self.image_base); - man.hash.addListOfBytes(self.base.options.lib_dirs); - man.hash.add(self.base.options.skip_linker_dependencies); - if (self.base.options.link_libc) { + man.hash.addListOfBytes(self.lib_dirs); + man.hash.add(comp.skip_linker_dependencies); + if (comp.config.link_libc) { man.hash.add(self.base.comp.libc_installation != null); if (self.base.comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); @@ -95,18 +95,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } try link.hashAddSystemLibs(&man, self.base.comp.system_libs); - man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys()); - man.hash.addOptional(self.base.options.subsystem); - man.hash.add(self.base.options.is_test); - man.hash.add(self.base.options.tsaware); - man.hash.add(self.base.options.nxcompat); - man.hash.add(self.base.options.dynamicbase); + man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); + man.hash.addOptional(self.subsystem); + man.hash.add(comp.config.is_test); + man.hash.add(self.tsaware); + man.hash.add(self.nxcompat); + man.hash.add(self.dynamicbase); man.hash.addOptional(self.base.allow_shlib_undefined); // strip does not need to go into the linker hash because it is part of the hash namespace - man.hash.addOptional(self.base.options.major_subsystem_version); - man.hash.addOptional(self.base.options.minor_subsystem_version); - man.hash.addOptional(self.base.options.version); - try man.addOptionalFile(self.base.options.module_definition_file); + man.hash.addOptional(self.major_subsystem_version); + man.hash.addOptional(self.minor_subsystem_version); + man.hash.addOptional(comp.version); + try man.addOptionalFile(self.module_definition_file); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try man.hit(); @@ -141,8 +141,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { - if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0].path; + if (comp.objects.len != 0) + break :blk comp.objects[0].path; if (comp.c_object_table.count() != 0) 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 try argv.append("-ERRORLIMIT:0"); try argv.append("-NOLOGO"); - if (!self.base.options.strip) { + if (self.base.debug_format != .strip) { try argv.append("-DEBUG"); const out_ext = std.fs.path.extension(full_out_path); - const out_pdb = self.base.options.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{ + const out_pdb = self.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{ full_out_path[0 .. full_out_path.len - out_ext.len], }); try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb})); try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb})); } - if (self.base.options.version) |version| { + if (comp.version) |version| { try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor })); } - if (self.base.options.lto) { + if (comp.config.lto) { switch (optimize_mode) { .Debug => {}, .ReleaseSmall => try argv.append("-OPT:lldlto=2"), @@ -209,7 +209,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } - for (self.base.options.force_undefined_symbols.keys()) |symbol| { + for (self.base.force_undefined_symbols.keys()) |symbol| { try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol})); } @@ -217,17 +217,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append("-DLL"); } - if (self.base.options.entry) |entry| { + if (comp.config.entry) |entry| { try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry})); } - if (self.base.options.tsaware) { + if (self.tsaware) { try argv.append("-tsaware"); } - if (self.base.options.nxcompat) { + if (self.nxcompat) { try argv.append("-nxcompat"); } - if (!self.base.options.dynamicbase) { + if (!self.dynamicbase) { try argv.append("-dynamicbase:NO"); } if (self.base.allow_shlib_undefined) { @@ -236,12 +236,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); - if (self.base.options.implib_emit) |emit| { + if (self.implib_emit) |emit| { const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path}); try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path})); } - if (self.base.options.link_libc) { + if (comp.config.link_libc) { if (self.base.comp.libc_installation) |libc_installation| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?})); @@ -252,12 +252,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } - for (self.base.options.lib_dirs) |lib_dir| { + for (self.lib_dirs) |lib_dir| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir})); } - try argv.ensureUnusedCapacity(self.base.options.objects.len); - for (self.base.options.objects) |obj| { + try argv.ensureUnusedCapacity(comp.objects.len); + for (comp.objects) |obj| { if (obj.must_link) { argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{s}", .{obj.path})); } else { @@ -279,18 +279,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(p); } - if (self.base.options.module_definition_file) |def| { + if (self.module_definition_file) |def| { try argv.append(try allocPrint(arena, "-DEF:{s}", .{def})); } const resolved_subsystem: ?std.Target.SubSystem = blk: { - if (self.base.options.subsystem) |explicit| break :blk explicit; + if (self.subsystem) |explicit| break :blk explicit; switch (target.os.tag) { .windows => { if (self.base.comp.module) |module| { if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib) break :blk null; - if (module.stage1_flags.have_c_main or self.base.options.is_test or + if (module.stage1_flags.have_c_main or comp.config.is_test or module.stage1_flags.have_winmain_crt_startup or module.stage1_flags.have_wwinmain_crt_startup) { @@ -310,8 +310,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const mode: Mode = mode: { if (resolved_subsystem) |subsystem| { const subsystem_suffix = ss: { - if (self.base.options.major_subsystem_version) |major| { - if (self.base.options.minor_subsystem_version) |minor| { + if (self.major_subsystem_version) |major| { + if (self.minor_subsystem_version) |minor| { break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); } else { break :ss try allocPrint(arena, ",{d}", .{major}); @@ -447,7 +447,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } else { try argv.append("-NODEFAULTLIB"); - if (!is_lib and self.base.options.entry == null) { + if (!is_lib and comp.config.entry == null) { if (self.base.comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); @@ -463,18 +463,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } // libc++ dep - if (self.base.options.link_libcpp) { + if (comp.config.link_libcpp) { try argv.append(comp.libcxxabi_static_lib.?.full_object_path); try argv.append(comp.libcxx_static_lib.?.full_object_path); } // libunwind dep - if (self.base.options.link_libunwind) { + if (comp.config.link_libunwind) { try argv.append(comp.libunwind_static_lib.?.full_object_path); } - if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) { - if (!self.base.options.link_libc) { + if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) { + if (!comp.config.link_libc) { if (comp.libc_static_lib) |lib| { try argv.append(lib.full_object_path); } @@ -492,13 +492,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod argv.appendAssumeCapacity(crt_file.full_object_path); continue; } - if (try findLib(arena, lib_basename, self.base.options.lib_dirs)) |full_path| { + if (try findLib(arena, lib_basename, self.lib_dirs)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } if (target.abi.isGnu()) { const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key}); - if (try findLib(arena, fallback_name, self.base.options.lib_dirs)) |full_path| { + if (try findLib(arena, fallback_name, self.lib_dirs)) |full_path| { argv.appendAssumeCapacity(full_path); continue; } @@ -582,7 +582,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } - if (!self.base.options.disable_lld_caching) { + if (!self.base.disable_lld_caching) { // Update the file with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index ef803a45f18b..5bd65b222793 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1022,16 +1022,18 @@ const min_nop_size = 2; /// actual_capacity + (actual_capacity / ideal_factor) const ideal_factor = 3; -pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf { - const target = &bin_file.options.target; +pub fn init(lf: *File, format: Format) Dwarf { + const comp = lf.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, else => unreachable, }; return .{ - .allocator = allocator, - .bin_file = bin_file, + .allocator = gpa, + .bin_file = lf, .format = format, .ptr_width = ptr_width, .dbg_line_header = switch (target.cpu.arch) { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index df83878494e1..a116c46d2f56 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,5 +1,6 @@ base: link.File, image_base: u64, +rdynamic: bool, ptr_width: PtrWidth, @@ -358,19 +359,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, .function_sections = options.function_sections, .data_sections = options.data_sections, - - .image_base = b: { - if (is_dyn_lib) break :b 0; - if (output_mode == .Exe and comp.config.pie) return 0; - return options.image_base orelse switch (ptr_width) { - .p32 => 0x1000, - .p64 => 0x1000000, - }; - }, }, .ptr_width = ptr_width, .page_size = page_size, .default_sym_version = default_sym_version, + + .image_base = b: { + if (is_dyn_lib) break :b 0; + if (output_mode == .Exe and comp.config.pie) break :b 0; + break :b options.image_base orelse switch (ptr_width) { + .p32 => 0x1000, + .p64 => 0x1000000, + }; + }, + + .rdynamic = options.rdynamic, }; if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); @@ -1006,7 +1009,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node break :blk path; } } else null; - const gc_sections = self.base.gc_sections; // --verbose-link 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 var rpath_table = std.StringArrayHashMap(void).init(gpa); defer rpath_table.deinit(); - for (self.base.options.rpath_list) |rpath| { + for (self.base.rpath_list) |rpath| { _ = try rpath_table.put(rpath, {}); } - if (self.base.options.each_lib_rpath) { + if (self.each_lib_rpath) { var test_path = std.ArrayList(u8).init(gpa); defer test_path.deinit(); - for (self.base.options.lib_dirs) |lib_dir_path| { + for (self.lib_dirs) |lib_dir_path| { for (self.base.comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; @@ -1076,9 +1078,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // libc - if (!self.base.options.skip_linker_dependencies and - !self.base.options.link_libc) - { + if (!comp.skip_linker_dependencies and !comp.config.link_libc) { if (comp.libc_static_lib) |lib| { try positionals.append(.{ .path = lib.full_object_path }); } @@ -1263,10 +1263,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node self.entry_index = if (entry) |name| self.globalByName(name) else null; } - if (gc_sections) { + if (self.base.gc_sections) { try gc.gcAtoms(self); - if (self.base.options.print_gc_sections) { + if (self.base.print_gc_sections) { try gc.dumpPrunedAtoms(self); } } @@ -1347,13 +1347,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); defer positionals.deinit(); - try positionals.ensureUnusedCapacity(self.base.options.objects.len); - positionals.appendSliceAssumeCapacity(self.base.options.objects); + try positionals.ensureUnusedCapacity(comp.objects.len); + positionals.appendSliceAssumeCapacity(comp.objects); // This is a set of object files emitted by clang in a single `build-exe` invocation. // 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) var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); defer positionals.deinit(); - try positionals.ensureUnusedCapacity(self.base.options.objects.len); - positionals.appendSliceAssumeCapacity(self.base.options.objects); + try positionals.ensureUnusedCapacity(comp.objects.len); + positionals.appendSliceAssumeCapacity(comp.objects); // This is a set of object files emitted by clang in a single `build-exe` invocation. // 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 { try argv.append(full_out_path); if (self.base.isRelocatable()) { - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { try argv.append(obj.path); } @@ -1626,28 +1626,28 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } if (self.base.isDynLib()) { - if (self.base.options.soname) |name| { + if (self.soname) |name| { try argv.append("-soname"); try argv.append(name); } } - if (self.base.options.entry) |entry| { + if (comp.config.entry) |entry| { try argv.append("--entry"); try argv.append(entry); } - for (self.base.options.rpath_list) |rpath| { + for (self.base.rpath_list) |rpath| { try argv.append("-rpath"); try argv.append(rpath); } - if (self.base.options.each_lib_rpath) { - for (self.base.options.lib_dirs) |lib_dir_path| { + if (self.each_lib_rpath) { + for (self.lib_dirs) |lib_dir_path| { try argv.append("-rpath"); try argv.append(lib_dir_path); } - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { if (Compilation.classifyFileExt(obj.path) == .shared_library) { const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; if (obj.loption) continue; @@ -1669,29 +1669,29 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("--gc-sections"); } - if (self.base.options.print_gc_sections) { + if (self.base.print_gc_sections) { try argv.append("--print-gc-sections"); } - if (self.base.options.eh_frame_hdr) { + if (self.eh_frame_hdr) { try argv.append("--eh-frame-hdr"); } - if (self.base.options.rdynamic) { + if (self.rdynamic) { try argv.append("--export-dynamic"); } - if (self.base.options.z_notext) { + if (self.z_notext) { try argv.append("-z"); try argv.append("notext"); } - if (self.base.options.z_nocopyreloc) { + if (self.z_nocopyreloc) { try argv.append("-z"); try argv.append("nocopyreloc"); } - if (self.base.options.z_now) { + if (self.z_now) { try argv.append("-z"); try argv.append("now"); } @@ -1702,11 +1702,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("-shared"); } - if (self.base.options.pie and self.base.isExe()) { + if (comp.config.pie and self.base.isExe()) { try argv.append("-pie"); } - if (self.base.options.strip) { + if (self.base.debug_format == .strip) { try argv.append("-s"); } @@ -1715,12 +1715,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { if (csu.crti) |v| try argv.append(v); if (csu.crtbegin) |v| try argv.append(v); - for (self.base.options.lib_dirs) |lib_dir| { + for (self.lib_dirs) |lib_dir| { try argv.append("-L"); try argv.append(lib_dir); } - if (self.base.options.link_libc) { + if (comp.config.link_libc) { if (self.base.comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); @@ -1728,7 +1728,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } var whole_archive = false; - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { if (obj.must_link and !whole_archive) { try argv.append("-whole-archive"); whole_archive = true; @@ -1756,15 +1756,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append(p); } - // TSAN - if (self.base.options.tsan) { + if (comp.config.any_sanitize_thread) { try argv.append(comp.tsan_static_lib.?.full_object_path); } // libc - if (!self.base.options.skip_linker_dependencies and - !self.base.options.link_libc) - { + if (!comp.skip_linker_dependencies and !comp.config.link_libc) { if (comp.libc_static_lib) |lib| { try argv.append(lib.full_object_path); } @@ -1799,18 +1796,18 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } // libc++ dep - if (self.base.options.link_libcpp) { + if (comp.config.link_libcpp) { try argv.append(comp.libcxxabi_static_lib.?.full_object_path); try argv.append(comp.libcxx_static_lib.?.full_object_path); } // libunwind dep - if (self.base.options.link_libunwind) { + if (comp.config.link_libunwind) { try argv.append(comp.libunwind_static_lib.?.full_object_path); } // libc dep - if (self.base.options.link_libc) { + if (comp.config.link_libc) { if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); @@ -1963,8 +1960,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { defer script.deinit(gpa); try script.parse(data, self); - const lib_dirs = self.base.options.lib_dirs; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -1981,7 +1976,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { // TODO I think technically we should re-use the mechanism used by the frontend here. // Maybe we should hoist search-strategy all the way here? - for (lib_dirs) |lib_dir| { + for (self.lib_dirs) |lib_dir| { if (!self.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic)) break :success; @@ -1998,7 +1993,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { } else |_| {} try checked_paths.append(try gpa.dupe(u8, scr_obj.path)); - for (lib_dirs) |lib_dir| { + for (self.lib_dirs) |lib_dir| { if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, scr_obj.path, null)) break :success; } @@ -2338,7 +2333,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const link_mode = self.base.comp.config.link_mode; const is_dyn_lib = link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; - const have_dynamic_linker = self.base.options.link_libc and + const have_dynamic_linker = comp.config.link_libc and link_mode == .Dynamic and is_exe_or_dyn_lib; const target = self.base.comp.root_mod.resolved_target.result; const compiler_rt_path: ?[]const u8 = blk: { @@ -2358,11 +2353,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v const id_symlink_basename = "lld.id"; var man: Cache.Manifest = undefined; - defer if (!self.base.options.disable_lld_caching) man.deinit(); + defer if (!self.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - if (!self.base.options.disable_lld_caching) { + if (!self.base.disable_lld_caching) { man = comp.cache_parent.obtain(); // 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 comptime assert(Compilation.link_hash_implementation_version == 10); - try man.addOptionalFile(self.base.options.linker_script); - try man.addOptionalFile(self.base.options.version_script); - for (self.base.options.objects) |obj| { + try man.addOptionalFile(self.linker_script); + try man.addOptionalFile(self.version_script); + for (comp.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); man.hash.add(obj.loption); @@ -2385,34 +2380,34 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. - man.hash.addOptionalBytes(self.base.options.entry); + man.hash.addOptionalBytes(comp.config.entry); man.hash.addOptional(self.image_base); man.hash.add(self.base.gc_sections); - man.hash.addOptional(self.base.options.sort_section); - man.hash.add(self.base.options.eh_frame_hdr); - man.hash.add(self.base.options.emit_relocs); - man.hash.add(self.base.options.rdynamic); - man.hash.addListOfBytes(self.base.options.lib_dirs); - man.hash.addListOfBytes(self.base.options.rpath_list); - man.hash.add(self.base.options.each_lib_rpath); + man.hash.addOptional(self.sort_section); + man.hash.add(self.eh_frame_hdr); + man.hash.add(self.emit_relocs); + man.hash.add(self.rdynamic); + man.hash.addListOfBytes(self.lib_dirs); + man.hash.addListOfBytes(self.base.rpath_list); + man.hash.add(self.each_lib_rpath); if (output_mode == .Exe) { man.hash.add(self.base.stack_size); man.hash.add(self.base.build_id); } - man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys()); - man.hash.add(self.base.options.skip_linker_dependencies); - man.hash.add(self.base.options.z_nodelete); - man.hash.add(self.base.options.z_notext); - man.hash.add(self.base.options.z_defs); - man.hash.add(self.base.options.z_origin); - man.hash.add(self.base.options.z_nocopyreloc); - man.hash.add(self.base.options.z_now); - man.hash.add(self.base.options.z_relro); - man.hash.add(self.base.options.z_common_page_size orelse 0); - man.hash.add(self.base.options.z_max_page_size orelse 0); - man.hash.add(self.base.options.hash_style); + man.hash.addListOfBytes(self.symbol_wrap_set.keys()); + man.hash.add(comp.skip_linker_dependencies); + man.hash.add(self.z_nodelete); + man.hash.add(self.z_notext); + man.hash.add(self.z_defs); + man.hash.add(self.z_origin); + man.hash.add(self.z_nocopyreloc); + man.hash.add(self.z_now); + man.hash.add(self.z_relro); + man.hash.add(self.z_common_page_size orelse 0); + man.hash.add(self.z_max_page_size orelse 0); + man.hash.add(self.hash_style); // strip does not need to go into the linker hash because it is part of the hash namespace - if (self.base.options.link_libc) { + if (comp.config.link_libc) { man.hash.add(self.base.comp.libc_installation != null); if (self.base.comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); @@ -2421,16 +2416,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addOptionalBytes(target.dynamic_linker.get()); } } - man.hash.addOptionalBytes(self.base.options.soname); - man.hash.addOptional(self.base.options.version); + man.hash.addOptionalBytes(self.soname); + man.hash.addOptional(comp.version); try link.hashAddSystemLibs(&man, self.base.comp.system_libs); - man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys()); + man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); man.hash.add(self.base.allow_shlib_undefined); - man.hash.add(self.base.options.bind_global_refs_locally); - man.hash.add(self.base.options.compress_debug_sections); - man.hash.add(self.base.options.tsan); - man.hash.addOptionalBytes(self.base.options.sysroot); - man.hash.add(self.base.options.linker_optimization); + 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); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try man.hit(); @@ -2466,14 +2461,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails // before even generating the relocatable. if (output_mode == .Obj and - (self.base.options.lto or target.isBpfFreestanding())) + (comp.config.lto or target.isBpfFreestanding())) { // In this case we must do a simple file copy // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { - if (self.base.options.objects.len != 0) - break :blk self.base.options.objects[0].path; + if (comp.objects.len != 0) + break :blk comp.objects[0].path; if (comp.c_object_table.count() != 0) 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 try argv.append("--error-limit=0"); - if (self.base.options.sysroot) |sysroot| { + if (self.sysroot) |sysroot| { try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot})); } - if (self.base.options.lto) { - switch (self.base.options.optimize_mode) { + if (comp.config.lto) { + switch (comp.root_mod.optimize_mode) { .Debug => {}, .ReleaseSmall => try argv.append("--lto-O2"), .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"), } } try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{ - self.base.options.linker_optimization, + self.optimization, })); - if (self.base.options.entry) |entry| { + if (comp.config.entry) |entry| { try argv.append("--entry"); try argv.append(entry); } - for (self.base.options.force_undefined_symbols.keys()) |sym| { + for (self.base.force_undefined_symbols.keys()) |sym| { try argv.append("-u"); try argv.append(sym); } - switch (self.base.options.hash_style) { + switch (self.hash_style) { .gnu => try argv.append("--hash-style=gnu"), .sysv => try argv.append("--hash-style=sysv"), .both => {}, // this is the default @@ -2559,12 +2554,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); - if (self.base.options.linker_script) |linker_script| { + if (self.linker_script) |linker_script| { try argv.append("-T"); try argv.append(linker_script); } - if (self.base.options.sort_section) |how| { + if (self.sort_section) |how| { const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)}); try argv.append(arg); } @@ -2573,67 +2568,67 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--gc-sections"); } - if (self.base.options.print_gc_sections) { + if (self.base.print_gc_sections) { try argv.append("--print-gc-sections"); } - if (self.base.options.print_icf_sections) { + if (self.print_icf_sections) { try argv.append("--print-icf-sections"); } - if (self.base.options.print_map) { + if (self.print_map) { try argv.append("--print-map"); } - if (self.base.options.eh_frame_hdr) { + if (self.eh_frame_hdr) { try argv.append("--eh-frame-hdr"); } - if (self.base.options.emit_relocs) { + if (self.emit_relocs) { try argv.append("--emit-relocs"); } - if (self.base.options.rdynamic) { + if (self.rdynamic) { try argv.append("--export-dynamic"); } - if (self.base.options.strip) { + if (self.base.debug_format == .strip) { try argv.append("-s"); } - if (self.base.options.z_nodelete) { + if (self.z_nodelete) { try argv.append("-z"); try argv.append("nodelete"); } - if (self.base.options.z_notext) { + if (self.z_notext) { try argv.append("-z"); try argv.append("notext"); } - if (self.base.options.z_defs) { + if (self.z_defs) { try argv.append("-z"); try argv.append("defs"); } - if (self.base.options.z_origin) { + if (self.z_origin) { try argv.append("-z"); try argv.append("origin"); } - if (self.base.options.z_nocopyreloc) { + if (self.z_nocopyreloc) { try argv.append("-z"); try argv.append("nocopyreloc"); } - if (self.base.options.z_now) { + if (self.z_now) { // LLD defaults to -zlazy try argv.append("-znow"); } - if (!self.base.options.z_relro) { + if (!self.z_relro) { // LLD defaults to -zrelro try argv.append("-znorelro"); } - if (self.base.options.z_common_page_size) |size| { + if (self.z_common_page_size) |size| { try argv.append("-z"); try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size})); } - if (self.base.options.z_max_page_size) |size| { + if (self.z_max_page_size) |size| { try argv.append("-z"); try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size})); } @@ -2658,7 +2653,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-shared"); } - if (self.base.options.pie and output_mode == .Exe) { + if (comp.config.pie and output_mode == .Exe) { try argv.append("-pie"); } @@ -2683,20 +2678,20 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // rpaths var rpath_table = std.StringHashMap(void).init(gpa); defer rpath_table.deinit(); - for (self.base.options.rpath_list) |rpath| { + for (self.base.rpath_list) |rpath| { if ((try rpath_table.fetchPut(rpath, {})) == null) { try argv.append("-rpath"); try argv.append(rpath); } } - for (self.base.options.symbol_wrap_set.keys()) |symbol_name| { + for (self.symbol_wrap_set.keys()) |symbol_name| { try argv.appendSlice(&.{ "-wrap", symbol_name }); } - if (self.base.options.each_lib_rpath) { + if (self.each_lib_rpath) { var test_path = std.ArrayList(u8).init(arena); - for (self.base.options.lib_dirs) |lib_dir_path| { + for (self.lib_dirs) |lib_dir_path| { for (self.base.comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; @@ -2706,7 +2701,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } } - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { if (Compilation.classifyFileExt(obj.path) == .shared_library) { const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; if (obj.loption) continue; @@ -2719,12 +2714,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } - for (self.base.options.lib_dirs) |lib_dir| { + for (self.lib_dirs) |lib_dir| { try argv.append("-L"); try argv.append(lib_dir); } - if (self.base.options.link_libc) { + if (comp.config.link_libc) { if (self.base.comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); @@ -2739,11 +2734,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } if (is_dyn_lib) { - if (self.base.options.soname) |soname| { + if (self.soname) |soname| { try argv.append("-soname"); try argv.append(soname); } - if (self.base.options.version_script) |version_script| { + if (self.version_script) |version_script| { try argv.append("-version-script"); try argv.append(version_script); } @@ -2751,7 +2746,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // Positional arguments to the linker such as object files. var whole_archive = false; - for (self.base.options.objects) |obj| { + for (comp.objects) |obj| { if (obj.must_link and !whole_archive) { try argv.append("-whole-archive"); whole_archive = true; @@ -2779,15 +2774,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(p); } - // TSAN - if (self.base.options.tsan) { + if (comp.config.any_sanitize_thread) { try argv.append(comp.tsan_static_lib.?.full_object_path); } // libc if (is_exe_or_dyn_lib and - !self.base.options.skip_linker_dependencies and - !self.base.options.link_libc) + !comp.skip_linker_dependencies and + !comp.config.link_libc) { if (comp.libc_static_lib) |lib| { try argv.append(lib.full_object_path); @@ -2832,19 +2826,19 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } // libc++ dep - if (self.base.options.link_libcpp) { + if (comp.config.link_libcpp) { try argv.append(comp.libcxxabi_static_lib.?.full_object_path); try argv.append(comp.libcxx_static_lib.?.full_object_path); } // libunwind dep - if (self.base.options.link_libunwind) { + if (comp.config.link_libunwind) { try argv.append(comp.libunwind_static_lib.?.full_object_path); } // libc dep self.error_flags.missing_libc = false; - if (self.base.options.link_libc) { + if (comp.config.link_libc) { if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); @@ -2884,13 +2878,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--allow-shlib-undefined"); } - switch (self.base.options.compress_debug_sections) { + switch (self.compress_debug_sections) { .none => {}, .zlib => try argv.append("--compress-debug-sections=zlib"), .zstd => try argv.append("--compress-debug-sections=zstd"), } - if (self.base.options.bind_global_refs_locally) { + if (self.bind_global_refs_locally) { try argv.append("-Bsymbolic"); } @@ -2964,7 +2958,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } - if (!self.base.options.disable_lld_caching) { + if (!self.base.disable_lld_caching) { // Update the file with the digest. If it fails we can continue; it only // means that the next invocation will have an unnecessary cache miss. Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| { @@ -3101,7 +3095,8 @@ fn writeElfHeader(self: *Elf) !void { }; index += 1; - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const target = comp.root_mod.resolved_target.result; const endian = target.cpu.arch.endian(); hdr_buf[index] = switch (endian) { .little => elf.ELFDATA2LSB, @@ -3120,10 +3115,10 @@ fn writeElfHeader(self: *Elf) !void { assert(index == 16); - const output_mode = self.base.comp.config.output_mode; - const link_mode = self.base.comp.config.link_mode; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; const elf_type: elf.ET = switch (output_mode) { - .Exe => if (self.base.options.pie) .DYN else .EXEC, + .Exe => if (comp.config.pie) .DYN else .EXEC, .Obj => .REL, .Lib => switch (link_mode) { .Static => @as(elf.ET, .REL), @@ -3283,7 +3278,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self); self.end_index = try linker_defined.addGlobal("_end", self); - if (self.base.options.eh_frame_hdr) { + if (self.eh_frame_hdr) { self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self); } @@ -3314,7 +3309,8 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { } fn allocateLinkerDefinedSymbols(self: *Elf) void { - const link_mode = self.base.comp.config.link_mode; + const comp = self.base.comp; + const link_mode = comp.config.link_mode; // _DYNAMIC if (self.dynamic_section_index) |shndx| { @@ -3398,7 +3394,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { // __rela_iplt_start, __rela_iplt_end if (self.rela_dyn_section_index) |shndx| blk: { - if (link_mode != .Static or self.base.options.pie) break :blk; + if (link_mode != .Static or comp.config.pie) break :blk; const shdr = &self.shdrs.items[shndx]; const end_addr = shdr.sh_addr + shdr.sh_size; const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); @@ -3445,7 +3441,8 @@ fn initOutputSections(self: *Elf) !void { } fn initSyntheticSections(self: *Elf) !void { - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const target = comp.root_mod.resolved_target.result; const ptr_size = self.ptrWidthBytes(); const needs_eh_frame = for (self.objects.items) |index| { @@ -3460,7 +3457,7 @@ fn initSyntheticSections(self: *Elf) !void { .offset = std.math.maxInt(u64), }); - if (self.base.options.eh_frame_hdr) { + if (self.eh_frame_hdr) { self.eh_frame_hdr_section_index = try self.addSection(.{ .name = ".eh_frame_hdr", .type = elf.SHT_PROGBITS, @@ -3554,7 +3551,7 @@ fn initSyntheticSections(self: *Elf) !void { // In this case, if we do generate .interp section and segment, we will get // a segfault in the dynamic linker trying to load a binary that is static // and doesn't contain .dynamic section. - if (self.isStatic() and !self.base.options.pie) break :blk false; + if (self.isStatic() and !comp.config.pie) break :blk false; break :blk target.dynamic_linker.get() != null; }; if (needs_interp) { @@ -3567,7 +3564,7 @@ fn initSyntheticSections(self: *Elf) !void { }); } - if (self.base.isDynLib() or self.shared_objects.items.len > 0 or self.base.options.pie) { + if (self.base.isDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) { self.dynstrtab_section_index = try self.addSection(.{ .name = ".dynstr", .flags = elf.SHF_ALLOC, @@ -3859,7 +3856,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { } if (self.base.isDynLib()) { - if (self.base.options.soname) |soname| { + if (self.soname) |soname| { try self.dynamic.setSoname(soname, self); } } diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index b3d7b51d3e05..dc330fa54b30 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -543,7 +543,7 @@ fn scanReloc( try self.reportPicError(symbol, rel, elf_file), .copyrel => { - if (elf_file.base.options.z_nocopyreloc) { + if (elf_file.z_nocopyreloc) { if (symbol.isAbs(elf_file)) try self.reportNoPicError(symbol, rel, elf_file) else @@ -553,9 +553,9 @@ fn scanReloc( }, .dyn_copyrel => { - if (is_writeable or elf_file.base.options.z_nocopyreloc) { + if (is_writeable or elf_file.z_nocopyreloc) { if (!is_writeable) { - if (elf_file.base.options.z_notext) { + if (elf_file.z_notext) { elf_file.has_text_reloc = true; } else { try self.reportTextRelocError(symbol, rel, elf_file); @@ -587,7 +587,7 @@ fn scanReloc( .dynrel, .baserel, .ifunc => { if (!is_writeable) { - if (elf_file.base.options.z_notext) { + if (elf_file.z_notext) { elf_file.has_text_reloc = true; } else { try self.reportTextRelocError(symbol, rel, elf_file); @@ -657,11 +657,12 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { } fn outputType(elf_file: *Elf) u2 { + const comp = elf_file.base.comp; assert(!elf_file.isRelocatable()); return switch (elf_file.base.comp.config.output_mode) { .Obj => unreachable, .Lib => 0, - .Exe => if (elf_file.base.options.pie) 1 else 2, + .Exe => if (comp.config.pie) 1 else 2, }; } @@ -979,7 +980,7 @@ fn resolveDynAbsReloc( => try writer.writeInt(i32, @as(i32, @truncate(S + A)), .little), .dyn_copyrel => { - if (is_writeable or elf_file.base.options.z_nocopyreloc) { + if (is_writeable or elf_file.z_nocopyreloc) { elf_file.addRelaDynAssumeCapacity(.{ .offset = P, .sym = target.extra(elf_file).?.dynamic, diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 347f96d45117..5fa31711e68e 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -299,7 +299,7 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { if (mem.startsWith(u8, name, ".note")) break :blk true; if (mem.startsWith(u8, name, ".comment")) break :blk true; if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; - if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and + if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and mem.startsWith(u8, name, ".debug")) break :blk true; break :blk false; }; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 15ae3bb94301..05ff55dd1877 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -97,7 +97,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { symbol_ptr.esym_index = esym_index; if (elf_file.base.debug_format != .strip) { - self.dwarf = Dwarf.init(gpa, &elf_file.base, .dwarf32); + self.dwarf = Dwarf.init(&elf_file.base, .dwarf32); } } diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 1e7f2f4f9f2a..92d5318c0219 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -32,7 +32,7 @@ pub const DynamicSection = struct { fn getFlags(dt: DynamicSection, elf_file: *Elf) ?u64 { _ = dt; var flags: u64 = 0; - if (elf_file.base.options.z_now) { + if (elf_file.z_now) { flags |= elf.DF_BIND_NOW; } for (elf_file.got.entries.items) |entry| switch (entry.tag) { @@ -49,15 +49,16 @@ pub const DynamicSection = struct { } fn getFlags1(dt: DynamicSection, elf_file: *Elf) ?u64 { + const comp = elf_file.base.comp; _ = dt; var flags_1: u64 = 0; - if (elf_file.base.options.z_now) { + if (elf_file.z_now) { flags_1 |= elf.DF_1_NOW; } - if (elf_file.isExe() and elf_file.base.options.pie) { + if (elf_file.isExe() and comp.config.pie) { flags_1 |= elf.DF_1_PIE; } - // if (elf_file.base.options.z_nodlopen) { + // if (elf_file.z_nodlopen) { // flags_1 |= elf.DF_1_NOOPEN; // } return if (flags_1 > 0) flags_1 else null; @@ -246,12 +247,13 @@ pub const ZigGotSection = struct { } pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { + const comp = elf_file.base.comp; const index = try zig_got.allocateEntry(elf_file.base.allocator); const entry = &zig_got.entries.items[index]; entry.* = sym_index; const symbol = elf_file.symbol(sym_index); symbol.flags.has_zig_got = true; - if (elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) { + if (elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) { zig_got.flags.needs_rela = true; } if (symbol.extra(elf_file)) |extra| { @@ -478,6 +480,7 @@ pub const GotSection = struct { } pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { + const comp = elf_file.base.comp; const index = try got.allocateEntry(elf_file.base.allocator); const entry = &got.entries.items[index]; entry.tag = .got; @@ -485,7 +488,7 @@ pub const GotSection = struct { const symbol = elf_file.symbol(sym_index); symbol.flags.has_got = true; if (symbol.flags.import or symbol.isIFunc(elf_file) or - ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and !symbol.isAbs(elf_file))) + ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file))) { got.flags.needs_rela = true; } @@ -561,6 +564,7 @@ pub const GotSection = struct { } pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void { + const comp = elf_file.base.comp; const is_dyn_lib = elf_file.isDynLib(); const apply_relocs = true; // TODO add user option for this @@ -576,7 +580,7 @@ pub const GotSection = struct { if (symbol.?.flags.import) break :blk 0; if (symbol.?.isIFunc(elf_file)) break :blk if (apply_relocs) value else 0; - if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and + if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file)) { break :blk if (apply_relocs) value else 0; @@ -623,6 +627,7 @@ pub const GotSection = struct { } pub fn addRela(got: GotSection, elf_file: *Elf) !void { + const comp = elf_file.base.comp; const is_dyn_lib = elf_file.isDynLib(); try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file)); @@ -652,7 +657,7 @@ pub const GotSection = struct { }); continue; } - if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and + if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file)) { elf_file.addRelaDynAssumeCapacity(.{ @@ -725,6 +730,7 @@ pub const GotSection = struct { } pub fn numRela(got: GotSection, elf_file: *Elf) usize { + const comp = elf_file.base.comp; const is_dyn_lib = elf_file.isDynLib(); var num: usize = 0; for (got.entries.items) |entry| { @@ -734,7 +740,7 @@ pub const GotSection = struct { }; switch (entry.tag) { .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or - ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and + ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file))) { num += 1; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 3da076ba5675..87faec65373f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -252,7 +252,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { self.d_sym = .{ .allocator = gpa, - .dwarf = link.File.Dwarf.init(gpa, &self.base, .dwarf32), + .dwarf = link.File.Dwarf.init(&self.base, .dwarf32), .file = d_sym_file, }; } @@ -573,7 +573,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try self.writeLinkeditSegmentData(); - var codesig: ?CodeSignature = if (requiresCodeSignature(&self.base.options)) blk: { + var codesig: ?CodeSignature = if (self.requiresCodeSignature()) blk: { // Preallocate space for the code signature. // We need to do this at this stage so that we have the load commands with proper values // written out to the file. @@ -619,12 +619,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No }); }, .Lib => if (self.base.comp.config.link_mode == .Dynamic) { - try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer); + try load_commands.writeDylibIdLC(self, lc_writer); }, else => {}, } - try load_commands.writeRpathLCs(gpa, &self.base.options, lc_writer); + try load_commands.writeRpathLCs(self, lc_writer); try lc_writer.writeStruct(macho.source_version_command{ .version = 0, }); @@ -713,7 +713,7 @@ pub fn resolveLibSystem( success: { if (self.sdk_layout) |sdk_layout| switch (sdk_layout) { .sdk => { - const dir = try fs.path.join(arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" }); + const dir = try fs.path.join(arena, &[_][]const u8{ comp.sysroot.?, "usr", "lib" }); if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success; }, .vendored => { @@ -1156,7 +1156,8 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void { // 2) afterwards, we parse dependents of the included dylibs // TODO this should not be performed if the user specifies `-flat_namespace` flag. // See ld64 manpages. - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; while (dependent_libs.readItem()) |dep_id| { defer dep_id.id.deinit(gpa); @@ -1176,7 +1177,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void { var checked_paths = std.ArrayList([]const u8).init(arena); success: { - if (self.base.options.sysroot) |root| { + if (comp.sysroot) |root| { const dir = try fs.path.join(arena, &[_][]const u8{ root, dirname }); if (try accessLibPath(gpa, &test_path, &checked_paths, dir, stem)) break :success; } @@ -1713,12 +1714,12 @@ pub fn resolveSymbols(self: *MachO) !void { // we search for it in libraries should there be no object files specified // on the linker line. if (output_mode == .Exe) { - const entry_name = self.base.options.entry orelse load_commands.default_entry_point; + const entry_name = comp.config.entry.?; _ = try self.addUndefined(entry_name, .{}); } // Force resolution of any symbols requested by the user. - for (self.base.options.force_undefined_symbols.keys()) |sym_name| { + for (self.base.force_undefined_symbols.keys()) |sym_name| { _ = try self.addUndefined(sym_name, .{}); } @@ -4367,7 +4368,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx { // We generate stabs last in order to ensure that the strtab always has debug info // strings trailing - if (!self.base.options.strip) { + if (self.base.debug_format != .strip) { for (self.objects.items) |object| { assert(self.d_sym == null); // TODO try self.generateSymbolStabs(object, &locals); @@ -5171,7 +5172,8 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 { /// Returns symbol location corresponding to the set entrypoint if any. /// Asserts output mode is executable. pub fn getEntryPoint(self: MachO) ?SymbolWithLoc { - const entry_name = self.base.options.entry orelse load_commands.default_entry_point; + const comp = self.base.comp; + const entry_name = comp.config.entry orelse return null; const global = self.getGlobal(entry_name) orelse return null; return global; } @@ -5189,11 +5191,13 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 { }; } -pub fn requiresCodeSignature(options: *const link.Options) bool { - if (options.entitlements) |_| return true; - const cpu_arch = options.target.cpu.arch; - const os_tag = options.target.os.tag; - const abi = options.target.abi; +pub fn requiresCodeSignature(m: *MachO) bool { + if (m.entitlements) |_| return true; + const comp = m.base.comp; + const target = comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; + const os_tag = target.os.tag; + const abi = target.abi; if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) return true; return false; } diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 2e7f8e49af73..74a4afeb5415 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -198,10 +198,10 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64 } pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { + const comp = macho_file.base.comp; // TODO This linker code currently assumes there is only 1 compilation unit // and it corresponds to the Zig source code. - const options = macho_file.base.options; - const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; for (self.relocs.items) |*reloc| { const sym = switch (reloc.type) { @@ -245,7 +245,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; const low_pc = text_section.addr; const high_pc = text_section.addr + text_section.size; - try self.dwarf.writeDbgInfoHeader(module, low_pc, high_pc); + try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); self.debug_info_header_dirty = false; } @@ -572,6 +572,5 @@ const trace = @import("../../tracy.zig").trace; const Allocator = mem.Allocator; const Dwarf = @import("../Dwarf.zig"); const MachO = @import("../MachO.zig"); -const Module = @import("../../Module.zig"); const StringTable = @import("../StringTable.zig"); const Type = @import("../../type.zig").Type; diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index 51a43351ba03..a92126c07ec8 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -60,7 +60,7 @@ fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void { } // Add all symbols force-defined by the user. - for (macho_file.base.options.force_undefined_symbols.keys()) |sym_name| { + for (macho_file.base.force_undefined_symbols.keys()) |sym_name| { const global_index = macho_file.resolver.get(sym_name).?; const global = macho_file.globals.items[global_index]; const sym = macho_file.getSymbol(global); diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index be8ac636423c..3bffc7f73e3c 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -1,6 +1,3 @@ -/// Default implicit entrypoint symbol name. -pub const default_entry_point: []const u8 = "_main"; - /// Default path to dyld. pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; @@ -17,7 +14,9 @@ const CalcLCsSizeCtx = struct { wants_function_starts: bool = true, }; -fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 { +fn calcLCsSize(m: *MachO, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 { + const comp = m.base.comp; + const gpa = comp.gpa; var has_text_segment: bool = false; var sizeofcmds: u64 = 0; for (ctx.segments) |seg| { @@ -46,15 +45,15 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx false, ); // LC_MAIN - if (options.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { sizeofcmds += @sizeOf(macho.entry_point_command); } // LC_ID_DYLIB - if (options.output_mode == .Lib and options.link_mode == .Dynamic) { + if (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic) { sizeofcmds += blk: { - const emit = options.emit.?; - const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path}); - defer if (options.install_name == null) gpa.free(install_name); + const emit = m.base.emit; + const install_name = m.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path}); + defer if (m.install_name == null) gpa.free(install_name); break :blk calcInstallNameLen( @sizeOf(macho.dylib_command), install_name, @@ -64,7 +63,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx } // LC_RPATH { - var it = RpathIterator.init(gpa, options.rpath_list); + var it = RpathIterator.init(gpa, m.rpath_list); defer it.deinit(); while (try it.next()) |rpath| { sizeofcmds += calcInstallNameLen( @@ -78,7 +77,8 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx sizeofcmds += @sizeOf(macho.source_version_command); // LC_BUILD_VERSION or LC_VERSION_MIN_ or nothing { - const platform = Platform.fromTarget(options.target); + const target = comp.root_mod.resolved_target.result; + const platform = Platform.fromTarget(target); if (platform.isBuildVersionCompatible()) { // LC_BUILD_VERSION 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 ); } // LC_CODE_SIGNATURE - if (MachO.requiresCodeSignature(options)) { + if (m.requiresCodeSignature()) { sizeofcmds += @sizeOf(macho.linkedit_data_command); } - return @as(u32, @intCast(sizeofcmds)); + return @intCast(sizeofcmds); } -pub fn calcMinHeaderPad(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx) !u64 { - var padding: u32 = (try calcLCsSize(gpa, options, ctx, false)) + (options.headerpad_size orelse 0); +pub fn calcMinHeaderPad(m: *MachO, ctx: CalcLCsSizeCtx) !u64 { + var padding: u32 = (try calcLCsSize(m, ctx, false)) + m.headerpad_size; log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)}); - if (options.headerpad_max_install_names) { - const min_headerpad_size: u32 = try calcLCsSize(gpa, options, ctx, true); + if (m.headerpad_max_install_names) { + const min_headerpad_size: u32 = try calcLCsSize(m, ctx, true); log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{ min_headerpad_size + @sizeOf(macho.mach_header_64), }); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 8b0aa90f96f1..f40aaea4db72 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -499,7 +499,7 @@ pub fn linkWithZld( } // Write code signature padding if required - var codesig: ?CodeSignature = if (MachO.requiresCodeSignature(&macho_file.base.options)) blk: { + var codesig: ?CodeSignature = if (macho_file.requiresCodeSignature()) blk: { // Preallocate space for the code signature. // We need to do this at this stage so that we have the load commands with proper values // written out to the file. @@ -547,12 +547,12 @@ pub fn linkWithZld( }); }, .Lib => if (link_mode == .Dynamic) { - try load_commands.writeDylibIdLC(gpa, &macho_file.base.options, lc_writer); + try load_commands.writeDylibIdLC(macho_file, lc_writer); }, else => {}, } - try load_commands.writeRpathLCs(gpa, &macho_file.base.options, lc_writer); + try load_commands.writeRpathLCs(macho_file, lc_writer); try lc_writer.writeStruct(macho.source_version_command{ .version = 0, }); @@ -1072,11 +1072,10 @@ fn calcSectionSizes(macho_file: *MachO) !void { } fn allocateSegments(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; for (macho_file.segments.items, 0..) |*segment, segment_index| { const is_text_segment = mem.eql(u8, segment.segName(), "__TEXT"); const base_size = if (is_text_segment) - try load_commands.calcMinHeaderPad(gpa, &macho_file.base.options, .{ + try load_commands.calcMinHeaderPad(macho_file, .{ .segments = macho_file.segments.items, .dylibs = macho_file.dylibs.items, .referenced_dylibs = macho_file.referenced_dylibs.keys(), diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 1cfc14cef028..846e496ec1d0 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -57,6 +57,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, .function_sections = options.function_sections, .data_sections = options.data_sections, }, @@ -66,7 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { return nvptx; } -pub fn open(arena: Allocator, options: link.FileOpenOptions) !*NvPtx { +pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { const target = options.comp.root_mod.resolved_target.result; assert(target.ofmt == .nvptx); return createEmpty(arena, options); diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 247986d76773..b3c08fb66ba3 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -295,26 +295,36 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { - _ = arena; - const target = options.comp.root_mod.resolved_target.result; - const gpa = options.comp.gpa; + const comp = options.comp; + const target = comp.root_mod.resolved_target.result; + const gpa = comp.gpa; + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; - const sixtyfour_bit: bool = switch (options.target.ptrBitWidth()) { + const sixtyfour_bit: bool = switch (target.ptrBitWidth()) { 0...32 => false, 33...64 => true, else => return error.UnsupportedP9Architecture, }; - const arena_allocator = std.heap.ArenaAllocator.init(gpa); - - const self = try gpa.create(Plan9); + const self = try arena.create(Plan9); self.* = .{ - .path_arena = arena_allocator, + .path_arena = std.heap.ArenaAllocator.init(gpa), .base = .{ .tag = .plan9, - .options = options, - .allocator = gpa, + .comp = comp, + .emit = options.emit, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }, .sixtyfour_bit = sixtyfour_bit, .bases = undefined, @@ -602,7 +612,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; assert(!use_lld); - switch (self.base.options.effectiveOutputMode()) { + switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) { .Exe => {}, // plan9 object files are totally different .Obj => return error.TODOImplementPlan9Objs, diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 414ebcf98787..d8f78c32f197 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -67,6 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV { .force_undefined_symbols = options.force_undefined_symbols, .function_sections = options.function_sections, .data_sections = options.data_sections, + .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, }, .object = codegen.Object.init(gpa), }; @@ -102,7 +103,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV { errdefer spirv.base.destroy(); // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.?.directory.handle.createFile(options.emit.sub_path, .{ + const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{ .truncate = true, .read = true, }); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 0a728c7b6b08..74d83e6c3caa 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -37,6 +37,13 @@ pub const Relocation = types.Relocation; pub const base_tag: link.File.Tag = .wasm; base: link.File, +import_symbols: bool, +export_symbol_names: []const []const u8, +rdynamic: bool, +global_base: ?u64, +initial_memory: ?u64, +max_memory: ?u64, +wasi_emulated_libs: []const wasi_libc.CRTFile, /// Output name of the file name: []const u8, /// 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 { pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { if (build_options.only_c) unreachable; - const gpa = options.comp.gpa; - const target = options.comp.root_mod.resolved_target.result; + const comp = options.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .wasm); - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; - const output_mode = options.comp.config.output_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; + const output_mode = comp.config.output_mode; + const shared_memory = comp.config.shared_memory; const wasm = try createEmpty(arena, options); errdefer wasm.base.destroy(); @@ -395,7 +404,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { }; // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + const file = try options.emit.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = if (fs.has_executable_bit) @@ -480,7 +489,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { } // shared-memory symbols for TLS support - if (wasm.base.options.shared_memory) { + if (shared_memory) { { const loc = try wasm.createSyntheticSymbol("__tls_base", .global); const symbol = loc.getSymbol(wasm); @@ -522,14 +531,15 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { - const use_llvm = options.comp.config.use_llvm; - const output_mode = options.comp.config.output_mode; + const comp = options.comp; + const use_llvm = comp.config.use_llvm; + const output_mode = comp.config.output_mode; const wasm = try arena.create(Wasm); wasm.* = .{ .base = .{ .tag = .wasm, - .comp = options.comp, + .comp = comp, .emit = options.emit, .gc_sections = options.gc_sections orelse (output_mode != .Obj), .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 { .name = undefined, .import_table = options.import_table, .export_table = options.export_table, + .import_symbols = options.import_symbols, + .export_symbol_names = options.export_symbol_names, + .rdynamic = options.rdynamic, + .global_base = options.global_base, + .initial_memory = options.initial_memory, + .max_memory = options.max_memory, + .wasi_emulated_libs = options.wasi_emulated_libs, }; if (use_llvm) { @@ -909,7 +926,10 @@ fn writeI32Const(writer: anytype, val: u32) !void { } fn setupInitMemoryFunction(wasm: *Wasm) !void { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; + const import_memory = comp.config.import_memory; // Passive segments are used to avoid memory being reinitialized on each // thread's instantiation. These passive segments are initialized and @@ -920,7 +940,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { return; } - const flag_address: u32 = if (wasm.base.options.shared_memory) address: { + const flag_address: u32 = if (shared_memory) address: { // when we have passive initialization segments and shared memory // `setupMemory` will create this symbol and set its virtual address. const loc = wasm.findGlobalSymbol("__wasm_init_memory_flag").?; @@ -934,7 +954,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { // we have 0 locals try leb.writeULEB128(writer, @as(u32, 0)); - if (wasm.base.options.shared_memory) { + if (shared_memory) { // destination blocks // based on values we jump to corresponding label try writer.writeByte(std.wasm.opcode(.block)); // $drop @@ -968,14 +988,14 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { var segment_index: u32 = 0; while (it.next()) |entry| : (segment_index += 1) { const segment: Segment = wasm.segments.items[entry.value_ptr.*]; - if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) { + if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) { // For passive BSS segments we can simple issue a memory.fill(0). // For non-BSS segments we do a memory.init. Both these // instructions take as their first argument the destination // address. try writeI32Const(writer, segment.offset); - if (wasm.base.options.shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) { + if (shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) { // When we initialize the TLS segment we also set the `__tls_base` // global. This allows the runtime to use this static copy of the // TLS data for the first/main thread. @@ -1000,7 +1020,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { } } - if (wasm.base.options.shared_memory) { + if (shared_memory) { // we set the init memory flag to value '2' try writeI32Const(writer, flag_address); try writeI32Const(writer, 2); @@ -1043,12 +1063,12 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { while (it.next()) |entry| : (segment_index += 1) { const name = entry.key_ptr.*; const segment: Segment = wasm.segments.items[entry.value_ptr.*]; - if (segment.needsPassiveInitialization(wasm.base.options.import_memory, name) and + if (segment.needsPassiveInitialization(import_memory, name) and !std.mem.eql(u8, name, ".bss")) { // The TLS region should not be dropped since its is needed // during the initialization of each thread (__wasm_init_tls). - if (wasm.base.options.shared_memory and std.mem.eql(u8, name, ".tdata")) { + if (shared_memory and std.mem.eql(u8, name, ".tdata")) { continue; } @@ -1071,11 +1091,13 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void { /// Constructs a synthetic function that performs runtime relocations for /// TLS symbols. This function is called by `__wasm_init_tls`. fn setupTLSRelocationsFunction(wasm: *Wasm) !void { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; // When we have TLS GOT entries and shared memory is enabled, // we must perform runtime relocations or else we don't create the function. - if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) { + if (!shared_memory or !wasm.requiresTLSReloc()) { return; } @@ -1119,7 +1141,9 @@ fn validateFeatures( to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool, emit_features_count: *u32, ) !void { - const target = wasm.base.comp.root_mod.resolved_target.result; + const comp = wasm.base.comp; + const target = comp.root_mod.resolved_target.result; + const shared_memory = comp.config.shared_memory; const cpu_features = target.cpu.features; const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects. const known_features_count = @typeInfo(types.Feature.Tag).Enum.fields.len; @@ -1190,7 +1214,7 @@ fn validateFeatures( return error.InvalidFeatureSet; } - if (wasm.base.options.shared_memory) { + if (shared_memory) { const disallowed_feature = disallowed[@intFromEnum(types.Feature.Tag.shared_mem)]; if (@as(u1, @truncate(disallowed_feature)) != 0) { log.err( @@ -1255,7 +1279,9 @@ fn validateFeatures( /// if one or multiple undefined references exist. When none exist, the symbol will /// not be created, ensuring we don't unneccesarily emit unreferenced symbols. fn resolveLazySymbols(wasm: *Wasm) !void { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; if (wasm.string_table.getOffset("__heap_base")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { @@ -1273,7 +1299,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void { } } - if (!wasm.base.options.shared_memory) { + if (!shared_memory) { if (wasm.string_table.getOffset("__tls_base")) |name_offset| { if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global); @@ -1306,8 +1332,9 @@ pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc { } fn checkUndefinedSymbols(wasm: *const Wasm) !void { - if (wasm.base.comp.config.output_mode == .Obj) return; - if (wasm.base.options.import_symbols) return; + const comp = wasm.base.comp; + if (comp.config.output_mode == .Obj) return; + if (wasm.import_symbols) return; var found_undefined_symbols = false; for (wasm.undefs.values()) |undef| { @@ -2182,7 +2209,10 @@ const Kind = union(enum) { /// Parses an Atom and inserts its metadata into the corresponding sections. fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; + const import_memory = comp.config.import_memory; const atom = wasm.getAtomPtr(atom_index); const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); const do_garbage_collect = wasm.base.gc_sections; @@ -2233,7 +2263,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { // we set the entire region of it to zeroes. // We do not have to do this when exporting the memory (the default) because the runtime // will do it for us, and we do not emit the bss segment at all. - if ((wasm.base.comp.config.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) { + if ((wasm.base.comp.config.output_mode == .Obj or import_memory) and kind.data == .uninitialized) { @memset(atom.code.items, 0); } @@ -2250,7 +2280,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { } else { const index: u32 = @intCast(wasm.segments.items.len); var flags: u32 = 0; - if (wasm.base.options.shared_memory) { + if (shared_memory) { flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); } try wasm.segments.append(gpa, .{ @@ -2679,9 +2709,11 @@ fn setupStartSection(wasm: *Wasm) !void { } fn initializeTLSFunction(wasm: *Wasm) !void { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; - if (!wasm.base.options.shared_memory) return; + if (!shared_memory) return; var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); @@ -2940,7 +2972,7 @@ fn setupExports(wasm: *Wasm) !void { if (wasm.base.comp.config.output_mode == .Obj) return; log.debug("Building exports from symbols", .{}); - const force_exp_names = wasm.base.options.export_symbol_names; + const force_exp_names = wasm.export_symbol_names; if (force_exp_names.len > 0) { var failed_exports = false; @@ -2962,7 +2994,7 @@ fn setupExports(wasm: *Wasm) !void { for (wasm.resolved_symbols.keys()) |sym_loc| { const symbol = sym_loc.getSymbol(wasm); - if (!symbol.isExported(wasm.base.options.rdynamic)) continue; + if (!symbol.isExported(wasm.rdynamic)) continue; const sym_name = sym_loc.getName(wasm); const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: { @@ -2997,8 +3029,9 @@ fn setupExports(wasm: *Wasm) !void { } fn setupStart(wasm: *Wasm) !void { + const comp = wasm.base.comp; // do not export entry point if user set none or no default was set. - const entry_name = wasm.base.options.entry orelse return; + const entry_name = comp.config.entry orelse return; const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); @@ -3012,13 +3045,15 @@ fn setupStart(wasm: *Wasm) !void { } // Ensure the symbol is exported so host environment can access it - if (wasm.base.comp.config.output_mode != .Obj) { + if (comp.config.output_mode != .Obj) { symbol.setFlag(.WASM_SYM_EXPORTED); } } /// Sets up the memory section of the wasm module, as well as the stack. fn setupMemory(wasm: *Wasm) !void { + const comp = wasm.base.comp; + const shared_memory = comp.config.shared_memory; log.debug("Setting up memory layout", .{}); const page_size = std.wasm.page_size; // 64kb const stack_alignment: Alignment = .@"16"; // wasm's stack alignment as specified by tool-convention @@ -3027,12 +3062,12 @@ fn setupMemory(wasm: *Wasm) !void { // Always place the stack at the start by default // unless the user specified the global-base flag var place_stack_first = true; - var memory_ptr: u64 = if (wasm.base.options.global_base) |base| blk: { + var memory_ptr: u64 = if (wasm.global_base) |base| blk: { place_stack_first = false; break :blk base; } else 0; - const is_obj = wasm.base.comp.config.output_mode == .Obj; + const is_obj = comp.config.output_mode == .Obj; if (place_stack_first and !is_obj) { memory_ptr = stack_alignment.forward(memory_ptr); @@ -3059,7 +3094,7 @@ fn setupMemory(wasm: *Wasm) !void { } if (wasm.findGlobalSymbol("__tls_base")) |loc| { const sym = loc.getSymbol(wasm); - wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (wasm.base.options.shared_memory) + wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (shared_memory) @as(i32, 0) else @as(i32, @intCast(memory_ptr)); @@ -3072,7 +3107,7 @@ fn setupMemory(wasm: *Wasm) !void { } // create the memory init flag which is used by the init memory function - if (wasm.base.options.shared_memory and wasm.hasPassiveInitializationSegments()) { + if (shared_memory and wasm.hasPassiveInitializationSegments()) { // align to pointer size memory_ptr = mem.alignForward(u64, memory_ptr, 4); const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data); @@ -3098,7 +3133,7 @@ fn setupMemory(wasm: *Wasm) !void { // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1 const max_memory_allowed: u64 = (1 << 32) - 1; - if (wasm.base.options.initial_memory) |initial_memory| { + if (wasm.initial_memory) |initial_memory| { if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) { log.err("Initial memory must be {d}-byte aligned", .{page_size}); return error.MissAlignment; @@ -3124,7 +3159,7 @@ fn setupMemory(wasm: *Wasm) !void { symbol.virtual_address = @as(u32, @intCast(memory_ptr)); } - if (wasm.base.options.max_memory) |max_memory| { + if (wasm.max_memory) |max_memory| { if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) { log.err("Maximum memory must be {d}-byte aligned", .{page_size}); return error.MissAlignment; @@ -3139,7 +3174,7 @@ fn setupMemory(wasm: *Wasm) !void { } wasm.memories.limits.max = @as(u32, @intCast(max_memory / page_size)); wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_HAS_MAX); - if (wasm.base.options.shared_memory) { + if (shared_memory) { wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_IS_SHARED); } log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max}); @@ -3150,20 +3185,22 @@ fn setupMemory(wasm: *Wasm) !void { /// index of the segment within the final data section. When the segment does not yet /// exist, a new one will be initialized and appended. The new index will be returned in that case. pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u32 { - const gpa = wasm.base.comp.gpa; + const comp = wasm.base.comp; + const gpa = comp.gpa; const object: Object = wasm.objects.items[object_index]; const symbol = object.symtable[symbol_index]; const index: u32 = @intCast(wasm.segments.items.len); + const shared_memory = comp.config.shared_memory; switch (symbol.tag) { .data => { const segment_info = object.segment_info[symbol.index]; - const merge_segment = wasm.base.comp.config.output_mode != .Obj; + const merge_segment = comp.config.output_mode != .Obj; const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment)); if (!result.found_existing) { result.value_ptr.* = index; var flags: u32 = 0; - if (wasm.base.options.shared_memory) { + if (shared_memory) { flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); } try wasm.segments.append(gpa, .{ @@ -3445,6 +3482,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l defer tracy.end(); const gpa = wasm.base.comp.gpa; + const shared_memory = comp.config.shared_memory; + const import_memory = comp.config.import_memory; // Used for all temporary memory allocated during flushin var arena_instance = std.heap.ArenaAllocator.init(gpa); @@ -3509,8 +3548,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l man.hash.addOptionalBytes(wasm.base.comp.config.entry); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); - man.hash.add(wasm.base.comp.config.import_memory); - man.hash.add(wasm.base.comp.config.shared_memory); + man.hash.add(import_memory); + man.hash.add(shared_memory); man.hash.add(wasm.import_table); man.hash.add(wasm.export_table); man.hash.addOptional(wasm.initial_memory); @@ -3726,8 +3765,12 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } else if (Value.fromInterned(variable.init).isUndefDeep(mod)) { // for safe build modes, we store the atom in the data segment, // whereas for unsafe build modes we store it in bss. - const is_initialized = wasm.base.options.optimize_mode == .Debug or - wasm.base.options.optimize_mode == .ReleaseSafe; + const decl_namespace = mod.namespacePtr(decl.src_namespace); + const optimize_mode = decl_namespace.file_scope.mod.optimize_mode; + const is_initialized = switch (optimize_mode) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, + }; try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized }); } else { // when the decl is all zeroes, we store the atom in the bss segment, @@ -3788,9 +3831,13 @@ fn writeToFile( feature_count: u32, arena: Allocator, ) !void { - const gpa = wasm.base.comp.gpa; - const use_llvm = wasm.base.comp.config.use_llvm; - const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const use_llvm = comp.config.use_llvm; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const shared_memory = comp.config.shared_memory; + const import_memory = comp.config.import_memory; + const export_memory = comp.config.export_memory; // Size of each section header const header_size = 5 + 1; @@ -3800,7 +3847,7 @@ fn writeToFile( var code_section_index: ?u32 = null; // Index of the data section. Used to tell relocation table where the section lives. var data_section_index: ?u32 = null; - const is_obj = wasm.base.comp.config.output_mode == .Obj or (!use_llvm and use_lld); + const is_obj = comp.config.output_mode == .Obj or (!use_llvm and use_lld); var binary_bytes = std.ArrayList(u8).init(gpa); defer binary_bytes.deinit(); @@ -3840,8 +3887,6 @@ fn writeToFile( } // Import section - const import_memory = wasm.base.options.import_memory or is_obj; - const export_memory = wasm.base.options.export_memory; if (wasm.imports.count() != 0 or import_memory) { const header_offset = try reserveVecSectionHeader(&binary_bytes); @@ -4018,7 +4063,7 @@ fn writeToFile( // When the shared-memory option is enabled, we *must* emit the 'data count' section. const data_segments_count = wasm.data_segments.count() - @intFromBool(wasm.data_segments.contains(".bss") and !import_memory); - if (data_segments_count != 0 and wasm.base.options.shared_memory) { + if (data_segments_count != 0 and shared_memory) { const header_offset = try reserveVecSectionHeader(&binary_bytes); try writeVecSectionHeader( binary_bytes.items, @@ -4160,11 +4205,11 @@ fn writeToFile( if (data_section_index) |data_index| { try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); } - } else if (!wasm.base.options.strip) { + } else if (wasm.base.debug_format != .strip) { try wasm.emitNameSection(&binary_bytes, arena); } - if (!wasm.base.options.strip) { + if (wasm.base.debug_format != .strip) { // The build id must be computed on the main sections only, // so we have to do it now, before the debug sections. switch (wasm.base.build_id) { @@ -4193,7 +4238,7 @@ fn writeToFile( } // if (wasm.dwarf) |*dwarf| { - // const mod = wasm.base.comp.module.?; + // const mod = comp.module.?; // try dwarf.writeDbgAbbrev(); // // for debug info and ranges, the address is always 0, // // as locations are always offsets relative to 'code' section. @@ -4380,6 +4425,8 @@ fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []con } fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void { + const comp = wasm.base.comp; + const import_memory = comp.config.import_memory; const Name = struct { index: u32, name: []const u8, @@ -4418,7 +4465,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem for (wasm.data_segments.keys()) |key| { // bss section is not emitted when this condition holds true, so we also // do not output a name for it. - if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue; + if (!import_memory and std.mem.eql(u8, key, ".bss")) continue; segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key }); data_segment_index += 1; } @@ -4528,6 +4575,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const tracy = trace(@src()); defer tracy.end(); + const shared_memory = comp.config.shared_memory; + const export_memory = comp.config.export_memory; + const import_memory = comp.config.import_memory; + const target = comp.root_mod.resolved_target.result; + const gpa = wasm.base.comp.gpa; var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); @@ -4560,8 +4612,6 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! break :blk null; }; - const target = wasm.base.comp.root_mod.resolved_target.result; - const id_symlink_basename = "lld.id"; var man: Cache.Manifest = undefined; @@ -4577,7 +4627,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! comptime assert(Compilation.link_hash_implementation_version == 10); - for (wasm.base.options.objects) |obj| { + for (comp.objects) |obj| { _ = try man.addFile(obj.path, null); man.hash.add(obj.must_link); } @@ -4589,17 +4639,17 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! man.hash.addOptionalBytes(wasm.base.comp.config.entry); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); - man.hash.add(wasm.base.options.import_memory); - man.hash.add(wasm.base.options.export_memory); + man.hash.add(import_memory); + man.hash.add(export_memory); man.hash.add(wasm.import_table); man.hash.add(wasm.export_table); - man.hash.addOptional(wasm.base.options.initial_memory); - man.hash.addOptional(wasm.base.options.max_memory); - man.hash.add(wasm.base.options.shared_memory); - man.hash.addOptional(wasm.base.options.global_base); - man.hash.add(wasm.base.options.export_symbol_names.len); + man.hash.addOptional(wasm.initial_memory); + man.hash.addOptional(wasm.max_memory); + man.hash.add(shared_memory); + man.hash.addOptional(wasm.global_base); + man.hash.add(wasm.export_symbol_names.len); // strip does not need to go into the linker hash because it is part of the hash namespace - for (wasm.base.options.export_symbol_names) |symbol_name| { + for (wasm.export_symbol_names) |symbol_name| { man.hash.addBytes(symbol_name); } @@ -4637,8 +4687,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. const the_object_path = blk: { - if (wasm.base.options.objects.len != 0) - break :blk wasm.base.options.objects[0].path; + if (comp.objects.len != 0) + break :blk comp.objects[0].path; if (comp.c_object_table.count() != 0) 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) ! try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command }); try argv.append("--error-limit=0"); - if (wasm.base.options.lto) { - switch (wasm.base.options.optimize_mode) { + if (comp.config.lto) { + switch (comp.root_mod.optimize_mode) { .Debug => {}, .ReleaseSmall => try argv.append("-O2"), .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), } } - if (wasm.base.options.import_memory) { + if (import_memory) { try argv.append("--import-memory"); } - if (wasm.base.options.export_memory) { + if (export_memory) { try argv.append("--export-memory"); } @@ -4698,25 +4748,25 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--no-gc-sections"); } - if (wasm.base.options.strip) { + if (wasm.base.debug_format == .strip) { try argv.append("-s"); } - if (wasm.base.options.initial_memory) |initial_memory| { + if (wasm.initial_memory) |initial_memory| { const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory}); try argv.append(arg); } - if (wasm.base.options.max_memory) |max_memory| { + if (wasm.max_memory) |max_memory| { const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory}); try argv.append(arg); } - if (wasm.base.options.shared_memory) { + if (shared_memory) { try argv.append("--shared-memory"); } - if (wasm.base.options.global_base) |global_base| { + if (wasm.global_base) |global_base| { const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base}); try argv.append(arg); } else { @@ -4728,16 +4778,16 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } // Users are allowed to specify which symbols they want to export to the wasm host. - for (wasm.base.options.export_symbol_names) |symbol_name| { + for (wasm.export_symbol_names) |symbol_name| { const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); try argv.append(arg); } - if (wasm.base.options.rdynamic) { + if (wasm.rdynamic) { try argv.append("--export-dynamic"); } - if (wasm.base.options.entry) |entry| { + if (comp.config.entry) |entry| { try argv.append("--entry"); try argv.append(entry); } else { @@ -4749,14 +4799,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}), }); - if (wasm.base.options.import_symbols) { + if (wasm.import_symbols) { try argv.append("--allow-undefined"); } if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) { try argv.append("--shared"); } - if (wasm.base.options.pie) { + if (comp.config.pie) { try argv.append("--pie"); } @@ -4782,15 +4832,15 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! )); } - if (wasm.base.options.link_libc) { + if (comp.config.link_libc) { try argv.append(try comp.get_libc_crt_file( arena, - wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model), + wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model), )); try argv.append(try comp.get_libc_crt_file(arena, "libc.a")); } - if (wasm.base.options.link_libcpp) { + if (comp.config.link_libcpp) { try argv.append(comp.libcxx_static_lib.?.full_object_path); try argv.append(comp.libcxxabi_static_lib.?.full_object_path); } @@ -4799,7 +4849,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // Positional arguments to the linker such as object files. var whole_archive = false; - for (wasm.base.options.objects) |obj| { + for (comp.objects) |obj| { if (obj.must_link and !whole_archive) { try argv.append("-whole-archive"); whole_archive = true; @@ -4822,8 +4872,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } if (wasm.base.comp.config.output_mode != .Obj and - !wasm.base.options.skip_linker_dependencies and - !wasm.base.options.link_libc) + !comp.skip_linker_dependencies and + !comp.config.link_libc) { try argv.append(comp.libc_static_lib.?.full_object_path); } @@ -5168,10 +5218,13 @@ fn emitDataRelocations( } fn hasPassiveInitializationSegments(wasm: *const Wasm) bool { + const comp = wasm.base.comp; + const import_memory = comp.config.import_memory; + var it = wasm.data_segments.iterator(); while (it.next()) |entry| { const segment: Segment = wasm.segments.items[entry.value_ptr.*]; - if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) { + if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) { return true; } } @@ -5227,14 +5280,14 @@ fn markReferences(wasm: *Wasm) !void { for (wasm.resolved_symbols.keys()) |sym_loc| { const sym = sym_loc.getSymbol(wasm); - if (sym.isExported(wasm.base.options.rdynamic) or sym.isNoStrip() or !do_garbage_collect) { + if (sym.isExported(wasm.rdynamic) or sym.isNoStrip() or !do_garbage_collect) { try wasm.mark(sym_loc); continue; } // Debug sections may require to be parsed and marked when it contains // relocations to alive symbols. - if (sym.tag == .section and !wasm.base.options.strip) { + if (sym.tag == .section and wasm.base.debug_format != .strip) { const file = sym_loc.file orelse continue; // Incremental debug info is done independently const object = &wasm.objects.items[file]; const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm); From 41a8f5aec34ad4d6e4f5c4a2a2dc47f10bb1311d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 12:33:37 -0700 Subject: [PATCH 034/133] remove parent_compilation_link_libc --- src/Compilation.zig | 2 +- src/link.zig | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index cedbf5024fb6..1abd124af4f3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1697,7 +1697,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .soname = options.soname, .compatibility_version = options.compatibility_version, .dll_export_fns = dll_export_fns, - .parent_compilation_link_libc = options.parent_compilation_link_libc, .each_lib_rpath = each_lib_rpath, .build_id = build_id, .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, @@ -6191,6 +6190,7 @@ fn buildOutputFromZig( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .unwind_tables = comp.bin_file.options.eh_frame_hdr, .pic = comp.root_mod.pic, + .optimize_mode = comp.compilerRtOptMode(), }, .global = config, .cc_argv = &.{}, diff --git a/src/link.zig b/src/link.zig index 612c05f82b8a..580b2d7daf33 100644 --- a/src/link.zig +++ b/src/link.zig @@ -133,7 +133,6 @@ pub const File = struct { export_symbol_names: []const []const u8, global_base: ?u64, dll_export_fns: bool, - parent_compilation_link_libc: bool, each_lib_rpath: bool, build_id: std.zig.BuildId, disable_lld_caching: bool, From f5ddef1e45fb5e6defcad21e50736c6e0f63c089 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 13:05:57 -0700 Subject: [PATCH 035/133] update references to module (to be renamed to zcu) --- src/Compilation.zig | 64 +++++----- src/arch/aarch64/CodeGen.zig | 136 ++++++++++---------- src/arch/arm/CodeGen.zig | 140 ++++++++++---------- src/arch/riscv64/CodeGen.zig | 44 +++---- src/arch/sparc64/CodeGen.zig | 86 ++++++------- src/arch/wasm/CodeGen.zig | 2 +- src/arch/x86_64/CodeGen.zig | 240 +++++++++++++++++------------------ src/codegen.zig | 16 +-- src/codegen/llvm.zig | 2 +- 9 files changed, 365 insertions(+), 365 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 1abd124af4f3..9d2e80cb5a17 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1915,7 +1915,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } pub fn destroy(self: *Compilation) void { - const optional_module = self.bin_file.options.module; + const optional_module = self.module; self.bin_file.destroy(); if (optional_module) |module| module.deinit(); @@ -2017,7 +2017,7 @@ fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Director // Restore the Module's previous zig_cache_artifact_directory // This is only for cleanup purposes; Module.deinit calls close // on the handle of zig_cache_artifact_directory. - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { const builtin_mod = module.main_mod.deps.get("builtin").?; module.zig_cache_artifact_directory = builtin_mod.root.root_dir; } @@ -2109,7 +2109,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void }; // This updates the output directory for linker outputs. - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { module.zig_cache_artifact_directory = tmp_artifact_directory.?; } @@ -2155,7 +2155,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } } - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { module.compile_log_text.shrinkAndFree(module.gpa, 0); module.generation += 1; @@ -2206,7 +2206,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void try comp.performAllTheWork(main_progress_node); - if (comp.bin_file.options.module) |module| { + 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, @@ -2277,7 +2277,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest(). - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { // We need to set the zig_cache_artifact_directory for -femit-asm, -femit-llvm-ir, // etc to know where to output to. var artifact_dir = try comp.local_cache_directory.handle.openDir(o_sub_path, .{}); @@ -2322,7 +2322,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // to it, and (2) generic instantiations, comptime calls, inline calls will need // to reference the ZIR. if (!comp.keep_source_files_loaded) { - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { for (module.import_table.values()) |file| { file.unloadTree(comp.gpa); file.unloadSource(comp.gpa); @@ -2332,7 +2332,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } fn maybeGenerateAutodocs(comp: *Compilation, prog_node: *std.Progress.Node) !void { - const mod = comp.bin_file.options.module orelse return; + const mod = comp.module orelse return; // TODO: do this in a separate job during performAllTheWork(). The // file copies at the end of generate() can also be extracted to // separate jobs @@ -2360,7 +2360,7 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void { }; comp.link_error_flags = comp.bin_file.errorFlags(); - if (comp.bin_file.options.module) |module| { + if (comp.module) |module| { try link.File.C.flushEmitH(module); } } @@ -2421,7 +2421,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes comptime assert(link_hash_implementation_version == 10); - if (comp.bin_file.options.module) |mod| { + if (comp.module) |mod| { const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path); _ = try man.addFile(main_zig_file, null); try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.main_mod, .{ .files = man }); @@ -2559,7 +2559,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } fn emitOthers(comp: *Compilation) void { - if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or + if (comp.bin_file.options.output_mode != .Obj or comp.module != null or comp.c_object_table.count() == 0) { return; @@ -2727,7 +2727,7 @@ pub fn saveState(comp: *Compilation) !void { const emit = comp.bin_file.options.emit orelse return; - if (comp.bin_file.options.module) |mod| { + if (comp.module) |mod| { const ip = &mod.intern_pool; const header: Header = .{ .intern_pool = .{ @@ -2792,7 +2792,7 @@ pub fn totalErrorCount(self: *Compilation) u32 { } } - if (self.bin_file.options.module) |module| { + if (self.module) |module| { total += module.failed_exports.count(); total += module.failed_embed_files.count(); @@ -2844,7 +2844,7 @@ pub fn totalErrorCount(self: *Compilation) u32 { // Compile log errors only count if there are no other errors. if (total == 0) { - if (self.bin_file.options.module) |module| { + if (self.module) |module| { total += @intFromBool(module.compile_log_decls.count() != 0); } } @@ -2896,7 +2896,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { .msg = try bundle.addString("memory allocation failure"), }); } - if (self.bin_file.options.module) |module| { + if (self.module) |module| { for (module.failed_files.keys(), module.failed_files.values()) |file, error_msg| { if (error_msg) |msg| { try addModuleErrorMsg(module, &bundle, msg.*); @@ -3002,7 +3002,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { } } - if (self.bin_file.options.module) |module| { + if (self.module) |module| { if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { const keys = module.compile_log_decls.keys(); const values = module.compile_log_decls.values(); @@ -3030,7 +3030,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { assert(self.totalErrorCount() == bundle.root_list.items.len); - const compile_log_text = if (self.bin_file.options.module) |m| m.compile_log_text.items else ""; + const compile_log_text = if (self.module) |m| m.compile_log_text.items else ""; return bundle.toOwnedBundle(compile_log_text); } @@ -3314,7 +3314,7 @@ pub fn performAllTheWork( // 1. to avoid race condition of zig processes truncating each other's builtin.zig files // 2. optimization; in the hot path it only incurs a stat() syscall, which happens // in the `astgen_wait_group`. - if (comp.bin_file.options.module) |mod| { + if (comp.module) |mod| { if (mod.job_queued_update_builtin_zig) { mod.job_queued_update_builtin_zig = false; @@ -3356,15 +3356,15 @@ pub fn performAllTheWork( } } - if (comp.bin_file.options.module) |mod| { + if (comp.module) |mod| { try reportMultiModuleErrors(mod); } - if (comp.bin_file.options.module) |mod| { + if (comp.module) |mod| { mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); mod.sema_prog_node.activate(); } - defer if (comp.bin_file.options.module) |mod| { + defer if (comp.module) |mod| { mod.sema_prog_node.end(); mod.sema_prog_node = undefined; }; @@ -3398,7 +3398,7 @@ pub fn performAllTheWork( fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !void { switch (job) { .codegen_decl => |decl_index| { - const module = comp.bin_file.options.module.?; + const module = comp.module.?; const decl = module.declPtr(decl_index); switch (decl.analysis) { @@ -3436,14 +3436,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v const named_frame = tracy.namedFrame("codegen_func"); defer named_frame.end(); - const module = comp.bin_file.options.module.?; + const module = comp.module.?; module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => return, }; }, .emit_h_decl => |decl_index| { - const module = comp.bin_file.options.module.?; + const module = comp.module.?; const decl = module.declPtr(decl_index); switch (decl.analysis) { @@ -3502,7 +3502,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v } }, .analyze_decl => |decl_index| { - const module = comp.bin_file.options.module.?; + const module = comp.module.?; module.ensureDeclAnalyzed(decl_index) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => return, @@ -3520,7 +3520,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v defer named_frame.end(); const gpa = comp.gpa; - const module = comp.bin_file.options.module.?; + const module = comp.module.?; const decl = module.declPtr(decl_index); comp.bin_file.updateDeclLineNumber(module, decl_index) catch |err| { try module.failed_decls.ensureUnusedCapacity(gpa, 1); @@ -3537,7 +3537,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v const named_frame = tracy.namedFrame("analyze_mod"); defer named_frame.end(); - const module = comp.bin_file.options.module.?; + const module = comp.module.?; module.semaPkg(pkg) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => return, @@ -3716,7 +3716,7 @@ fn workerAstGenFile( child_prog_node.activate(); defer child_prog_node.end(); - const mod = comp.bin_file.options.module.?; + const mod = comp.module.?; mod.astGenFile(file) catch |err| switch (err) { error.AnalysisFail => return, else => { @@ -3819,7 +3819,7 @@ fn workerCheckEmbedFile( } fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !void { - const mod = comp.bin_file.options.module.?; + const mod = comp.module.?; const ip = &mod.intern_pool; const sub_file_path = ip.stringToSlice(embed_file.sub_file_path); var file = try embed_file.owner.root.openFile(sub_file_path, .{}); @@ -4142,7 +4142,7 @@ fn reportRetryableAstGenError( file: *Module.File, err: anyerror, ) error{OutOfMemory}!void { - const mod = comp.bin_file.options.module.?; + const mod = comp.module.?; const gpa = mod.gpa; file.status = .retryable_failure; @@ -4181,7 +4181,7 @@ fn reportRetryableEmbedFileError( embed_file: *Module.EmbedFile, err: anyerror, ) error{OutOfMemory}!void { - const mod = comp.bin_file.options.module.?; + const mod = comp.module.?; const gpa = mod.gpa; const src_loc = embed_file.src_loc; const ip = &mod.intern_pool; @@ -4248,7 +4248,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P // Special case when doing build-obj for just one C file. When there are more than one object // 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.bin_file.options.module == null and + 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; const o_basename_noext = if (direct_o) comp.bin_file.options.root_name diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 9ad7b0bbaa07..c70b61c30d2e 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -341,7 +341,7 @@ pub fn generate( @panic("Attempted to compile for architecture that was disabled by build configuration"); } - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); @@ -476,7 +476,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { } fn gen(self: *Self) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const cc = self.fn_type.fnCallingConvention(mod); if (cc != .Naked) { // stp fp, lr, [sp, #-16]! @@ -656,7 +656,7 @@ fn gen(self: *Self) !void { } fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); @@ -1028,7 +1028,7 @@ fn allocMem( /// Use a pointer instruction as the basis for allocating stack memory. fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst).childType(mod); if (!elem_ty.hasRuntimeBits(mod)) { @@ -1048,7 +1048,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { } fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); }; @@ -1139,7 +1139,7 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { } fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = switch (self.ret_mcv) { .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) }, .stack_offset => blk: { @@ -1176,7 +1176,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const operand = ty_op.operand; const operand_mcv = try self.resolveInst(operand); const operand_ty = self.typeOf(operand); @@ -1257,7 +1257,7 @@ fn trunc( operand_ty: Type, dest_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const info_a = operand_ty.intInfo(mod); const info_b = dest_ty.intInfo(mod); @@ -1320,7 +1320,7 @@ fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { fn airNot(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -1415,7 +1415,7 @@ fn minMax( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM min/max on floats", .{}), .Vector => return self.fail("TODO ARM min/max on vectors", .{}), @@ -1905,7 +1905,7 @@ fn addSub( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO binary operations on floats", .{}), .Vector => return self.fail("TODO binary operations on vectors", .{}), @@ -1966,7 +1966,7 @@ fn mul( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO binary operations on vectors", .{}), .Int => { @@ -1998,7 +1998,7 @@ fn divFloat( _ = rhs_ty; _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO div_float", .{}), .Vector => return self.fail("TODO div_float on vectors", .{}), @@ -2014,7 +2014,7 @@ fn divTrunc( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO div on floats", .{}), .Vector => return self.fail("TODO div on vectors", .{}), @@ -2048,7 +2048,7 @@ fn divFloor( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO div on floats", .{}), .Vector => return self.fail("TODO div on vectors", .{}), @@ -2081,7 +2081,7 @@ fn divExact( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO div on floats", .{}), .Vector => return self.fail("TODO div on vectors", .{}), @@ -2117,7 +2117,7 @@ fn rem( ) InnerError!MCValue { _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO rem/mod on floats", .{}), .Vector => return self.fail("TODO rem/mod on vectors", .{}), @@ -2188,7 +2188,7 @@ fn modulo( _ = rhs_ty; _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO mod on floats", .{}), .Vector => return self.fail("TODO mod on vectors", .{}), @@ -2206,7 +2206,7 @@ fn wrappingArithmetic( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO binary operations on vectors", .{}), .Int => { @@ -2241,7 +2241,7 @@ fn bitwise( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO binary operations on vectors", .{}), .Int => { @@ -2276,7 +2276,7 @@ fn shiftExact( ) InnerError!MCValue { _ = rhs_ty; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO binary operations on vectors", .{}), .Int => { @@ -2326,7 +2326,7 @@ fn shiftNormal( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO binary operations on vectors", .{}), .Int => { @@ -2366,7 +2366,7 @@ fn booleanOp( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Bool => { assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema @@ -2393,7 +2393,7 @@ fn ptrArithmetic( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Pointer => { assert(rhs_ty.eql(Type.usize, mod)); @@ -2516,7 +2516,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; @@ -2644,7 +2644,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = result: { const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; @@ -2868,7 +2868,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = result: { const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; @@ -3016,7 +3016,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { } fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const payload_ty = optional_ty.optionalChild(mod); if (!payload_ty.hasRuntimeBits(mod)) return MCValue.none; if (optional_ty.isPtrLikeOptional(mod)) { @@ -3060,7 +3060,7 @@ fn errUnionErr( error_union_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); if (err_ty.errorSetIsEmpty(mod)) { @@ -3140,7 +3140,7 @@ fn errUnionPayload( error_union_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); if (err_ty.errorSetIsEmpty(mod)) { @@ -3252,7 +3252,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; if (self.liveness.isUnused(inst)) { @@ -3297,7 +3297,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { /// T to E!T fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = ty_op.ty.toType(); @@ -3323,7 +3323,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const error_union_ty = ty_op.ty.toType(); const error_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); @@ -3426,7 +3426,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const slice_ty = self.typeOf(bin_op.lhs); const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: { @@ -3450,7 +3450,7 @@ fn ptrElemVal( ptr_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); const elem_size = @as(u32, @intCast(elem_ty.abiSize(mod))); @@ -3492,7 +3492,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { } fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: { @@ -3615,7 +3615,7 @@ fn reuseOperand( } fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); const elem_size = elem_ty.abiSize(mod); @@ -3863,7 +3863,7 @@ fn genInlineMemsetCode( } fn airLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const elem_ty = self.typeOfIndex(inst); const elem_size = elem_ty.abiSize(mod); @@ -3894,7 +3894,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { } fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); const tag: Mir.Inst.Tag = switch (abi_size) { @@ -3917,7 +3917,7 @@ fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type } fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); const tag: Mir.Inst.Tag = switch (abi_size) { @@ -3939,7 +3939,7 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type } fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; log.debug("store: storing {} to {}", .{ value, ptr }); const abi_size = value_ty.abiSize(mod); @@ -4092,7 +4092,7 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { return if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv = try self.resolveInst(operand); const ptr_ty = self.typeOf(operand); const struct_ty = ptr_ty.childType(mod); @@ -4117,7 +4117,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { const operand = extra.struct_operand; const index = extra.field_index; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv = try self.resolveInst(operand); const struct_ty = self.typeOf(operand); const struct_field_ty = struct_ty.structFieldType(index, mod); @@ -4167,7 +4167,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { } fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { @@ -4195,7 +4195,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { while (self.args[arg_index] == .none) arg_index += 1; self.arg_index = arg_index + 1; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty = self.typeOfIndex(inst); const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index; @@ -4250,7 +4250,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier const extra = self.air.extraData(Air.Call, pl_op.payload); const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len])); const ty = self.typeOf(callee); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const fn_ty = switch (ty.zigTypeTag(mod)) { .Fn => ty, @@ -4422,7 +4422,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier } fn airRet(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const ret_ty = self.fn_type.fnReturnType(mod); @@ -4454,7 +4454,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { } fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ptr = try self.resolveInst(un_op); const ptr_ty = self.typeOf(un_op); @@ -4514,7 +4514,7 @@ fn cmp( lhs_ty: Type, op: math.CompareOperator, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const int_ty = switch (lhs_ty.zigTypeTag(mod)) { .Optional => blk: { const payload_ty = lhs_ty.optionalChild(mod); @@ -4622,7 +4622,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const func = mod.funcInfo(ty_fn.func); // TODO emit debug info for function change _ = func; @@ -4830,7 +4830,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { } fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional(mod)) blk: { const payload_ty = operand_ty.optionalChild(mod); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) @@ -4886,7 +4886,7 @@ fn isErr( error_union_bind: ReadArg.Bind, error_union_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const error_type = error_union_ty.errorUnionSet(mod); if (error_type.errorSetIsEmpty(mod)) { @@ -4928,7 +4928,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -4955,7 +4955,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -4982,7 +4982,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { } fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -5009,7 +5009,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -5226,7 +5226,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { } fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const block_data = self.blocks.getPtr(block).?; if (self.typeOf(operand).hasRuntimeBits(mod)) { @@ -5403,7 +5403,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { } fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = @as(u32, @intCast(ty.abiSize(mod))); switch (mcv) { .dead => unreachable, @@ -5573,7 +5573,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro } fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (mcv) { .dead => unreachable, .unreach, .none => return, // Nothing to do. @@ -5735,7 +5735,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void } fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = @as(u32, @intCast(ty.abiSize(mod))); switch (mcv) { .dead => unreachable, @@ -5934,7 +5934,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { } fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const ptr_ty = self.typeOf(ty_op.operand); @@ -6054,7 +6054,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const vector_ty = self.typeOfIndex(inst); const len = vector_ty.vectorLen(mod); const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -6098,7 +6098,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { } fn airTry(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.Try, pl_op.payload); const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); @@ -6135,7 +6135,7 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { } fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; // If the type has no codegen bits, no need to store it. const inst_ty = self.typeOf(inst); @@ -6200,7 +6200,7 @@ const CallMCValues = struct { /// Caller must call `CallMCValues.deinit`. fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(fn_ty).?; const cc = fn_info.cc; @@ -6363,7 +6363,7 @@ fn parseRegName(name: []const u8) ?Register { } fn registerAlias(self: *Self, reg: Register, ty: Type) Register { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); switch (reg.class()) { @@ -6392,11 +6392,11 @@ fn registerAlias(self: *Self, reg: Register, ty: Type) Register { } fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOfIndex(inst, &mod.intern_pool); } diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index ef3ee3871b98..8304e06b4c0b 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -260,7 +260,7 @@ const DbgInfoReloc = struct { } fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void { - const mod = function.bin_file.options.module.?; + const mod = function.bin_file.comp.module.?; switch (function.debug_output) { .dwarf => |dw| { const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) { @@ -289,7 +289,7 @@ const DbgInfoReloc = struct { } fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { - const mod = function.bin_file.options.module.?; + const mod = function.bin_file.comp.module.?; const is_ptr = switch (reloc.tag) { .dbg_var_ptr => true, .dbg_var_val => false, @@ -348,7 +348,7 @@ pub fn generate( @panic("Attempted to compile for architecture that was disabled by build configuration"); } - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); @@ -482,7 +482,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { } fn gen(self: *Self) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const cc = self.fn_type.fnCallingConvention(mod); if (cc != .Naked) { // push {fp, lr} @@ -642,7 +642,7 @@ fn gen(self: *Self) !void { } fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); @@ -1010,7 +1010,7 @@ fn allocMem( /// Use a pointer instruction as the basis for allocating stack memory. fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst).childType(mod); if (!elem_ty.hasRuntimeBits(mod)) { @@ -1031,7 +1031,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { } fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); }; @@ -1118,7 +1118,7 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { } fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = switch (self.ret_mcv) { .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) }, .stack_offset => blk: { @@ -1151,7 +1151,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { } fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); @@ -1217,7 +1217,7 @@ fn trunc( operand_ty: Type, dest_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const info_a = operand_ty.intInfo(mod); const info_b = dest_ty.intInfo(mod); @@ -1281,7 +1281,7 @@ fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { fn airNot(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand }; const operand_ty = self.typeOf(ty_op.operand); @@ -1377,7 +1377,7 @@ fn minMax( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM min/max on floats", .{}), .Vector => return self.fail("TODO ARM min/max on vectors", .{}), @@ -1586,7 +1586,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; @@ -1699,7 +1699,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = result: { const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; @@ -1863,7 +1863,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = result: { const lhs_ty = self.typeOf(extra.lhs); const rhs_ty = self.typeOf(extra.rhs); @@ -2019,7 +2019,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const optional_ty = self.typeOfIndex(inst); @@ -2042,7 +2042,7 @@ fn errUnionErr( error_union_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); if (err_ty.errorSetIsEmpty(mod)) { @@ -2119,7 +2119,7 @@ fn errUnionPayload( error_union_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); if (err_ty.errorSetIsEmpty(mod)) { @@ -2229,7 +2229,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { /// T to E!T fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = ty_op.ty.toType(); @@ -2253,7 +2253,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { /// E to E!T fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = ty_op.ty.toType(); @@ -2370,7 +2370,7 @@ fn ptrElemVal( ptr_ty: Type, maybe_inst: ?Air.Inst.Index, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); const elem_size: u32 = @intCast(elem_ty.abiSize(mod)); @@ -2429,7 +2429,7 @@ fn ptrElemVal( } fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const slice_ty = self.typeOf(bin_op.lhs); const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: { @@ -2472,7 +2472,7 @@ fn arrayElemVal( array_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = array_ty.childType(mod); const mcv = try array_bind.resolveToMcv(self); @@ -2528,7 +2528,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { } fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: { @@ -2662,7 +2662,7 @@ fn reuseOperand( } fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); const elem_size: u32 = @intCast(elem_ty.abiSize(mod)); @@ -2739,7 +2739,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo } fn airLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const elem_ty = self.typeOfIndex(inst); const result: MCValue = result: { @@ -2768,7 +2768,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { } fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_size: u32 = @intCast(value_ty.abiSize(mod)); switch (ptr) { @@ -2888,7 +2888,7 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { return if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv = try self.resolveInst(operand); const ptr_ty = self.typeOf(operand); const struct_ty = ptr_ty.childType(mod); @@ -2912,7 +2912,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; const operand = extra.struct_operand; const index = extra.field_index; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const mcv = try self.resolveInst(operand); const struct_ty = self.typeOf(operand); @@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { } fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { @@ -3396,7 +3396,7 @@ fn addSub( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3452,7 +3452,7 @@ fn mul( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3485,7 +3485,7 @@ fn divFloat( _ = rhs_ty; _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3501,7 +3501,7 @@ fn divTrunc( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3544,7 +3544,7 @@ fn divFloor( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3592,7 +3592,7 @@ fn divExact( _ = rhs_ty; _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3609,7 +3609,7 @@ fn rem( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3678,7 +3678,7 @@ fn modulo( _ = rhs_ty; _ = maybe_inst; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO ARM binary operations on floats", .{}), .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), @@ -3696,7 +3696,7 @@ fn wrappingArithmetic( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), .Int => { @@ -3734,7 +3734,7 @@ fn bitwise( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), .Int => { @@ -3779,7 +3779,7 @@ fn shiftExact( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), .Int => { @@ -3818,7 +3818,7 @@ fn shiftNormal( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), .Int => { @@ -3861,7 +3861,7 @@ fn booleanOp( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Bool => { const lhs_immediate = try lhs_bind.resolveToImmediate(self); @@ -3895,7 +3895,7 @@ fn ptrArithmetic( rhs_ty: Type, maybe_inst: ?Air.Inst.Index, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lhs_ty.zigTypeTag(mod)) { .Pointer => { assert(rhs_ty.eql(Type.usize, mod)); @@ -3932,7 +3932,7 @@ fn ptrArithmetic( } fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); const tag: Mir.Inst.Tag = switch (abi_size) { @@ -3967,7 +3967,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) } fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); const tag: Mir.Inst.Tag = switch (abi_size) { @@ -4174,7 +4174,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { while (self.args[arg_index] == .none) arg_index += 1; self.arg_index = arg_index + 1; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty = self.typeOfIndex(inst); const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index; @@ -4229,7 +4229,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier const extra = self.air.extraData(Air.Call, pl_op.payload); const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); const ty = self.typeOf(callee); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const fn_ty = switch (ty.zigTypeTag(mod)) { .Fn => ty, @@ -4380,7 +4380,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier } fn airRet(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const ret_ty = self.fn_type.fnReturnType(mod); @@ -4412,7 +4412,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { } fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ptr = try self.resolveInst(un_op); const ptr_ty = self.typeOf(un_op); @@ -4473,7 +4473,7 @@ fn cmp( lhs_ty: Type, op: math.CompareOperator, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const int_ty = switch (lhs_ty.zigTypeTag(mod)) { .Optional => blk: { const payload_ty = lhs_ty.optionalChild(mod); @@ -4580,7 +4580,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const func = mod.funcInfo(ty_fn.func); // TODO emit debug info for function change _ = func; @@ -4795,7 +4795,7 @@ fn isNull( operand_bind: ReadArg.Bind, operand_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (operand_ty.isPtrLikeOptional(mod)) { assert(operand_ty.abiSize(mod) == 4); @@ -4829,7 +4829,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -4856,7 +4856,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -4876,7 +4876,7 @@ fn isErr( error_union_bind: ReadArg.Bind, error_union_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const error_type = error_union_ty.errorUnionSet(mod); if (error_type.errorSetIsEmpty(mod)) { @@ -4918,7 +4918,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { } fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -4945,7 +4945,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { } fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand_ptr = try self.resolveInst(un_op); @@ -5160,7 +5160,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { } fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const block_data = self.blocks.getPtr(block).?; if (self.typeOf(operand).hasRuntimeBits(mod)) { @@ -5331,7 +5331,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { } fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); switch (mcv) { .dead => unreachable, @@ -5493,7 +5493,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro } fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (mcv) { .dead => unreachable, .unreach, .none => return, // Nothing to do. @@ -5740,7 +5740,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void } fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); switch (mcv) { .dead => unreachable, @@ -5896,7 +5896,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { } fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const ptr_ty = self.typeOf(ty_op.operand); @@ -6015,7 +6015,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const vector_ty = self.typeOfIndex(inst); const len = vector_ty.vectorLen(mod); const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -6066,7 +6066,7 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { const result: MCValue = result: { const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand }; const error_union_ty = self.typeOf(pl_op.operand); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const error_union_size: u32 = @intCast(error_union_ty.abiSize(mod)); const error_union_align = error_union_ty.abiAlignment(mod); @@ -6097,7 +6097,7 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { } fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; // If the type has no codegen bits, no need to store it. const inst_ty = self.typeOf(inst); @@ -6125,7 +6125,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, @@ -6161,7 +6161,7 @@ const CallMCValues = struct { /// Caller must call `CallMCValues.deinit`. fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(fn_ty).?; const cc = fn_info.cc; @@ -6312,11 +6312,11 @@ fn parseRegName(name: []const u8) ?Register { } fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOfIndex(inst, &mod.intern_pool); } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index c217288e63eb..4de9313a948a 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -229,7 +229,7 @@ pub fn generate( @panic("Attempted to compile for architecture that was disabled by build configuration"); } - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); @@ -350,7 +350,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { } fn gen(self: *Self) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const cc = self.fn_type.fnCallingConvention(mod); if (cc != .Naked) { // TODO Finish function prologue and epilogue for riscv64. @@ -474,7 +474,7 @@ fn gen(self: *Self) !void { } fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); @@ -805,7 +805,7 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignme /// Use a pointer instruction as the basis for allocating stack memory. fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst).childType(mod); const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); @@ -816,7 +816,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { } fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst); const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); @@ -893,7 +893,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); const info_a = operand_ty.intInfo(mod); @@ -1069,7 +1069,7 @@ fn binOp( lhs_ty: Type, rhs_ty: Type, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (tag) { // Arithmetic operations on integers and floats .add, @@ -1332,7 +1332,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const optional_ty = self.typeOfIndex(inst); // Optional with a zero-bit payload type is just a boolean true @@ -1506,7 +1506,7 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind } fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); switch (ptr) { .none => unreachable, @@ -1532,7 +1532,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo } fn airLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const elem_ty = self.typeOfIndex(inst); const result: MCValue = result: { @@ -1633,7 +1633,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { } fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg; const ty = arg.ty.toType(); const owner_decl = mod.funcOwnerDeclIndex(self.func_index); @@ -1710,7 +1710,7 @@ fn airFence(self: *Self) !void { } fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{}); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const fn_ty = self.typeOf(pl_op.operand); @@ -1812,7 +1812,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier } fn ret(self: *Self, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ret_ty = self.fn_type.fnReturnType(mod); try self.setRegOrMem(ret_ty, self.ret_mcv, mcv); // Just add space for an instruction, patch this later @@ -1843,7 +1843,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); const ty = self.typeOf(bin_op.lhs); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; assert(ty.eql(self.typeOf(bin_op.rhs), mod)); if (ty.zigTypeTag(mod) == .ErrorSet) return self.fail("TODO implement cmp for errors", .{}); @@ -1887,7 +1887,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const func = mod.funcInfo(ty_fn.func); // TODO emit debug info for function change _ = func; @@ -2125,7 +2125,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { const block_data = self.blocks.getPtr(block).?; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (self.typeOf(operand).hasRuntimeBits(mod)) { const operand_mcv = try self.resolveInst(operand); const block_mcv = block_data.mcv; @@ -2508,7 +2508,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const vector_ty = self.typeOfIndex(inst); const len = vector_ty.vectorLen(mod); const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -2553,7 +2553,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { } fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; // If the type has no codegen bits, no need to store it. const inst_ty = self.typeOf(inst); @@ -2581,7 +2581,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, @@ -2617,7 +2617,7 @@ const CallMCValues = struct { /// Caller must call `CallMCValues.deinit`. fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(fn_ty).?; const cc = fn_info.cc; @@ -2739,11 +2739,11 @@ fn parseRegName(name: []const u8) ?Register { } fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOfIndex(inst, &mod.intern_pool); } diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 79dd6ec8d8dc..f252563b357f 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -272,7 +272,7 @@ pub fn generate( @panic("Attempted to compile for architecture that was disabled by build configuration"); } - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); @@ -364,7 +364,7 @@ pub fn generate( } fn gen(self: *Self) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const cc = self.fn_type.fnCallingConvention(mod); if (cc != .Naked) { // TODO Finish function prologue and epilogue for sparc64. @@ -492,7 +492,7 @@ fn gen(self: *Self) !void { } fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); @@ -762,7 +762,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs = try self.resolveInst(extra.lhs); const rhs = try self.resolveInst(extra.rhs); @@ -840,7 +840,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const vector_ty = self.typeOfIndex(inst); const len = vector_ty.vectorLen(mod); const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -874,7 +874,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { } fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const ptr_ty = self.typeOf(ty_op.operand); @@ -1011,7 +1011,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { } fn airArg(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const arg_index = self.arg_index; self.arg_index += 1; @@ -1206,7 +1206,7 @@ fn airBreakpoint(self: *Self) !void { } fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you. @@ -1298,7 +1298,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier const extra = self.air.extraData(Air.Call, pl_op.payload); const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end .. extra.end + extra.data.args_len])); const ty = self.typeOf(callee); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const fn_ty = switch (ty.zigTypeTag(mod)) { .Fn => ty, .Pointer => ty.childType(mod), @@ -1430,7 +1430,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -1662,7 +1662,7 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void { fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void { const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const func = mod.funcInfo(ty_fn.func); // TODO emit debug info for function change _ = func; @@ -1758,7 +1758,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); const info_a = operand_ty.intInfo(mod); @@ -1819,7 +1819,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { } fn airLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const elem_ty = self.typeOfIndex(inst); const elem_size = elem_ty.abiSize(mod); @@ -1903,7 +1903,7 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); const rhs_ty = self.typeOf(bin_op.rhs); - assert(lhs_ty.eql(rhs_ty, self.bin_file.options.module.?)); + assert(lhs_ty.eql(rhs_ty, self.bin_file.comp.module.?)); if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); @@ -2045,7 +2045,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { //const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs = try self.resolveInst(extra.lhs); const rhs = try self.resolveInst(extra.rhs); @@ -2109,7 +2109,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { fn airNot(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -2341,7 +2341,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const lhs = try self.resolveInst(extra.lhs); const rhs = try self.resolveInst(extra.rhs); @@ -2446,7 +2446,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { } fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -2571,7 +2571,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { const operand = extra.struct_operand; const index = extra.field_index; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv = try self.resolveInst(operand); const struct_ty = self.typeOf(operand); const struct_field_offset = @as(u32, @intCast(struct_ty.structFieldOffset(index, mod))); @@ -2704,7 +2704,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { } fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = self.typeOf(ty_op.operand); @@ -2718,7 +2718,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { } fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = self.typeOf(ty_op.operand); @@ -2732,7 +2732,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { /// E to E!T fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = ty_op.ty.toType(); @@ -2753,7 +2753,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const optional_ty = self.typeOfIndex(inst); @@ -2793,7 +2793,7 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignme /// Use a pointer instruction as the basis for allocating stack memory. fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst).childType(mod); if (!elem_ty.hasRuntimeBits(mod)) { @@ -2813,7 +2813,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { } fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = self.typeOfIndex(inst); const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); @@ -2860,7 +2860,7 @@ fn binOp( rhs_ty: Type, metadata: ?BinOpMetadata, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (tag) { .add, .sub, @@ -3401,7 +3401,7 @@ fn binOpRegister( fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { const block_data = self.blocks.getPtr(block).?; - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (self.typeOf(operand).hasRuntimeBits(mod)) { const operand_mcv = try self.resolveInst(operand); const block_mcv = block_data.mcv; @@ -3521,7 +3521,7 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { /// Given an error union, returns the payload fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = error_union_ty.errorUnionSet(mod); const payload_ty = error_union_ty.errorUnionPayload(mod); if (err_ty.errorSetIsEmpty(mod)) { @@ -3591,7 +3591,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live } fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg; const ty = arg.ty.toType(); const owner_decl = mod.funcOwnerDeclIndex(self.func_index); @@ -3740,7 +3740,7 @@ fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Reg } fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (mcv) { .dead => unreachable, .unreach, .none => return, // Nothing to do. @@ -3951,7 +3951,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void } fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); switch (mcv) { .dead => unreachable, @@ -4125,7 +4125,7 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re } fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, @@ -4161,7 +4161,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const error_type = ty.errorUnionSet(mod); const payload_type = ty.errorUnionPayload(mod); @@ -4259,7 +4259,7 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void { } fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const elem_ty = ptr_ty.childType(mod); const elem_size = elem_ty.abiSize(mod); @@ -4330,7 +4330,7 @@ fn minMax( lhs_ty: Type, rhs_ty: Type, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; assert(lhs_ty.eql(rhs_ty, mod)); switch (lhs_ty.zigTypeTag(mod)) { .Float => return self.fail("TODO min/max on floats", .{}), @@ -4450,7 +4450,7 @@ fn realStackOffset(off: u32) u32 { /// Caller must call `CallMCValues.deinit`. fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const fn_info = mod.typeToFunc(fn_ty).?; const cc = fn_info.cc; @@ -4542,7 +4542,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) } fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty = self.typeOf(ref); // If the type has no codegen bits, no need to store it. @@ -4559,7 +4559,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { } fn ret(self: *Self, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ret_ty = self.fn_type.fnReturnType(mod); try self.setRegOrMem(ret_ty, self.ret_mcv, mcv); @@ -4661,7 +4661,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void } fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = value_ty.abiSize(mod); switch (ptr) { @@ -4703,7 +4703,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { return if (self.liveness.isUnused(inst)) .dead else result: { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mcv = try self.resolveInst(operand); const ptr_ty = self.typeOf(operand); const struct_ty = ptr_ty.childType(mod); @@ -4745,7 +4745,7 @@ fn trunc( operand_ty: Type, dest_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const info_a = operand_ty.intInfo(mod); const info_b = dest_ty.intInfo(mod); @@ -4866,11 +4866,11 @@ fn wantSafety(self: *Self) bool { } fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOfIndex(inst, &mod.intern_pool); } diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index e0be273c2631..819cc3e9a07e 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1210,7 +1210,7 @@ pub fn generate( debug_output: codegen.DebugInfoOutput, ) codegen.CodeGenError!codegen.Result { _ = src_loc; - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); var code_gen: CodeGen = .{ .gpa = bin_file.allocator, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 0a4c9844dcca..9a4c73c74d93 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -131,7 +131,7 @@ const Owner = union(enum) { fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 { switch (owner) { .func_index => |func_index| { - const mod = ctx.bin_file.options.module.?; + const mod = ctx.bin_file.comp.module.?; const decl_index = mod.funcOwnerDeclIndex(func_index); if (ctx.bin_file.cast(link.File.Elf)) |elf_file| { return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); @@ -799,7 +799,7 @@ pub fn generate( @panic("Attempted to compile for architecture that was disabled by build configuration"); } - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); @@ -1060,7 +1060,7 @@ fn formatDecl( } fn fmtDecl(self: *Self, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) { return .{ .data = .{ - .mod = self.bin_file.options.module.?, + .mod = self.bin_file.comp.module.?, .decl_index = decl_index, } }; } @@ -1077,7 +1077,7 @@ fn formatAir( ) @TypeOf(writer).Error!void { @import("../../print_air.zig").dumpInst( data.inst, - data.self.bin_file.options.module.?, + data.self.bin_file.comp.module.?, data.self.air, data.self.liveness, ); @@ -1683,7 +1683,7 @@ fn asmMemoryRegisterImmediate( } fn gen(self: *Self) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const fn_info = mod.typeToFunc(self.fn_type).?; const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); if (cc != .Naked) { @@ -1885,7 +1885,7 @@ fn gen(self: *Self) InnerError!void { } fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); @@ -2167,7 +2167,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { } fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (lazy_sym.ty.zigTypeTag(mod)) { .Enum => { const enum_ty = lazy_sym.ty; @@ -2418,7 +2418,7 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { /// Use a pointer instruction as the basis for allocating stack memory. fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ptr_ty = self.typeOfIndex(inst); const val_ty = ptr_ty.childType(mod); return self.allocFrameIndex(FrameAlloc.init(.{ @@ -2438,7 +2438,7 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue { } fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = math.cast(u32, ty.abiSize(mod)) orelse { return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); }; @@ -2471,7 +2471,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b } fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return switch (ty.zigTypeTag(mod)) { .Float => switch (ty.floatBits(self.target.*)) { 80 => abi.RegisterClass.x87, @@ -2884,7 +2884,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { } fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const src_ty = self.typeOf(ty_op.operand); @@ -2975,7 +2975,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { } fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dst_ty = self.typeOfIndex(inst); @@ -3102,7 +3102,7 @@ fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { } fn airSlice(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3131,7 +3131,7 @@ fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { } fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs); @@ -3172,7 +3172,7 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void } fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const air_tag = self.air.instructions.items(.tag); const air_data = self.air.instructions.items(.data); @@ -3206,7 +3206,7 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { } fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const result = result: { const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; @@ -3432,7 +3432,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { } fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = self.typeOf(bin_op.lhs); if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( @@ -3515,7 +3515,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { } fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = self.typeOf(bin_op.lhs); if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( @@ -3591,7 +3591,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { } fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = self.typeOf(bin_op.lhs); @@ -3731,7 +3731,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { } fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const result: MCValue = result: { @@ -3792,7 +3792,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { } fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const result: MCValue = result: { @@ -3871,7 +3871,7 @@ fn genSetFrameTruncatedOverflowCompare( src_mcv: MCValue, overflow_cc: ?Condition, ) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const src_lock = switch (src_mcv) { .register => |reg| self.register_manager.lockReg(reg), else => null, @@ -3935,7 +3935,7 @@ fn genSetFrameTruncatedOverflowCompare( } fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const tuple_ty = self.typeOfIndex(inst); @@ -4169,7 +4169,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { /// Clobbers .rax and .rdx registers. /// Quotient is saved in .rax and remainder in .rdx. fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); const bit_size: u32 = @intCast(self.regBitSize(ty)); if (abi_size > 8) { @@ -4219,7 +4219,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue /// Always returns a register. /// Clobbers .rax and .rdx registers. fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); const int_info = ty.intInfo(mod); const dividend = switch (lhs) { @@ -4271,7 +4271,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa } fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const air_tags = self.air.instructions.items(.tag); @@ -4546,7 +4546,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { } fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const pl_ty = self.typeOfIndex(inst); @@ -4592,7 +4592,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result = result: { const dst_ty = self.typeOfIndex(inst); @@ -4626,7 +4626,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const err_union_ty = self.typeOf(ty_op.operand); const err_ty = err_union_ty.errorUnionSet(mod); @@ -4678,7 +4678,7 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { // *(E!T) -> E fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_ty = self.typeOf(ty_op.operand); @@ -4725,7 +4725,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const src_ty = self.typeOf(ty_op.operand); @@ -4785,7 +4785,7 @@ fn genUnwrapErrUnionPayloadMir( err_union_ty: Type, err_union: MCValue, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const payload_ty = err_union_ty.errorUnionPayload(mod); const result: MCValue = result: { @@ -4833,7 +4833,7 @@ fn genUnwrapErrUnionPayloadPtrMir( ptr_ty: Type, ptr_mcv: MCValue, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_union_ty = ptr_ty.childType(mod); const payload_ty = err_union_ty.errorUnionPayload(mod); @@ -4867,7 +4867,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const pl_ty = self.typeOf(ty_op.operand); @@ -4921,7 +4921,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { /// T to E!T fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const eu_ty = ty_op.ty.toType(); @@ -4944,7 +4944,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { /// E to E!T fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const eu_ty = ty_op.ty.toType(); @@ -5003,7 +5003,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { } fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_ty = self.typeOf(ty_op.operand); @@ -5071,7 +5071,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi } fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const slice_ty = self.typeOf(lhs); const slice_mcv = try self.resolveInst(lhs); const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) { @@ -5107,7 +5107,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { } fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const result: MCValue = result: { @@ -5132,7 +5132,7 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const result: MCValue = result: { @@ -5246,7 +5246,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { } fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); @@ -5296,7 +5296,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { } fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -5341,7 +5341,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_union_ty = self.typeOf(bin_op.lhs); const union_ty = ptr_union_ty.childType(mod); @@ -5385,7 +5385,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { } fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const tag_ty = self.typeOfIndex(inst); @@ -5439,7 +5439,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { } fn airClz(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result = result: { const dst_ty = self.typeOfIndex(inst); @@ -5598,7 +5598,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { } fn airCtz(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result = result: { const dst_ty = self.typeOfIndex(inst); @@ -5716,7 +5716,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { } fn airPopCount(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { try self.spillEflagsIfOccupied(); @@ -5779,7 +5779,7 @@ fn genPopCount( src_mcv: MCValue, dst_contains_src: bool, ) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const src_abi_size: u32 = @intCast(src_ty.abiSize(mod)); if (self.hasFeature(.popcnt)) return self.genBinOpMir( @@ -5871,7 +5871,7 @@ fn genByteSwap( src_mcv: MCValue, mem_ok: bool, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; if (src_ty.zigTypeTag(mod) == .Vector) return self.fail( @@ -5962,7 +5962,7 @@ fn genByteSwap( } fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_ty = self.typeOf(ty_op.operand); @@ -5984,7 +5984,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { } fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_ty = self.typeOf(ty_op.operand); @@ -6106,7 +6106,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { } fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; const result = result: { @@ -6282,7 +6282,7 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void { } fn getRoundTag(self: *Self, ty: Type) ?Mir.Inst.FixedTag { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return if (self.hasFeature(.sse4_1)) switch (ty.zigTypeTag(mod)) { .Float => switch (ty.floatBits(self.target.*)) { 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, @@ -6314,7 +6314,7 @@ fn getRoundTag(self: *Self, ty: Type) ?Mir.Inst.FixedTag { } fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (self.getRoundTag(ty)) |_| return .none; if (ty.zigTypeTag(mod) != .Float) @@ -6338,7 +6338,7 @@ fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MC } fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: RoundMode) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const mir_tag = self.getRoundTag(ty) orelse { const result = try self.genRoundLibcall(ty, src_mcv, mode); return self.genSetReg(dst_reg, ty, result); @@ -6380,7 +6380,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro } fn airAbs(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ty = self.typeOf(ty_op.operand); @@ -6520,7 +6520,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { } fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ty = self.typeOf(un_op); const abi_size: u32 = @intCast(ty.abiSize(mod)); @@ -6765,7 +6765,7 @@ fn reuseOperandAdvanced( } fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ptr_info = ptr_ty.ptrInfo(mod); const val_ty = Type.fromInterned(ptr_info.child); @@ -6864,7 +6864,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn } fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const dst_ty = ptr_ty.childType(mod); if (!dst_ty.hasRuntimeBitsIgnoreComptime(mod)) return; switch (ptr_mcv) { @@ -6905,7 +6905,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro } fn airLoad(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const elem_ty = self.typeOfIndex(inst); const result: MCValue = result: { @@ -6962,7 +6962,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { } fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ptr_info = ptr_ty.ptrInfo(mod); const src_ty = Type.fromInterned(ptr_info.child); if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return; @@ -7059,7 +7059,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In } fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const src_ty = ptr_ty.childType(mod); if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return; switch (ptr_mcv) { @@ -7100,7 +7100,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr } fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; result: { @@ -7138,7 +7138,7 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { } fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ptr_field_ty = self.typeOfIndex(inst); const ptr_container_ty = self.typeOf(operand); const ptr_container_ty_info = ptr_container_ty.ptrInfo(mod); @@ -7163,7 +7163,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 } fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; const result: MCValue = result: { @@ -7451,7 +7451,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { } fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; @@ -7470,7 +7470,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { } fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const src_ty = self.typeOf(src_air); if (src_ty.zigTypeTag(mod) == .Vector) return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(mod)}); @@ -7558,7 +7558,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: } fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(dst_ty.abiSize(mod)); if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ mir_tag, dst_ty.fmt(mod) }); switch (dst_mcv) { @@ -7605,7 +7605,7 @@ fn genShiftBinOpMir( lhs_mcv: MCValue, shift_mcv: MCValue, ) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const rhs_mcv: MCValue = rhs: { switch (shift_mcv) { .immediate => |imm| switch (imm) { @@ -7975,7 +7975,7 @@ fn genShiftBinOp( lhs_ty: Type, rhs_ty: Type, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (lhs_ty.zigTypeTag(mod) == .Vector) return self.fail("TODO implement genShiftBinOp for {}", .{ lhs_ty.fmt(mod), }); @@ -8041,7 +8041,7 @@ fn genMulDivBinOp( lhs_mcv: MCValue, rhs_mcv: MCValue, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; if (dst_ty.zigTypeTag(mod) == .Vector or dst_ty.zigTypeTag(mod) == .Float) return self.fail( "TODO implement genMulDivBinOp for {s} from {} to {}", .{ @tagName(tag), src_ty.fmt(mod), dst_ty.fmt(mod) }, @@ -8283,7 +8283,7 @@ fn genBinOp( lhs_air: Air.Inst.Ref, rhs_air: Air.Inst.Ref, ) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const lhs_ty = self.typeOf(lhs_air); const rhs_ty = self.typeOf(rhs_air); const abi_size: u32 = @intCast(lhs_ty.abiSize(mod)); @@ -10015,7 +10015,7 @@ fn genBinOpMir( dst_mcv: MCValue, src_mcv: MCValue, ) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); try self.spillEflagsIfOccupied(); switch (dst_mcv) { @@ -10435,7 +10435,7 @@ fn genBinOpMir( /// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv. /// Does not support byte-size operands. fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(dst_ty.abiSize(mod)); try self.spillEflagsIfOccupied(); switch (dst_mcv) { @@ -10560,7 +10560,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M } fn airArg(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; // skip zero-bit arguments as they don't have a corresponding arg instruction var arg_index = self.arg_index; while (self.args[arg_index] == .none) arg_index += 1; @@ -10593,7 +10593,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { } fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (self.debug_output) { .dwarf => |dw| { const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) { @@ -10629,7 +10629,7 @@ fn genVarDbgInfo( mcv: MCValue, name: [:0]const u8, ) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const is_ptr = switch (tag) { .dbg_var_ptr => true, .dbg_var_val => false, @@ -10748,7 +10748,7 @@ fn genCall(self: *Self, info: union(enum) { callee: []const u8, }, }, arg_types: []const Type, args: []const MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const fn_ty = switch (info) { .air => |callee| fn_info: { @@ -10969,7 +10969,7 @@ fn genCall(self: *Self, info: union(enum) { } fn airRet(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ret_ty = self.fn_type.fnReturnType(mod); @@ -11018,7 +11018,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { } fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ty = self.typeOf(bin_op.lhs); @@ -11412,7 +11412,7 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { } fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); @@ -11551,7 +11551,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { } fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); switch (mcv) { .eflags => |cc| { @@ -11624,7 +11624,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { } fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (opt_mcv) { .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() }, else => {}, @@ -11732,7 +11732,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC } fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const opt_ty = ptr_ty.childType(mod); const pl_ty = opt_ty.optionalChild(mod); @@ -11768,7 +11768,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) } fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const err_ty = eu_ty.errorUnionSet(mod); if (err_ty.errorSetIsEmpty(mod)) return MCValue{ .immediate = 0 }; // always false @@ -11815,7 +11815,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) } fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const eu_ty = ptr_ty.childType(mod); const err_ty = eu_ty.errorUnionSet(mod); if (err_ty.errorSetIsEmpty(mod)) return MCValue{ .immediate = 0 }; // always false @@ -12097,7 +12097,7 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { } fn airBr(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; const block_ty = self.typeOfIndex(br.block_inst); @@ -12158,7 +12158,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { } fn airAsm(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Asm, ty_pl.payload); const clobbers_len: u31 = @truncate(extra.data.flags); @@ -12865,7 +12865,7 @@ const MoveStrategy = union(enum) { } }; fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; switch (class) { .general_purpose, .segment => return .{ .move = .{ ._, .mov } }, .x87 => return .x87_load_store, @@ -13164,7 +13164,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo } fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; defer if (src_lock) |lock| self.register_manager.unlockReg(lock); @@ -13262,7 +13262,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError } fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); if (ty.bitSize(mod) > dst_reg.bitSize()) return self.fail("genSetReg called with a value larger than dst_reg", .{}); @@ -13561,7 +13561,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr } fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size: u32 = @intCast(ty.abiSize(mod)); const dst_ptr_mcv: MCValue = switch (base) { .none => .{ .immediate = @bitCast(@as(i64, disp)) }, @@ -13922,7 +13922,7 @@ fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { } fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dst_ty = self.typeOfIndex(inst); const src_ty = self.typeOf(ty_op.operand); @@ -13980,7 +13980,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { } fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const slice_ty = self.typeOfIndex(inst); @@ -14003,7 +14003,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { } fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dst_ty = self.typeOfIndex(inst); @@ -14082,7 +14082,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { } fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dst_ty = self.typeOfIndex(inst); @@ -14153,7 +14153,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { } fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; @@ -14249,7 +14249,7 @@ fn atomicOp( rmw_op: ?std.builtin.AtomicRmwOp, order: std.builtin.AtomicOrder, ) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ptr_lock = switch (ptr_mcv) { .register => |reg| self.register_manager.lockReg(reg), else => null, @@ -14653,7 +14653,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr } fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; result: { @@ -14781,7 +14781,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { } fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); @@ -14836,7 +14836,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { } fn airTagName(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const inst_ty = self.typeOfIndex(inst); const enum_ty = self.typeOf(un_op); @@ -14878,7 +14878,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { } fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const err_ty = self.typeOf(un_op); @@ -14980,7 +14980,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { } fn airSplat(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const vector_ty = self.typeOfIndex(inst); const vector_len = vector_ty.vectorLen(mod); @@ -15332,7 +15332,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { } fn airReduce(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; const result: MCValue = result: { @@ -15389,7 +15389,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const result_ty = self.typeOfIndex(inst); const len: usize = @intCast(result_ty.arrayLen(mod)); const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -15562,7 +15562,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { } fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; @@ -15613,7 +15613,7 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { } fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; const ty = self.typeOfIndex(inst); @@ -15780,7 +15780,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { } fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const va_list_ty = self.air.instructions.items(.data)[@intFromEnum(inst)].ty; const ptr_anyopaque_ty = try mod.singleMutPtrType(Type.anyopaque); @@ -15833,7 +15833,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { } fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ty = self.typeOfIndex(inst); const promote_ty = self.promoteVarArg(ty); @@ -16042,7 +16042,7 @@ fn airVaEnd(self: *Self, inst: Air.Inst.Index) !void { } fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ty = self.typeOf(ref); // If the type has no codegen bits, no need to store it. @@ -16116,7 +16116,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV } fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl(mod))) { .mcv => |mcv| switch (mcv) { .none => .none, @@ -16156,7 +16156,7 @@ fn resolveCallingConventionValues( var_args: []const Type, stack_frame_base: FrameIndex, ) !CallMCValues { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const ip = &mod.intern_pool; const cc = fn_info.cc; const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len); @@ -16468,7 +16468,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { } fn memSize(self: *Self, ty: Type) Memory.Size { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return switch (ty.zigTypeTag(mod)) { .Float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)), else => Memory.Size.fromSize(@intCast(ty.abiSize(mod))), @@ -16476,7 +16476,7 @@ fn memSize(self: *Self, ty: Type) Memory.Size { } fn splitType(self: *Self, ty: Type) ![2]Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none); var parts: [2]Type = undefined; if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| { @@ -16505,7 +16505,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { /// Truncates the value in the register in place. /// Clobbers any remaining bits. fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ .signedness = .unsigned, .bits = @intCast(ty.bitSize(mod)), @@ -16550,7 +16550,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { } fn regBitSize(self: *Self, ty: Type) u64 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const abi_size = ty.abiSize(mod); return switch (ty.zigTypeTag(mod)) { else => switch (abi_size) { @@ -16569,7 +16569,7 @@ fn regBitSize(self: *Self, ty: Type) u64 { } fn regExtraBits(self: *Self, ty: Type) u64 { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.regBitSize(ty) - ty.bitSize(mod); } @@ -16584,12 +16584,12 @@ fn hasAllFeatures(self: *Self, features: anytype) bool { } fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; return self.air.typeOfIndex(inst, &mod.intern_pool); } @@ -16641,7 +16641,7 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 { } fn promoteInt(self: *Self, ty: Type) Type { - const mod = self.bin_file.options.module.?; + const mod = self.bin_file.comp.module.?; const int_info: InternPool.Key.IntType = switch (ty.toIntern()) { .bool_type => .{ .signedness = .unsigned, .bits = 1 }, else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty, diff --git a/src/codegen.zig b/src/codegen.zig index 5efde3985cbe..54bdf295b32b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -110,7 +110,7 @@ pub fn generateLazySymbol( const target = bin_file.options.target; const endian = target.cpu.arch.endian(); - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; log.debug("generateLazySymbol: kind = {s}, ty = {}", .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod), @@ -165,7 +165,7 @@ pub fn generateSymbol( const tracy = trace(@src()); defer tracy.end(); - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const ip = &mod.intern_pool; const typed_value = arg_tv; @@ -662,7 +662,7 @@ fn lowerParentPtr( debug_output: DebugInfoOutput, reloc_info: RelocInfo, ) CodeGenError!Result { - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr; assert(ptr.len == .none); return switch (ptr.addr) { @@ -766,7 +766,7 @@ fn lowerAnonDeclRef( ) CodeGenError!Result { _ = debug_output; const target = bin_file.options.target; - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); const decl_val = anon_decl.val; @@ -812,7 +812,7 @@ fn lowerDeclRef( _ = src_loc; _ = debug_output; const target = bin_file.options.target; - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const ptr_width = target.ptrBitWidth(); const decl = mod.declPtr(decl_index); @@ -902,7 +902,7 @@ fn genDeclRef( tv: TypedValue, ptr_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); const target = bin_file.options.target; @@ -1010,7 +1010,7 @@ fn genUnnamedConst( tv: TypedValue, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); const target = bin_file.options.target; @@ -1038,7 +1038,7 @@ pub fn genTypedValue( arg_tv: TypedValue, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.options.module.?; + const mod = bin_file.comp.module.?; const typed_value = arg_tv; log.debug("genTypedValue: ty = {}, val = {}", .{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 522da0f8c956..40fffcfd5fa2 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1227,7 +1227,7 @@ pub const Object = struct { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const mod = comp.bin_file.options.module.?; + const mod = comp.module.?; const cache_dir = mod.zig_cache_artifact_directory; if (std.debug.runtime_safety and !try self.builder.verify()) { From 1642c003b4bab4a53b6094b42d10f6934896801e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 13:31:07 -0700 Subject: [PATCH 036/133] update libunwind references to bin_file.options --- src/Compilation.zig | 2 +- src/libunwind.zig | 74 ++++++++++++++++++++++++++++----------------- src/main.zig | 32 +++++++++----------- 3 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 9d2e80cb5a17..a772e896804f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6212,9 +6212,9 @@ fn buildOutputFromZig( .local_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, .resolved = config, + .root_mod = root_mod, .cache_mode = .whole, .root_name = root_name, - .root_mod = root_mod, .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, diff --git a/src/libunwind.zig b/src/libunwind.zig index 876bd7a31fd8..9215e24f7cd2 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -4,6 +4,7 @@ const assert = std.debug.assert; const target_util = @import("target.zig"); const Compilation = @import("Compilation.zig"); +const Module = @import("Package/Module.zig"); const build_options = @import("build_options"); const trace = @import("tracy.zig").trace; @@ -19,10 +20,44 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const root_name = "unwind"; const output_mode = .Lib; + const config = try Compilation.Config.resolve(.{ + .output_mode = .Lib, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = comp.compilerRtOptMode(), + .link_libc = true, + // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 + .lto = false, + }); + const root_mod = 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, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .sanitize_c = false, + .sanitize_thread = false, + .unwind_tables = false, + .pic = comp.root_mod.pic, + .optimize_mode = comp.compilerRtOptMode(), + }, + .global = config, + .cc_argv = &.{}, + }); + + const root_name = "unwind"; const link_mode = .Static; - const target = comp.getTarget(); + const target = comp.root_mod.resolved_target.result; const basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, @@ -64,7 +99,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { // defines will be correct. try cflags.append("-D_LIBUNWIND_IS_NATIVE_ONLY"); - if (comp.bin_file.options.optimize_mode == .Debug) { + if (comp.root_mod.optimize_mode == .Debug) { try cflags.append("-D_DEBUG"); } if (!comp.config.any_non_single_threaded) { @@ -83,46 +118,29 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { }; } const sub_compilation = try Compilation.create(comp.gpa, .{ + .self_exe_path = comp.self_exe_path, .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .resolved = config, + .root_mod = root_mod, .cache_mode = .whole, - .target = target, .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 = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), .link_mode = link_mode, - .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, - // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 - .want_lto = false, - .function_sections = comp.bin_file.options.function_sections, - .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, + .function_sections = comp.bin_file.function_sections, .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_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_cimport = comp.verbose_cimport, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, - .link_libc = true, .skip_linker_dependencies = true, }); defer sub_compilation.destroy(); @@ -132,8 +150,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { assert(comp.libunwind_static_lib == null); comp.libunwind_static_lib = 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(), }; diff --git a/src/main.zig b/src/main.zig index 499d0f57f9cd..5f65908b5c85 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3552,7 +3552,7 @@ fn buildOutputType( if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: { // Default to using `zig run` to execute the produced .c code from `zig test`. const c_code_loc = emit_bin_loc orelse break :default_exec_args; - const c_code_directory = c_code_loc.directory orelse comp.bin_file.options.emit.?.directory; + const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.directory; const c_code_path = try fs.path.join(arena, &[_][]const u8{ c_code_directory.path orelse ".", c_code_loc.basename, }); @@ -3921,7 +3921,7 @@ fn serve( continue; } - if (comp.bin_file.options.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { try comp.makeBinFileWritable(); } @@ -3971,7 +3971,7 @@ fn serve( try comp.hotCodeSwap(main_progress_node, pid); try serveUpdateResults(&server, comp); } else { - if (comp.bin_file.options.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { try comp.makeBinFileWritable(); } try comp.update(main_progress_node); @@ -4067,13 +4067,14 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { // system depends on that fact. So, until the protocol is changed to // reflect this, this logic only needs to ensure that emit_bin_path is // emitted for at least one thing, if there are any artifacts. - if (comp.bin_file.options.emit) |emit| { + if (comp.bin_file) |lf| { + const emit = lf.emit; const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); defer gpa.free(full_path); try s.serveEmitBinPath(full_path, .{ .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, }); - } else if (comp.bin_file.options.docs_emit) |emit| { + } else if (comp.docs_emit) |emit| { const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); defer gpa.free(full_path); try s.serveEmitBinPath(full_path, .{ @@ -4148,11 +4149,11 @@ fn runOrTest( runtime_args_start: ?usize, link_libc: bool, ) !void { - const exe_emit = comp.bin_file.options.emit orelse return; + const lf = comp.bin_file orelse return; // A naive `directory.join` here will indeed get the correct path to the binary, // however, in the case of cwd, we actually want `./foo` so that the path can be executed. const exe_path = try fs.path.join(arena, &[_][]const u8{ - exe_emit.directory.path orelse ".", exe_emit.sub_path, + lf.emit.directory.path orelse ".", lf.emit.sub_path, }); var argv = std.ArrayList([]const u8).init(gpa); @@ -4244,7 +4245,7 @@ fn runOrTestHotSwap( all_args: []const []const u8, runtime_args_start: ?usize, ) !std.ChildProcess.Id { - const exe_emit = comp.bin_file.options.emit.?; + const lf = comp.bin_file.?; const exe_path = switch (builtin.target.os.tag) { // On Windows it seems impossible to perform an atomic rename of a file that is currently @@ -4252,16 +4253,16 @@ fn runOrTestHotSwap( // tmp zig-cache and use it to spawn the child process. This way we are free to update // the binary with each requested hot update. .windows => blk: { - try exe_emit.directory.handle.copyFile(exe_emit.sub_path, comp.local_cache_directory.handle, exe_emit.sub_path, .{}); + try lf.emit.directory.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{}); break :blk try fs.path.join(gpa, &[_][]const u8{ - comp.local_cache_directory.path orelse ".", exe_emit.sub_path, + comp.local_cache_directory.path orelse ".", lf.emit.sub_path, }); }, // A naive `directory.join` here will indeed get the correct path to the binary, // however, in the case of cwd, we actually want `./foo` so that the path can be executed. else => try fs.path.join(gpa, &[_][]const u8{ - exe_emit.directory.path orelse ".", exe_emit.sub_path, + lf.emit.directory.path orelse ".", lf.emit.sub_path, }), }; defer gpa.free(exe_path); @@ -4367,7 +4368,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati assert(comp.c_source_files.len == 1); const c_source_file = comp.c_source_files[0]; - const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.bin_file.options.root_name}); + const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name}); var man: Cache.Manifest = comp.obtainCObjectCacheManifest(); man.want_shared_lock = false; @@ -5450,11 +5451,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi }; try comp.makeBinFileExecutable(); - const emit = comp.bin_file.options.emit.?; - child_argv.items[argv_index_exe] = try emit.directory.join( - arena, - &[_][]const u8{emit.sub_path}, - ); + const emit = comp.bin_file.?.emit; + child_argv.items[argv_index_exe] = try emit.directory.join(arena, &.{emit.sub_path}); break :argv child_argv.items; }; From bc4d2b646d5d09ecb86a3806886fed37e522fdc9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 15:19:51 -0700 Subject: [PATCH 037/133] compiler: update references to target --- src/Compilation.zig | 27 ++-- src/Module.zig | 42 +++--- src/arch/aarch64/CodeGen.zig | 45 +++--- src/arch/arm/CodeGen.zig | 47 +++--- src/arch/riscv64/CodeGen.zig | 43 +++--- src/arch/sparc64/CodeGen.zig | 43 +++--- src/arch/wasm/CodeGen.zig | 7 +- src/arch/x86_64/CodeGen.zig | 17 ++- src/codegen.zig | 282 +++++++++++++++++++---------------- src/link/Dwarf.zig | 56 ++++--- 10 files changed, 326 insertions(+), 283 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index a772e896804f..be9fb2a98905 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1915,9 +1915,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } pub fn destroy(self: *Compilation) void { - const optional_module = self.module; - self.bin_file.destroy(); - if (optional_module) |module| module.deinit(); + if (self.bin_file) |lf| lf.destroy(); + if (self.module) |zcu| zcu.deinit(); const gpa = self.gpa; self.work_queue.deinit(); @@ -2059,9 +2058,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // If using the whole caching strategy, we check for *everything* up front, including // C source files. - if (comp.bin_file.options.cache_mode == .whole) { + if (comp.cache_mode == .whole) { // We are about to obtain this lock, so here we give other processes a chance first. - comp.bin_file.releaseLock(); + if (comp.bin_file) |lf| lf.releaseLock(); man = comp.cache_parent.obtain(); comp.whole_cache_manifest = &man; @@ -5948,14 +5947,14 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const } fn wantBuildLibCFromSource(comp: Compilation) bool { - const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { + const is_exe_or_dyn_lib = switch (comp.config.output_mode) { .Obj => false, - .Lib => comp.bin_file.options.link_mode == .Dynamic, + .Lib => comp.config.link_mode == .Dynamic, .Exe => true, }; + const ofmt = comp.root_mod.resolved_target.result.ofmt; return comp.config.link_libc and is_exe_or_dyn_lib and - comp.bin_file.options.libc_installation == null and - comp.bin_file.options.target.ofmt != .c; + comp.libc_installation == null and ofmt != .c; } fn wantBuildGLibCFromSource(comp: Compilation) bool { @@ -5977,13 +5976,13 @@ fn wantBuildMinGWFromSource(comp: Compilation) bool { } fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { - const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { + const is_exe_or_dyn_lib = switch (comp.config.output_mode) { .Obj => false, - .Lib => comp.bin_file.options.link_mode == .Dynamic, + .Lib => comp.config.link_mode == .Dynamic, .Exe => true, }; - return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and - comp.bin_file.options.target.ofmt != .c; + const ofmt = comp.root_mod.resolved_target.result.ofmt; + return is_exe_or_dyn_lib and comp.config.link_libunwind and ofmt != .c; } fn setAllocFailure(comp: *Compilation) void { @@ -6112,7 +6111,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool { } pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend { - const target = comp.bin_file.options.target; + const target = comp.root_mod.resolved_target.result; return target_util.zigBackend(target, comp.bin_file.options.use_llvm); } diff --git a/src/Module.zig b/src/Module.zig index 5ec949293e55..018037a46ab6 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -623,7 +623,8 @@ pub const Decl = struct { // Sanitize the name for nvptx which is more restrictive. // TODO This should be handled by the backend, not the frontend. Have a // look at how the C backend does it for inspiration. - if (mod.comp.bin_file.options.target.cpu.arch.isNvptx()) { + const cpu_arch = mod.root_mod.resolved_target.cpu.arch; + if (cpu_arch.isNvptx()) { for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) { '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_', else => {}, @@ -4873,12 +4874,18 @@ pub fn errNoteNonLazy( }; } -pub fn getTarget(mod: Module) Target { - return mod.comp.bin_file.options.target; +/// Deprecated. There is no global target for a Zig Compilation Unit. Instead, +/// look up the target based on the Module that contains the source code being +/// analyzed. +pub fn getTarget(zcu: Module) Target { + return zcu.root_mod.resolved_target.result; } -pub fn optimizeMode(mod: Module) std.builtin.OptimizeMode { - return mod.comp.bin_file.options.optimize_mode; +/// Deprecated. There is no global optimization mode for a Zig Compilation +/// Unit. Instead, look up the optimization mode based on the Module that +/// contains the source code being analyzed. +pub fn optimizeMode(zcu: Module) std.builtin.OptimizeMode { + return zcu.root_mod.optimize_mode; } fn lockAndClearFileCompileError(mod: *Module, file: *File) void { @@ -5620,20 +5627,19 @@ pub const Feature = enum { safety_checked_instructions, }; -pub fn backendSupportsFeature(mod: Module, feature: Feature) bool { +pub fn backendSupportsFeature(zcu: Module, feature: Feature) bool { + const cpu_arch = zcu.root_mod.resolved_target.cpu.arch; + const ofmt = zcu.root_mod.resolved_target.ofmt; + const use_llvm = zcu.comp.config.use_llvm; return switch (feature) { - .panic_fn => mod.comp.bin_file.options.target.ofmt == .c or - mod.comp.bin_file.options.use_llvm or - mod.comp.bin_file.options.target.cpu.arch == .x86_64, - .panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or - mod.comp.bin_file.options.use_llvm, - .safety_check_formatted => mod.comp.bin_file.options.target.ofmt == .c or - mod.comp.bin_file.options.use_llvm, - .error_return_trace => mod.comp.bin_file.options.use_llvm, - .is_named_enum_value => mod.comp.bin_file.options.use_llvm, - .error_set_has_value => mod.comp.bin_file.options.use_llvm or mod.comp.bin_file.options.target.isWasm(), - .field_reordering => mod.comp.bin_file.options.use_llvm, - .safety_checked_instructions => mod.comp.bin_file.options.use_llvm, + .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64, + .panic_unwrap_error => ofmt == .c or use_llvm, + .safety_check_formatted => ofmt == .c or use_llvm, + .error_return_trace => use_llvm, + .is_named_enum_value => use_llvm, + .error_set_has_value => use_llvm or cpu_arch.isWasm(), + .field_reordering => use_llvm, + .safety_checked_instructions => use_llvm, }; } diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index c70b61c30d2e..2fb740474b92 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -329,7 +329,7 @@ const BigTomb = struct { const Self = @This(); pub fn generate( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, func_index: InternPool.Index, air: Air, @@ -337,31 +337,30 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { - @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - - const mod = bin_file.comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const gpa = lf.comp.gpa; + const zcu = lf.comp.module.?; + const func = zcu.funcInfo(func_index); + const fn_owner_decl = zcu.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const target = &namespace.file_scope.mod.target; - var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); + var branch_stack = std.ArrayList(Branch).init(gpa); defer { assert(branch_stack.items.len == 1); - branch_stack.items[0].deinit(bin_file.allocator); + branch_stack.items[0].deinit(gpa); branch_stack.deinit(); } try branch_stack.append(.{}); var function = Self{ - .gpa = bin_file.allocator, + .gpa = gpa, .air = air, .liveness = liveness, .debug_output = debug_output, - .target = &bin_file.options.target, - .bin_file = bin_file, + .target = target, + .bin_file = lf, .func_index = func_index, .owner_decl = func.owner_decl, .err_msg = null, @@ -375,15 +374,15 @@ pub fn generate( .end_di_line = func.rbrace_line, .end_di_column = func.rbrace_column, }; - defer function.stack.deinit(bin_file.allocator); - defer function.blocks.deinit(bin_file.allocator); - defer function.exitlude_jump_relocs.deinit(bin_file.allocator); - defer function.dbg_info_relocs.deinit(bin_file.allocator); + defer function.stack.deinit(gpa); + defer function.blocks.deinit(gpa); + defer function.exitlude_jump_relocs.deinit(gpa); + defer function.dbg_info_relocs.deinit(gpa); var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -397,7 +396,7 @@ pub fn generate( function.gen() catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -408,15 +407,15 @@ pub fn generate( var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .mir = mir, - .bin_file = bin_file, + .bin_file = lf, .debug_output = debug_output, - .target = &bin_file.options.target, + .target = target, .src_loc = src_loc, .code = code, .prev_di_pc = 0, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 8304e06b4c0b..0df653ff35d8 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -336,7 +336,7 @@ const DbgInfoReloc = struct { const Self = @This(); pub fn generate( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, func_index: InternPool.Index, air: Air, @@ -344,30 +344,29 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { - @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - - const mod = bin_file.comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const gpa = lf.comp.gpa; + const zcu = lf.comp.module.?; + const func = zcu.funcInfo(func_index); + const fn_owner_decl = zcu.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const target = &namespace.file_scope.mod.target; - var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); + var branch_stack = std.ArrayList(Branch).init(gpa); defer { assert(branch_stack.items.len == 1); - branch_stack.items[0].deinit(bin_file.allocator); + branch_stack.items[0].deinit(gpa); branch_stack.deinit(); } try branch_stack.append(.{}); - var function = Self{ - .gpa = bin_file.allocator, + var function: Self = .{ + .gpa = gpa, .air = air, .liveness = liveness, - .target = &bin_file.options.target, - .bin_file = bin_file, + .target = target, + .bin_file = lf, .debug_output = debug_output, .func_index = func_index, .err_msg = null, @@ -381,15 +380,15 @@ pub fn generate( .end_di_line = func.rbrace_line, .end_di_column = func.rbrace_column, }; - defer function.stack.deinit(bin_file.allocator); - defer function.blocks.deinit(bin_file.allocator); - defer function.exitlude_jump_relocs.deinit(bin_file.allocator); - defer function.dbg_info_relocs.deinit(bin_file.allocator); + defer function.stack.deinit(gpa); + defer function.blocks.deinit(gpa); + defer function.exitlude_jump_relocs.deinit(gpa); + defer function.dbg_info_relocs.deinit(gpa); var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -403,7 +402,7 @@ pub fn generate( function.gen() catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -414,15 +413,15 @@ pub fn generate( var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .mir = mir, - .bin_file = bin_file, + .bin_file = lf, .debug_output = debug_output, - .target = &bin_file.options.target, + .target = target, .src_loc = src_loc, .code = code, .prev_di_pc = 0, diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 4de9313a948a..30c6e38c8ac3 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -217,7 +217,7 @@ const BigTomb = struct { const Self = @This(); pub fn generate( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, func_index: InternPool.Index, air: Air, @@ -225,30 +225,29 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { - @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - - const mod = bin_file.comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const gpa = lf.comp.gpa; + const zcu = lf.comp.module.?; + const func = zcu.funcInfo(func_index); + const fn_owner_decl = zcu.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const target = &namespace.file_scope.mod.target; - var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); + var branch_stack = std.ArrayList(Branch).init(gpa); defer { assert(branch_stack.items.len == 1); - branch_stack.items[0].deinit(bin_file.allocator); + branch_stack.items[0].deinit(gpa); branch_stack.deinit(); } try branch_stack.append(.{}); var function = Self{ - .gpa = bin_file.allocator, + .gpa = gpa, .air = air, .liveness = liveness, - .target = &bin_file.options.target, - .bin_file = bin_file, + .target = target, + .bin_file = lf, .func_index = func_index, .code = code, .debug_output = debug_output, @@ -263,14 +262,14 @@ pub fn generate( .end_di_line = func.rbrace_line, .end_di_column = func.rbrace_column, }; - defer function.stack.deinit(bin_file.allocator); - defer function.blocks.deinit(bin_file.allocator); - defer function.exitlude_jump_relocs.deinit(bin_file.allocator); + defer function.stack.deinit(gpa); + defer function.blocks.deinit(gpa); + defer function.exitlude_jump_relocs.deinit(gpa); var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -284,22 +283,22 @@ pub fn generate( function.gen() catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .mir = mir, - .bin_file = bin_file, + .bin_file = lf, .debug_output = debug_output, - .target = &bin_file.options.target, + .target = target, .src_loc = src_loc, .code = code, .prev_di_pc = 0, diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index f252563b357f..bd0208c3c2e0 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -260,7 +260,7 @@ const BigTomb = struct { }; pub fn generate( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, func_index: InternPool.Index, air: Air, @@ -268,31 +268,30 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { - @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - - const mod = bin_file.comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const gpa = lf.comp.gpa; + const zcu = lf.comp.module.?; + const func = zcu.funcInfo(func_index); + const fn_owner_decl = zcu.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const target = &namespace.file_scope.mod.target; - var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); + var branch_stack = std.ArrayList(Branch).init(gpa); defer { assert(branch_stack.items.len == 1); - branch_stack.items[0].deinit(bin_file.allocator); + branch_stack.items[0].deinit(gpa); branch_stack.deinit(); } try branch_stack.append(.{}); var function = Self{ - .gpa = bin_file.allocator, + .gpa = gpa, .air = air, .liveness = liveness, - .target = &bin_file.options.target, + .target = target, .func_index = func_index, - .bin_file = bin_file, + .bin_file = lf, .code = code, .debug_output = debug_output, .err_msg = null, @@ -306,14 +305,14 @@ pub fn generate( .end_di_line = func.rbrace_line, .end_di_column = func.rbrace_column, }; - defer function.stack.deinit(bin_file.allocator); - defer function.blocks.deinit(bin_file.allocator); - defer function.exitlude_jump_relocs.deinit(bin_file.allocator); + defer function.stack.deinit(gpa); + defer function.blocks.deinit(gpa); + defer function.exitlude_jump_relocs.deinit(gpa); var call_info = function.resolveCallingConventionValues(fn_type, .callee) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; @@ -327,22 +326,22 @@ pub fn generate( function.gen() catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .mir = mir, - .bin_file = bin_file, + .bin_file = lf, .debug_output = debug_output, - .target = &bin_file.options.target, + .target = target, .src_loc = src_loc, .code = code, .prev_di_pc = 0, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 819cc3e9a07e..23193303336c 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1212,16 +1212,19 @@ pub fn generate( _ = src_loc; const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); + const decl = mod.declPtr(func.owner_decl); + const namespace = mod.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; var code_gen: CodeGen = .{ .gpa = bin_file.allocator, .air = air, .liveness = liveness, .code = code, .decl_index = func.owner_decl, - .decl = mod.declPtr(func.owner_decl), + .decl = decl, .err_msg = undefined, .locals = .{}, - .target = bin_file.options.target, + .target = target, .bin_file = bin_file.cast(link.File.Wasm).?, .debug_output = debug_output, .func_index = func_index, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9a4c73c74d93..b3c5df02d98e 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -795,22 +795,20 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { - @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - const mod = bin_file.comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; + const namespace = mod.namespacePtr(fn_owner_decl.src_namespace); + const target = namespace.file_scope.mod.target; const gpa = bin_file.allocator; var function = Self{ .gpa = gpa, .air = air, .liveness = liveness, - .target = &bin_file.options.target, + .target = target, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .func_index = func_index }, @@ -882,7 +880,7 @@ pub fn generate( .size = Type.usize.abiSize(mod), .alignment = Alignment.min( call_info.stack_align, - Alignment.fromNonzeroByteUnits(bin_file.options.target.stackAlignment()), + Alignment.fromNonzeroByteUnits(target.stackAlignment()), ), })); function.frame_allocs.set( @@ -967,11 +965,16 @@ pub fn generateLazy( debug_output: DebugInfoOutput, ) CodeGenError!Result { const gpa = bin_file.allocator; + const zcu = bin_file.comp.module.?; + const decl_index = lazy_sym.ty.getOwnerDecl(zcu); + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; var function = Self{ .gpa = gpa, .air = undefined, .liveness = undefined, - .target = &bin_file.options.target, + .target = target, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .lazy_sym = lazy_sym }, diff --git a/src/codegen.zig b/src/codegen.zig index 54bdf295b32b..e579cb50f1d1 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -45,7 +45,7 @@ pub const DebugInfoOutput = union(enum) { }; pub fn generateFunction( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, func_index: InternPool.Index, air: Air, @@ -53,33 +53,43 @@ pub fn generateFunction( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - switch (bin_file.options.target.cpu.arch) { + const zcu = lf.comp.module.?; + const func = zcu.funcInfo(func_index); + const decl = zcu.declPtr(func.owner_decl); + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; + switch (target.cpu.arch) { .arm, .armeb, - => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), + => return @import("arch/arm/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), .aarch64, .aarch64_be, .aarch64_32, - => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), - .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), - .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), - .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), + => return @import("arch/aarch64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), + .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), + .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), + .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), .wasm32, .wasm64, - => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output), + => return @import("arch/wasm/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output), else => unreachable, } } pub fn generateLazyFunction( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, lazy_sym: link.File.LazySymbol, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - switch (bin_file.options.target.cpu.arch) { - .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(bin_file, src_loc, lazy_sym, code, debug_output), + const zcu = lf.comp.module.?; + const decl_index = lazy_sym.ty.getOwnerDecl(zcu); + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; + switch (target.cpu.arch) { + .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(lf, src_loc, lazy_sym, code, debug_output), else => unreachable, } } @@ -107,13 +117,16 @@ pub fn generateLazySymbol( const tracy = trace(@src()); defer tracy.end(); - const target = bin_file.options.target; + const zcu = bin_file.comp.module.?; + const decl_index = lazy_sym.ty.getOwnerDecl(zcu); + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; const endian = target.cpu.arch.endian(); - const mod = bin_file.comp.module.?; log.debug("generateLazySymbol: kind = {s}, ty = {}", .{ @tagName(lazy_sym.kind), - lazy_sym.ty.fmt(mod), + lazy_sym.ty.fmt(zcu), }); if (lazy_sym.kind == .code) { @@ -121,14 +134,14 @@ pub fn generateLazySymbol( return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output); } - if (lazy_sym.ty.isAnyError(mod)) { + if (lazy_sym.ty.isAnyError(zcu)) { alignment.* = .@"4"; - const err_names = mod.global_error_set.keys(); + const err_names = zcu.global_error_set.keys(); mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian); var offset = code.items.len; try code.resize((1 + err_names.len + 1) * 4); for (err_names) |err_name_nts| { - const err_name = mod.intern_pool.stringToSlice(err_name_nts); + const err_name = zcu.intern_pool.stringToSlice(err_name_nts); mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian); offset += 4; try code.ensureUnusedCapacity(err_name.len + 1); @@ -137,10 +150,10 @@ pub fn generateLazySymbol( } mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian); return Result.ok; - } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) { + } else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) { alignment.* = .@"1"; - for (lazy_sym.ty.enumFields(mod)) |tag_name_ip| { - const tag_name = mod.intern_pool.stringToSlice(tag_name_ip); + for (lazy_sym.ty.enumFields(zcu)) |tag_name_ip| { + const tag_name = zcu.intern_pool.stringToSlice(tag_name_ip); try code.ensureUnusedCapacity(tag_name.len + 1); code.appendSliceAssumeCapacity(tag_name); code.appendAssumeCapacity(0); @@ -150,7 +163,7 @@ pub fn generateLazySymbol( bin_file.allocator, src_loc, "TODO implement generateLazySymbol for {s} {}", - .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod) }, + .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(zcu) }, ) }; } @@ -757,7 +770,7 @@ const RelocInfo = struct { }; fn lowerAnonDeclRef( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, code: *std.ArrayList(u8), @@ -765,27 +778,27 @@ fn lowerAnonDeclRef( reloc_info: RelocInfo, ) CodeGenError!Result { _ = debug_output; - const target = bin_file.options.target; - const mod = bin_file.comp.module.?; + const zcu = lf.comp.module.?; + const target = lf.comp.root_mod.resolved_target.result; const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); const decl_val = anon_decl.val; - const decl_ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); - log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(mod)}); - const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; - if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { + const decl_ty = Type.fromInterned(zcu.intern_pool.typeOf(decl_val)); + log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(zcu)}); + const is_fn_body = decl_ty.zigTypeTag(zcu) == .Fn; + if (!is_fn_body and !decl_ty.hasRuntimeBits(zcu)) { try code.appendNTimes(0xaa, ptr_width_bytes); return Result.ok; } - const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; - const res = try bin_file.lowerAnonDecl(decl_val, decl_align, src_loc); + const decl_align = zcu.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; + const res = try lf.lowerAnonDecl(decl_val, decl_align, src_loc); switch (res) { .ok => {}, .fail => |em| return .{ .fail = em }, } - const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{ + const vaddr = try lf.getAnonDeclVAddr(decl_val, .{ .parent_atom_index = reloc_info.parent_atom_index, .offset = code.items.len, .addend = reloc_info.addend orelse 0, @@ -802,7 +815,7 @@ fn lowerAnonDeclRef( } fn lowerDeclRef( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, decl_index: InternPool.DeclIndex, code: *std.ArrayList(u8), @@ -811,20 +824,21 @@ fn lowerDeclRef( ) CodeGenError!Result { _ = src_loc; _ = debug_output; - const target = bin_file.options.target; - const mod = bin_file.comp.module.?; + const zcu = lf.comp.module.?; + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; const ptr_width = target.ptrBitWidth(); - const decl = mod.declPtr(decl_index); - const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn; - if (!is_fn_body and !decl.ty.hasRuntimeBits(mod)) { + const is_fn_body = decl.ty.zigTypeTag(zcu) == .Fn; + if (!is_fn_body and !decl.ty.hasRuntimeBits(zcu)) { try code.appendNTimes(0xaa, @divExact(ptr_width, 8)); return Result.ok; } - try mod.markDeclAlive(decl); + try zcu.markDeclAlive(decl); - const vaddr = try bin_file.getDeclVAddr(decl_index, .{ + const vaddr = try lf.getDeclVAddr(decl_index, .{ .parent_atom_index = reloc_info.parent_atom_index, .offset = code.items.len, .addend = reloc_info.addend orelse 0, @@ -897,27 +911,29 @@ pub const GenResult = union(enum) { }; fn genDeclRef( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, tv: TypedValue, ptr_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.comp.module.?; - log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); + const zcu = lf.comp.module.?; + log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) }); + + const ptr_decl = zcu.declPtr(ptr_decl_index); + const namespace = zcu.namespacePtr(ptr_decl.src_namespace); + const target = namespace.file_scope.mod.target; - const target = bin_file.options.target; const ptr_bits = target.ptrBitWidth(); const ptr_bytes: u64 = @divExact(ptr_bits, 8); - const ptr_decl = mod.declPtr(ptr_decl_index); - const decl_index = switch (mod.intern_pool.indexToKey(try ptr_decl.internValue(mod))) { + const decl_index = switch (zcu.intern_pool.indexToKey(try ptr_decl.internValue(zcu))) { .func => |func| func.owner_decl, .extern_func => |extern_func| extern_func.decl, else => ptr_decl_index, }; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); - if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { + if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { const imm: u64 = switch (ptr_bytes) { 1 => 0xaa, 2 => 0xaaaa, @@ -929,30 +945,30 @@ fn genDeclRef( } // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? - if (tv.ty.castPtrToFn(mod)) |fn_ty| { - if (mod.typeToFunc(fn_ty).?.is_generic) { - return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod).toByteUnitsOptional().? }); + if (tv.ty.castPtrToFn(zcu)) |fn_ty| { + if (zcu.typeToFunc(fn_ty).?.is_generic) { + return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? }); } - } else if (tv.ty.zigTypeTag(mod) == .Pointer) { - const elem_ty = tv.ty.elemType2(mod); - if (!elem_ty.hasRuntimeBits(mod)) { - return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod).toByteUnitsOptional().? }); + } else if (tv.ty.zigTypeTag(zcu) == .Pointer) { + const elem_ty = tv.ty.elemType2(zcu); + if (!elem_ty.hasRuntimeBits(zcu)) { + return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? }); } } - try mod.markDeclAlive(decl); + try zcu.markDeclAlive(decl); - const decl_namespace = mod.namespacePtr(decl.namespace_index); - const single_threaded = decl_namespace.file_scope.mod.single_threaded; - const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !single_threaded; - const is_extern = decl.isExtern(mod); + const decl_namespace = zcu.namespacePtr(decl.namespace_index); + const single_threaded = decl_namespace.file_scope.zcu.single_threaded; + const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded; + const is_extern = decl.isExtern(zcu); - if (bin_file.cast(link.File.Elf)) |elf_file| { + if (lf.cast(link.File.Elf)) |elf_file| { if (is_extern) { - const name = mod.intern_pool.stringToSlice(decl.name); + const name = zcu.intern_pool.stringToSlice(decl.name); // TODO audit this - const lib_name = if (decl.getOwnedVariable(mod)) |ov| - mod.intern_pool.stringToSliceUnwrap(ov.lib_name) + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| + zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) else null; const sym_index = try elf_file.getGlobalSymbol(name, lib_name); @@ -965,12 +981,12 @@ fn genDeclRef( return GenResult.mcv(.{ .load_tlv = sym.esym_index }); } return GenResult.mcv(.{ .load_symbol = sym.esym_index }); - } else if (bin_file.cast(link.File.MachO)) |macho_file| { + } else if (lf.cast(link.File.MachO)) |macho_file| { if (is_extern) { // TODO make this part of getGlobalSymbol - const name = mod.intern_pool.stringToSlice(decl.name); - const sym_name = try std.fmt.allocPrint(bin_file.allocator, "_{s}", .{name}); - defer bin_file.allocator.free(sym_name); + const name = zcu.intern_pool.stringToSlice(decl.name); + const sym_name = try std.fmt.allocPrint(lf.allocator, "_{s}", .{name}); + defer lf.allocator.free(sym_name); const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); } @@ -980,110 +996,118 @@ fn genDeclRef( return GenResult.mcv(.{ .load_tlv = sym_index }); } return GenResult.mcv(.{ .load_got = sym_index }); - } else if (bin_file.cast(link.File.Coff)) |coff_file| { + } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { - const name = mod.intern_pool.stringToSlice(decl.name); + const name = zcu.intern_pool.stringToSlice(decl.name); // TODO audit this - const lib_name = if (decl.getOwnedVariable(mod)) |ov| - mod.intern_pool.stringToSliceUnwrap(ov.lib_name) + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| + zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) else null; const global_index = try coff_file.getGlobalSymbol(name, lib_name); - try coff_file.need_got_table.put(bin_file.allocator, global_index, {}); // needs GOT + try coff_file.need_got_table.put(lf.allocator, global_index, {}); // needs GOT return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index }); } const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index); const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; return GenResult.mcv(.{ .load_got = sym_index }); - } else if (bin_file.cast(link.File.Plan9)) |p9| { + } else if (lf.cast(link.File.Plan9)) |p9| { const atom_index = try p9.seeDecl(decl_index); const atom = p9.getAtom(atom_index); return GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(p9) }); } else { - return GenResult.fail(bin_file.allocator, src_loc, "TODO genDeclRef for target {}", .{target}); + return GenResult.fail(lf.allocator, src_loc, "TODO genDeclRef for target {}", .{target}); } } fn genUnnamedConst( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, tv: TypedValue, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.comp.module.?; - log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); + const zcu = lf.comp.module.?; + const gpa = lf.comp.gpa; + log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) }); - const target = bin_file.options.target; - const local_sym_index = bin_file.lowerUnnamedConst(tv, owner_decl_index) catch |err| { - return GenResult.fail(bin_file.allocator, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); + const local_sym_index = lf.lowerUnnamedConst(tv, owner_decl_index) catch |err| { + return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); }; - if (bin_file.cast(link.File.Elf)) |elf_file| { - const local = elf_file.symbol(local_sym_index); - return GenResult.mcv(.{ .load_symbol = local.esym_index }); - } else if (bin_file.cast(link.File.MachO)) |_| { - return GenResult.mcv(.{ .load_direct = local_sym_index }); - } else if (bin_file.cast(link.File.Coff)) |_| { - return GenResult.mcv(.{ .load_direct = local_sym_index }); - } else if (bin_file.cast(link.File.Plan9)) |_| { - const atom_index = local_sym_index; // plan9 returns the atom_index - return GenResult.mcv(.{ .load_direct = atom_index }); - } else { - return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target}); + switch (lf.tag) { + .elf => { + const elf_file = lf.cast(link.File.Elf).?; + const local = elf_file.symbol(local_sym_index); + return GenResult.mcv(.{ .load_symbol = local.esym_index }); + }, + .macho, .coff => { + return GenResult.mcv(.{ .load_direct = local_sym_index }); + }, + .plan9 => { + const atom_index = local_sym_index; // plan9 returns the atom_index + return GenResult.mcv(.{ .load_direct = atom_index }); + }, + + .c => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for -ofmt=c", .{}), + .wasm => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for wasm", .{}), + .spirv => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for spirv", .{}), + .nvptx => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for nvptx", .{}), } } pub fn genTypedValue( - bin_file: *link.File, + lf: *link.File, src_loc: Module.SrcLoc, arg_tv: TypedValue, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { - const mod = bin_file.comp.module.?; + const zcu = lf.comp.module.?; const typed_value = arg_tv; log.debug("genTypedValue: ty = {}, val = {}", .{ - typed_value.ty.fmt(mod), - typed_value.val.fmtValue(typed_value.ty, mod), + typed_value.ty.fmt(zcu), + typed_value.val.fmtValue(typed_value.ty, zcu), }); - if (typed_value.val.isUndef(mod)) + if (typed_value.val.isUndef(zcu)) return GenResult.mcv(.undef); - const target = bin_file.options.target; + const owner_decl = zcu.declPtr(owner_decl_index); + const namespace = zcu.namespacePtr(owner_decl.src_namespace); + const target = namespace.file_scope.mod.target; const ptr_bits = target.ptrBitWidth(); - if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) { + if (!typed_value.ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl), - .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl), + .decl => |decl| return genDeclRef(lf, src_loc, typed_value, decl), + .mut_decl => |mut_decl| return genDeclRef(lf, src_loc, typed_value, mut_decl.decl), else => {}, }, else => {}, }; - switch (typed_value.ty.zigTypeTag(mod)) { + switch (typed_value.ty.zigTypeTag(zcu)) { .Void => return GenResult.mcv(.none), - .Pointer => switch (typed_value.ty.ptrSize(mod)) { + .Pointer => switch (typed_value.ty.ptrSize(zcu)) { .Slice => {}, else => switch (typed_value.val.toIntern()) { .null_value => { return GenResult.mcv(.{ .immediate = 0 }); }, .none => {}, - else => switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) { + else => switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { .int => { - return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) }); + return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(zcu) }); }, else => {}, }, }, }, .Int => { - const info = typed_value.ty.intInfo(mod); + const info = typed_value.ty.intInfo(zcu); if (info.bits <= ptr_bits) { const unsigned = switch (info.signedness) { - .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(mod))), - .unsigned => typed_value.val.toUnsignedInt(mod), + .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(zcu))), + .unsigned => typed_value.val.toUnsignedInt(zcu), }; return GenResult.mcv(.{ .immediate = unsigned }); } @@ -1092,45 +1116,45 @@ pub fn genTypedValue( return GenResult.mcv(.{ .immediate = @intFromBool(typed_value.val.toBool()) }); }, .Optional => { - if (typed_value.ty.isPtrLikeOptional(mod)) { - return genTypedValue(bin_file, src_loc, .{ - .ty = typed_value.ty.optionalChild(mod), - .val = typed_value.val.optionalValue(mod) orelse return GenResult.mcv(.{ .immediate = 0 }), + if (typed_value.ty.isPtrLikeOptional(zcu)) { + return genTypedValue(lf, src_loc, .{ + .ty = typed_value.ty.optionalChild(zcu), + .val = typed_value.val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), }, owner_decl_index); - } else if (typed_value.ty.abiSize(mod) == 1) { - return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(mod)) }); + } else if (typed_value.ty.abiSize(zcu) == 1) { + return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(zcu)) }); } }, .Enum => { - const enum_tag = mod.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag; - const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int); - return genTypedValue(bin_file, src_loc, .{ + const enum_tag = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag; + const int_tag_ty = zcu.intern_pool.typeOf(enum_tag.int); + return genTypedValue(lf, src_loc, .{ .ty = Type.fromInterned(int_tag_ty), .val = Value.fromInterned(enum_tag.int), }, owner_decl_index); }, .ErrorSet => { - const err_name = mod.intern_pool.indexToKey(typed_value.val.toIntern()).err.name; - const error_index = mod.global_error_set.getIndex(err_name).?; + const err_name = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).err.name; + const error_index = zcu.global_error_set.getIndex(err_name).?; return GenResult.mcv(.{ .immediate = error_index }); }, .ErrorUnion => { - const err_type = typed_value.ty.errorUnionSet(mod); - const payload_type = typed_value.ty.errorUnionPayload(mod); - if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { + const err_type = typed_value.ty.errorUnionSet(zcu); + const payload_type = typed_value.ty.errorUnionPayload(zcu); + if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { // We use the error type directly as the type. - const err_int_ty = try mod.errorIntType(); - switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) { - .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{ + const err_int_ty = try zcu.errorIntType(); + switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) { + .err_name => |err_name| return genTypedValue(lf, src_loc, .{ .ty = err_type, - .val = Value.fromInterned((try mod.intern(.{ .err = .{ + .val = Value.fromInterned((try zcu.intern(.{ .err = .{ .ty = err_type.toIntern(), .name = err_name, } }))), }, owner_decl_index), - .payload => return genTypedValue(bin_file, src_loc, .{ + .payload => return genTypedValue(lf, src_loc, .{ .ty = err_int_ty, - .val = try mod.intValue(err_int_ty, 0), + .val = try zcu.intValue(err_int_ty, 0), }, owner_decl_index), } } @@ -1148,7 +1172,7 @@ pub fn genTypedValue( else => {}, } - return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index); + return genUnnamedConst(lf, src_loc, typed_value, owner_decl_index); } pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 5bd65b222793..525ca90bc333 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1192,7 +1192,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde pub fn commitDeclState( self: *Dwarf, - mod: *Module, + zcu: *Module, decl_index: InternPool.DeclIndex, sym_addr: u64, sym_size: u64, @@ -1202,15 +1202,17 @@ pub fn commitDeclState( defer tracy.end(); const gpa = self.allocator; + const decl = zcu.declPtr(decl_index); + const ip = &zcu.intern_pool; + const namespace = zcu.namespacePtr(decl.src_namespace); + const target = namespace.file_scope.mod.target; + const target_endian = target.cpu.arch.endian(); + var dbg_line_buffer = &decl_state.dbg_line; var dbg_info_buffer = &decl_state.dbg_info; - const decl = mod.declPtr(decl_index); - const ip = &mod.intern_pool; - - const target_endian = self.bin_file.options.target.cpu.arch.endian(); assert(decl.has_tv); - switch (decl.ty.zigTypeTag(mod)) { + switch (decl.ty.zigTypeTag(zcu)) { .Fn => { try decl_state.setInlineFunc(decl.val.toIntern()); @@ -1409,18 +1411,18 @@ pub fn commitDeclState( if (ip.isErrorSetType(ty.toIntern())) continue; symbol.offset = @intCast(dbg_info_buffer.items.len); - try decl_state.addDbgInfoType(mod, di_atom_index, ty); + try decl_state.addDbgInfoType(zcu, di_atom_index, ty); } } try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); while (decl_state.abbrev_relocs.popOrNull()) |reloc| { - if (reloc.target) |target| { - const symbol = decl_state.abbrev_table.items[target]; + if (reloc.target) |reloc_target| { + const symbol = decl_state.abbrev_table.items[reloc_target]; const ty = symbol.type; if (ip.isErrorSetType(ty.toIntern())) { - log.debug("resolving %{d} deferred until flush", .{target}); + log.debug("resolving %{d} deferred until flush", .{reloc_target}); try self.global_abbrev_relocs.append(gpa, .{ .target = null, .offset = reloc.offset, @@ -1433,8 +1435,8 @@ pub fn commitDeclState( log.debug("{x}: [() => {x}] (%{d}, '{}')", .{ reloc.offset, value, - target, - ty.fmt(mod), + reloc_target, + ty.fmt(zcu), }); mem.writeInt( u32, @@ -1897,7 +1899,7 @@ fn dbgInfoHeaderBytes(self: *Dwarf) usize { return 120; } -pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u64) !void { +pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64) !void { // If this value is null it means there is an error in the module; // leave debug_info_header_dirty=true. const first_dbg_info_off = self.getDebugInfoOff() orelse return; @@ -1908,7 +1910,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes); defer di_buf.deinit(); - const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const comp = self.bin_file.comp; + const target = comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); const init_len_size: usize = switch (self.format) { .dwarf32 => 4, .dwarf64 => 12, @@ -1931,9 +1935,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u di_buf.appendAssumeCapacity(self.ptrWidthBytes()); // address size // Write the form for the compile unit, which must match the abbrev table above. - const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path); + const name_strp = try self.strtab.insert(self.allocator, zcu.root_mod.root_src_path); var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; - const compile_unit_dir = resolveCompilationDir(module, &compile_unit_dir_buffer); + const compile_unit_dir = resolveCompilationDir(zcu, &compile_unit_dir_buffer); const comp_dir_strp = try self.strtab.insert(self.allocator, compile_unit_dir); const producer_strp = try self.strtab.insert(self.allocator, link.producer_string); @@ -1997,7 +2001,9 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) [] } fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void { - const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const comp = self.bin_file.comp; + const target = comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); switch (self.ptr_width) { .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(addr), target_endian), .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian), @@ -2005,7 +2011,9 @@ fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) voi } fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void { - const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const comp = self.bin_file.comp; + const target = comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); switch (self.format) { .dwarf32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(off), target_endian), .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian), @@ -2227,7 +2235,9 @@ fn writeDbgInfoNopsToArrayList( } pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { - const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const comp = self.bin_file.comp; + const target = comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); const ptr_width_bytes = self.ptrWidthBytes(); // Enough for all the data without resizing. When support for more compilation units @@ -2299,9 +2309,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { } pub fn writeDbgLineHeader(self: *Dwarf) !void { + const comp = self.bin_file.comp; const gpa = self.allocator; - - const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const target = comp.root_mod.resolved_target.result; + const target_endian = target.cpu.arch.endian(); const init_len_size: usize = switch (self.format) { .dwarf32 => 4, .dwarf64 => 12, @@ -2565,7 +2576,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { } pub fn flushModule(self: *Dwarf, module: *Module) !void { - const target = self.bin_file.options.target; + const comp = self.bin_file.comp; + const target = comp.root_mod.resolved_target.result; if (self.global_abbrev_relocs.items.len > 0) { const gpa = self.allocator; From b162c3c820d8a6446bbdfba90b3c135ebcd76fcb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 15:26:22 -0700 Subject: [PATCH 038/133] update bin_file.options references in Module (Zcu) --- src/Module.zig | 14 +++++--------- src/codegen/llvm.zig | 13 ++++++++++--- src/link/Coff.zig | 3 +++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index 018037a46ab6..aa107ea3f79d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3335,7 +3335,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr const comp = mod.comp; - const no_bin_file = (comp.bin_file.options.emit == null and + const no_bin_file = (comp.bin_file == null and comp.emit_asm == null and comp.emit_llvm_ir == null and comp.emit_llvm_bc == null); @@ -4311,14 +4311,14 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err 1 => blk: { // test decl with no name. Skip the part where we check against // the test name filter. - if (!comp.bin_file.options.is_test) break :blk false; + if (!comp.config.is_test) break :blk false; if (decl_mod != mod.main_mod) break :blk false; try mod.test_functions.put(gpa, new_decl_index, {}); break :blk true; }, else => blk: { if (!is_named_test) break :blk false; - if (!comp.bin_file.options.is_test) break :blk false; + if (!comp.config.is_test) break :blk false; if (decl_mod != mod.main_mod) break :blk false; if (comp.test_filter) |test_filter| { if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) { @@ -4627,7 +4627,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // If we don't get an error return trace from a caller, create our own. if (func.analysis(ip).calls_or_awaits_errorable_fn and - mod.comp.bin_file.options.error_return_tracing and + mod.comp.config.error_tracing and !sema.fn_ret_ty.isError(mod)) { sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { @@ -5475,7 +5475,7 @@ pub fn populateTestFunctions( pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void { const comp = mod.comp; - const no_bin_file = (comp.bin_file.options.emit == null and + const no_bin_file = (comp.bin_file == null and comp.emit_asm == null and comp.emit_llvm_ir == null and comp.emit_llvm_bc == null); @@ -5597,10 +5597,6 @@ pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u } } -pub fn wantDllExports(mod: Module) bool { - return mod.comp.bin_file.options.dll_export_fns and mod.getTarget().os.tag == .windows; -} - pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export { if (mod.decl_exports.get(decl_index)) |l| { return l.items; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 40fffcfd5fa2..beb3e5e9f662 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -15,6 +15,7 @@ const link = @import("../link.zig"); const Compilation = @import("../Compilation.zig"); const build_options = @import("build_options"); const Module = @import("../Module.zig"); +const Zcu = Module; const InternPool = @import("../InternPool.zig"); const Package = @import("../Package.zig"); const TypedValue = @import("../TypedValue.zig"); @@ -1723,7 +1724,7 @@ pub const Object = struct { try global_index.rename(decl_name, &self.builder); global_index.setLinkage(.external, &self.builder); global_index.setUnnamedAddr(.default, &self.builder); - if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); + if (wantDllExports(mod)) global_index.setDllStorageClass(.default, &self.builder); if (self.di_map.get(decl)) |di_node| { const decl_name_slice = decl_name.slice(&self.builder).?; if (try decl.isFunction(mod)) { @@ -1789,7 +1790,7 @@ pub const Object = struct { ); try global_index.rename(fqn, &self.builder); global_index.setLinkage(.internal, &self.builder); - if (mod.wantDllExports()) global_index.setDllStorageClass(.default, &self.builder); + if (wantDllExports(mod)) global_index.setDllStorageClass(.default, &self.builder); global_index.setUnnamedAddr(.unnamed_addr, &self.builder); if (decl.val.getVariable(mod)) |decl_var| { const decl_namespace = mod.namespacePtr(decl.namespace_index); @@ -1848,7 +1849,7 @@ pub const Object = struct { exports: []const *Module.Export, ) link.File.UpdateExportsError!void { global_index.setUnnamedAddr(.default, &o.builder); - if (mod.wantDllExports()) global_index.setDllStorageClass(.dllexport, &o.builder); + if (wantDllExports(mod)) global_index.setDllStorageClass(.dllexport, &o.builder); global_index.setLinkage(switch (exports[0].opts.linkage) { .Internal => unreachable, .Strong => .external, @@ -11767,3 +11768,9 @@ fn constraintAllowsRegister(constraint: []const u8) bool { } } else return false; } + +fn wantDllExports(zcu: *const Zcu) bool { + const lf = zcu.bin_file.?; + const coff = lf.cast(link.File.Coff) orelse return false; + return coff.dll_export_fns; +} diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 6bb2e6b1f817..41cf524ec0f5 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -9,6 +9,7 @@ llvm_object: ?*LlvmObject = null, base: link.File, image_base: u64, error_flags: link.File.ErrorFlags = .{}, +dll_export_fns: bool, ptr_width: PtrWidth, page_size: u32, @@ -400,6 +401,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { .Lib => 0x10000000, .Obj => 0, }, + + .dll_export_fns = options.dll_export_fns, }; const use_llvm = comp.config.use_llvm; From 33cdf33b95676dca9f91216e0f8742f9cf7e84fb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 18:28:00 -0700 Subject: [PATCH 039/133] compiler: update many references to bin_file.options --- src/Compilation.zig | 370 ++++++++++++++++--------------- 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, 319 insertions(+), 231 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index be9fb2a98905..5f99c85ba0b7 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 f1e709185578..091674287635 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 beb3e5e9f662..ee9e3de086bf 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 fb1f2bb827bd..6b2587e3cb87 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 580b2d7daf33..5908a07dec47 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 41cf524ec0f5..db99ba189cbd 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 a116c46d2f56..b54bde325f2b 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 3bffc7f73e3c..8bcf43935442 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 f40aaea4db72..06fede6e1b3e 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 d8f78c32f197..bb278a8e4a0a 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 5f65908b5c85..9acad1a0ca5f 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); From 769dea6e37ffef32f0972a0b958ff2ea38db6854 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2023 23:59:02 -0700 Subject: [PATCH 040/133] Compilation: redo whole vs incremental logic in create and update --- src/Compilation.zig | 852 ++++++++++++++++++++------------------------ src/Module.zig | 3 - src/link.zig | 63 ---- 3 files changed, 385 insertions(+), 533 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 5f99c85ba0b7..8cf7a66fbc80 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -48,6 +48,9 @@ arena: std.heap.ArenaAllocator, /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. /// TODO: rename to zcu: ?*Zcu module: ?*Module, +/// Contains different state depending on whether the Compilation uses +/// incremental or whole cache mode. +cache_use: CacheUse, /// All compilations have a root module because this is where some important /// settings are stored, such as target and optimization mode. This module /// might not have any .zig code associated with it, however. @@ -66,7 +69,6 @@ implib_emit: ?Emit, /// This is non-null when `-femit-docs` is provided. docs_emit: ?Emit, root_name: [:0]const u8, -cache_mode: CacheMode, include_compiler_rt: bool, objects: []Compilation.LinkObject, /// Needed only for passing -F args to clang. @@ -82,9 +84,6 @@ 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) = if (build_options.only_core_functionality) {} else .{}, -/// This is a pointer to a local variable inside `update()`. -whole_cache_manifest: ?*Cache.Manifest = null, -whole_cache_manifest_mutex: std.Thread.Mutex = .{}, link_error_flags: link.File.ErrorFlags = .{}, lld_errors: std.ArrayListUnmanaged(LldError) = .{}, @@ -154,14 +153,6 @@ rc_source_files: []const RcSourceFile, cache_parent: *Cache, /// Path to own executable for invoking `zig clang`. self_exe_path: ?[]const u8, -/// null means -fno-emit-bin. -/// This is mutable memory allocated into the Compilation-lifetime arena (`arena`) -/// of exactly the correct size for "o/[digest]/[basename]". -/// The basename is of the outputted binary file in case we don't know the directory yet. -whole_bin_sub_path: ?[]u8, -/// Same as `whole_bin_sub_path` but for implibs. -whole_implib_sub_path: ?[]u8, -whole_docs_sub_path: ?[]u8, zig_lib_directory: Directory, local_cache_directory: Directory, global_cache_directory: Directory, @@ -199,9 +190,6 @@ glibc_so_files: ?glibc.BuiltSharedObjects = null, /// The key is the basename, and the value is the absolute path to the completed build artifact. crt_files: std.StringHashMapUnmanaged(CRTFile) = .{}, -/// Keeping track of this possibly open resource so we can close it later. -owned_link_dir: ?std.fs.Dir, - /// This is for stage1 and should be deleted upon completion of self-hosting. /// Don't use this for anything other than stage1 compatibility. color: Color = .auto, @@ -869,7 +857,32 @@ pub const ClangPreprocessorMode = enum { pub const Framework = link.File.MachO.Framework; pub const SystemLib = link.SystemLib; -pub const CacheMode = link.CacheMode; + +pub const CacheMode = enum { incremental, whole }; + +pub const CacheUse = union(CacheMode) { + incremental: *Incremental, + whole: *Whole, + + pub const Whole = struct { + /// This is a pointer to a local variable inside `update()`. + cache_manifest: ?*Cache.Manifest = null, + cache_manifest_mutex: std.Thread.Mutex = .{}, + /// null means -fno-emit-bin. + /// This is mutable memory allocated into the Compilation-lifetime arena (`arena`) + /// of exactly the correct size for "o/[digest]/[basename]". + /// The basename is of the outputted binary file in case we don't know the directory yet. + bin_sub_path: ?[]u8, + /// Same as `whole_bin_sub_path` but for implibs. + implib_sub_path: ?[]u8, + docs_sub_path: ?[]u8, + }; + + pub const Incremental = struct { + /// Where build artifacts and incremental compilation metadata serialization go. + artifact_directory: Compilation.Directory, + }; +}; pub const LinkObject = struct { path: []const u8, @@ -1280,6 +1293,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1); + const each_lib_rpath = options.each_lib_rpath orelse + options.root_mod.resolved_target.is_native_os; + // We put everything into the cache hash that *cannot be modified // during an incremental update*. For example, one cannot change the // target between updates, but one can change source files, so the @@ -1319,73 +1335,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.config.wasi_exec_model); // TODO audit this and make sure everything is in it - const zcu: ?*Module = if (have_zcu) blk: { - // Options that are specific to zig source files, that cannot be - // modified between incremental updates. - var hash = cache.hash; - - switch (cache_mode) { - .incremental => { - // Here we put the root source file path name, but *not* with addFile. - // We want the hash to be the same regardless of the contents of the - // source file, because incremental compilation will handle it, but we - // do want to namespace different source file names because they are - // likely different compilations and therefore this would be likely to - // cause cache hits. - try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, .path_bytes); - }, - .whole => { - // In this case, we postpone adding the input source file until - // we create the cache manifest, in update(), because we want to - // track it and packages as files. - }, - } - - // Synchronize with other matching comments: ZigOnlyHashStuff - hash.add(use_llvm); - hash.add(options.config.use_lib_llvm); - hash.add(dll_export_fns); - hash.add(options.config.is_test); - hash.add(options.config.test_evented_io); - hash.addOptionalBytes(options.test_filter); - hash.addOptionalBytes(options.test_name_prefix); - hash.add(options.skip_linker_dependencies); - hash.add(formatted_panics); - hash.add(options.emit_h != null); - hash.add(error_limit); - - // 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 - // build artifacts are stored (even while in-progress). - // - // For whole cache mode, it is still used for builtin.zig so that the file - // path to builtin.zig can remain consistent during a debugging session at - // runtime. However, we don't know where to put outputs from the linker - // until the final cache hash, which is available after the - // compilation is complete. - // - // Therefore, in whole cache mode, we additionally create a temporary cache - // directory for these two kinds of build artifacts, and then rename it - // into place after the final hash is known. However, we don't want - // to create the temporary directory here, because in the case of a cache hit, - // this would have been wasted syscalls to make the directory and then not - // use it (or delete it). - // - // In summary, for whole cache mode, we simulate `-fno-emit-bin` in this - // function, and `zig_cache_artifact_directory` is *wrong* except for builtin.zig, - // and then at the beginning of `update()` when we find out whether we need - // a temporary directory, we patch up all the places that the incorrect - // `zig_cache_artifact_directory` was passed to various components of the compiler. - - const digest = hash.final(); - const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); - var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); - errdefer artifact_dir.close(); - const zig_cache_artifact_directory: Directory = .{ - .handle = artifact_dir, - .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), - }; - + const opt_zcu: ?*Module = if (have_zcu) blk: { // Pre-open the directory handles for cached ZIR code so that it does not need // to redundantly happen for each AstGen operation. const zir_sub_dir = "z"; @@ -1404,27 +1354,18 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }; const emit_h: ?*Module.GlobalEmitH = if (options.emit_h) |loc| eh: { - const eh = try gpa.create(Module.GlobalEmitH); + const eh = try arena.create(Module.GlobalEmitH); eh.* = .{ .loc = loc }; break :eh eh; } else null; - errdefer if (emit_h) |eh| gpa.destroy(eh); - - // TODO when we implement serialization and deserialization of incremental - // compilation metadata, this is where we would load it. We have open a handle - // to the directory where the output either already is, or will be. - // However we currently do not have serialization of such metadata, so for now - // we set up an empty Module that does the entire compilation fresh. const zcu = try arena.create(Module); - errdefer zcu.deinit(); zcu.* = .{ .gpa = gpa, .comp = comp, .main_mod = options.main_mod orelse options.root_mod, .root_mod = options.root_mod, .std_mod = options.std_mod, - .zig_cache_artifact_directory = zig_cache_artifact_directory, .global_zir_cache = global_zir_cache, .local_zir_cache = local_zir_cache, .emit_h = emit_h, @@ -1432,155 +1373,33 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .error_limit = error_limit, }; try zcu.init(); - break :blk zcu; } else blk: { if (options.emit_h != null) return error.NoZigModuleForCHeader; break :blk null; }; - errdefer if (zcu) |u| u.deinit(); - - // For resource management purposes. - var owned_link_dir: ?std.fs.Dir = null; - errdefer if (owned_link_dir) |*dir| dir.close(); - - const bin_file_emit: ?Emit = blk: { - const emit_bin = options.emit_bin orelse break :blk null; - - if (emit_bin.directory) |directory| { - break :blk Emit{ - .directory = directory, - .sub_path = emit_bin.basename, - }; - } - - // In case of whole cache mode, `whole_bin_sub_path` is used to distinguish - // between -femit-bin and -fno-emit-bin. - switch (cache_mode) { - .whole => break :blk null, - .incremental => {}, - } - - if (zcu) |u| { - break :blk Emit{ - .directory = u.zig_cache_artifact_directory, - .sub_path = emit_bin.basename, - }; - } - - // We could use the cache hash as is no problem, however, we increase - // the likelihood of cache hits by adding the first C source file - // path name (not contents) to the hash. This way if the user is compiling - // foo.c and bar.c as separate compilations, they get different cache - // directories. - var hash = cache.hash; - if (options.c_source_files.len >= 1) { - hash.addBytes(options.c_source_files[0].src_path); - } else if (options.link_objects.len >= 1) { - hash.addBytes(options.link_objects[0].path); - } - - const digest = hash.final(); - const artifact_sub_dir = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); - const artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); - owned_link_dir = artifact_dir; - const link_artifact_directory: Directory = .{ - .handle = artifact_dir, - .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), - }; - break :blk Emit{ - .directory = link_artifact_directory, - .sub_path = emit_bin.basename, - }; - }; - - const implib_emit: ?Emit = blk: { - const emit_implib = options.emit_implib orelse break :blk null; - - if (emit_implib.directory) |directory| { - break :blk Emit{ - .directory = directory, - .sub_path = emit_implib.basename, - }; - } - - // This is here for the same reason as in `bin_file_emit` above. - switch (cache_mode) { - .whole => break :blk null, - .incremental => {}, - } - - // Use the same directory as the bin. The CLI already emits an - // error if -fno-emit-bin is combined with -femit-implib. - break :blk Emit{ - .directory = bin_file_emit.?.directory, - .sub_path = emit_implib.basename, - }; - }; + errdefer if (opt_zcu) |zcu| zcu.deinit(); - const docs_emit: ?Emit = blk: { - const emit_docs = options.emit_docs orelse break :blk null; - - if (emit_docs.directory) |directory| { - break :blk .{ - .directory = directory, - .sub_path = emit_docs.basename, - }; - } - - // This is here for the same reason as in `bin_file_emit` above. - switch (cache_mode) { - .whole => break :blk null, - .incremental => {}, - } - - // Use the same directory as the bin, if possible. - if (bin_file_emit) |x| break :blk .{ - .directory = x.directory, - .sub_path = emit_docs.basename, - }; - - break :blk .{ - .directory = zcu.?.zig_cache_artifact_directory, - .sub_path = emit_docs.basename, - }; - }; - - // This is so that when doing `CacheMode.whole`, the mechanism in update() - // can use it for communicating the result directory via `bin_file.emit`. - // This is used to distinguish between -fno-emit-bin and -femit-bin - // for `CacheMode.whole`. - // This memory will be overwritten with the real digest in update() but - // the basename will be preserved. - const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin); - // Same thing but for implibs. - const whole_implib_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_implib); - const whole_docs_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_docs); - - var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{}; + const system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init( + gpa, + options.system_lib_names, + options.system_lib_infos, + ); errdefer system_libs.deinit(gpa); - try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len); - for (options.system_lib_names, 0..) |lib_name, i| { - system_libs.putAssumeCapacity(lib_name, options.system_lib_infos[i]); - } - - const each_lib_rpath = options.each_lib_rpath orelse - options.root_mod.resolved_target.is_native_os; comp.* = .{ .gpa = gpa, .arena = arena_allocator, - .module = zcu, + .module = opt_zcu, + .cache_use = undefined, // populated below + .bin_file = null, // populated below + .implib_emit = null, // handled below + .docs_emit = null, // handled below .root_mod = options.root_mod, .config = options.config, - .bin_file = null, - .cache_mode = cache_mode, .zig_lib_directory = options.zig_lib_directory, .local_cache_directory = options.local_cache_directory, .global_cache_directory = options.global_cache_directory, - .whole_bin_sub_path = whole_bin_sub_path, - .whole_implib_sub_path = whole_implib_sub_path, - .whole_docs_sub_path = whole_docs_sub_path, .emit_asm = options.emit_asm, .emit_llvm_ir = options.emit_llvm_ir, .emit_llvm_bc = options.emit_llvm_bc, @@ -1611,7 +1430,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, .verbose_link = options.verbose_link, .disable_c_depfile = options.disable_c_depfile, - .owned_link_dir = owned_link_dir, .color = options.color, .reference_trace = options.reference_trace, .formatted_panics = formatted_panics, @@ -1622,8 +1440,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, .debug_compile_errors = options.debug_compile_errors, .libcxx_abi_version = options.libcxx_abi_version, - .implib_emit = implib_emit, - .docs_emit = docs_emit, .root_name = root_name, .sysroot = sysroot, .system_libs = system_libs, @@ -1637,76 +1453,166 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .no_builtin = options.no_builtin, }; - if (bin_file_emit) |emit| { - comp.bin_file = try link.File.open(arena, .{ - .comp = comp, - .emit = emit, - .linker_script = options.linker_script, - .z_nodelete = options.linker_z_nodelete, - .z_notext = options.linker_z_notext, - .z_defs = options.linker_z_defs, - .z_origin = options.linker_z_origin, - .z_nocopyreloc = options.linker_z_nocopyreloc, - .z_now = options.linker_z_now, - .z_relro = options.linker_z_relro, - .z_common_page_size = options.linker_z_common_page_size, - .z_max_page_size = options.linker_z_max_page_size, - .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, - .frameworks = options.frameworks, - .wasi_emulated_libs = options.wasi_emulated_libs, - .lib_dirs = options.lib_dirs, - .rpath_list = options.rpath_list, - .symbol_wrap_set = options.symbol_wrap_set, - .function_sections = options.function_sections, - .data_sections = options.data_sections, - .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, - .module_definition_file = options.linker_module_definition_file, - .sort_section = options.linker_sort_section, - .import_symbols = options.linker_import_symbols, - .import_table = options.linker_import_table, - .export_table = options.linker_export_table, - .initial_memory = options.linker_initial_memory, - .max_memory = options.linker_max_memory, - .global_base = options.linker_global_base, - .export_symbol_names = options.linker_export_symbol_names, - .print_gc_sections = options.linker_print_gc_sections, - .print_icf_sections = options.linker_print_icf_sections, - .print_map = options.linker_print_map, - .tsaware = options.linker_tsaware, - .nxcompat = options.linker_nxcompat, - .dynamicbase = options.linker_dynamicbase, - .major_subsystem_version = options.major_subsystem_version, - .minor_subsystem_version = options.minor_subsystem_version, - .stack_size = options.stack_size, - .image_base = options.image_base, - .version_script = options.version_script, - .gc_sections = options.linker_gc_sections, - .eh_frame_hdr = link_eh_frame_hdr, - .emit_relocs = options.link_emit_relocs, - .rdynamic = options.rdynamic, - .soname = options.soname, - .compatibility_version = options.compatibility_version, - .dll_export_fns = dll_export_fns, - .each_lib_rpath = each_lib_rpath, - .build_id = build_id, - .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, - .subsystem = options.subsystem, - .debug_format = options.debug_format, - .hash_style = options.hash_style, - .enable_link_snapshots = options.enable_link_snapshots, - .install_name = options.install_name, - .entitlements = options.entitlements, - .pagezero_size = options.pagezero_size, - .headerpad_size = options.headerpad_size, - .headerpad_max_install_names = options.headerpad_max_install_names, - .dead_strip_dylibs = options.dead_strip_dylibs, - .force_undefined_symbols = options.force_undefined_symbols, - .pdb_source_path = options.pdb_source_path, - .pdb_out_path = options.pdb_out_path, - .entry_addr = null, // CLI does not expose this option (yet?) - }); + const lf_open_opts: link.File.OpenOptions = .{ + .comp = comp, + .linker_script = options.linker_script, + .z_nodelete = options.linker_z_nodelete, + .z_notext = options.linker_z_notext, + .z_defs = options.linker_z_defs, + .z_origin = options.linker_z_origin, + .z_nocopyreloc = options.linker_z_nocopyreloc, + .z_now = options.linker_z_now, + .z_relro = options.linker_z_relro, + .z_common_page_size = options.linker_z_common_page_size, + .z_max_page_size = options.linker_z_max_page_size, + .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, + .frameworks = options.frameworks, + .wasi_emulated_libs = options.wasi_emulated_libs, + .lib_dirs = options.lib_dirs, + .rpath_list = options.rpath_list, + .symbol_wrap_set = options.symbol_wrap_set, + .function_sections = options.function_sections, + .data_sections = options.data_sections, + .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, + .module_definition_file = options.linker_module_definition_file, + .sort_section = options.linker_sort_section, + .import_symbols = options.linker_import_symbols, + .import_table = options.linker_import_table, + .export_table = options.linker_export_table, + .initial_memory = options.linker_initial_memory, + .max_memory = options.linker_max_memory, + .global_base = options.linker_global_base, + .export_symbol_names = options.linker_export_symbol_names, + .print_gc_sections = options.linker_print_gc_sections, + .print_icf_sections = options.linker_print_icf_sections, + .print_map = options.linker_print_map, + .tsaware = options.linker_tsaware, + .nxcompat = options.linker_nxcompat, + .dynamicbase = options.linker_dynamicbase, + .major_subsystem_version = options.major_subsystem_version, + .minor_subsystem_version = options.minor_subsystem_version, + .stack_size = options.stack_size, + .image_base = options.image_base, + .version_script = options.version_script, + .gc_sections = options.linker_gc_sections, + .eh_frame_hdr = link_eh_frame_hdr, + .emit_relocs = options.link_emit_relocs, + .rdynamic = options.rdynamic, + .soname = options.soname, + .compatibility_version = options.compatibility_version, + .dll_export_fns = dll_export_fns, + .each_lib_rpath = each_lib_rpath, + .build_id = build_id, + .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, + .subsystem = options.subsystem, + .debug_format = options.debug_format, + .hash_style = options.hash_style, + .enable_link_snapshots = options.enable_link_snapshots, + .install_name = options.install_name, + .entitlements = options.entitlements, + .pagezero_size = options.pagezero_size, + .headerpad_size = options.headerpad_size, + .headerpad_max_install_names = options.headerpad_max_install_names, + .dead_strip_dylibs = options.dead_strip_dylibs, + .force_undefined_symbols = options.force_undefined_symbols, + .pdb_source_path = options.pdb_source_path, + .pdb_out_path = options.pdb_out_path, + .entry_addr = null, // CLI does not expose this option (yet?) + }; + + switch (cache_mode) { + .incremental => { + // Options that are specific to zig source files, that cannot be + // modified between incremental updates. + var hash = cache.hash; + + // Synchronize with other matching comments: ZigOnlyHashStuff + hash.add(use_llvm); + hash.add(options.config.use_lib_llvm); + hash.add(dll_export_fns); + hash.add(options.config.is_test); + hash.add(options.config.test_evented_io); + hash.addOptionalBytes(options.test_filter); + hash.addOptionalBytes(options.test_name_prefix); + hash.add(options.skip_linker_dependencies); + hash.add(formatted_panics); + hash.add(options.emit_h != null); + hash.add(error_limit); + + // Here we put the root source file path name, but *not* with addFile. + // We want the hash to be the same regardless of the contents of the + // source file, because incremental compilation will handle it, but we + // do want to namespace different source file names because they are + // likely different compilations and therefore this would be likely to + // cause cache hits. + try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, .path_bytes); + + // In the case of incremental cache mode, this `artifact_directory` + // is computed based on a hash of non-linker inputs, and it is where all + // build artifacts are stored (even while in-progress). + const digest = hash.final(); + const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest; + var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); + errdefer artifact_dir.close(); + const artifact_directory: Directory = .{ + .handle = artifact_dir, + .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), + }; + + const incremental = try arena.create(CacheUse.Incremental); + incremental.* = .{ + .artifact_directory = artifact_directory, + }; + comp.cache_use = .{ .incremental = incremental }; + + if (options.emit_bin) |emit_bin| { + const emit: Emit = .{ + .directory = emit_bin.directory orelse artifact_directory, + .sub_path = emit_bin.basename, + }; + comp.bin_file = try link.File.open(arena, emit, lf_open_opts); + } + + if (options.implib_emit) |emit_implib| { + comp.implib_emit = .{ + .directory = emit_implib.directory orelse artifact_directory, + .sub_path = emit_implib.basename, + }; + } + + if (options.docs_emit) |emit_docs| { + comp.docs_emit = .{ + .directory = emit_docs.directory orelse artifact_directory, + .sub_path = emit_docs.basename, + }; + } + }, + .whole => { + // For whole cache mode, we don't know where to put outputs from + // the linker until the final cache hash, which is available after + // the compilation is complete. + // + // Therefore, bin_file is left null until the beginning of update(), + // where it may find a cache hit, or use a temporary directory to + // hold output artifacts. + const whole = try arena.create(CacheUse.Whole); + whole.* = .{ + // This is kept here so that link.File.open can be called later. + .lf_open_opts = lf_open_opts, + // This is so that when doing `CacheMode.whole`, the mechanism in update() + // can use it for communicating the result directory via `bin_file.emit`. + // This is used to distinguish between -fno-emit-bin and -femit-bin + // for `CacheMode.whole`. + // This memory will be overwritten with the real digest in update() but + // the basename will be preserved. + .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin), + .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib), + .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs), + }; + comp.cache_use = .{ .whole = whole }; + }, } break :comp comp; @@ -1981,7 +1887,6 @@ pub fn destroy(self: *Compilation) void { self.clearMiscFailures(); self.cache_parent.manifest_dir.close(); - if (self.owned_link_dir) |*dir| dir.close(); // This destroys `self`. var arena_instance = self.arena; @@ -2001,30 +1906,6 @@ pub fn getTarget(self: Compilation) Target { return self.root_mod.resolved_target.result; } -fn restorePrevZigCacheArtifactDirectory(comp: *Compilation, directory: *Directory) void { - if (directory.path) |p| comp.gpa.free(p); - - // Restore the Module's previous zig_cache_artifact_directory - // This is only for cleanup purposes; Module.deinit calls close - // on the handle of zig_cache_artifact_directory. - if (comp.module) |module| { - const builtin_mod = module.main_mod.deps.get("builtin").?; - module.zig_cache_artifact_directory = builtin_mod.root.root_dir; - } -} - -fn cleanupTmpArtifactDirectory( - comp: *Compilation, - tmp_artifact_directory: *?Directory, - tmp_dir_sub_path: []const u8, -) void { - comp.gpa.free(tmp_dir_sub_path); - if (tmp_artifact_directory.*) |*directory| { - directory.handle.close(); - restorePrevZigCacheArtifactDirectory(comp, directory); - } -} - pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.ChildProcess.Id) !void { comp.bin_file.child_pid = pid; try comp.makeBinFileWritable(); @@ -2032,6 +1913,27 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C try comp.makeBinFileExecutable(); } +fn cleanupAfterUpdate(comp: *Compilation) void { + switch (comp) { + .incremental => return, + .whole => |whole| { + if (whole.cache_manifest) |man| { + man.deinit(); + whole.cache_manifest = null; + } + if (comp.bin_file) |lf| { + lf.destroy(); + comp.bin_file = null; + } + if (whole.tmp_artifact_directory) |directory| { + directory.handle.close(); + if (directory.path) |p| comp.gpa.free(p); + whole.tmp_artifact_directory = null; + } + }, + } +} + /// Detect changes to source files, perform semantic analysis, and update the output files. pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void { const tracy_trace = trace(@src()); @@ -2041,92 +1943,91 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void comp.last_update_was_cache_hit = false; var man: Cache.Manifest = undefined; - defer if (comp.whole_cache_manifest != null) man.deinit(); + defer cleanupAfterUpdate(comp); - var tmp_dir_sub_path: []const u8 = &.{}; - var tmp_artifact_directory: ?Directory = null; - defer cleanupTmpArtifactDirectory(comp, &tmp_artifact_directory, tmp_dir_sub_path); + var tmp_dir_rand_int: u64 = undefined; // If using the whole caching strategy, we check for *everything* up front, including // C source files. - if (comp.cache_mode == .whole) { - // We are about to obtain this lock, so here we give other processes a chance first. - if (comp.bin_file) |lf| lf.releaseLock(); - - man = comp.cache_parent.obtain(); - comp.whole_cache_manifest = &man; - try comp.addNonIncrementalStuffToCacheManifest(&man); - - const is_hit = man.hit() catch |err| { - // TODO properly bubble these up instead of emitting a warning - const i = man.failed_file_index orelse return err; - const pp = man.files.items[i].prefixed_path orelse return err; - const prefix = man.cache.prefixes()[pp.prefix].path orelse ""; - std.log.warn("{s}: {s}{s}", .{ @errorName(err), prefix, pp.sub_path }); - return err; - }; - if (is_hit) { - comp.last_update_was_cache_hit = true; - log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); - const digest = man.final(); - - comp.wholeCacheModeSetBinFilePath(&digest); + switch (comp.cache_use) { + .whole => |whole| { + // We are about to obtain this lock, so here we give other processes a chance first. + assert(comp.bin_file == null); + + man = comp.cache_parent.obtain(); + whole.cache_manifest = &man; + try comp.addNonIncrementalStuffToCacheManifest(&man); + + const is_hit = man.hit() catch |err| { + // TODO properly bubble these up instead of emitting a warning + const i = man.failed_file_index orelse return err; + const pp = man.files.items[i].prefixed_path orelse return err; + const prefix = man.cache.prefixes()[pp.prefix].path orelse ""; + std.log.warn("{s}: {s}{s}", .{ @errorName(err), prefix, pp.sub_path }); + return err; + }; + if (is_hit) { + comp.last_update_was_cache_hit = true; + log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); + const digest = man.final(); - assert(comp.bin_file.lock == null); - comp.bin_file.lock = man.toOwnedLock(); - return; - } - log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name}); + comp.wholeCacheModeSetBinFilePath(&digest); - // Initialize `bin_file.emit` with a temporary Directory so that compilation can - // continue on the same path as incremental, using the temporary Directory. - tmp_artifact_directory = d: { - const s = std.fs.path.sep_str; - const rand_int = std.crypto.random.int(u64); + assert(comp.bin_file.lock == null); + comp.bin_file.lock = man.toOwnedLock(); + return; + } + log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name}); - tmp_dir_sub_path = try std.fmt.allocPrint(comp.gpa, "tmp" ++ s ++ "{x}", .{rand_int}); + // Compile the artifacts to a temporary directory. + const tmp_artifact_directory = d: { + const s = std.fs.path.sep_str; + tmp_dir_rand_int = std.crypto.random.int(u64); + const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); - const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path}); - errdefer comp.gpa.free(path); + const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path}); + errdefer comp.gpa.free(path); - const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); - errdefer handle.close(); + const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); + errdefer handle.close(); - break :d .{ - .path = path, - .handle = handle, + break :d .{ + .path = path, + .handle = handle, + }; }; - }; + whole.tmp_artifact_directory = tmp_artifact_directory; - // This updates the output directory for linker outputs. - if (comp.module) |module| { - module.zig_cache_artifact_directory = tmp_artifact_directory.?; - } + // Now that the directory is known, it is time to create the Emit + // objects and call link.File.open. - // This resets the link.File to operate as if we called openPath() in create() - // instead of simulating -fno-emit-bin. - var options = comp.bin_file.options.move(); - if (comp.whole_bin_sub_path) |sub_path| { - options.emit = .{ - .directory = tmp_artifact_directory.?, - .sub_path = std.fs.path.basename(sub_path), - }; - } - if (comp.whole_implib_sub_path) |sub_path| { - options.implib_emit = .{ - .directory = tmp_artifact_directory.?, - .sub_path = std.fs.path.basename(sub_path), - }; - } - if (comp.whole_docs_sub_path) |sub_path| { - options.docs_emit = .{ - .directory = tmp_artifact_directory.?, - .sub_path = std.fs.path.basename(sub_path), - }; - } - var old_bin_file = comp.bin_file; - comp.bin_file = try link.File.openPath(comp.gpa, options); - old_bin_file.destroy(); + if (comp.whole_implib_sub_path) |sub_path| { + comp.implib_emit = .{ + .directory = tmp_artifact_directory, + .sub_path = std.fs.path.basename(sub_path), + }; + } + + if (comp.whole_docs_sub_path) |sub_path| { + comp.docs_emit = .{ + .directory = tmp_artifact_directory, + .sub_path = std.fs.path.basename(sub_path), + }; + } + + if (comp.whole_bin_sub_path) |sub_path| { + const emit: Emit = .{ + .directory = tmp_artifact_directory, + .sub_path = std.fs.path.basename(sub_path), + }; + // It's a bit strange to use the Compilation arena allocator here + // but in practice it won't leak much and usually whole cache mode + // will be combined with exactly one call to update(). + const arena = comp.arena.allocator(); + comp.bin_file = try link.File.open(arena, emit, whole.lf_open_opts); + } + }, + .incremental => {}, } // For compiling C objects, we rely on the cache hash system to avoid duplicating work. @@ -2231,80 +2132,43 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and // -femit-asm to handle, in the case of C objects. comp.emitOthers(); + try comp.flush(main_progress_node); + if (comp.totalErrorCount() != 0) return; + try maybeGenerateAutodocs(comp, main_progress_node); - if (comp.whole_cache_manifest != null) { - const digest = man.final(); - - // Rename the temporary directory into place. - var directory = tmp_artifact_directory.?; - tmp_artifact_directory = null; - - directory.handle.close(); - defer restorePrevZigCacheArtifactDirectory(comp, &directory); - - const o_sub_path = try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest }); - defer comp.gpa.free(o_sub_path); - - // Work around windows `AccessDenied` if any files within this directory are open - // by closing and reopening the file handles. - const need_writable_dance = builtin.os.tag == .windows and comp.bin_file.file != null; - if (need_writable_dance) { - // We cannot just call `makeExecutable` as it makes a false assumption that we have a - // file handle open only when linking an executable file. This used to be true when - // our linkers were incapable of emitting relocatables and static archive. Now that - // they are capable, we need to unconditionally close the file handle and re-open it - // in the follow up call to `makeWritable`. - comp.bin_file.file.?.close(); - comp.bin_file.file = null; - } - - try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); - comp.wholeCacheModeSetBinFilePath(&digest); + switch (comp.cache_use) { + .whole => |whole| { + const digest = man.final(); - // Has to be after the `wholeCacheModeSetBinFilePath` above. - if (need_writable_dance) { - try comp.bin_file.makeWritable(); - } + // Rename the temporary directory into place. + // Close tmp dir and link.File to avoid open handle during rename. + if (whole.tmp_artifact_directory) |tmp_directory| { + tmp_directory.handle.close(); + if (tmp_directory.path) |p| comp.gpa.free(p); + whole.tmp_artifact_directory = null; + } else unreachable; + + if (comp.bin_file) |lf| { + lf.destroy(); + comp.bin_file = null; + } - // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest(). - if (comp.module) |module| { - // We need to set the zig_cache_artifact_directory for -femit-asm, -femit-llvm-ir, - // etc to know where to output to. - var artifact_dir = try comp.local_cache_directory.handle.openDir(o_sub_path, .{}); - defer artifact_dir.close(); + const s = std.fs.path.sep_str; + const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); + const o_sub_path = "o" ++ s ++ digest; - const dir_path = try comp.local_cache_directory.join(comp.gpa, &.{o_sub_path}); - defer comp.gpa.free(dir_path); + try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); + comp.wholeCacheModeSetBinFilePath(&digest); - module.zig_cache_artifact_directory = .{ - .handle = artifact_dir, - .path = dir_path, + // Failure here only means an unnecessary cache miss. + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); }; - try comp.flush(main_progress_node); - if (comp.totalErrorCount() != 0) return; - - // Note the placement of this logic is relying on the call to - // `wholeCacheModeSetBinFilePath` above. - try maybeGenerateAutodocs(comp, main_progress_node); - } else { - try comp.flush(main_progress_node); - if (comp.totalErrorCount() != 0) return; - } - - // Failure here only means an unnecessary cache miss. - man.writeManifest() catch |err| { - log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); - }; - - assert(comp.bin_file.lock == null); - comp.bin_file.lock = man.toOwnedLock(); - } else { - try comp.flush(main_progress_node); - - if (comp.totalErrorCount() == 0) { - try maybeGenerateAutodocs(comp, main_progress_node); - } + assert(comp.bin_file.lock == null); + comp.bin_file.lock = man.toOwnedLock(); + }, + .incremental => {}, } // Unload all source files to save memory. @@ -2321,6 +2185,60 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } } +/// This function is called by the frontend before flush(). It communicates that +/// `options.bin_file.emit` directory needs to be renamed from +/// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`. +/// The frontend would like to simply perform a file system rename, however, +/// some linker backends care about the file paths of the objects they are linking. +/// So this function call tells linker backends to rename the paths of object files +/// to observe the new directory path. +/// Linker backends which do not have this requirement can fall back to the simple +/// implementation at the bottom of this function. +/// This function is only called when CacheMode is `whole`. +fn renameTmpIntoCache( + cache_directory: Compilation.Directory, + tmp_dir_sub_path: []const u8, + o_sub_path: []const u8, +) !void { + while (true) { + if (builtin.os.tag == .windows) { + // Work around windows `renameW` can't fail with `PathAlreadyExists` + // See https://github.com/ziglang/zig/issues/8362 + if (cache_directory.handle.access(o_sub_path, .{})) |_| { + try cache_directory.handle.deleteTree(o_sub_path); + continue; + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return e, + } + std.fs.rename( + cache_directory.handle, + tmp_dir_sub_path, + cache_directory.handle, + o_sub_path, + ) catch |err| { + log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) }); + return err; + }; + break; + } else { + std.fs.rename( + cache_directory.handle, + tmp_dir_sub_path, + cache_directory.handle, + o_sub_path, + ) catch |err| switch (err) { + error.PathAlreadyExists => { + try cache_directory.handle.deleteTree(o_sub_path); + continue; + }, + else => |e| return e, + }; + break; + } + } +} + fn maybeGenerateAutodocs(comp: *Compilation, prog_node: *std.Progress.Node) !void { const mod = comp.module orelse return; // TODO: do this in a separate job during performAllTheWork(). The @@ -2362,7 +2280,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di if (comp.whole_bin_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); - comp.bin_file.options.emit = .{ + comp.bin_file.?.emit = .{ .directory = comp.local_cache_directory, .sub_path = sub_path, }; @@ -2371,7 +2289,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di if (comp.whole_implib_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); - comp.bin_file.options.implib_emit = .{ + comp.implib_emit = .{ .directory = comp.local_cache_directory, .sub_path = sub_path, }; @@ -2380,7 +2298,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di if (comp.whole_docs_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); - comp.bin_file.options.docs_emit = .{ + comp.docs_emit = .{ .directory = comp.local_cache_directory, .sub_path = sub_path, }; diff --git a/src/Module.zig b/src/Module.zig index aa107ea3f79d..e32bad72950c 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -52,8 +52,6 @@ comptime { gpa: Allocator, comp: *Compilation, -/// Where build artifacts and incremental compilation metadata serialization go. -zig_cache_artifact_directory: Compilation.Directory, /// Pointer to externally managed resource. root_mod: *Package.Module, /// Normally, `main_mod` and `root_mod` are the same. The exception is `zig test`, in which @@ -2508,7 +2506,6 @@ pub fn deinit(mod: *Module) void { emit_h.failed_decls.deinit(gpa); emit_h.decl_table.deinit(gpa); emit_h.allocated_emit_h.deinit(gpa); - gpa.destroy(emit_h); } for (mod.failed_files.values()) |value| { diff --git a/src/link.zig b/src/link.zig index 5908a07dec47..2a61e4696994 100644 --- a/src/link.zig +++ b/src/link.zig @@ -32,8 +32,6 @@ pub const SystemLib = struct { path: ?[]const u8, }; -pub const CacheMode = enum { incremental, whole }; - pub fn hashAddSystemLibs( man: *Cache.Manifest, hm: std.StringArrayHashMapUnmanaged(SystemLib), @@ -776,67 +774,6 @@ pub const File = struct { } } - /// This function is called by the frontend before flush(). It communicates that - /// `options.bin_file.emit` directory needs to be renamed from - /// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`. - /// The frontend would like to simply perform a file system rename, however, - /// some linker backends care about the file paths of the objects they are linking. - /// So this function call tells linker backends to rename the paths of object files - /// to observe the new directory path. - /// Linker backends which do not have this requirement can fall back to the simple - /// implementation at the bottom of this function. - /// This function is only called when CacheMode is `whole`. - pub fn renameTmpIntoCache( - base: *File, - cache_directory: Compilation.Directory, - tmp_dir_sub_path: []const u8, - o_sub_path: []const u8, - ) !void { - // So far, none of the linker backends need to respond to this event, however, - // it makes sense that they might want to. So we leave this mechanism here - // for now. Once the linker backends get more mature, if it turns out this - // is not needed we can refactor this into having the frontend do the rename - // directly, and remove this function from link.zig. - _ = base; - while (true) { - if (builtin.os.tag == .windows) { - // Work around windows `renameW` can't fail with `PathAlreadyExists` - // See https://github.com/ziglang/zig/issues/8362 - if (cache_directory.handle.access(o_sub_path, .{})) |_| { - try cache_directory.handle.deleteTree(o_sub_path); - continue; - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return e, - } - std.fs.rename( - cache_directory.handle, - tmp_dir_sub_path, - cache_directory.handle, - o_sub_path, - ) catch |err| { - log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) }); - return err; - }; - break; - } else { - std.fs.rename( - cache_directory.handle, - tmp_dir_sub_path, - cache_directory.handle, - o_sub_path, - ) catch |err| switch (err) { - error.PathAlreadyExists => { - try cache_directory.handle.deleteTree(o_sub_path); - continue; - }, - else => |e| return e, - }; - break; - } - } - } - pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { const tracy = trace(@src()); defer tracy.end(); From f54471b54c471bb6f8e51a1383be09d01c24d0c3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Dec 2023 16:41:20 -0700 Subject: [PATCH 041/133] compiler: miscellaneous branch progress implement builtin.zig file population for all modules rather than assuming there is only one global builtin.zig module. move some fields from link.File to Compilation move some fields from Module to Compilation compute debug_format in global Compilation config resolution wire up C compilation to the concept of owner modules make whole cache mode call link.File.createEmpty() instead of link.File.open() --- src/Builtin.zig | 62 ++++++++++++- src/Compilation.zig | 183 +++++++++++++++++++++---------------- src/Compilation/Config.zig | 31 +++++++ src/Module.zig | 69 -------------- src/Package/Module.zig | 31 ++++++- src/Sema.zig | 7 +- src/codegen/llvm.zig | 16 +--- src/libunwind.zig | 3 +- src/link.zig | 41 +++++---- src/link/C.zig | 26 +++--- src/link/Coff.zig | 42 +++++---- src/link/Coff/lld.zig | 2 +- src/link/Elf.zig | 48 +++++----- src/link/Elf/Object.zig | 3 +- src/link/Elf/ZigObject.zig | 12 ++- src/link/MachO.zig | 39 ++++---- src/link/NvPtx.zig | 33 ++++--- src/link/Plan9.zig | 36 +++++--- src/link/SpirV.zig | 35 ++++--- src/link/Wasm.zig | 41 +++++---- src/main.zig | 33 ++++--- 21 files changed, 457 insertions(+), 336 deletions(-) diff --git a/src/Builtin.zig b/src/Builtin.zig index 7224a6fd24fb..4c8038019c10 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -20,8 +20,11 @@ wasi_exec_model: std.builtin.WasiExecModel, pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 { var buffer = std.ArrayList(u8).init(allocator); - defer buffer.deinit(); + try append(opts, &buffer); + return buffer.toOwnedSliceSentinel(0); +} +pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { const target = opts.target; const generic_arch_name = target.cpu.arch.genericName(); const zig_backend = opts.zig_backend; @@ -231,10 +234,65 @@ pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 { ); } } +} - return buffer.toOwnedSliceSentinel(0); +pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { + assert(file.source_loaded == true); + + if (mod.root.statFile(mod.root_src_path)) |stat| { + if (stat.size != file.source.len) { + std.log.warn( + "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++ + "Overwriting with correct file contents now", + .{ mod.root, mod.root_src_path, file.source.len, stat.size }, + ); + + try writeFile(file, mod); + } else { + file.stat = .{ + .size = stat.size, + .inode = stat.inode, + .mtime = stat.mtime, + }; + } + } else |err| switch (err) { + error.BadPathName => unreachable, // it's always "builtin.zig" + error.NameTooLong => unreachable, // it's always "builtin.zig" + error.PipeBusy => unreachable, // it's not a pipe + error.WouldBlock => unreachable, // not asking for non-blocking I/O + + error.FileNotFound => try writeFile(file, mod), + + else => |e| return e, + } + + file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig); + file.tree_loaded = true; + assert(file.tree.errors.len == 0); // builtin.zig must parse + + file.zir = try AstGen.generate(comp.gpa, file.tree); + file.zir_loaded = true; + file.status = .success_zir; +} + +fn writeFile(file: *File, mod: *Module) !void { + var af = try mod.root.atomicFile(mod.root_src_path, .{}); + defer af.deinit(); + try af.file.writeAll(file.source); + try af.finish(); + + file.stat = .{ + .size = file.source.len, + .inode = 0, // dummy value + .mtime = 0, // dummy value + }; } const std = @import("std"); const Allocator = std.mem.Allocator; const build_options = @import("build_options"); +const Module = @import("Package/Module.zig"); +const assert = std.debug.assert; +const AstGen = @import("AstGen.zig"); +const File = @import("Module.zig").File; +const Compilation = @import("Compilation.zig"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 8cf7a66fbc80..35ee24361732 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -37,6 +37,7 @@ const Zir = @import("Zir.zig"); const Autodoc = @import("Autodoc.zig"); const Color = @import("main.zig").Color; const resinator = @import("resinator.zig"); +const Builtin = @import("Builtin.zig"); pub const Config = @import("Compilation/Config.zig"); @@ -59,7 +60,10 @@ root_mod: *Package.Module, /// User-specified settings that have all the defaults resolved into concrete values. config: Config, -/// This is `null` when `-fno-emit-bin` is used. +/// The main output file. +/// In whole cache mode, this is null except for during the body of the update +/// function. In incremental cache mode, this is a long-lived object. +/// In both cases, this is `null` when `-fno-emit-bin` is used. bin_file: ?*link.File, /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) @@ -80,6 +84,8 @@ version: ?std.SemanticVersion, libc_installation: ?*const LibCInstallation, skip_linker_dependencies: bool, no_builtin: bool, +function_sections: bool, +data_sections: bool, c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = @@ -120,7 +126,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std /// Miscellaneous things that can fail. misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{}, -keep_source_files_loaded: bool, /// When this is `true` it means invoking clang as a sub-process is expected to inherit /// stdin, stdout, stderr, and if it returns non success, to forward the exit code. /// Otherwise we attempt to parse the error messages and expose them via the Compilation API. @@ -144,6 +149,7 @@ debug_compiler_runtime_libs: bool, debug_compile_errors: bool, job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, +job_queued_update_builtin_zig: bool, alloc_failure_occurred: bool = false, formatted_panics: bool = false, last_update_was_cache_hit: bool = false, @@ -814,13 +820,13 @@ pub const cache_helpers = struct { addEmitLoc(hh, optional_emit_loc orelse return); } - pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?link.File.DebugFormat) void { + pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void { hh.add(x != null); addDebugFormat(hh, x orelse return); } - pub fn addDebugFormat(hh: *Cache.HashHelper, x: link.File.DebugFormat) void { - const tag: @typeInfo(link.File.DebugFormat).Union.tag_type.? = x; + pub fn addDebugFormat(hh: *Cache.HashHelper, x: Config.DebugFormat) void { + const tag: @typeInfo(Config.DebugFormat).Union.tag_type.? = x; hh.add(tag); switch (x) { .strip, .code_view => {}, @@ -860,11 +866,11 @@ pub const SystemLib = link.SystemLib; pub const CacheMode = enum { incremental, whole }; -pub const CacheUse = union(CacheMode) { +const CacheUse = union(CacheMode) { incremental: *Incremental, whole: *Whole, - pub const Whole = struct { + const Whole = struct { /// This is a pointer to a local variable inside `update()`. cache_manifest: ?*Cache.Manifest = null, cache_manifest_mutex: std.Thread.Mutex = .{}, @@ -873,12 +879,14 @@ pub const CacheUse = union(CacheMode) { /// of exactly the correct size for "o/[digest]/[basename]". /// The basename is of the outputted binary file in case we don't know the directory yet. bin_sub_path: ?[]u8, - /// Same as `whole_bin_sub_path` but for implibs. + /// Same as `bin_sub_path` but for implibs. implib_sub_path: ?[]u8, docs_sub_path: ?[]u8, + lf_open_opts: link.File.OpenOptions, + tmp_artifact_directory: ?Cache.Directory, }; - pub const Incremental = struct { + const Incremental = struct { /// Where build artifacts and incremental compilation metadata serialization go. artifact_directory: Compilation.Directory, }; @@ -937,7 +945,6 @@ pub const InitOptions = struct { /// this flag would be set to disable this machinery to avoid false positives. disable_lld_caching: bool = false, cache_mode: CacheMode = .incremental, - keep_source_files_loaded: bool = false, lib_dirs: []const []const u8 = &[0][]const u8{}, rpath_list: []const []const u8 = &[0][]const u8{}, symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}, @@ -1040,7 +1047,6 @@ pub const InitOptions = struct { test_name_prefix: ?[]const u8 = null, test_runner_path: ?[]const u8 = null, subsystem: ?std.Target.SubSystem = null, - debug_format: ?link.File.DebugFormat = null, /// (Zig compiler development) Enable dumping linker's state as JSON. enable_link_snapshots: bool = false, /// (Darwin) Install name of the dylib @@ -1327,7 +1333,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.config.link_libcpp); cache.hash.add(options.config.link_libunwind); cache.hash.add(output_mode); - cache_helpers.addOptionalDebugFormat(&cache.hash, options.debug_format); + cache_helpers.addDebugFormat(&cache.hash, comp.config.debug_format); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); @@ -1380,7 +1386,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }; errdefer if (opt_zcu) |zcu| zcu.deinit(); - const system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init( + var system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init( gpa, options.system_lib_names, options.system_lib_infos, @@ -1409,7 +1415,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa), - .keep_source_files_loaded = options.keep_source_files_loaded, .c_source_files = options.c_source_files, .rc_source_files = options.rc_source_files, .cache_parent = cache, @@ -1451,10 +1456,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit, .skip_linker_dependencies = options.skip_linker_dependencies, .no_builtin = options.no_builtin, + .job_queued_update_builtin_zig = have_zcu, + .function_sections = options.function_sections, + .data_sections = options.data_sections, }; const lf_open_opts: link.File.OpenOptions = .{ - .comp = comp, .linker_script = options.linker_script, .z_nodelete = options.linker_z_nodelete, .z_notext = options.linker_z_notext, @@ -1471,8 +1478,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .lib_dirs = options.lib_dirs, .rpath_list = options.rpath_list, .symbol_wrap_set = options.symbol_wrap_set, - .function_sections = options.function_sections, - .data_sections = options.data_sections, .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, @@ -1507,7 +1512,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .build_id = build_id, .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, .subsystem = options.subsystem, - .debug_format = options.debug_format, .hash_style = options.hash_style, .enable_link_snapshots = options.enable_link_snapshots, .install_name = options.install_name, @@ -1572,17 +1576,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .directory = emit_bin.directory orelse artifact_directory, .sub_path = emit_bin.basename, }; - comp.bin_file = try link.File.open(arena, emit, lf_open_opts); + comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts); } - if (options.implib_emit) |emit_implib| { + if (options.emit_implib) |emit_implib| { comp.implib_emit = .{ .directory = emit_implib.directory orelse artifact_directory, .sub_path = emit_implib.basename, }; } - if (options.docs_emit) |emit_docs| { + if (options.emit_docs) |emit_docs| { comp.docs_emit = .{ .directory = emit_docs.directory orelse artifact_directory, .sub_path = emit_docs.basename, @@ -1610,6 +1614,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin), .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib), .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs), + .tmp_artifact_directory = null, }; comp.cache_use = .{ .whole = whole }; }, @@ -1662,7 +1667,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } } - const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null; + const have_bin_emit = switch (comp.cache_use) { + .whole => |whole| whole.bin_sub_path != null, + .incremental => comp.bin_file != null, + }; if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) { if (target.isDarwin()) { @@ -1814,8 +1822,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { pub fn destroy(self: *Compilation) void { if (self.bin_file) |lf| lf.destroy(); if (self.module) |zcu| zcu.deinit(); + switch (self.cache_use) { + .incremental => |incremental| { + incremental.artifact_directory.handle.close(); + }, + .whole => {}, + } - const gpa = self.gpa; self.work_queue.deinit(); self.anon_work_queue.deinit(); self.c_object_work_queue.deinit(); @@ -1825,6 +1838,9 @@ pub fn destroy(self: *Compilation) void { self.astgen_work_queue.deinit(); self.embed_file_work_queue.deinit(); + const gpa = self.gpa; + self.system_libs.deinit(gpa); + { var it = self.crt_files.iterator(); while (it.next()) |entry| { @@ -1914,7 +1930,7 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C } fn cleanupAfterUpdate(comp: *Compilation) void { - switch (comp) { + switch (comp.cache_use) { .incremental => return, .whole => |whole| { if (whole.cache_manifest) |man| { @@ -1971,7 +1987,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); const digest = man.final(); - comp.wholeCacheModeSetBinFilePath(&digest); + comp.wholeCacheModeSetBinFilePath(whole, &digest); assert(comp.bin_file.lock == null); comp.bin_file.lock = man.toOwnedLock(); @@ -2001,21 +2017,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Now that the directory is known, it is time to create the Emit // objects and call link.File.open. - if (comp.whole_implib_sub_path) |sub_path| { + if (whole.implib_sub_path) |sub_path| { comp.implib_emit = .{ .directory = tmp_artifact_directory, .sub_path = std.fs.path.basename(sub_path), }; } - if (comp.whole_docs_sub_path) |sub_path| { + if (whole.docs_sub_path) |sub_path| { comp.docs_emit = .{ .directory = tmp_artifact_directory, .sub_path = std.fs.path.basename(sub_path), }; } - if (comp.whole_bin_sub_path) |sub_path| { + if (whole.bin_sub_path) |sub_path| { const emit: Emit = .{ .directory = tmp_artifact_directory, .sub_path = std.fs.path.basename(sub_path), @@ -2024,7 +2040,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // but in practice it won't leak much and usually whole cache mode // will be combined with exactly one call to update(). const arena = comp.arena.allocator(); - comp.bin_file = try link.File.open(arena, emit, whole.lf_open_opts); + comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts); } }, .incremental => {}, @@ -2158,7 +2174,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void const o_sub_path = "o" ++ s ++ digest; try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); - comp.wholeCacheModeSetBinFilePath(&digest); + comp.wholeCacheModeSetBinFilePath(whole, &digest); // Failure here only means an unnecessary cache miss. man.writeManifest() catch |err| { @@ -2170,19 +2186,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void }, .incremental => {}, } - - // Unload all source files to save memory. - // The ZIR needs to stay loaded in memory because (1) Decl objects contain references - // to it, and (2) generic instantiations, comptime calls, inline calls will need - // to reference the ZIR. - if (!comp.keep_source_files_loaded) { - if (comp.module) |module| { - for (module.import_table.values()) |file| { - file.unloadTree(comp.gpa); - file.unloadSource(comp.gpa); - } - } - } } /// This function is called by the frontend before flush(). It communicates that @@ -2274,10 +2277,14 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void { } /// Communicate the output binary location to parent Compilations. -fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_digest_len]u8) void { +fn wholeCacheModeSetBinFilePath( + comp: *Compilation, + whole: *CacheUse.Whole, + digest: *const [Cache.hex_digest_len]u8, +) void { const digest_start = 2; // "o/[digest]/[basename]" - if (comp.whole_bin_sub_path) |sub_path| { + if (whole.bin_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); comp.bin_file.?.emit = .{ @@ -2286,7 +2293,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di }; } - if (comp.whole_implib_sub_path) |sub_path| { + if (whole.implib_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); comp.implib_emit = .{ @@ -2295,7 +2302,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di }; } - if (comp.whole_docs_sub_path) |sub_path| { + if (whole.docs_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); comp.docs_emit = .{ @@ -3232,13 +3239,25 @@ pub fn performAllTheWork( // 1. to avoid race condition of zig processes truncating each other's builtin.zig files // 2. optimization; in the hot path it only incurs a stat() syscall, which happens // in the `astgen_wait_group`. - if (comp.module) |mod| { - if (mod.job_queued_update_builtin_zig) { - mod.job_queued_update_builtin_zig = false; + if (comp.job_queued_update_builtin_zig) b: { + comp.job_queued_update_builtin_zig = false; + const zcu = comp.module orelse break :b; + _ = zcu; + // TODO put all the modules in a flat array to make them easy to iterate. + var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{}; + defer seen.deinit(comp.gpa); + try seen.put(comp.gpa, comp.root_mod); + var i: usize = 0; + while (i < seen.count()) : (i += 1) { + const mod = seen.keys()[i]; + for (mod.deps.values()) |dep| + try seen.put(comp.gpa, dep); + + const file = mod.builtin_file orelse continue; comp.astgen_wait_group.start(); try comp.thread_pool.spawn(workerUpdateBuiltinZigFile, .{ - comp, mod, &comp.astgen_wait_group, + comp, mod, file, &comp.astgen_wait_group, }); } } @@ -3702,19 +3721,17 @@ fn workerAstGenFile( fn workerUpdateBuiltinZigFile( comp: *Compilation, - mod: *Module, + mod: *Package.Module, + file: *Module.File, wg: *WaitGroup, ) void { defer wg.finish(); - - mod.populateBuiltinFile() catch |err| { - const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse "."; - + Builtin.populateFile(comp, mod, file) catch |err| { comp.mutex.lock(); defer comp.mutex.unlock(); - comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{ - dir_path, @errorName(err), + comp.setMiscFailure(.write_builtin_zig, "unable to write '{}{s}': {s}", .{ + mod.root, mod.root_src_path, @errorName(err), }); }; } @@ -3755,14 +3772,17 @@ fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !voi @panic("TODO: handle embed file incremental update"); } -pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest { +pub fn obtainCObjectCacheManifest( + comp: *const Compilation, + owner_mod: *Package.Module, +) Cache.Manifest { var man = comp.cache_parent.obtain(); // Only things that need to be added on top of the base hash, and only things // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. - man.hash.add(comp.sanitize_c); - man.hash.addListOfBytes(comp.clang_argv); + man.hash.add(owner_mod.sanitize_c); + man.hash.addListOfBytes(owner_mod.clang_argv); man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list @@ -3797,19 +3817,19 @@ pub const CImportResult = struct { /// Caller owns returned memory. /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked /// a bit when we want to start using it from self-hosted. -pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { +pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build"); const tracy_trace = trace(@src()); defer tracy_trace.end(); const cimport_zig_basename = "cimport.zig"; - var man = comp.obtainCObjectCacheManifest(); + var man = comp.obtainCObjectCacheManifest(owner_mod); defer man.deinit(); man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects man.hash.addBytes(c_src); - man.hash.add(comp.c_frontend); + man.hash.add(comp.config.c_frontend); // If the previous invocation resulted in clang errors, we will see a hit // here with 0 files in the manifest, in which case it is actually a miss. @@ -3846,15 +3866,15 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { var argv = std.ArrayList([]const u8).init(comp.gpa); defer argv.deinit(); - try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1] - try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path); + try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1] + try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod); try argv.append(out_h_path); if (comp.verbose_cc) { dump_argv(argv.items); } - var tree = switch (comp.c_frontend) { + var tree = switch (comp.config.c_frontend) { .aro => tree: { const translate_c = @import("aro_translate_c.zig"); _ = translate_c; @@ -4119,7 +4139,7 @@ fn reportRetryableEmbedFileError( } fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void { - if (comp.c_frontend == .aro) { + if (comp.config.c_frontend == .aro) { return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{}); } if (!build_options.have_llvm) { @@ -4142,7 +4162,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P _ = comp.failed_c_objects.swapRemove(c_object); } - var man = comp.obtainCObjectCacheManifest(); + var man = comp.obtainCObjectCacheManifest(c_object.src.owner); defer man.deinit(); man.hash.add(comp.clang_preprocessor_mode); @@ -4219,7 +4239,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P if (std.process.can_execv and direct_o and comp.disable_c_depfile and comp.clang_passthrough_mode) { - try comp.addCCArgs(arena, &argv, ext, null); + try comp.addCCArgs(arena, &argv, ext, null, c_object.src.owner); try argv.appendSlice(c_object.src.extra_flags); try argv.appendSlice(c_object.src.cache_exempt_flags); @@ -4262,7 +4282,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P null else try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path}); - try comp.addCCArgs(arena, &argv, ext, out_dep_path); + try comp.addCCArgs(arena, &argv, ext, out_dep_path, c_object.src.owner); try argv.appendSlice(c_object.src.extra_flags); try argv.appendSlice(c_object.src.cache_exempt_flags); @@ -4610,7 +4630,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // mode. While these defines are not normally present when calling rc.exe directly, // them being defined matches the behavior of how MSVC calls rc.exe which is the more // relevant behavior in this case. - try comp.addCCArgs(arena, &argv, .rc, out_dep_path); + try comp.addCCArgs(arena, &argv, .rc, out_dep_path, rc_src.owner); if (comp.verbose_cc) { dump_argv(argv.items); @@ -4788,11 +4808,12 @@ pub fn addTranslateCCArgs( argv: *std.ArrayList([]const u8), ext: FileExt, out_dep_path: ?[]const u8, + owner_mod: *Package.Module, ) !void { - try argv.appendSlice(&[_][]const u8{ "-x", "c" }); - try comp.addCCArgs(arena, argv, ext, out_dep_path); + try argv.appendSlice(&.{ "-x", "c" }); + try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); // This gives us access to preprocessing entities, presumably at the cost of performance. - try argv.appendSlice(&[_][]const u8{ "-Xclang", "-detailed-preprocessing-record" }); + try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); } /// Add common C compiler args between translate-c and C object compilation. @@ -4825,11 +4846,11 @@ pub fn addCCArgs( try argv.append("-fno-caret-diagnostics"); } - if (comp.bin_file.function_sections) { + if (comp.function_sections) { try argv.append("-ffunction-sections"); } - if (comp.bin_file.data_sections) { + if (comp.data_sections) { try argv.append("-fdata-sections"); } @@ -5088,7 +5109,7 @@ pub fn addCCArgs( try argv.append("-fPIC"); } - if (comp.unwind_tables) { + if (mod.unwind_tables) { try argv.append("-funwind-tables"); } else { try argv.append("-fno-unwind-tables"); @@ -5174,7 +5195,7 @@ pub fn addCCArgs( } try argv.ensureUnusedCapacity(2); - switch (comp.bin_file.debug_format) { + switch (comp.config.debug_format) { .strip => {}, .code_view => { // -g is required here because -gcodeview doesn't trigger debug info @@ -5210,7 +5231,7 @@ pub fn addCCArgs( try argv.append("-ffreestanding"); } - try argv.appendSlice(comp.clang_argv); + try argv.appendSlice(mod.cc_argv); } fn failCObj( @@ -6094,6 +6115,7 @@ fn buildOutputFromZig( .have_zcu = true, .emit_bin = true, .root_optimize_mode = comp.compilerRtOptMode(), + .root_strip = comp.compilerRtStrip(), .link_libc = comp.config.link_libc, .any_unwind_tables = unwind_tables, }); @@ -6198,6 +6220,7 @@ pub fn build_crt_file( .have_zcu = false, .emit_bin = true, .root_optimize_mode = comp.compilerRtOptMode(), + .root_strip = comp.compilerRtStrip(), .link_libc = false, .lto = switch (output_mode) { .Lib => comp.config.lto, diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index aba21e4bfe8d..0afb633c86a5 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -33,9 +33,16 @@ shared_memory: bool, is_test: bool, test_evented_io: bool, entry: ?[]const u8, +debug_format: DebugFormat, pub const CFrontend = enum { clang, aro }; +pub const DebugFormat = union(enum) { + strip, + dwarf: std.dwarf.Format, + code_view, +}; + pub const Options = struct { output_mode: std.builtin.OutputMode, resolved_target: Module.ResolvedTarget, @@ -43,6 +50,7 @@ pub const Options = struct { have_zcu: bool, emit_bin: bool, root_optimize_mode: ?std.builtin.OptimizeMode = null, + root_strip: ?bool = null, link_mode: ?std.builtin.LinkMode = null, ensure_libc_on_non_freestanding: bool = false, ensure_libcpp_on_non_freestanding: bool = false, @@ -51,6 +59,7 @@ pub const Options = struct { any_unwind_tables: bool = false, any_dyn_libs: bool = false, any_c_source_files: bool = false, + any_non_stripped: bool = false, emit_llvm_ir: bool = false, emit_llvm_bc: bool = false, link_libc: ?bool = null, @@ -74,6 +83,7 @@ pub const Options = struct { export_memory: ?bool = null, shared_memory: ?bool = null, test_evented_io: bool = false, + debug_format: ?Config.DebugFormat = null, }; pub fn resolve(options: Options) !Config { @@ -365,6 +375,26 @@ pub fn resolve(options: Options) !Config { break :b false; }; + const root_strip = b: { + if (options.root_strip) |x| break :b x; + if (root_optimize_mode == .ReleaseSmall) break :b true; + if (!target_util.hasDebugInfo(target)) break :b true; + break :b false; + }; + + const debug_format: DebugFormat = b: { + if (root_strip and !options.any_non_stripped) break :b .strip; + break :b switch (target.ofmt) { + .elf, .macho, .wasm => .{ .dwarf = .@"32" }, + .coff => .code_view, + .c => switch (target.os.tag) { + .windows, .uefi => .code_view, + else => .{ .dwarf = .@"32" }, + }, + .spirv, .nvptx, .dxcontainer, .hex, .raw, .plan9 => .strip, + }; + }; + return .{ .output_mode = options.output_mode, .have_zcu = options.have_zcu, @@ -388,6 +418,7 @@ pub fn resolve(options: Options) !Config { .use_lld = use_lld, .entry = entry, .wasi_exec_model = wasi_exec_model, + .debug_format = debug_format, }; } diff --git a/src/Module.zig b/src/Module.zig index e32bad72950c..121f639f6bed 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -152,8 +152,6 @@ stage1_flags: packed struct { reserved: u2 = 0, } = .{}, -job_queued_update_builtin_zig: bool = true, - compile_log_text: ArrayListUnmanaged(u8) = .{}, emit_h: ?*GlobalEmitH, @@ -2490,7 +2488,6 @@ pub fn deinit(mod: *Module) void { mod.compile_log_text.deinit(gpa); - mod.zig_cache_artifact_directory.handle.close(); mod.local_zir_cache.handle.close(); mod.global_zir_cache.handle.close(); @@ -3075,72 +3072,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { } } -pub fn populateBuiltinFile(mod: *Module) !void { - const tracy = trace(@src()); - defer tracy.end(); - - const comp = mod.comp; - const builtin_mod, const file = blk: { - comp.mutex.lock(); - defer comp.mutex.unlock(); - - const builtin_mod = mod.main_mod.deps.get("builtin").?; - const result = try mod.importPkg(builtin_mod); - break :blk .{ builtin_mod, result.file }; - }; - const gpa = mod.gpa; - file.source = try comp.generateBuiltinZigSource(gpa); - file.source_loaded = true; - - if (builtin_mod.root.statFile(builtin_mod.root_src_path)) |stat| { - if (stat.size != file.source.len) { - log.warn( - "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++ - "Overwriting with correct file contents now", - .{ builtin_mod.root, builtin_mod.root_src_path, file.source.len, stat.size }, - ); - - try writeBuiltinFile(file, builtin_mod); - } else { - file.stat = .{ - .size = stat.size, - .inode = stat.inode, - .mtime = stat.mtime, - }; - } - } else |err| switch (err) { - error.BadPathName => unreachable, // it's always "builtin.zig" - error.NameTooLong => unreachable, // it's always "builtin.zig" - error.PipeBusy => unreachable, // it's not a pipe - error.WouldBlock => unreachable, // not asking for non-blocking I/O - - error.FileNotFound => try writeBuiltinFile(file, builtin_mod), - - else => |e| return e, - } - - file.tree = try Ast.parse(gpa, file.source, .zig); - file.tree_loaded = true; - assert(file.tree.errors.len == 0); // builtin.zig must parse - - file.zir = try AstGen.generate(gpa, file.tree); - file.zir_loaded = true; - file.status = .success_zir; -} - -fn writeBuiltinFile(file: *File, builtin_mod: *Package.Module) !void { - var af = try builtin_mod.root.atomicFile(builtin_mod.root_src_path, .{}); - defer af.deinit(); - try af.file.writeAll(file.source); - try af.finish(); - - file.stat = .{ - .size = file.source.len, - .inode = 0, // dummy value - .mtime = 0, // dummy value - }; -} - pub fn mapOldZirToNew( gpa: Allocator, old_zir: Zir, diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 091674287635..051303ca26f1 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -33,11 +33,16 @@ 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, +/// If the module is an `@import("builtin")` module, this is the `File` that +/// is preallocated for it. Otherwise this field is null. +builtin_file: ?*File, pub const Deps = std.StringArrayHashMapUnmanaged(*Module); +pub fn isBuiltin(m: Module) bool { + return m.file != null; +} + pub const Tree = struct { /// Each `Package` exposes a `Module` with build.zig as its root source file. build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module), @@ -329,6 +334,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .wasi_exec_model = options.global.wasi_exec_model, }, arena); + const new_file = try arena.create(File); + const digest = Cache.HashHelper.oneShot(generated_builtin_source); const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest); const new = try arena.create(Module); @@ -359,12 +366,25 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .stack_protector = stack_protector, .code_model = code_model, .red_zone = red_zone, - .generated_builtin_source = generated_builtin_source, .sanitize_c = sanitize_c, .sanitize_thread = sanitize_thread, .unwind_tables = unwind_tables, .cc_argv = &.{}, .structured_cfg = structured_cfg, + .builtin_file = new_file, + }; + new_file.* = .{ + .sub_file_path = "builtin.zig", + .source = generated_builtin_source, + .source_loaded = true, + .tree_loaded = false, + .zir_loaded = false, + .stat = undefined, + .tree = undefined, + .zir = undefined, + .status = .never_loaded, + .mod = new, + .root_decl = .none, }; break :b new; }; @@ -391,12 +411,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .stack_protector = stack_protector, .code_model = code_model, .red_zone = red_zone, - .generated_builtin_source = builtin_mod.generated_builtin_source, .sanitize_c = sanitize_c, .sanitize_thread = sanitize_thread, .unwind_tables = unwind_tables, .cc_argv = options.cc_argv, .structured_cfg = structured_cfg, + .builtin_file = null, }; try mod.deps.ensureUnusedCapacity(arena, 1); @@ -437,8 +457,8 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P .sanitize_thread = undefined, .unwind_tables = undefined, .cc_argv = undefined, - .generated_builtin_source = undefined, .structured_cfg = undefined, + .builtin_file = null, }; return mod; } @@ -457,3 +477,4 @@ const Cache = std.Build.Cache; const Builtin = @import("../Builtin.zig"); const assert = std.debug.assert; const Compilation = @import("../Compilation.zig"); +const File = @import("../Module.zig").File; diff --git a/src/Sema.zig b/src/Sema.zig index 910b1cca47cc..2d46faf4358c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -784,6 +784,11 @@ pub const Block = struct { } } + pub fn ownerModule(block: Block) *Package.Module { + const zcu = block.sema.mod; + return zcu.namespacePtr(block.namespace).file_scope.mod; + } + pub fn startAnonDecl(block: *Block) !WipAnonDecl { return WipAnonDecl{ .block = block, @@ -5733,7 +5738,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr // Ignore the result, all the relevant operations have written to c_import_buf already. _ = try sema.analyzeBodyBreak(&child_block, body); - var c_import_res = comp.cImport(c_import_buf.items) catch |err| + var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err| return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); defer c_import_res.deinit(gpa); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ee9e3de086bf..709b2bf6a933 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -854,9 +854,8 @@ pub const Object = struct { /// want to iterate over it while adding entries to it. pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); - pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object { + pub fn create(arena: Allocator, comp: *Compilation) !*Object { if (build_options.only_c) unreachable; - const comp = options.comp; const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; const llvm_target_triple = try targetTriple(arena, target); @@ -878,14 +877,7 @@ pub const Object = struct { var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined; if (builder.useLibLlvm()) { debug_info: { - const debug_format = options.debug_format orelse b: { - if (strip) break :b .strip; - break :b switch (target.ofmt) { - .coff => .code_view, - else => .{ .dwarf = .@"32" }, - }; - }; - switch (debug_format) { + switch (comp.config.debug_format) { .strip => break :debug_info, .code_view => builder.llvm.module.?.addModuleCodeViewFlag(), .dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"), @@ -961,8 +953,8 @@ pub const Object = struct { opt_level, reloc_mode, code_model, - options.function_sections orelse false, - options.data_sections orelse false, + comp.function_sections, + comp.data_sections, float_abi, if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, ); diff --git a/src/libunwind.zig b/src/libunwind.zig index 9215e24f7cd2..bc1c0d0343b2 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -28,6 +28,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { .have_zcu = false, .emit_bin = true, .root_optimize_mode = comp.compilerRtOptMode(), + .root_strip = comp.compilerRtStrip(), .link_libc = true, // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 .lto = false, @@ -131,7 +132,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { .libc_installation = comp.libc_installation, .emit_bin = emit_bin, .link_mode = link_mode, - .function_sections = comp.bin_file.function_sections, + .function_sections = comp.function_sections, .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, diff --git a/src/link.zig b/src/link.zig index 2a61e4696994..91def2a13475 100644 --- a/src/link.zig +++ b/src/link.zig @@ -68,9 +68,6 @@ pub const File = struct { force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), allow_shlib_undefined: bool, stack_size: u64, - debug_format: DebugFormat, - function_sections: bool, - data_sections: bool, /// Prevents other processes from clobbering files in the output directory /// of this linking operation. @@ -78,16 +75,7 @@ pub const File = struct { child_pid: ?std.ChildProcess.Id = null, - pub const DebugFormat = union(enum) { - strip, - dwarf: std.dwarf.Format, - code_view, - }; - pub const OpenOptions = struct { - comp: *Compilation, - emit: Compilation.Emit, - symbol_count_hint: u64 = 32, program_code_size_hint: u64 = 256 * 1024, @@ -95,8 +83,6 @@ pub const File = struct { entry_addr: ?u64, stack_size: ?u64, image_base: ?u64, - function_sections: bool, - data_sections: bool, eh_frame_hdr: bool, emit_relocs: bool, rdynamic: bool, @@ -150,8 +136,6 @@ pub const File = struct { compatibility_version: ?std.SemanticVersion, - debug_format: ?DebugFormat, - // TODO: remove this. libraries are resolved by the frontend. lib_dirs: []const []const u8, rpath_list: []const []const u8, @@ -190,10 +174,29 @@ pub const File = struct { /// rewriting it. A malicious file is detected as incremental link failure /// and does not cause Illegal Behavior. This operation is not atomic. /// `arena` is used for allocations with the same lifetime as the created File. - pub fn open(arena: Allocator, options: OpenOptions) !*File { - switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) { + pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: OpenOptions, + ) !*File { + switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { + inline else => |tag| { + const ptr = try tag.Type().open(arena, comp, emit, options); + return &ptr.base; + }, + } + } + + pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: OpenOptions, + ) !*File { + switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { inline else => |tag| { - const ptr = try tag.Type().open(arena, options); + const ptr = try tag.Type().createEmpty(arena, comp, emit, options); return &ptr.base; }, } diff --git a/src/link/C.zig b/src/link/C.zig index 043ca0ce6fd7..ce44cc4c06eb 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -92,21 +92,24 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { }; } -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { - const target = options.comp.root_mod.resolved_target.result; +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*C { + const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .c); - const optimize_mode = options.comp.root_mod.optimize_mode; - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; - const output_mode = options.comp.config.output_mode; - const link_mode = options.comp.config.link_mode; + const optimize_mode = comp.root_mod.optimize_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; // These are caught by `Compilation.Config.resolve`. assert(!use_lld); assert(!use_llvm); - const emit = options.emit; - const file = try emit.directory.handle.createFile(emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, @@ -119,7 +122,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { c_file.* = .{ .base = .{ .tag = .c, - .comp = options.comp, + .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .stack_size = options.stack_size orelse 16777216, @@ -129,9 +132,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index db99ba189cbd..eba24f0d1767 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -234,44 +234,49 @@ const ideal_factor = 3; const minimum_text_block_size = 64; pub const min_text_capacity = padToIdeal(minimum_text_block_size); -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Coff { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; + const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .coff); - const self = try createEmpty(arena, options); + const self = try createEmpty(arena, comp, emit, options); errdefer self.base.destroy(); - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; if (use_lld and use_llvm) { // LLVM emits the object file; LLD links it into the final product. return self; } - const sub_path = if (!use_lld) options.emit.sub_path else p: { + const sub_path = if (!use_lld) emit.sub_path else p: { // Open a temporary object file, not the final output file because we // want to link with LLD. const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); self.base.intermediary_basename = o_file_path; break :p o_file_path; }; - self.base.file = try options.emit.directory.handle.createFile(sub_path, .{ + self.base.file = try emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.File.determineMode( use_lld, - options.comp.config.output_mode, - options.comp.config.link_mode, + comp.config.output_mode, + comp.config.link_mode, ), }); assert(self.llvm_object == null); - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32)); self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32)); @@ -362,8 +367,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { return self; } -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { - const comp = options.comp; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Coff { const target = comp.root_mod.resolved_target.result; const optimize_mode = comp.root_mod.optimize_mode; const output_mode = comp.config.output_mode; @@ -380,7 +389,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { .base = .{ .tag = .coff, .comp = comp, - .emit = options.emit, + .emit = emit, .stack_size = options.stack_size orelse 16777216, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -389,9 +398,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .code_view, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, .ptr_width = ptr_width, .page_size = page_size, @@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { const use_llvm = comp.config.use_llvm; if (use_llvm and comp.config.have_zcu) { - self.llvm_object = try LlvmObject.create(arena, options); + self.llvm_object = try LlvmObject.create(arena, comp); } return self; } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 1719d5fa6703..ad9e18fa2262 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -171,7 +171,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append("-ERRORLIMIT:0"); try argv.append("-NOLOGO"); - if (self.base.debug_format != .strip) { + if (comp.config.debug_format != .strip) { try argv.append("-DEBUG"); const out_ext = std.fs.path.extension(full_out_path); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index b54bde325f2b..5f96e195ab66 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -228,18 +228,23 @@ 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 { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Elf { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; + const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .elf); - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; - const opt_zcu = options.comp.module; - const output_mode = options.comp.config.output_mode; - const link_mode = options.comp.config.link_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; + const opt_zcu = comp.module; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; - const self = try createEmpty(arena, options); + const self = try createEmpty(arena, comp, emit, options); errdefer self.base.destroy(); if (use_lld and use_llvm) { @@ -250,23 +255,23 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { const is_obj = output_mode == .Obj; const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static); - const sub_path = if (!use_lld) options.emit.sub_path else p: { + const sub_path = if (!use_lld) emit.sub_path else p: { // Open a temporary object file, not the final output file because we // want to link with LLD. const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); self.base.intermediary_basename = o_file_path; break :p o_file_path; }; - self.base.file = try options.emit.directory.handle.createFile(sub_path, .{ + self.base.file = try emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); - const gpa = options.comp.gpa; + const gpa = comp.gpa; // Index 0 is always a null symbol. try self.symbols.append(gpa, .{}); @@ -343,8 +348,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { return self; } -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { - const comp = options.comp; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Elf { const use_llvm = comp.config.use_llvm; const optimize_mode = comp.root_mod.optimize_mode; const target = comp.root_mod.resolved_target.result; @@ -373,7 +382,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .base = .{ .tag = .elf, .comp = comp, - .emit = options.emit, + .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, @@ -382,9 +391,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, .ptr_width = ptr_width, .page_size = page_size, @@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { .version_script = options.version_script, }; if (use_llvm and comp.config.have_zcu) { - self.llvm_object = try LlvmObject.create(arena, options); + self.llvm_object = try LlvmObject.create(arena, comp); } return self; @@ -1753,7 +1759,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("-pie"); } - if (self.base.debug_format == .strip) { + if (comp.config.debug_format == .strip) { try argv.append("-s"); } @@ -2640,7 +2646,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--export-dynamic"); } - if (self.base.debug_format == .strip) { + if (comp.config.debug_format == .strip) { try argv.append("-s"); } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 5fa31711e68e..0bf1e837e352 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -293,13 +293,14 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem } fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { + const comp = elf_file.base.comp; const shdr = self.shdrs.items[index]; const name = self.getString(shdr.sh_name); const ignore = blk: { if (mem.startsWith(u8, name, ".note")) break :blk true; if (mem.startsWith(u8, name, ".comment")) break :blk true; if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; - if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and + if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and mem.startsWith(u8, name, ".debug")) break :blk true; break :blk false; }; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 05ff55dd1877..75bc53bb48d4 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -76,7 +76,8 @@ pub const symbol_mask: u32 = 0x7fffffff; pub const SHN_ATOM: u16 = 0x100; pub fn init(self: *ZigObject, elf_file: *Elf) !void { - const gpa = elf_file.base.comp.gpa; + const comp = elf_file.base.comp; + const gpa = comp.gpa; try self.atoms.append(gpa, 0); // null input section try self.relocs.append(gpa, .{}); // null relocs section @@ -96,8 +97,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { esym.st_shndx = elf.SHN_ABS; symbol_ptr.esym_index = esym_index; - if (elf_file.base.debug_format != .strip) { - self.dwarf = Dwarf.init(&elf_file.base, .dwarf32); + switch (comp.config.debug_format) { + .strip => {}, + .dwarf => |v| { + assert(v == .@"32"); + self.dwarf = Dwarf.init(&elf_file.base, .dwarf32); + }, + .code_view => unreachable, } } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 87faec65373f..25d59f3de3e2 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -182,18 +182,21 @@ pub const SdkLayout = enum { vendored, }; -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*MachO { if (build_options.only_c) unreachable; - const comp = options.comp; const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; assert(target.ofmt == .macho); const gpa = comp.gpa; - const emit = options.emit; const mode: Mode = mode: { - if (use_llvm or comp.module == null or comp.cache_mode == .whole) + if (use_llvm or comp.module == null or comp.cache_use == .whole) break :mode .zld; break :mode .incremental; }; @@ -201,7 +204,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { if (comp.module == null) { // No point in opening a file, we would not write anything to it. // Initialize with empty. - return createEmpty(arena, options); + return createEmpty(arena, comp, emit, options); } // Open a temporary object file, not the final output file because we // want to link with LLD. @@ -210,7 +213,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { }); } else emit.sub_path; - const self = try createEmpty(arena, options); + const self = try createEmpty(arena, comp, emit, options); errdefer self.base.destroy(); if (mode == .zld) { @@ -232,7 +235,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { }); self.base.file = file; - if (self.base.debug_format != .strip and comp.module != null) { + if (comp.config.debug_format != .strip and comp.module != null) { // Create dSYM bundle. log.debug("creating {s}.dSYM bundle", .{sub_path}); @@ -279,8 +282,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO { return self; } -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { - const comp = options.comp; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*MachO { const optimize_mode = comp.root_mod.optimize_mode; const use_llvm = comp.config.use_llvm; @@ -289,7 +296,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { .base = .{ .tag = .macho, .comp = comp, - .emit = options.emit, + .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -298,11 +305,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, - .mode = if (use_llvm or comp.module == null or comp.cache_mode == .whole) + .mode = if (use_llvm or comp.module == null or comp.cache_use == .whole) .zld else .incremental, @@ -317,7 +321,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO { }; if (use_llvm and comp.module != null) { - self.llvm_object = try LlvmObject.create(arena, options); + self.llvm_object = try LlvmObject.create(arena, comp); } log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); @@ -4313,7 +4317,8 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList } fn writeSymtab(self: *MachO) !SymtabCtx { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; var locals = std.ArrayList(macho.nlist_64).init(gpa); defer locals.deinit(); @@ -4368,7 +4373,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx { // We generate stabs last in order to ensure that the strtab always has debug info // strings trailing - if (self.base.debug_format != .strip) { + if (comp.config.debug_format != .strip) { for (self.objects.items) |object| { assert(self.d_sym == null); // TODO try self.generateSymbolStabs(object, &locals); diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 846e496ec1d0..57a835289847 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -25,12 +25,17 @@ const LlvmObject = @import("../codegen/llvm.zig").Object; base: link.File, llvm_object: *LlvmObject, -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*NvPtx { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; + const target = comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; assert(use_llvm); // Caught by Compilation.Config.resolve. assert(!use_lld); // Caught by Compilation.Config.resolve. @@ -42,13 +47,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { else => return error.PtxArchNotSupported, } - const llvm_object = try LlvmObject.create(arena, options); + const llvm_object = try LlvmObject.create(arena, comp); const nvptx = try arena.create(NvPtx); nvptx.* = .{ .base = .{ .tag = .nvptx, - .comp = options.comp, - .emit = options.emit, + .comp = comp, + .emit = emit, .gc_sections = options.gc_sections orelse false, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -57,9 +62,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, .llvm_object = llvm_object, }; @@ -67,10 +69,15 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { return nvptx; } -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx { - const target = options.comp.root_mod.resolved_target.result; +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*NvPtx { + const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .nvptx); - return createEmpty(arena, options); + return createEmpty(arena, comp, emit, options); } pub fn deinit(self: *NvPtx) void { diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index b3c08fb66ba3..c970e72e5110 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -294,8 +294,12 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { }; } -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { - const comp = options.comp; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Plan9 { const target = comp.root_mod.resolved_target.result; const gpa = comp.gpa; const optimize_mode = comp.root_mod.optimize_mode; @@ -313,7 +317,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { .base = .{ .tag = .plan9, .comp = comp, - .emit = options.emit, + .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -322,9 +326,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, .sixtyfour_bit = sixtyfour_bit, .bases = undefined, @@ -1308,26 +1309,31 @@ pub fn deinit(self: *Plan9) void { } } -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Plan9 { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; + const target = comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; assert(!use_llvm); // Caught by Compilation.Config.resolve. assert(!use_lld); // Caught by Compilation.Config.resolve. assert(target.ofmt == .plan9); - const self = try createEmpty(arena, options); + const self = try createEmpty(arena, comp, emit, options); errdefer self.base.destroy(); - const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{ + const file = try emit.directory.handle.createFile(emit.sub_path, .{ .read = true, .mode = link.File.determineMode( use_lld, - options.comp.config.output_mode, - options.comp.config.link_mode, + comp.config.output_mode, + comp.config.link_mode, ), }); errdefer file.close(); @@ -1335,7 +1341,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 { self.bases = defaultBaseAddrs(target.cpu.arch); - const gpa = options.comp.gpa; + const gpa = comp.gpa; try self.syms.appendSlice(gpa, &.{ // we include the global offset table to make it easier for debugging diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index bb278a8e4a0a..853d97b0142b 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -49,16 +49,21 @@ 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; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*SpirV { + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const self = try arena.create(SpirV); self.* = .{ .base = .{ .tag = .spirv, - .comp = options.comp, - .emit = options.emit, + .comp = comp, + .emit = emit, .gc_sections = options.gc_sections orelse false, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -67,9 +72,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .function_sections = options.function_sections, - .data_sections = options.data_sections, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, }, .object = codegen.Object.init(gpa), }; @@ -90,22 +92,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV { return self; } -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*SpirV { if (build_options.only_c) unreachable; - const target = options.comp.root_mod.resolved_target.result; - const use_lld = build_options.have_llvm and options.comp.config.use_lld; - const use_llvm = options.comp.config.use_llvm; + const target = comp.root_mod.resolved_target.result; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; assert(!use_llvm); // Caught by Compilation.Config.resolve. assert(!use_lld); // Caught by Compilation.Config.resolve. assert(target.ofmt == .spirv); // Caught by Compilation.Config.resolve. - const spirv = try createEmpty(arena, options); + const spirv = try createEmpty(arena, comp, emit, options); errdefer spirv.base.destroy(); // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{ + const file = try emit.directory.handle.createFile(emit.sub_path, .{ .truncate = true, .read = true, }); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 74d83e6c3caa..8f63e7c6fd51 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -373,9 +373,13 @@ pub const StringTable = struct { } }; -pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Wasm { if (build_options.only_c) unreachable; - const comp = options.comp; const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .wasm); @@ -385,7 +389,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { const output_mode = comp.config.output_mode; const shared_memory = comp.config.shared_memory; - const wasm = try createEmpty(arena, options); + const wasm = try createEmpty(arena, comp, emit, options); errdefer wasm.base.destroy(); if (use_lld and use_llvm) { @@ -393,18 +397,18 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { return wasm; } - const sub_path = if (!use_lld) options.emit.sub_path else p: { + const sub_path = if (!use_lld) emit.sub_path else p: { // Open a temporary object file, not the final output file because we // want to link with LLD. const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); wasm.base.intermediary_basename = o_file_path; break :p o_file_path; }; // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.directory.handle.createFile(sub_path, .{ + const file = try emit.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = if (fs.has_executable_bit) @@ -530,8 +534,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm { return wasm; } -pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { - const comp = options.comp; +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Wasm { const use_llvm = comp.config.use_llvm; const output_mode = comp.config.output_mode; @@ -540,7 +548,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { .base = .{ .tag = .wasm, .comp = comp, - .emit = options.emit, + .emit = emit, .gc_sections = options.gc_sections orelse (output_mode != .Obj), .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB .allow_shlib_undefined = options.allow_shlib_undefined orelse false, @@ -549,9 +557,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { .build_id = options.build_id, .rpath_list = options.rpath_list, .force_undefined_symbols = options.force_undefined_symbols, - .debug_format = options.debug_format orelse .{ .dwarf = .@"32" }, - .function_sections = options.function_sections, - .data_sections = options.data_sections, }, .name = undefined, .import_table = options.import_table, @@ -566,7 +571,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm { }; if (use_llvm) { - wasm.llvm_object = try LlvmObject.create(arena, options); + wasm.llvm_object = try LlvmObject.create(arena, comp); } return wasm; } @@ -4205,11 +4210,11 @@ fn writeToFile( if (data_section_index) |data_index| { try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); } - } else if (wasm.base.debug_format != .strip) { + } else if (comp.config.debug_format != .strip) { try wasm.emitNameSection(&binary_bytes, arena); } - if (wasm.base.debug_format != .strip) { + if (comp.config.debug_format != .strip) { // The build id must be computed on the main sections only, // so we have to do it now, before the debug sections. switch (wasm.base.build_id) { @@ -4748,7 +4753,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--no-gc-sections"); } - if (wasm.base.debug_format == .strip) { + if (comp.config.debug_format == .strip) { try argv.append("-s"); } @@ -5276,7 +5281,9 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s fn markReferences(wasm: *Wasm) !void { const tracy = trace(@src()); defer tracy.end(); + const do_garbage_collect = wasm.base.gc_sections; + const comp = wasm.base.comp; for (wasm.resolved_symbols.keys()) |sym_loc| { const sym = sym_loc.getSymbol(wasm); @@ -5287,7 +5294,7 @@ fn markReferences(wasm: *Wasm) !void { // Debug sections may require to be parsed and marked when it contains // relocations to alive symbols. - if (sym.tag == .section and wasm.base.debug_format != .strip) { + if (sym.tag == .section and comp.config.debug_format != .strip) { const file = sym_loc.file orelse continue; // Incremental debug info is done independently const object = &wasm.objects.items[file]; const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm); diff --git a/src/main.zig b/src/main.zig index 9acad1a0ca5f..dbd975901591 100644 --- a/src/main.zig +++ b/src/main.zig @@ -892,7 +892,6 @@ fn buildOutputType( var contains_res_file: bool = false; var reference_trace: ?u32 = null; var pdb_out_path: ?[]const u8 = null; - var debug_format: ?link.File.DebugFormat = null; var error_limit: ?Module.ErrorInt = null; // These are before resolving sysroot. var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{}; @@ -1054,6 +1053,8 @@ fn buildOutputType( create_module.opts.any_sanitize_thread = true; if (mod_opts.unwind_tables == true) create_module.opts.any_unwind_tables = true; + if (mod_opts.strip == false) + create_module.opts.any_non_stripped = true; const root_src = try introspect.resolvePath(arena, root_src_orig); try create_module.modules.put(arena, mod_name, .{ @@ -1480,9 +1481,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-strip")) { mod_opts.strip = false; } else if (mem.eql(u8, arg, "-gdwarf32")) { - debug_format = .{ .dwarf = .@"32" }; + create_module.opts.debug_format = .{ .dwarf = .@"32" }; } else if (mem.eql(u8, arg, "-gdwarf64")) { - debug_format = .{ .dwarf = .@"64" }; + create_module.opts.debug_format = .{ .dwarf = .@"64" }; } else if (mem.eql(u8, arg, "-fformatted-panics")) { formatted_panics = true; } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { @@ -1989,11 +1990,11 @@ fn buildOutputType( }, .gdwarf32 => { mod_opts.strip = false; - debug_format = .{ .dwarf = .@"32" }; + create_module.opts.debug_format = .{ .dwarf = .@"32" }; }, .gdwarf64 => { mod_opts.strip = false; - debug_format = .{ .dwarf = .@"64" }; + create_module.opts.debug_format = .{ .dwarf = .@"64" }; }, .sanitize => { if (mem.eql(u8, it.only_arg, "undefined")) { @@ -2532,6 +2533,8 @@ fn buildOutputType( create_module.opts.any_sanitize_thread = true; if (mod_opts.unwind_tables == true) create_module.opts.any_unwind_tables = true; + if (mod_opts.strip == false) + create_module.opts.any_non_stripped = true; const src_path = try introspect.resolvePath(arena, unresolved_src_path); try create_module.modules.put(arena, "main", .{ @@ -3359,7 +3362,6 @@ fn buildOutputType( .emit_docs = emit_docs_resolved.data, .emit_implib = emit_implib_resolved.data, .dll_export_fns = dll_export_fns, - .keep_source_files_loaded = false, .lib_dirs = lib_dirs.items, .rpath_list = rpath_list.items, .symbol_wrap_set = symbol_wrap_set, @@ -3443,7 +3445,6 @@ fn buildOutputType( .test_runner_path = test_runner_path, .disable_lld_caching = !output_to_cache, .subsystem = subsystem, - .debug_format = debug_format, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, .install_name = install_name, @@ -3484,7 +3485,9 @@ fn buildOutputType( defer if (!comp_destroyed) comp.destroy(); if (show_builtin) { - return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena)); + const builtin_mod = comp.root_mod.deps.get("builtin").?; + const source = builtin_mod.builtin_file.?.source; + return std.io.getStdOut().writeAll(source); } switch (listen) { .none => {}, @@ -3737,6 +3740,7 @@ fn createModule( const resolved_target = cli_mod.inherited.resolved_target.?; create_module.opts.resolved_target = resolved_target; create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode; + create_module.opts.root_strip = cli_mod.inherited.strip; const target = resolved_target.result; // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. @@ -4366,12 +4370,12 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name}); - var man: Cache.Manifest = comp.obtainCObjectCacheManifest(); + var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod); man.want_shared_lock = false; defer man.deinit(); man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects - man.hash.add(comp.c_frontend); + man.hash.add(comp.config.c_frontend); Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| { fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) }); }; @@ -4380,14 +4384,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati const digest = if (try man.hit()) man.final() else digest: { if (fancy_output) |p| p.cache_hit = false; var argv = std.ArrayList([]const u8).init(arena); - try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1] + try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1] var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); defer zig_cache_tmp_dir.close(); const ext = Compilation.classifyFileExt(c_source_file.src_path); const out_dep_path: ?[]const u8 = blk: { - if (comp.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile()) + if (comp.config.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile()) break :blk null; const c_src_basename = fs.path.basename(c_source_file.src_path); @@ -4397,14 +4401,15 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati }; // TODO - if (comp.c_frontend != .aro) try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path); + if (comp.config.c_frontend != .aro) + try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); try argv.append(c_source_file.src_path); if (comp.verbose_cc) { Compilation.dump_argv(argv.items); } - var tree = switch (comp.c_frontend) { + var tree = switch (comp.config.c_frontend) { .aro => tree: { const aro = @import("aro"); const translate_c = @import("aro_translate_c.zig"); From c49957dbe82d7f0db555160b50306335bfa03165 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Dec 2023 18:47:58 -0700 Subject: [PATCH 042/133] fix a round of compile errors caused by this branch --- src/Compilation.zig | 153 ++++++++++++++++++++++------------- src/Module.zig | 127 ++++++++++++++++------------- src/arch/aarch64/CodeGen.zig | 6 +- src/arch/aarch64/Emit.zig | 29 ++++--- src/arch/arm/CodeGen.zig | 8 +- src/arch/arm/Emit.zig | 30 ++++--- src/arch/riscv64/CodeGen.zig | 6 +- src/arch/riscv64/Emit.zig | 4 +- src/arch/sparc64/CodeGen.zig | 5 +- src/arch/sparc64/Emit.zig | 29 ++++--- src/arch/wasm/CodeGen.zig | 10 ++- src/arch/wasm/Emit.zig | 24 ++++-- src/arch/x86_64/CodeGen.zig | 42 +++++----- src/codegen.zig | 33 ++++---- src/codegen/llvm.zig | 4 +- src/libunwind.zig | 2 +- src/link.zig | 63 +++++++-------- src/link/C.zig | 12 ++- src/link/Coff.zig | 5 +- src/link/Coff/Atom.zig | 9 ++- src/link/Dwarf.zig | 2 +- src/link/Elf.zig | 52 ++++++------ src/link/Elf/Atom.zig | 14 +++- src/link/MachO.zig | 42 ++++------ src/link/MachO/Atom.zig | 12 ++- src/link/Plan9.zig | 1 - 26 files changed, 411 insertions(+), 313 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 35ee24361732..693e46c07c08 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -884,12 +884,32 @@ const CacheUse = union(CacheMode) { docs_sub_path: ?[]u8, lf_open_opts: link.File.OpenOptions, tmp_artifact_directory: ?Cache.Directory, + /// Prevents other processes from clobbering files in the output directory. + lock: ?Cache.Lock, + + fn releaseLock(whole: *Whole) void { + if (whole.lock) |*lock| { + lock.release(); + whole.lock = null; + } + } }; const Incremental = struct { /// Where build artifacts and incremental compilation metadata serialization go. artifact_directory: Compilation.Directory, }; + + fn deinit(cu: CacheUse) void { + switch (cu) { + .incremental => |incremental| { + incremental.artifact_directory.handle.close(); + }, + .whole => |whole| { + whole.releaseLock(); + }, + } + } }; pub const LinkObject = struct { @@ -916,7 +936,7 @@ pub const InitOptions = struct { /// Normally, `main_mod` and `root_mod` are the same. The exception is `zig /// test`, in which `root_mod` is the test runner, and `main_mod` is the /// user's source file which has the tests. - main_mod: ?*Package.Module, + main_mod: ?*Package.Module = null, /// This is provided so that the API user has a chance to tweak the /// per-module settings of the standard library. std_mod: *Package.Module, @@ -1615,6 +1635,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib), .docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs), .tmp_artifact_directory = null, + .lock = null, }; comp.cache_use = .{ .whole = whole }; }, @@ -1822,13 +1843,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { pub fn destroy(self: *Compilation) void { if (self.bin_file) |lf| lf.destroy(); if (self.module) |zcu| zcu.deinit(); - switch (self.cache_use) { - .incremental => |incremental| { - incremental.artifact_directory.handle.close(); - }, - .whole => {}, - } - + self.cache_use.deinit(); self.work_queue.deinit(); self.anon_work_queue.deinit(); self.c_object_work_queue.deinit(); @@ -1922,11 +1937,17 @@ pub fn getTarget(self: Compilation) Target { return self.root_mod.resolved_target.result; } -pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.ChildProcess.Id) !void { - comp.bin_file.child_pid = pid; - try comp.makeBinFileWritable(); +/// Only legal to call when cache mode is incremental and a link file is present. +pub fn hotCodeSwap( + comp: *Compilation, + prog_node: *std.Progress.Node, + pid: std.ChildProcess.Id, +) !void { + const lf = comp.bin_file.?; + lf.child_pid = pid; + try lf.makeWritable(); try comp.update(prog_node); - try comp.makeBinFileExecutable(); + try lf.makeExecutable(); } fn cleanupAfterUpdate(comp: *Compilation) void { @@ -1941,7 +1962,7 @@ fn cleanupAfterUpdate(comp: *Compilation) void { lf.destroy(); comp.bin_file = null; } - if (whole.tmp_artifact_directory) |directory| { + if (whole.tmp_artifact_directory) |*directory| { directory.handle.close(); if (directory.path) |p| comp.gpa.free(p); whole.tmp_artifact_directory = null; @@ -1967,8 +1988,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // C source files. switch (comp.cache_use) { .whole => |whole| { - // We are about to obtain this lock, so here we give other processes a chance first. assert(comp.bin_file == null); + // We are about to obtain this lock, so here we give other processes a chance first. + whole.releaseLock(); man = comp.cache_parent.obtain(); whole.cache_manifest = &man; @@ -1989,8 +2011,8 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void comp.wholeCacheModeSetBinFilePath(whole, &digest); - assert(comp.bin_file.lock == null); - comp.bin_file.lock = man.toOwnedLock(); + assert(whole.lock == null); + whole.lock = man.toOwnedLock(); return; } log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name}); @@ -2158,7 +2180,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Rename the temporary directory into place. // Close tmp dir and link.File to avoid open handle during rename. - if (whole.tmp_artifact_directory) |tmp_directory| { + if (whole.tmp_artifact_directory) |*tmp_directory| { tmp_directory.handle.close(); if (tmp_directory.path) |p| comp.gpa.free(p); whole.tmp_artifact_directory = null; @@ -2181,8 +2203,8 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); }; - assert(comp.bin_file.lock == null); - comp.bin_file.lock = man.toOwnedLock(); + assert(whole.lock == null); + whole.lock = man.toOwnedLock(); }, .incremental => {}, } @@ -2263,13 +2285,15 @@ fn maybeGenerateAutodocs(comp: *Compilation, prog_node: *std.Progress.Node) !voi } fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void { - // This is needed before reading the error flags. - comp.bin_file.flush(comp, prog_node) catch |err| switch (err) { - error.FlushFailure => {}, // error reported through link_error_flags - error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr - else => |e| return e, - }; - comp.link_error_flags = comp.bin_file.errorFlags(); + if (comp.bin_file) |lf| { + // This is needed before reading the error flags. + lf.flush(comp, prog_node) catch |err| switch (err) { + error.FlushFailure => {}, // error reported through link_error_flags + error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr + else => |e| return e, + }; + comp.link_error_flags = lf.error_flags; + } if (comp.module) |module| { try link.File.C.flushEmitH(module); @@ -2445,9 +2469,9 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes .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); + man.hash.addOptional(wasm.initial_memory); + man.hash.addOptional(wasm.max_memory); + man.hash.addOptional(wasm.global_base); }, .macho => { const macho = lf.cast(link.File.MachO).?; @@ -2626,12 +2650,14 @@ fn reportMultiModuleErrors(mod: *Module) !void { /// binary is concerned. This will remove the write flag, or close the file, /// or whatever is needed so that it can be executed. /// After this, one must call` makeFileWritable` before calling `update`. -pub fn makeBinFileExecutable(self: *Compilation) !void { - return self.bin_file.makeExecutable(); +pub fn makeBinFileExecutable(comp: *Compilation) !void { + const lf = comp.bin_file orelse return; + return lf.makeExecutable(); } -pub fn makeBinFileWritable(self: *Compilation) !void { - return self.bin_file.makeWritable(); +pub fn makeBinFileWritable(comp: *Compilation) !void { + const lf = comp.bin_file orelse return; + return lf.makeWritable(); } const Header = extern struct { @@ -2764,8 +2790,9 @@ pub fn totalErrorCount(self: *Compilation) u32 { } total += @intFromBool(self.link_error_flags.missing_libc); - // Misc linker errors - total += self.bin_file.miscErrors().len; + if (self.bin_file) |lf| { + total += lf.misc_errors.items.len; + } // Compile log errors only count if there are no other errors. if (total == 0) { @@ -2914,7 +2941,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { })); } - for (self.bin_file.miscErrors()) |link_err| { + if (self.bin_file) |lf| for (lf.misc_errors.items) |link_err| { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString(link_err.msg), .notes_len = @intCast(link_err.notes.len), @@ -2925,7 +2952,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { .msg = try bundle.addString(note.msg), })); } - } + }; if (self.module) |module| { if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { @@ -3246,12 +3273,12 @@ pub fn performAllTheWork( // TODO put all the modules in a flat array to make them easy to iterate. var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{}; defer seen.deinit(comp.gpa); - try seen.put(comp.gpa, comp.root_mod); + try seen.put(comp.gpa, comp.root_mod, {}); var i: usize = 0; while (i < seen.count()) : (i += 1) { const mod = seen.keys()[i]; for (mod.deps.values()) |dep| - try seen.put(comp.gpa, dep); + try seen.put(comp.gpa, dep, {}); const file = mod.builtin_file orelse continue; @@ -3459,7 +3486,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v const gpa = comp.gpa; const module = comp.module.?; const decl = module.declPtr(decl_index); - comp.bin_file.updateDeclLineNumber(module, decl_index) catch |err| { + const lf = comp.bin_file.?; + lf.updateDeclLineNumber(module, decl_index) catch |err| { try module.failed_decls.ensureUnusedCapacity(gpa, 1); module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( gpa, @@ -3782,7 +3810,7 @@ pub fn obtainCObjectCacheManifest( // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. man.hash.add(owner_mod.sanitize_c); - man.hash.addListOfBytes(owner_mod.clang_argv); + man.hash.addListOfBytes(owner_mod.cc_argv); man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list @@ -6099,7 +6127,8 @@ fn buildOutputFromZig( const tracy_trace = trace(@src()); defer tracy_trace.end(); - var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -6110,6 +6139,7 @@ fn buildOutputFromZig( const config = try Config.resolve(.{ .output_mode = output_mode, + .link_mode = .Static, .resolved_target = comp.root_mod.resolved_target, .is_test = false, .have_zcu = true, @@ -6120,7 +6150,8 @@ fn buildOutputFromZig( .any_unwind_tables = unwind_tables, }); - const root_mod = Package.Module.create(.{ + const root_mod = try Package.Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, .paths = .{ .root = .{ .root_dir = comp.zig_lib_directory }, .root_src_path = src_basename, @@ -6139,6 +6170,8 @@ fn buildOutputFromZig( }, .global = config, .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, }); const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; const target = comp.getTarget(); @@ -6148,23 +6181,21 @@ fn buildOutputFromZig( .output_mode = output_mode, }); - const emit_bin = Compilation.EmitLoc{ - .directory = null, // Put it in the cache directory. - .basename = bin_basename, - }; - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(gpa, .{ .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, + .config = config, .root_mod = root_mod, .cache_mode = .whole, .root_name = root_name, .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, - .emit_bin = emit_bin, - .link_mode = .Static, + .emit_bin = .{ + .directory = null, // Put it in the cache directory. + .basename = bin_basename, + }, .function_sections = true, .data_sections = true, .no_builtin = true, @@ -6186,8 +6217,8 @@ fn buildOutputFromZig( try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); assert(out.* == null); - out.* = Compilation.CRTFile{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(comp.gpa, &[_][]const u8{ + out.* = .{ + .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &.{ sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), @@ -6206,12 +6237,15 @@ pub fn build_crt_file( defer tracy_trace.end(); const gpa = comp.gpa; - const basename = try std.zig.binNameAlloc(gpa, .{ + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = comp.root_mod.resolved_target.result, .output_mode = output_mode, }); - errdefer gpa.free(basename); const config = try Config.resolve(.{ .output_mode = output_mode, @@ -6227,7 +6261,8 @@ pub fn build_crt_file( .Obj, .Exe => false, }, }); - const root_mod = Package.Module.create(.{ + const root_mod = try Package.Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, .paths = .{ .root = .{ .root_dir = comp.zig_lib_directory }, .root_src_path = "", @@ -6249,6 +6284,8 @@ pub fn build_crt_file( }, .global = config, .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, }); const sub_compilation = try Compilation.create(gpa, .{ @@ -6257,7 +6294,7 @@ pub fn build_crt_file( .zig_lib_directory = comp.zig_lib_directory, .self_exe_path = comp.self_exe_path, .cache_mode = .whole, - .resolved = config, + .config = config, .root_mod = root_mod, .root_name = root_name, .thread_pool = comp.thread_pool, @@ -6287,7 +6324,7 @@ pub fn build_crt_file( try comp.crt_files.ensureUnusedCapacity(gpa, 1); comp.crt_files.putAssumeCapacityNoClobber(basename, .{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &[_][]const u8{ + .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &.{ sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), diff --git a/src/Module.zig b/src/Module.zig index 121f639f6bed..0645b6f04f34 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -619,7 +619,7 @@ pub const Decl = struct { // Sanitize the name for nvptx which is more restrictive. // TODO This should be handled by the backend, not the frontend. Have a // look at how the C backend does it for inspiration. - const cpu_arch = mod.root_mod.resolved_target.cpu.arch; + const cpu_arch = mod.root_mod.resolved_target.result.cpu.arch; if (cpu_arch.isNvptx()) { for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) { '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_', @@ -3313,7 +3313,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr if (no_bin_file and !dump_llvm_ir) return; - comp.bin_file.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) { + const lf = comp.bin_file.?; + lf.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { decl.analysis = .codegen_failure; @@ -3488,25 +3489,29 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { new_decl.owns_tv = true; new_decl.analysis = .complete; - if (mod.comp.whole_cache_manifest) |whole_cache_manifest| { - const source = file.getSource(gpa) catch |err| { - try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); - return error.AnalysisFail; - }; + const comp = mod.comp; + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |man| { + const source = file.getSource(gpa) catch |err| { + try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)}); + return error.AnalysisFail; + }; - const resolved_path = std.fs.path.resolve(gpa, &.{ - file.mod.root.root_dir.path orelse ".", - file.mod.root.sub_path, - file.sub_file_path, - }) catch |err| { - try reportRetryableFileError(mod, file, "unable to resolve path: {s}", .{@errorName(err)}); - return error.AnalysisFail; - }; - errdefer gpa.free(resolved_path); + const resolved_path = std.fs.path.resolve(gpa, &.{ + file.mod.root.root_dir.path orelse ".", + file.mod.root.sub_path, + file.sub_file_path, + }) catch |err| { + try reportRetryableFileError(mod, file, "unable to resolve path: {s}", .{@errorName(err)}); + return error.AnalysisFail; + }; + errdefer gpa.free(resolved_path); - mod.comp.whole_cache_manifest_mutex.lock(); - defer mod.comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addFilePostContents(resolved_path, source.bytes, source.stat); + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try man.addFilePostContents(resolved_path, source.bytes, source.stat); + }, + .incremental => {}, } } @@ -4045,12 +4050,16 @@ fn newEmbedFile( const actual_read = try file.readAll(ptr); if (actual_read != size) return error.UnexpectedEndOfFile; - if (mod.comp.whole_cache_manifest) |whole_cache_manifest| { - const copied_resolved_path = try gpa.dupe(u8, resolved_path); - errdefer gpa.free(copied_resolved_path); - mod.comp.whole_cache_manifest_mutex.lock(); - defer mod.comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addFilePostContents(copied_resolved_path, ptr, stat); + const comp = mod.comp; + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |man| { + const copied_resolved_path = try gpa.dupe(u8, resolved_path); + errdefer gpa.free(copied_resolved_path); + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try man.addFilePostContents(copied_resolved_path, ptr, stat); + }, + .incremental => {}, } const array_ty = try ip.get(gpa, .{ .array_type = .{ @@ -4393,7 +4402,9 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void } }, } - try mod.comp.bin_file.deleteDeclExport(decl_index, exp.opts.name); + if (mod.comp.bin_file) |lf| { + try lf.deleteDeclExport(decl_index, exp.opts.name); + } if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| { failed_kv.value.destroy(mod.gpa); } @@ -5247,7 +5258,8 @@ fn processExportsInner( gop.value_ptr.* = new_export; } } - mod.comp.bin_file.updateExports(mod, exported, exports) catch |err| switch (err) { + const lf = mod.comp.bin_file orelse return; + lf.updateExports(mod, exported, exports) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => { const new_export = exports[0]; @@ -5403,36 +5415,39 @@ pub fn populateTestFunctions( pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void { const comp = mod.comp; - const no_bin_file = (comp.bin_file == null and - comp.emit_asm == null and - comp.emit_llvm_ir == null and - comp.emit_llvm_bc == null); - - const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); - - if (no_bin_file and !dump_llvm_ir) return; - - const decl = mod.declPtr(decl_index); + if (comp.bin_file) |lf| { + const decl = mod.declPtr(decl_index); + lf.updateDecl(mod, decl_index) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.AnalysisFail => { + decl.analysis = .codegen_failure; + return; + }, + else => { + const gpa = mod.gpa; + try mod.failed_decls.ensureUnusedCapacity(gpa, 1); + mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( + gpa, + decl.srcLoc(mod), + "unable to codegen: {s}", + .{@errorName(err)}, + )); + decl.analysis = .codegen_failure_retryable; + return; + }, + }; + } else { + const dump_llvm_ir = builtin.mode == .Debug and + (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); - comp.bin_file.updateDecl(mod, decl_index) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.AnalysisFail => { - decl.analysis = .codegen_failure; - return; - }, - else => { - const gpa = mod.gpa; - try mod.failed_decls.ensureUnusedCapacity(gpa, 1); - mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( - gpa, - decl.srcLoc(mod), - "unable to codegen: {s}", - .{@errorName(err)}, - )); - decl.analysis = .codegen_failure_retryable; - return; - }, - }; + if (comp.emit_asm != null or + comp.emit_llvm_ir != null or + comp.emit_llvm_bc != null or + dump_llvm_ir) + { + @panic("TODO handle emit_asm, emit_llvm_ir, and emit_llvm_bc along with -fno-emit-bin"); + } + } } fn reportRetryableFileError( diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 2fb740474b92..341e4bef008c 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -344,7 +344,7 @@ pub fn generate( assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); - const target = &namespace.file_scope.mod.target; + const target = &namespace.file_scope.mod.resolved_target.result; var branch_stack = std.ArrayList(Branch).init(gpa); defer { @@ -6343,14 +6343,14 @@ fn wantSafety(self: *Self) bool { fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args); return error.CodegenFail; } fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args); return error.CodegenFail; } diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 9ba722f39368..3f629fd46f3e 100644 --- a/src/arch/aarch64/Emit.zig +++ b/src/arch/aarch64/Emit.zig @@ -218,14 +218,16 @@ pub fn emitMir( } pub fn deinit(emit: *Emit) void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; var iter = emit.branch_forward_origins.valueIterator(); while (iter.next()) |origin_list| { - origin_list.deinit(emit.bin_file.allocator); + origin_list.deinit(gpa); } - emit.branch_types.deinit(emit.bin_file.allocator); - emit.branch_forward_origins.deinit(emit.bin_file.allocator); - emit.code_offset_mapping.deinit(emit.bin_file.allocator); + emit.branch_types.deinit(gpa); + emit.branch_forward_origins.deinit(gpa); + emit.code_offset_mapping.deinit(gpa); emit.* = undefined; } @@ -314,8 +316,9 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index { } fn lowerBranches(emit: *Emit) !void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; const mir_tags = emit.mir.instructions.items(.tag); - const allocator = emit.bin_file.allocator; // First pass: Note down all branches and their target // instructions, i.e. populate branch_types, @@ -329,7 +332,7 @@ fn lowerBranches(emit: *Emit) !void { const target_inst = emit.branchTarget(inst); // Remember this branch instruction - try emit.branch_types.put(allocator, inst, BranchType.default(tag)); + try emit.branch_types.put(gpa, inst, BranchType.default(tag)); // Forward branches require some extra stuff: We only // know their offset once we arrive at the target @@ -339,14 +342,14 @@ fn lowerBranches(emit: *Emit) !void { // etc. if (target_inst > inst) { // Remember the branch instruction index - try emit.code_offset_mapping.put(allocator, inst, 0); + try emit.code_offset_mapping.put(gpa, inst, 0); if (emit.branch_forward_origins.getPtr(target_inst)) |origin_list| { - try origin_list.append(allocator, inst); + try origin_list.append(gpa, inst); } else { var origin_list: std.ArrayListUnmanaged(Mir.Inst.Index) = .{}; - try origin_list.append(allocator, inst); - try emit.branch_forward_origins.put(allocator, target_inst, origin_list); + try origin_list.append(gpa, inst); + try emit.branch_forward_origins.put(gpa, target_inst, origin_list); } } @@ -356,7 +359,7 @@ fn lowerBranches(emit: *Emit) !void { // putNoClobber may not be used as the put operation // may clobber the entry when multiple branches branch // to the same target instruction - try emit.code_offset_mapping.put(allocator, target_inst, 0); + try emit.code_offset_mapping.put(gpa, target_inst, 0); } } @@ -429,7 +432,9 @@ fn writeInstruction(emit: *Emit, instruction: Instruction) !void { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(emit.err_msg == null); - emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); + const comp = emit.bin_file.comp; + const gpa = comp.gpa; + emit.err_msg = try ErrorMsg.create(gpa, emit.src_loc, format, args); return error.EmitFail; } diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 0df653ff35d8..c9d6a3aef462 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -351,7 +351,7 @@ pub fn generate( assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); - const target = &namespace.file_scope.mod.target; + const target = &namespace.file_scope.mod.resolved_target.result; var branch_stack = std.ArrayList(Branch).init(gpa); defer { @@ -6292,14 +6292,16 @@ fn wantSafety(self: *Self) bool { fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + const gpa = self.gpa; + self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); return error.CodegenFail; } fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + const gpa = self.gpa; + self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); return error.CodegenFail; } diff --git a/src/arch/arm/Emit.zig b/src/arch/arm/Emit.zig index 45c3392918d5..2ab3b60ee6f6 100644 --- a/src/arch/arm/Emit.zig +++ b/src/arch/arm/Emit.zig @@ -152,14 +152,17 @@ pub fn emitMir( } pub fn deinit(emit: *Emit) void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; + var iter = emit.branch_forward_origins.valueIterator(); while (iter.next()) |origin_list| { - origin_list.deinit(emit.bin_file.allocator); + origin_list.deinit(gpa); } - emit.branch_types.deinit(emit.bin_file.allocator); - emit.branch_forward_origins.deinit(emit.bin_file.allocator); - emit.code_offset_mapping.deinit(emit.bin_file.allocator); + emit.branch_types.deinit(gpa); + emit.branch_forward_origins.deinit(gpa); + emit.code_offset_mapping.deinit(gpa); emit.* = undefined; } @@ -231,8 +234,9 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index { } fn lowerBranches(emit: *Emit) !void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; const mir_tags = emit.mir.instructions.items(.tag); - const allocator = emit.bin_file.allocator; // First pass: Note down all branches and their target // instructions, i.e. populate branch_types, @@ -246,7 +250,7 @@ fn lowerBranches(emit: *Emit) !void { const target_inst = emit.branchTarget(inst); // Remember this branch instruction - try emit.branch_types.put(allocator, inst, BranchType.default(tag)); + try emit.branch_types.put(gpa, inst, BranchType.default(tag)); // Forward branches require some extra stuff: We only // know their offset once we arrive at the target @@ -256,14 +260,14 @@ fn lowerBranches(emit: *Emit) !void { // etc. if (target_inst > inst) { // Remember the branch instruction index - try emit.code_offset_mapping.put(allocator, inst, 0); + try emit.code_offset_mapping.put(gpa, inst, 0); if (emit.branch_forward_origins.getPtr(target_inst)) |origin_list| { - try origin_list.append(allocator, inst); + try origin_list.append(gpa, inst); } else { var origin_list: std.ArrayListUnmanaged(Mir.Inst.Index) = .{}; - try origin_list.append(allocator, inst); - try emit.branch_forward_origins.put(allocator, target_inst, origin_list); + try origin_list.append(gpa, inst); + try emit.branch_forward_origins.put(gpa, target_inst, origin_list); } } @@ -273,7 +277,7 @@ fn lowerBranches(emit: *Emit) !void { // putNoClobber may not be used as the put operation // may clobber the entry when multiple branches branch // to the same target instruction - try emit.code_offset_mapping.put(allocator, target_inst, 0); + try emit.code_offset_mapping.put(gpa, target_inst, 0); } } @@ -346,7 +350,9 @@ fn writeInstruction(emit: *Emit, instruction: Instruction) !void { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(emit.err_msg == null); - emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); + const comp = emit.bin_file.comp; + const gpa = comp.gpa; + emit.err_msg = try ErrorMsg.create(gpa, emit.src_loc, format, args); return error.EmitFail; } diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 30c6e38c8ac3..80daa8fd3a51 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -232,7 +232,7 @@ pub fn generate( assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); - const target = &namespace.file_scope.mod.target; + const target = &namespace.file_scope.mod.resolved_target.result; var branch_stack = std.ArrayList(Branch).init(gpa); defer { @@ -2719,14 +2719,14 @@ fn wantSafety(self: *Self) bool { fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args); return error.CodegenFail; } fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + self.err_msg = try ErrorMsg.create(self.gpa, self.src_loc, format, args); return error.CodegenFail; } diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig index 9d82cc38cc5d..f382f6f9ebf5 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -80,7 +80,9 @@ fn writeInstruction(emit: *Emit, instruction: Instruction) !void { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(emit.err_msg == null); - emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); + const comp = emit.bin_file.comp; + const gpa = comp.gpa; + emit.err_msg = try ErrorMsg.create(gpa, emit.src_loc, format, args); return error.EmitFail; } diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index bd0208c3c2e0..e58206ac1635 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -275,7 +275,7 @@ pub fn generate( assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); - const target = &namespace.file_scope.mod.target; + const target = &namespace.file_scope.mod.resolved_target.result; var branch_stack = std.ArrayList(Branch).init(gpa); defer { @@ -3546,7 +3546,8 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + const gpa = self.gpa; + self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); return error.CodegenFail; } diff --git a/src/arch/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig index 4701035bc922..b2f2e6f79d08 100644 --- a/src/arch/sparc64/Emit.zig +++ b/src/arch/sparc64/Emit.zig @@ -152,14 +152,16 @@ pub fn emitMir( } pub fn deinit(emit: *Emit) void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; var iter = emit.branch_forward_origins.valueIterator(); while (iter.next()) |origin_list| { - origin_list.deinit(emit.bin_file.allocator); + origin_list.deinit(gpa); } - emit.branch_types.deinit(emit.bin_file.allocator); - emit.branch_forward_origins.deinit(emit.bin_file.allocator); - emit.code_offset_mapping.deinit(emit.bin_file.allocator); + emit.branch_types.deinit(gpa); + emit.branch_forward_origins.deinit(gpa); + emit.code_offset_mapping.deinit(gpa); emit.* = undefined; } @@ -511,7 +513,9 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(emit.err_msg == null); - emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); + const comp = emit.bin_file.comp; + const gpa = comp.gpa; + emit.err_msg = try ErrorMsg.create(gpa, emit.src_loc, format, args); return error.EmitFail; } @@ -537,8 +541,9 @@ fn isBranch(tag: Mir.Inst.Tag) bool { } fn lowerBranches(emit: *Emit) !void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; const mir_tags = emit.mir.instructions.items(.tag); - const allocator = emit.bin_file.allocator; // First pass: Note down all branches and their target // instructions, i.e. populate branch_types, @@ -552,7 +557,7 @@ fn lowerBranches(emit: *Emit) !void { const target_inst = emit.branchTarget(inst); // Remember this branch instruction - try emit.branch_types.put(allocator, inst, BranchType.default(tag)); + try emit.branch_types.put(gpa, inst, BranchType.default(tag)); // Forward branches require some extra stuff: We only // know their offset once we arrive at the target @@ -562,14 +567,14 @@ fn lowerBranches(emit: *Emit) !void { // etc. if (target_inst > inst) { // Remember the branch instruction index - try emit.code_offset_mapping.put(allocator, inst, 0); + try emit.code_offset_mapping.put(gpa, inst, 0); if (emit.branch_forward_origins.getPtr(target_inst)) |origin_list| { - try origin_list.append(allocator, inst); + try origin_list.append(gpa, inst); } else { var origin_list: std.ArrayListUnmanaged(Mir.Inst.Index) = .{}; - try origin_list.append(allocator, inst); - try emit.branch_forward_origins.put(allocator, target_inst, origin_list); + try origin_list.append(gpa, inst); + try emit.branch_forward_origins.put(gpa, target_inst, origin_list); } } @@ -579,7 +584,7 @@ fn lowerBranches(emit: *Emit) !void { // putNoClobber may not be used as the put operation // may clobber the entry when multiple branches branch // to the same target instruction - try emit.code_offset_mapping.put(allocator, target_inst, 0); + try emit.code_offset_mapping.put(gpa, target_inst, 0); } } diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 23193303336c..da33ae521d49 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1210,13 +1210,15 @@ pub fn generate( debug_output: codegen.DebugInfoOutput, ) codegen.CodeGenError!codegen.Result { _ = src_loc; - const mod = bin_file.comp.module.?; + const comp = bin_file.comp; + const gpa = comp.gpa; + const mod = comp.module.?; const func = mod.funcInfo(func_index); const decl = mod.declPtr(func.owner_decl); const namespace = mod.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; var code_gen: CodeGen = .{ - .gpa = bin_file.allocator, + .gpa = gpa, .air = air, .liveness = liveness, .code = code, @@ -7731,7 +7733,7 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { // Only when the atomic feature is enabled, and we're not building // for a single-threaded build, can we emit the `fence` instruction. // In all other cases, we emit no instructions for a fence. - const func_namespace = zcu.namespacePtr(zcu.declPtr(func.decl).namespace); + const func_namespace = zcu.namespacePtr(func.decl.src_namespace); const single_threaded = func_namespace.file_scope.mod.single_threaded; if (func.useAtomicFeature() and !single_threaded) { try func.addAtomicTag(.atomic_fence); diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 990eb359e883..7e67a9828582 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -254,8 +254,10 @@ fn offset(self: Emit) u32 { fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { @setCold(true); std.debug.assert(emit.error_msg == null); - const mod = emit.bin_file.base.comp.module.?; - emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.base.allocator, mod.declPtr(emit.decl_index).srcLoc(mod), format, args); + const comp = emit.bin_file.base.comp; + const zcu = comp.module.?; + const gpa = comp.gpa; + emit.error_msg = try Module.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).srcLoc(zcu), format, args); return error.EmitFail; } @@ -299,6 +301,8 @@ fn emitLabel(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { } fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { + const comp = emit.bin_file.base.comp; + const gpa = comp.gpa; const label = emit.mir.instructions.items(.data)[inst].label; try emit.code.append(@intFromEnum(tag)); var buf: [5]u8 = undefined; @@ -308,7 +312,7 @@ fn emitGlobal(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) !void { const atom_index = emit.bin_file.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); - try atom.relocs.append(emit.bin_file.base.allocator, .{ + try atom.relocs.append(gpa, .{ .index = label, .offset = global_offset, .relocation_type = .R_WASM_GLOBAL_INDEX_LEB, @@ -356,6 +360,8 @@ fn encodeMemArg(mem_arg: Mir.MemArg, writer: anytype) !void { } fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { + const comp = emit.bin_file.base.comp; + const gpa = comp.gpa; const label = emit.mir.instructions.items(.data)[inst].label; try emit.code.append(std.wasm.opcode(.call)); const call_offset = emit.offset(); @@ -366,7 +372,7 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void { if (label != 0) { const atom_index = emit.bin_file.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); - try atom.relocs.append(emit.bin_file.base.allocator, .{ + try atom.relocs.append(gpa, .{ .offset = call_offset, .index = label, .relocation_type = .R_WASM_FUNCTION_INDEX_LEB, @@ -384,6 +390,8 @@ fn emitCallIndirect(emit: *Emit, inst: Mir.Inst.Index) !void { } fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void { + const comp = emit.bin_file.base.comp; + const gpa = comp.gpa; const symbol_index = emit.mir.instructions.items(.data)[inst].label; try emit.code.append(std.wasm.opcode(.i32_const)); const index_offset = emit.offset(); @@ -394,7 +402,7 @@ fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void { if (symbol_index != 0) { const atom_index = emit.bin_file.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); - try atom.relocs.append(emit.bin_file.base.allocator, .{ + try atom.relocs.append(gpa, .{ .offset = index_offset, .index = symbol_index, .relocation_type = .R_WASM_TABLE_INDEX_SLEB, @@ -406,7 +414,9 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { const extra_index = emit.mir.instructions.items(.data)[inst].payload; const mem = emit.mir.extraData(Mir.Memory, extra_index).data; const mem_offset = emit.offset() + 1; - const target = emit.bin_file.comp.root_mod.resolved_target.result; + const comp = emit.bin_file.base.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const is_wasm32 = target.cpu.arch == .wasm32; if (is_wasm32) { try emit.code.append(std.wasm.opcode(.i32_const)); @@ -423,7 +433,7 @@ fn emitMemAddress(emit: *Emit, inst: Mir.Inst.Index) !void { if (mem.pointer != 0) { const atom_index = emit.bin_file.decls.get(emit.decl_index).?; const atom = emit.bin_file.getAtomPtr(atom_index); - try atom.relocs.append(emit.bin_file.base.allocator, .{ + try atom.relocs.append(gpa, .{ .offset = mem_offset, .index = mem.pointer, .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_LEB else .R_WASM_MEMORY_ADDR_LEB64, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index b3c5df02d98e..5056bc32fd3e 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -795,15 +795,16 @@ pub fn generate( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - const mod = bin_file.comp.module.?; + const comp = bin_file.comp; + const gpa = comp.gpa; + const mod = comp.module.?; const func = mod.funcInfo(func_index); const fn_owner_decl = mod.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; const namespace = mod.namespacePtr(fn_owner_decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; - const gpa = bin_file.allocator; var function = Self{ .gpa = gpa, .air = air, @@ -860,7 +861,7 @@ pub fn generate( error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ .fail = try ErrorMsg.create( - bin_file.allocator, + gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}, @@ -904,22 +905,22 @@ pub fn generate( function.gen() catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), .frame_locs = function.frame_locs.toOwnedSlice(), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .lower = .{ .bin_file = bin_file, - .allocator = bin_file.allocator, + .allocator = gpa, .mir = mir, .cc = cc, .src_loc = src_loc, @@ -940,7 +941,7 @@ pub fn generate( }; return Result{ .fail = try ErrorMsg.create( - bin_file.allocator, + gpa, src_loc, "{s} This is a bug in the Zig compiler.", .{msg}, @@ -964,12 +965,13 @@ pub fn generateLazy( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - const gpa = bin_file.allocator; - const zcu = bin_file.comp.module.?; + const comp = bin_file.comp; + const gpa = comp.gpa; + const zcu = comp.module.?; const decl_index = lazy_sym.ty.getOwnerDecl(zcu); const decl = zcu.declPtr(decl_index); const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; var function = Self{ .gpa = gpa, .air = undefined, @@ -996,22 +998,22 @@ pub fn generateLazy( function.genLazy(lazy_sym) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, error.OutOfRegisters => return Result{ - .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), }, else => |e| return e, }; var mir = Mir{ .instructions = function.mir_instructions.toOwnedSlice(), - .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator), + .extra = try function.mir_extra.toOwnedSlice(gpa), .frame_locs = function.frame_locs.toOwnedSlice(), }; - defer mir.deinit(bin_file.allocator); + defer mir.deinit(gpa); var emit = Emit{ .lower = .{ .bin_file = bin_file, - .allocator = bin_file.allocator, + .allocator = gpa, .mir = mir, .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), .src_loc = src_loc, @@ -1032,7 +1034,7 @@ pub fn generateLazy( }; return Result{ .fail = try ErrorMsg.create( - bin_file.allocator, + gpa, src_loc, "{s} This is a bug in the Zig compiler.", .{msg}, @@ -16416,14 +16418,16 @@ fn resolveCallingConventionValues( fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + const gpa = self.gpa; + self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); return error.CodegenFail; } fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { @setCold(true); assert(self.err_msg == null); - self.err_msg = try ErrorMsg.create(self.bin_file.allocator, self.src_loc, format, args); + const gpa = self.gpa; + self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); return error.CodegenFail; } diff --git a/src/codegen.zig b/src/codegen.zig index e579cb50f1d1..65af8236deb9 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -57,7 +57,7 @@ pub fn generateFunction( const func = zcu.funcInfo(func_index); const decl = zcu.declPtr(func.owner_decl); const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; switch (target.cpu.arch) { .arm, .armeb, @@ -87,7 +87,7 @@ pub fn generateLazyFunction( const decl_index = lazy_sym.ty.getOwnerDecl(zcu); const decl = zcu.declPtr(decl_index); const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; switch (target.cpu.arch) { .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(lf, src_loc, lazy_sym, code, debug_output), else => unreachable, @@ -117,12 +117,14 @@ pub fn generateLazySymbol( const tracy = trace(@src()); defer tracy.end(); - const zcu = bin_file.comp.module.?; + const comp = bin_file.comp; + const zcu = comp.module.?; const decl_index = lazy_sym.ty.getOwnerDecl(zcu); const decl = zcu.declPtr(decl_index); const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; const endian = target.cpu.arch.endian(); + const gpa = comp.gpa; log.debug("generateLazySymbol: kind = {s}, ty = {}", .{ @tagName(lazy_sym.kind), @@ -160,7 +162,7 @@ pub fn generateLazySymbol( } return Result.ok; } else return .{ .fail = try ErrorMsg.create( - bin_file.allocator, + gpa, src_loc, "TODO implement generateLazySymbol for {s} {}", .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(zcu) }, @@ -827,7 +829,7 @@ fn lowerDeclRef( const zcu = lf.comp.module.?; const decl = zcu.declPtr(decl_index); const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; const ptr_width = target.ptrBitWidth(); const is_fn_body = decl.ty.zigTypeTag(zcu) == .Fn; @@ -921,7 +923,7 @@ fn genDeclRef( const ptr_decl = zcu.declPtr(ptr_decl_index); const namespace = zcu.namespacePtr(ptr_decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; const ptr_bits = target.ptrBitWidth(); const ptr_bytes: u64 = @divExact(ptr_bits, 8); @@ -944,6 +946,9 @@ fn genDeclRef( return GenResult.mcv(.{ .immediate = imm }); } + const comp = lf.comp; + const gpa = comp.gpa; + // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? if (tv.ty.castPtrToFn(zcu)) |fn_ty| { if (zcu.typeToFunc(fn_ty).?.is_generic) { @@ -958,8 +963,8 @@ fn genDeclRef( try zcu.markDeclAlive(decl); - const decl_namespace = zcu.namespacePtr(decl.namespace_index); - const single_threaded = decl_namespace.file_scope.zcu.single_threaded; + const decl_namespace = zcu.namespacePtr(decl.src_namespace); + const single_threaded = decl_namespace.file_scope.mod.single_threaded; const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded; const is_extern = decl.isExtern(zcu); @@ -985,8 +990,8 @@ fn genDeclRef( if (is_extern) { // TODO make this part of getGlobalSymbol const name = zcu.intern_pool.stringToSlice(decl.name); - const sym_name = try std.fmt.allocPrint(lf.allocator, "_{s}", .{name}); - defer lf.allocator.free(sym_name); + const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); + defer gpa.free(sym_name); const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); } @@ -1005,7 +1010,7 @@ fn genDeclRef( else null; const global_index = try coff_file.getGlobalSymbol(name, lib_name); - try coff_file.need_got_table.put(lf.allocator, global_index, {}); // needs GOT + try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index }); } const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index); @@ -1016,7 +1021,7 @@ fn genDeclRef( const atom = p9.getAtom(atom_index); return GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(p9) }); } else { - return GenResult.fail(lf.allocator, src_loc, "TODO genDeclRef for target {}", .{target}); + return GenResult.fail(gpa, src_loc, "TODO genDeclRef for target {}", .{target}); } } @@ -1073,7 +1078,7 @@ pub fn genTypedValue( const owner_decl = zcu.declPtr(owner_decl_index); const namespace = zcu.namespacePtr(owner_decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; const ptr_bits = target.ptrBitWidth(); if (!typed_value.ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 709b2bf6a933..6545f84f9d79 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1785,7 +1785,7 @@ pub const Object = struct { if (wantDllExports(mod)) global_index.setDllStorageClass(.default, &self.builder); global_index.setUnnamedAddr(.unnamed_addr, &self.builder); if (decl.val.getVariable(mod)) |decl_var| { - const decl_namespace = mod.namespacePtr(decl.namespace_index); + const decl_namespace = mod.namespacePtr(decl.src_namespace); const single_threaded = decl_namespace.file_scope.mod.single_threaded; global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( if (decl_var.is_threadlocal and !single_threaded) @@ -3173,7 +3173,7 @@ pub const Object = struct { variable_index.setLinkage(.external, &o.builder); variable_index.setUnnamedAddr(.default, &o.builder); if (decl.val.getVariable(mod)) |decl_var| { - const decl_namespace = mod.namespacePtr(decl.namespace_index); + const decl_namespace = mod.namespacePtr(decl.src_namespace); const single_threaded = decl_namespace.file_scope.mod.single_threaded; variable_index.setThreadLocal( if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, diff --git a/src/libunwind.zig b/src/libunwind.zig index bc1c0d0343b2..baf24d850827 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -123,7 +123,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, - .resolved = config, + .config = config, .root_mod = root_mod, .cache_mode = .whole, .root_name = root_name, diff --git a/src/link.zig b/src/link.zig index 91def2a13475..ce12e922d7f5 100644 --- a/src/link.zig +++ b/src/link.zig @@ -69,10 +69,12 @@ pub const File = struct { allow_shlib_undefined: bool, stack_size: u64, + error_flags: ErrorFlags = .{}, + misc_errors: std.ArrayListUnmanaged(ErrorMsg) = .{}, + /// Prevents other processes from clobbering files in the output directory /// of this linking operation. lock: ?Cache.Lock = null, - child_pid: ?std.ChildProcess.Id = null, pub const OpenOptions = struct { @@ -210,6 +212,8 @@ pub const File = struct { } pub fn makeWritable(base: *File) !void { + const comp = base.comp; + const gpa = comp.gpa; switch (base.tag) { .coff, .elf, .macho, .plan9, .wasm => { if (build_options.only_c) unreachable; @@ -225,9 +229,10 @@ pub const File = struct { // it will return ETXTBSY. So instead, we copy the file, atomically rename it // over top of the exe path, and then proceed normally. This changes the inode, // avoiding the error. - const tmp_sub_path = try std.fmt.allocPrint(base.allocator, "{s}-{x}", .{ + const tmp_sub_path = try std.fmt.allocPrint(gpa, "{s}-{x}", .{ emit.sub_path, std.crypto.random.int(u32), }); + defer gpa.free(tmp_sub_path); try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{}); try emit.directory.handle.rename(tmp_sub_path, emit.sub_path); switch (builtin.os.tag) { @@ -242,9 +247,9 @@ pub const File = struct { } } } - const use_lld = build_options.have_llvm and base.comp.config.use_lld; - const output_mode = base.comp.config.output_mode; - const link_mode = base.comp.config.link_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; base.file = try emit.directory.handle.createFile(emit.sub_path, .{ .truncate = false, .read = true, @@ -256,9 +261,10 @@ pub const File = struct { } pub fn makeExecutable(base: *File) !void { - const output_mode = base.comp.config.output_mode; - const link_mode = base.comp.config.link_mode; - const use_lld = build_options.have_llvm and base.comp.config.use_lld; + const comp = base.comp; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; switch (output_mode) { .Obj => return, @@ -464,8 +470,13 @@ pub const File = struct { } pub fn destroy(base: *File) void { + const gpa = base.comp.gpa; base.releaseLock(); if (base.file) |f| f.close(); + { + for (base.misc_errors.items) |*item| item.deinit(gpa); + base.misc_errors.deinit(gpa); + } switch (base.tag) { .coff => { if (build_options.only_c) unreachable; @@ -602,9 +613,9 @@ pub const File = struct { return; } - const use_lld = build_options.have_llvm and base.comp.config.use_lld; - const output_mode = base.comp.config.output_mode; - const link_mode = base.comp.config.link_mode; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; if (use_lld and output_mode == .Lib and link_mode == .Static) { return base.linkAsArchive(comp, prog_node); } @@ -657,25 +668,6 @@ pub const File = struct { } } - pub fn errorFlags(base: *File) ErrorFlags { - switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).error_flags, - .elf => return @fieldParentPtr(Elf, "base", base).error_flags, - .macho => return @fieldParentPtr(MachO, "base", base).error_flags, - .plan9 => return @fieldParentPtr(Plan9, "base", base).error_flags, - .c => return .{ .no_entry_point_found = false }, - .wasm, .spirv, .nvptx => return ErrorFlags{}, - } - } - - pub fn miscErrors(base: *File) []const ErrorMsg { - switch (base.tag) { - .elf => return @fieldParentPtr(Elf, "base", base).misc_errors.items, - .macho => return @fieldParentPtr(MachO, "base", base).misc_errors.items, - else => return &.{}, - } - } - pub const UpdateExportsError = error{ OutOfMemory, AnalysisFail, @@ -781,14 +773,15 @@ pub const File = struct { const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(base.allocator); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); const directory = base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); const full_out_path_z = try arena.dupeZ(u8, full_out_path); - const opt_zcu = base.comp.module; + const opt_zcu = comp.module; // If there is no Zig code to compile, then we should skip flushing the output file // because it will not be part of the linker line anyway. @@ -801,7 +794,7 @@ pub const File = struct { log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"}); - const compiler_rt_path: ?[]const u8 = if (base.comp.include_compiler_rt) + const compiler_rt_path: ?[]const u8 = if (comp.include_compiler_rt) comp.compiler_rt_obj.?.full_object_path else null; @@ -815,7 +808,7 @@ pub const File = struct { var man: Cache.Manifest = undefined; defer if (!base.disable_lld_caching) man.deinit(); - const objects = base.comp.objects; + const objects = comp.objects; var digest: [Cache.hex_digest_len]u8 = undefined; @@ -869,7 +862,7 @@ pub const File = struct { const win32_resource_table_len = if (build_options.only_core_functionality) 0 else comp.win32_resource_table.count(); const num_object_files = objects.len + comp.c_object_table.count() + win32_resource_table_len + 2; - var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files); + var object_files = try std.ArrayList([*:0]const u8).initCapacity(gpa, num_object_files); defer object_files.deinit(); for (objects) |obj| { diff --git a/src/link/C.zig b/src/link/C.zig index ce44cc4c06eb..3592052cf804 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -84,7 +84,8 @@ pub fn getString(this: C, s: String) []const u8 { } pub fn addString(this: *C, s: []const u8) Allocator.Error!String { - const gpa = this.base.allocator; + const comp = this.base.comp; + const gpa = comp.gpa; try this.string_bytes.appendSlice(gpa, s); return .{ .start = @intCast(this.string_bytes.items.len - s.len), @@ -97,6 +98,15 @@ pub fn open( comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, +) !*C { + return createEmpty(arena, comp, emit, options); +} + +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, ) !*C { const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .c); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index eba24f0d1767..762591442b15 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -8,7 +8,6 @@ llvm_object: ?*LlvmObject = null, base: link.File, image_base: u64, -error_flags: link.File.ErrorFlags = .{}, dll_export_fns: bool, subsystem: ?std.Target.SubSystem, tsaware: bool, @@ -1825,10 +1824,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.entry_addr == null and self.base.comp.config.output_mode == .Exe) { log.debug("flushing. no_entry_point_found = true\n", .{}); - self.error_flags.no_entry_point_found = true; + self.base.error_flags.no_entry_point_found = true; } else { log.debug("flushing. no_entry_point_found = false\n", .{}); - self.error_flags.no_entry_point_found = false; + self.base.error_flags.no_entry_point_found = false; try self.writeHeader(); } diff --git a/src/link/Coff/Atom.zig b/src/link/Coff/Atom.zig index 9e5557575541..4aa97fa6aced 100644 --- a/src/link/Coff/Atom.zig +++ b/src/link/Coff/Atom.zig @@ -94,7 +94,8 @@ pub fn freeListEligible(self: Atom, coff_file: *const Coff) bool { } pub fn addRelocation(coff_file: *Coff, atom_index: Index, reloc: Relocation) !void { - const gpa = coff_file.base.allocator; + const comp = coff_file.base.comp; + const gpa = comp.gpa; log.debug(" (adding reloc of type {s} to target %{d})", .{ @tagName(reloc.type), reloc.target.sym_index }); const gop = try coff_file.relocs.getOrPut(gpa, atom_index); if (!gop.found_existing) { @@ -104,7 +105,8 @@ pub fn addRelocation(coff_file: *Coff, atom_index: Index, reloc: Relocation) !vo } pub fn addBaseRelocation(coff_file: *Coff, atom_index: Index, offset: u32) !void { - const gpa = coff_file.base.allocator; + const comp = coff_file.base.comp; + const gpa = comp.gpa; log.debug(" (adding base relocation at offset 0x{x} in %{d})", .{ offset, coff_file.getAtom(atom_index).getSymbolIndex().?, @@ -117,7 +119,8 @@ pub fn addBaseRelocation(coff_file: *Coff, atom_index: Index, offset: u32) !void } pub fn freeRelocations(coff_file: *Coff, atom_index: Index) void { - const gpa = coff_file.base.allocator; + const comp = coff_file.base.comp; + const gpa = comp.gpa; var removed_relocs = coff_file.relocs.fetchOrderedRemove(atom_index); if (removed_relocs) |*relocs| relocs.value.deinit(gpa); var removed_base_relocs = coff_file.base_relocs.fetchOrderedRemove(atom_index); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 525ca90bc333..faaf5100a4a2 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1205,7 +1205,7 @@ pub fn commitDeclState( const decl = zcu.declPtr(decl_index); const ip = &zcu.intern_pool; const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.target; + const target = namespace.file_scope.mod.resolved_target.result; const target_endian = target.cpu.arch.endian(); var dbg_line_buffer = &decl_state.dbg_line; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 5f96e195ab66..3e237fe4944e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -196,9 +196,6 @@ resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, has_text_reloc: bool = false, num_ifunc_dynrelocs: usize = 0, -error_flags: link.File.ErrorFlags = link.File.ErrorFlags{}, -misc_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, - /// List of atoms that are owned directly by the linker. atoms: std.ArrayListUnmanaged(Atom) = .{}, @@ -477,7 +474,6 @@ pub fn deinit(self: *Elf) void { } self.last_atom_and_free_list_table.deinit(gpa); - self.misc_errors.deinit(gpa); self.comdat_groups.deinit(gpa); self.comdat_groups_owners.deinit(gpa); self.comdat_groups_table.deinit(gpa); @@ -1168,7 +1164,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // libc dep - self.error_flags.missing_libc = false; + self.base.error_flags.missing_libc = false; if (self.base.comp.config.link_libc) { if (self.base.comp.libc_installation) |lc| { const flags = target_util.libcFullLinkFlags(target); @@ -1219,7 +1215,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }); try system_libs.append(.{ .path = path }); } else { - self.error_flags.missing_libc = true; + self.base.error_flags.missing_libc = true; } } @@ -1257,7 +1253,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }; } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; // Init all objects for (self.objects.items) |index| { @@ -1267,7 +1263,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node try self.file(index).?.shared_object.init(self); } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; // Dedup shared objects { @@ -1389,14 +1385,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (self.entry_index == null and self.base.isExe()) { log.debug("flushing. no_entry_point_found = true", .{}); - self.error_flags.no_entry_point_found = true; + self.base.error_flags.no_entry_point_found = true; } else { log.debug("flushing. no_entry_point_found = false", .{}); - self.error_flags.no_entry_point_found = false; + self.base.error_flags.no_entry_point_found = false; try self.writeElfHeader(); } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; } pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { @@ -1428,7 +1424,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const }; } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; // First, we flush relocatable object file generated with our backends. if (self.zigObjectPtr()) |zig_object| { @@ -1540,7 +1536,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const try self.base.file.?.setEndPos(total_size); try self.base.file.?.pwriteAll(buffer.items, 0); - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; } pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { @@ -1571,14 +1567,14 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) }; } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; // Init all objects for (self.objects.items) |index| { try self.file(index).?.object.init(self); } - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; // Now, we are ready to resolve the symbols across all input files. // We will first resolve the files in the ZigObject, next in the parsed @@ -1612,7 +1608,7 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) try self.writeShdrTable(); try self.writeElfHeader(); - if (self.misc_errors.items.len > 0) return error.FlushFailure; + if (self.base.misc_errors.items.len > 0) return error.FlushFailure; } /// --verbose-link output @@ -2891,7 +2887,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } // libc dep - self.error_flags.missing_libc = false; + self.base.error_flags.missing_libc = false; if (comp.config.link_libc) { if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; @@ -2912,7 +2908,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .Dynamic => "libc.so", })); } else { - self.error_flags.missing_libc = true; + self.base.error_flags.missing_libc = true; } } } @@ -3135,7 +3131,7 @@ fn writePhdrTable(self: *Elf) !void { } fn writeElfHeader(self: *Elf) !void { - if (self.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable + if (self.base.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; @@ -6067,8 +6063,9 @@ const ErrorWithNotes = struct { comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = elf_file.base.allocator; - const err_msg = &elf_file.misc_errors.items[err.index]; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const err_msg = &elf_file.base.misc_errors.items[err.index]; err_msg.msg = try std.fmt.allocPrint(gpa, format, args); } @@ -6078,8 +6075,9 @@ const ErrorWithNotes = struct { comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = elf_file.base.allocator; - const err_msg = &elf_file.misc_errors.items[err.index]; + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const err_msg = &elf_file.base.misc_errors.items[err.index]; assert(err.note_slot < err_msg.notes.len); err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; err.note_slot += 1; @@ -6088,14 +6086,14 @@ const ErrorWithNotes = struct { pub fn addErrorWithNotes(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); return self.addErrorWithNotesAssumeCapacity(note_count); } fn addErrorWithNotesAssumeCapacity(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { const gpa = self.base.comp.gpa; - const index = self.misc_errors.items.len; - const err = self.misc_errors.addOneAssumeCapacity(); + const index = self.base.misc_errors.items.len; + const err = self.base.misc_errors.addOneAssumeCapacity(); err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; return .{ .index = index }; } @@ -6130,7 +6128,7 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { const gpa = self.base.comp.gpa; const max_notes = 4; - try self.misc_errors.ensureUnusedCapacity(gpa, undefs.count()); + try self.base.misc_errors.ensureUnusedCapacity(gpa, undefs.count()); var it = undefs.iterator(); while (it.next()) |entry| { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index dc330fa54b30..9f57dab28371 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -227,7 +227,8 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void { pub fn free(self: *Atom, elf_file: *Elf) void { log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const shndx = self.outputShndx().?; const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; const free_list = &meta.free_list; @@ -352,7 +353,8 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void { } pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const file_ptr = self.file(elf_file).?; assert(file_ptr == .zig_object); const zig_object = file_ptr.zig_object; @@ -747,6 +749,8 @@ fn reportUndefined( rel: elf.Elf64_Rela, undefs: anytype, ) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const rel_esym = switch (self.file(elf_file).?) { .zig_object => |x| x.elfSym(rel.r_sym()).*, .object => |x| x.symtab.items[rel.r_sym()], @@ -761,7 +765,7 @@ fn reportUndefined( { const gop = try undefs.getOrPut(sym_index); if (!gop.found_existing) { - gop.value_ptr.* = std.ArrayList(Atom.Index).init(elf_file.base.allocator); + gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa); } try gop.value_ptr.append(self.atom_index); } @@ -957,6 +961,8 @@ fn resolveDynAbsReloc( elf_file: *Elf, writer: anytype, ) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const P = self.value + rel.r_offset; const A = rel.r_addend; const S = @as(i64, @intCast(target.address(.{}, elf_file))); @@ -967,7 +973,7 @@ fn resolveDynAbsReloc( .shared_object => unreachable, inline else => |x| x.num_dynrelocs, }; - try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, num_dynrelocs); + try elf_file.rela_dyn.ensureUnusedCapacity(gpa, num_dynrelocs); switch (action) { .@"error", diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 25d59f3de3e2..104c83b3574e 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -67,9 +67,6 @@ tlv_ptr_table: TableSection(SymbolWithLoc) = .{}, thunk_table: std.AutoHashMapUnmanaged(Atom.Index, thunks.Thunk.Index) = .{}, thunks: std.ArrayListUnmanaged(thunks.Thunk) = .{}, -error_flags: File.ErrorFlags = File.ErrorFlags{}, -misc_errors: std.ArrayListUnmanaged(File.ErrorMsg) = .{}, - segment_table_dirty: bool = false, got_table_count_dirty: bool = false, got_table_contents_dirty: bool = false, @@ -337,8 +334,8 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li if (build_options.have_llvm) { return self.base.linkAsArchive(comp, prog_node); } else { - try self.misc_errors.ensureUnusedCapacity(gpa, 1); - self.misc_errors.appendAssumeCapacity(.{ + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try gpa.dupe(u8, "TODO: non-LLVM archiver for MachO object files"), }); return error.FlushFailure; @@ -492,7 +489,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try self.resolveSymbols(); if (self.getEntryPoint() == null) { - self.error_flags.no_entry_point_found = true; + self.base.error_flags.no_entry_point_found = true; } if (self.unresolved.count() > 0) { try self.reportUndefined(); @@ -2097,11 +2094,6 @@ pub fn deinit(self: *MachO) void { bindings.deinit(gpa); } self.bindings.deinit(gpa); - - for (self.misc_errors.items) |*err| { - err.deinit(gpa); - } - self.misc_errors.deinit(gpa); } fn freeAtom(self: *MachO, atom_index: Atom.Index) void { @@ -5341,13 +5333,13 @@ fn reportMissingLibraryError( args: anytype, ) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len); errdefer gpa.free(notes); for (checked_paths, notes) |path, *note| { note.* = .{ .msg = try std.fmt.allocPrint(gpa, "tried {s}", .{path}) }; } - self.misc_errors.appendAssumeCapacity(.{ + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5361,14 +5353,14 @@ fn reportDependencyError( args: anytype, ) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); defer notes.deinit(); if (path) |p| { notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) }); } notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "a dependency of {s}", .{parent}) }); - self.misc_errors.appendAssumeCapacity(.{ + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = try notes.toOwnedSlice(), }); @@ -5381,11 +5373,11 @@ pub fn reportParseError( args: anytype, ) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) }; - self.misc_errors.appendAssumeCapacity(.{ + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5398,11 +5390,11 @@ pub fn reportUnresolvedBoundarySymbol( args: anytype, ) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while resolving {s}", .{sym_name}) }; - self.misc_errors.appendAssumeCapacity(.{ + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5411,7 +5403,7 @@ pub fn reportUnresolvedBoundarySymbol( pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; const count = self.unresolved.count(); - try self.misc_errors.ensureUnusedCapacity(gpa, count); + try self.base.misc_errors.ensureUnusedCapacity(gpa, count); for (self.unresolved.keys()) |global_index| { const global = self.globals.items[global_index]; @@ -5432,7 +5424,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { }; err_msg.notes = try notes.toOwnedSlice(); - self.misc_errors.appendAssumeCapacity(err_msg); + self.base.misc_errors.appendAssumeCapacity(err_msg); } } @@ -5442,7 +5434,7 @@ fn reportSymbolCollision( other: SymbolWithLoc, ) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); defer notes.deinit(); @@ -5465,12 +5457,12 @@ fn reportSymbolCollision( }) }; err_msg.notes = try notes.toOwnedSlice(); - self.misc_errors.appendAssumeCapacity(err_msg); + self.base.misc_errors.appendAssumeCapacity(err_msg); } fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void { const gpa = self.base.comp.gpa; - try self.misc_errors.ensureUnusedCapacity(gpa, 1); + try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); @@ -5488,7 +5480,7 @@ fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{Ou else unreachable; - self.misc_errors.appendAssumeCapacity(.{ + self.base.misc_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "unhandled symbol type: '{s}' has type {s}", .{ self.getSymbolName(sym_with_loc), sym_type, diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 02639953593d..d76a6de841ce 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -253,7 +253,8 @@ pub fn addRelocation(macho_file: *MachO, atom_index: Index, reloc: Relocation) ! } pub fn addRelocations(macho_file: *MachO, atom_index: Index, relocs: []const Relocation) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const gop = try macho_file.relocs.getOrPut(gpa, atom_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; @@ -269,7 +270,8 @@ pub fn addRelocations(macho_file: *MachO, atom_index: Index, relocs: []const Rel } pub fn addRebase(macho_file: *MachO, atom_index: Index, offset: u32) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const atom = macho_file.getAtom(atom_index); log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, atom.getSymbolIndex() }); const gop = try macho_file.rebases.getOrPut(gpa, atom_index); @@ -280,7 +282,8 @@ pub fn addRebase(macho_file: *MachO, atom_index: Index, offset: u32) !void { } pub fn addBinding(macho_file: *MachO, atom_index: Index, binding: Binding) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const atom = macho_file.getAtom(atom_index); log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{ macho_file.getSymbolName(binding.target), @@ -307,7 +310,8 @@ pub fn resolveRelocations( } pub fn freeRelocations(macho_file: *MachO, atom_index: Index) void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var removed_relocs = macho_file.relocs.fetchOrderedRemove(atom_index); if (removed_relocs) |*relocs| relocs.value.deinit(gpa); var removed_rebases = macho_file.rebases.fetchOrderedRemove(atom_index); diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index c970e72e5110..3fe6aee00959 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -28,7 +28,6 @@ pub const base_tag = .plan9; base: link.File, sixtyfour_bit: bool, -error_flags: File.ErrorFlags = File.ErrorFlags{}, bases: Bases, /// A symbol's value is just casted down when compiling From 6b44bddf5dd4a50c79cd1a4d3596cc07d868dd63 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Dec 2023 19:09:38 -0700 Subject: [PATCH 043/133] linker: remove bad NvPtx flushModule implementation it's not supposed to mutate Compilation like this. --- src/link/NvPtx.zig | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 57a835289847..b59a527c5a1d 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -98,9 +98,9 @@ pub fn updateExports( exported: Module.Exported, exports: []const *Module.Export, ) !void { - if (build_options.skip_non_native and builtin.object_format != .nvptx) { + if (build_options.skip_non_native and builtin.object_format != .nvptx) @panic("Attempted to compile for object format that was disabled by build configuration"); - } + return self.llvm_object.updateExports(module, exported, exports); } @@ -113,27 +113,13 @@ pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) li } pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - if (build_options.skip_non_native) { + if (build_options.skip_non_native) @panic("Attempted to compile for architecture that was disabled by build configuration"); - } - const outfile = comp.bin_file.options.emit orelse return; - - const tracy = trace(@src()); - defer tracy.end(); - - // We modify 'comp' before passing it to LLVM, but restore value afterwards. - // We tell LLVM to not try to build a .o, only an "assembly" file. - // This is required by the LLVM PTX backend. - comp.bin_file.options.emit = null; - comp.emit_asm = .{ - // 'null' means using the default cache dir: zig-cache/o/... - .directory = null, - .basename = self.base.emit.sub_path, - }; - defer { - comp.bin_file.options.emit = outfile; - comp.emit_asm = null; - } - try self.llvm_object.flushModule(comp, prog_node); + // The code that was here before mutated the Compilation's file emission mechanism. + // That's not supposed to happen in flushModule, so I deleted the code. + _ = self; + _ = comp; + _ = prog_node; + @panic("TODO: rewrite the NvPtx.flushModule function"); } From 7e7d5dc958b08dc0f671cd1b119cd831fc877d16 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Dec 2023 19:10:32 -0700 Subject: [PATCH 044/133] musl: update references to bin_file.options --- src/Compilation.zig | 2 +- src/musl.zig | 86 ++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 693e46c07c08..2a2ef3e3296a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6241,7 +6241,7 @@ pub fn build_crt_file( defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const basename = try std.zig.binNameAlloc(arena, .{ + const basename = try std.zig.binNameAlloc(gpa, .{ .root_name = root_name, .target = comp.root_mod.resolved_target.result, .output_mode = output_mode, diff --git a/src/musl.zig b/src/musl.zig index 47b8c8d6b553..e29d348d1fe3 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -3,6 +3,7 @@ const Allocator = std.mem.Allocator; const mem = std.mem; const path = std.fs.path; const assert = std.debug.assert; +const Module = @import("Package/Module.zig"); const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); @@ -190,41 +191,70 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr return comp.build_crt_file("c", .Lib, .@"musl libc.a", prog_node, c_source_files.items); }, .libc_so => { - const target = comp.getTarget(); + const unwind_tables = false; + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + const config = try Compilation.Config.resolve(.{ + .output_mode = .Lib, + .link_mode = .Dynamic, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = false, + .any_unwind_tables = unwind_tables, + }); + + const target = comp.root_mod.resolved_target.result; const arch_define = try std.fmt.allocPrint(arena, "-DARCH_{s}", .{ @tagName(target.cpu.arch), }); - const clang_argv: []const []const u8 = if (target.ptrBitWidth() == 64) - &[_][]const u8{ "-DPTR64", arch_define } + const cc_argv: []const []const u8 = if (target.ptrBitWidth() == 64) + &.{ "-DPTR64", arch_define } else - &[_][]const u8{arch_define}; + &.{arch_define}; + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .strip = strip, + .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 = unwind_tables, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, - .cache_mode = .whole, .zig_lib_directory = comp.zig_lib_directory, - .target = target, - .root_name = "c", - .main_mod = null, - .output_mode = .Lib, - .link_mode = .Dynamic, + .self_exe_path = comp.self_exe_path, + .cache_mode = .whole, + .config = config, + .root_mod = root_mod, .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.libc_installation, - .emit_bin = Compilation.EmitLoc{ .directory = null, .basename = "libc.so" }, - .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, + .root_name = "c", + .libc_installation = comp.libc_installation, + .emit_bin = .{ .directory = null, .basename = "libc.so" }, .emit_h = null, - .strip = comp.compilerRtStrip(), - .is_native_os = false, - .is_native_abi = false, - .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, @@ -233,9 +263,9 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .c_source_files = &[_]Compilation.CSourceFile{ - .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "libc.S" }) }, + .{ .src_path = try comp.zig_lib_directory.join(arena, &.{ "libc", "musl", "libc.S" }) }, }, - .clang_argv = clang_argv, + .cc_argv = cc_argv, .skip_linker_dependencies = true, .soname = "libc.so", }); @@ -249,8 +279,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr errdefer comp.gpa.free(basename); 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(comp.gpa, &.{ + sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), }); From 2596f5d92593a5f7dad21d9a54f2d08f33639432 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Dec 2023 19:49:53 -0700 Subject: [PATCH 045/133] update bin_file.options references in Sema mainly pertaining to error return tracing --- src/Compilation/Config.zig | 22 +++++++++++++ src/Package/Module.zig | 10 ++---- src/Sema.zig | 64 +++++++++++++++++++------------------- src/codegen/llvm.zig | 10 +++--- src/main.zig | 5 +++ 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 0afb633c86a5..efe314095cc6 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -9,6 +9,10 @@ link_libunwind: bool, any_unwind_tables: bool, any_c_source_files: bool, any_non_single_threaded: bool, +/// This is true if any Module has error_tracing set to true. Function types +/// and function calling convention depend on this global value, however, other +/// kinds of error tracing are omitted depending on the per-Module setting. +any_error_tracing: bool, pie: bool, /// If this is true then linker code is responsible for making an LLVM IR /// Module, outputting it to an object file, and then linking that together @@ -34,6 +38,8 @@ is_test: bool, test_evented_io: bool, entry: ?[]const u8, debug_format: DebugFormat, +root_strip: bool, +root_error_tracing: bool, pub const CFrontend = enum { clang, aro }; @@ -51,6 +57,7 @@ pub const Options = struct { emit_bin: bool, root_optimize_mode: ?std.builtin.OptimizeMode = null, root_strip: ?bool = null, + root_error_tracing: ?bool = null, link_mode: ?std.builtin.LinkMode = null, ensure_libc_on_non_freestanding: bool = false, ensure_libcpp_on_non_freestanding: bool = false, @@ -60,6 +67,7 @@ pub const Options = struct { any_dyn_libs: bool = false, any_c_source_files: bool = false, any_non_stripped: bool = false, + any_error_tracing: bool = false, emit_llvm_ir: bool = false, emit_llvm_bc: bool = false, link_libc: ?bool = null, @@ -395,6 +403,17 @@ pub fn resolve(options: Options) !Config { }; }; + const root_error_tracing = b: { + if (options.root_error_tracing) |x| break :b x; + if (root_strip) break :b false; + break :b switch (root_optimize_mode) { + .Debug => true, + .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, + }; + }; + + const any_error_tracing = root_error_tracing or options.any_error_tracing; + return .{ .output_mode = options.output_mode, .have_zcu = options.have_zcu, @@ -407,6 +426,8 @@ pub fn resolve(options: Options) !Config { .any_unwind_tables = any_unwind_tables, .any_c_source_files = options.any_c_source_files, .any_non_single_threaded = options.any_non_single_threaded, + .any_error_tracing = any_error_tracing, + .root_error_tracing = root_error_tracing, .pie = pie, .lto = lto, .import_memory = import_memory, @@ -419,6 +440,7 @@ pub fn resolve(options: Options) !Config { .entry = entry, .wasi_exec_model = wasi_exec_model, .debug_format = debug_format, + .root_strip = root_strip, }; } diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 051303ca26f1..5e786a6fa2eb 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -114,9 +114,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { const strip = b: { if (options.inherited.strip) |x| break :b x; if (options.parent) |p| break :b p.strip; - if (optimize_mode == .ReleaseSmall) break :b true; - if (!target_util.hasDebugInfo(target)) break :b true; - break :b false; + break :b options.global.root_strip; }; const valgrind = b: { @@ -156,11 +154,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { const error_tracing = b: { if (options.inherited.error_tracing) |x| break :b x; if (options.parent) |p| break :b p.error_tracing; - if (strip) break :b false; - break :b switch (optimize_mode) { - .Debug => true, - .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, - }; + break :b options.global.root_error_tracing; }; const pic = b: { diff --git a/src/Sema.zig b/src/Sema.zig index 2d46faf4358c..6d14deb0953f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1329,13 +1329,13 @@ fn analyzeBodyInner( }, .dbg_block_begin => { dbg_block_begins += 1; - try sema.zirDbgBlockBegin(block); + try zirDbgBlockBegin(block); i += 1; continue; }, .dbg_block_end => { dbg_block_begins -= 1; - try sema.zirDbgBlockEnd(block); + try zirDbgBlockEnd(block); i += 1; continue; }, @@ -1830,17 +1830,17 @@ fn analyzeBodyInner( }; // balance out dbg_block_begins in case of early noreturn - const noreturn_inst = block.instructions.popOrNull(); - while (dbg_block_begins > 0) { - dbg_block_begins -= 1; - if (block.is_comptime or mod.comp.bin_file.options.strip) continue; - - _ = try block.addInst(.{ - .tag = .dbg_block_end, - .data = undefined, - }); + if (!block.is_comptime and !block.ownerModule().strip) { + const noreturn_inst = block.instructions.popOrNull(); + while (dbg_block_begins > 0) { + dbg_block_begins -= 1; + _ = try block.addInst(.{ + .tag = .dbg_block_end, + .data = undefined, + }); + } + if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); } - if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); // We may have overwritten the capture scope due to a `repeat` instruction where // the body had a capture; restore it now. @@ -6272,7 +6272,7 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi // ZIR code that possibly will need to generate runtime code. So error messages // and other source locations must not rely on sema.src being set from dbg_stmt // instructions. - if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return; + if (block.is_comptime or block.ownerModule().strip) return; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; @@ -6297,8 +6297,8 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi }); } -fn zirDbgBlockBegin(sema: *Sema, block: *Block) CompileError!void { - if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return; +fn zirDbgBlockBegin(block: *Block) CompileError!void { + if (block.is_comptime or block.ownerModule().strip) return; _ = try block.addInst(.{ .tag = .dbg_block_begin, @@ -6306,8 +6306,8 @@ fn zirDbgBlockBegin(sema: *Sema, block: *Block) CompileError!void { }); } -fn zirDbgBlockEnd(sema: *Sema, block: *Block) CompileError!void { - if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return; +fn zirDbgBlockEnd(block: *Block) CompileError!void { + if (block.is_comptime or block.ownerModule().strip) return; _ = try block.addInst(.{ .tag = .dbg_block_end, @@ -6321,7 +6321,7 @@ fn zirDbgVar( inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!void { - if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return; + if (block.is_comptime or block.ownerModule().strip) return; const str_op = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_op; const operand = try sema.resolveInst(str_op.operand); @@ -6519,7 +6519,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref const src = sema.src; if (!mod.backendSupportsFeature(.error_return_trace)) return .none; - if (!mod.comp.bin_file.options.error_return_tracing) return .none; + if (!block.ownerModule().error_tracing) return .none; if (block.is_comptime) return .none; @@ -6703,7 +6703,7 @@ fn zirCall( input_is_error = false; } - if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and + if (mod.backendSupportsFeature(.error_return_trace) and block.ownerModule().error_tracing and !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) { const return_ty = sema.typeOf(call_inst); @@ -7456,7 +7456,7 @@ fn analyzeCall( new_fn_info.return_type = sema.fn_ret_ty.toIntern(); const new_func_resolved_ty = try mod.funcType(new_fn_info); if (!is_comptime_call and !block.is_typeof) { - try sema.emitDbgInline(block, prev_fn_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); + try emitDbgInline(block, prev_fn_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin); const zir_tags = sema.code.instructions.items(.tag); for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) { @@ -7494,7 +7494,7 @@ fn analyzeCall( if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) { - try sema.emitDbgInline( + try emitDbgInline( block, module_fn_index, prev_fn_index, @@ -8067,15 +8067,13 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) } fn emitDbgInline( - sema: *Sema, block: *Block, old_func: InternPool.Index, new_func: InternPool.Index, new_func_ty: Type, tag: Air.Inst.Tag, ) CompileError!void { - const mod = sema.mod; - if (mod.comp.bin_file.options.strip) return; + if (block.ownerModule().strip) return; // Recursive inline call; no dbg_inline needed. if (old_func == new_func) return; @@ -9109,7 +9107,7 @@ fn handleExternLibName( ); break :blk; } - if (!target.isWasm() and !comp.bin_file.options.pic) { + if (!target.isWasm() and !block.ownerModule().pic) { return sema.fail( block, src_loc, @@ -18738,16 +18736,16 @@ fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool { const mod = sema.mod; if (!mod.backendSupportsFeature(.error_return_trace)) return false; - return fn_ret_ty.isError(mod) and - mod.comp.bin_file.options.error_return_tracing; + return fn_ret_ty.isError(mod) and mod.comp.config.any_error_tracing; } fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index; + // TODO: replace all of these checks with logic in module creation if (!mod.backendSupportsFeature(.error_return_trace)) return; - if (!mod.comp.bin_file.options.error_return_tracing) return; + if (!block.ownerModule().error_tracing) return; // This is only relevant at runtime. if (block.is_comptime or block.is_typeof) return; @@ -18774,7 +18772,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) if (!mod.backendSupportsFeature(.error_return_trace)) return; if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return; - if (!mod.comp.bin_file.options.error_return_tracing) return; + if (!start_block.ownerModule().error_tracing) return; const tracy = trace(@src()); defer tracy.end(); @@ -20045,7 +20043,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { if (sema.owner_func_index != .none and ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and - mod.comp.bin_file.options.error_return_tracing and + mod.ownerModule().error_tracing and mod.backendSupportsFeature(.error_return_trace)) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); @@ -34504,7 +34502,9 @@ pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void { try sema.resolveTypeFully(Type.fromInterned(fn_ty_info.return_type)); - if (mod.comp.bin_file.options.error_return_tracing and Type.fromInterned(fn_ty_info.return_type).isError(mod)) { + if (mod.comp.config.any_error_tracing and + Type.fromInterned(fn_ty_info.return_type).isError(mod)) + { // Ensure the type exists so that backends can assume that. _ = try sema.getBuiltinType("StackTrace"); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6545f84f9d79..75fb373d9be5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1398,7 +1398,7 @@ pub const Object = struct { }; const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.bin_file.options.error_return_tracing; + mod.comp.config.any_error_tracing; const err_ret_trace: Builder.Value = if (err_return_tracing) param: { const param = wip.arg(llvm_arg_i); @@ -2820,7 +2820,7 @@ pub const Object = struct { } if (Type.fromInterned(fn_info.return_type).isError(mod) and - o.module.comp.bin_file.options.error_return_tracing) + o.module.comp.config.any_error_tracing) { const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType()); try param_di_types.append(try o.lowerDebugType(ptr_ty, .full)); @@ -2988,7 +2988,7 @@ pub const Object = struct { } const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.bin_file.options.error_return_tracing; + mod.comp.config.any_error_tracing; if (err_return_tracing) { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); @@ -3677,7 +3677,7 @@ pub const Object = struct { } if (Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.bin_file.options.error_return_tracing) + mod.comp.config.any_error_tracing) { const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType()); try llvm_params.append(o.gpa, try o.lowerType(ptr_ty)); @@ -5142,7 +5142,7 @@ pub const FuncGen = struct { }; const err_return_tracing = return_type.isError(mod) and - o.module.comp.bin_file.options.error_return_tracing; + o.module.comp.config.any_error_tracing; if (err_return_tracing) { assert(self.err_ret_trace != .none); try llvm_args.append(self.err_ret_trace); diff --git a/src/main.zig b/src/main.zig index dbd975901591..b73023e5b35f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1055,6 +1055,8 @@ fn buildOutputType( create_module.opts.any_unwind_tables = true; if (mod_opts.strip == false) create_module.opts.any_non_stripped = true; + if (mod_opts.error_tracing == true) + create_module.opts.any_error_tracing = true; const root_src = try introspect.resolvePath(arena, root_src_orig); try create_module.modules.put(arena, mod_name, .{ @@ -2535,6 +2537,8 @@ fn buildOutputType( create_module.opts.any_unwind_tables = true; if (mod_opts.strip == false) create_module.opts.any_non_stripped = true; + if (mod_opts.error_tracing == true) + create_module.opts.any_error_tracing = true; const src_path = try introspect.resolvePath(arena, unresolved_src_path); try create_module.modules.put(arena, "main", .{ @@ -3741,6 +3745,7 @@ fn createModule( create_module.opts.resolved_target = resolved_target; create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode; create_module.opts.root_strip = cli_mod.inherited.strip; + create_module.opts.root_error_tracing = cli_mod.inherited.error_tracing; const target = resolved_target.result; // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. From a1236b32f9a4114231312b1493dcbac308a2c055 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 14:22:24 -0700 Subject: [PATCH 046/133] libcxx: update to new Compilation API --- src/Compilation/Config.zig | 2 + src/Module.zig | 6 +- src/Package/Module.zig | 5 ++ src/libcxx.zig | 157 ++++++++++++++++++++++++------------- src/musl.zig | 3 - 5 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index efe314095cc6..44ace55ae486 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -13,6 +13,7 @@ any_non_single_threaded: bool, /// and function calling convention depend on this global value, however, other /// kinds of error tracing are omitted depending on the per-Module setting. any_error_tracing: bool, +any_sanitize_thread: bool, pie: bool, /// If this is true then linker code is responsible for making an LLVM IR /// Module, outputting it to an object file, and then linking that together @@ -427,6 +428,7 @@ pub fn resolve(options: Options) !Config { .any_c_source_files = options.any_c_source_files, .any_non_single_threaded = options.any_non_single_threaded, .any_error_tracing = any_error_tracing, + .any_sanitize_thread = options.any_sanitize_thread, .root_error_tracing = root_error_tracing, .pie = pie, .lto = lto, diff --git a/src/Module.zig b/src/Module.zig index 0645b6f04f34..571301c8e68d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4566,7 +4566,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // If we don't get an error return trace from a caller, create our own. if (func.analysis(ip).calls_or_awaits_errorable_fn and - mod.comp.config.error_tracing and + mod.comp.config.any_error_tracing and !sema.fn_ret_ty.isError(mod)) { sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { @@ -5567,8 +5567,8 @@ pub const Feature = enum { }; pub fn backendSupportsFeature(zcu: Module, feature: Feature) bool { - const cpu_arch = zcu.root_mod.resolved_target.cpu.arch; - const ofmt = zcu.root_mod.resolved_target.ofmt; + const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch; + const ofmt = zcu.root_mod.resolved_target.result.ofmt; const use_llvm = zcu.comp.config.use_llvm; return switch (feature) { .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64, diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 5e786a6fa2eb..4ce0f0a8569f 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -102,6 +102,11 @@ pub const ResolvedTarget = struct { /// At least one of `parent` and `resolved_target` must be non-null. pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { + if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread); + if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded); + if (options.inherited.unwind_tables == true) assert(options.global.any_unwind_tables); + if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing); + const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target; const target = resolved_target.result; diff --git a/src/libcxx.zig b/src/libcxx.zig index 8ae7db80f133..1f78b867a324 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -6,6 +6,7 @@ const target_util = @import("target.zig"); const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); const trace = @import("tracy.zig").trace; +const Module = @import("Package/Module.zig"); pub const AbiVersion = enum(u2) { @"1" = 1, @@ -115,7 +116,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { const root_name = "c++"; const output_mode = .Lib; const link_mode = .Static; - const target = comp.getTarget(); + const target = comp.root_mod.resolved_target.result; const basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, @@ -226,46 +227,70 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + .lto = comp.config.lto, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .strip = strip, + .stack_check = false, + .stack_protector = 0, + .sanitize_c = false, + .sanitize_thread = comp.config.any_sanitize_thread, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .pic = comp.root_mod.pic, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + const sub_compilation = try Compilation.create(comp.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, + .config = 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 = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), - .link_mode = link_mode, - .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 = comp.bin_file.options.tsan, - .want_pic = comp.bin_file.options.pic, - .want_pie = null, - .want_lto = comp.bin_file.options.lto, - .function_sections = comp.bin_file.options.function_sections, .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.items, .verbose_cc = comp.verbose_cc, - .verbose_link = comp.bin_file.options.verbose_link, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_cimport = comp.verbose_cimport, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, - .link_libc = true, .skip_linker_dependencies = true, }); defer sub_compilation.destroy(); @@ -274,8 +299,8 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { assert(comp.libcxx_static_lib == null); comp.libcxx_static_lib = 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, &.{ + sub_compilation.bin_file.?.emit.sub_path, }), .lock = sub_compilation.bin_file.toOwnedLock(), }; @@ -296,7 +321,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { const root_name = "c++abi"; const output_mode = .Lib; const link_mode = .Static; - const target = comp.getTarget(); + const target = comp.root_mod.resolved_target.result; const basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, @@ -365,7 +390,6 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { } try cflags.append("-nostdinc++"); try cflags.append("-fstrict-aliasing"); - try cflags.append("-funwind-tables"); try cflags.append("-std=c++20"); // These depend on only the zig lib directory file path, which is @@ -389,46 +413,73 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + const unwind_tables = true; + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + .any_unwind_tables = unwind_tables, + .lto = comp.config.lto, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .strip = strip, + .stack_check = false, + .stack_protector = 0, + .sanitize_c = false, + .sanitize_thread = comp.config.any_sanitize_thread, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .unwind_tables = unwind_tables, + .pic = comp.root_mod.pic, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + const sub_compilation = try Compilation.create(comp.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, + .config = 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 = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), - .link_mode = link_mode, - .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 = comp.bin_file.options.tsan, - .want_pic = comp.bin_file.options.pic, - .want_pie = null, - .want_lto = comp.bin_file.options.lto, - .function_sections = comp.bin_file.options.function_sections, .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.items, .verbose_cc = comp.verbose_cc, - .verbose_link = comp.bin_file.options.verbose_link, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_cimport = comp.verbose_cimport, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, - .link_libc = true, .skip_linker_dependencies = true, }); defer sub_compilation.destroy(); @@ -437,8 +488,8 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { assert(comp.libcxxabi_static_lib == null); comp.libcxxabi_static_lib = 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(), }; diff --git a/src/musl.zig b/src/musl.zig index e29d348d1fe3..249753d4156e 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -191,7 +191,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr return comp.build_crt_file("c", .Lib, .@"musl libc.a", prog_node, c_source_files.items); }, .libc_so => { - const unwind_tables = false; const optimize_mode = comp.compilerRtOptMode(); const strip = comp.compilerRtStrip(); const config = try Compilation.Config.resolve(.{ @@ -204,7 +203,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .root_optimize_mode = optimize_mode, .root_strip = strip, .link_libc = false, - .any_unwind_tables = unwind_tables, }); const target = comp.root_mod.resolved_target.result; @@ -232,7 +230,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .red_zone = comp.root_mod.red_zone, .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, - .unwind_tables = unwind_tables, .optimize_mode = optimize_mode, .structured_cfg = comp.root_mod.structured_cfg, }, From ea0ba4f2b572fad8595ae02ac9c43ab7dd0cc2f2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 14:31:55 -0700 Subject: [PATCH 047/133] tsan: update to new Compilation API --- src/libtsan.zig | 74 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/src/libtsan.zig b/src/libtsan.zig index d0af65e4c654..745a947153df 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -4,6 +4,7 @@ const assert = std.debug.assert; const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); const trace = @import("tracy.zig").trace; +const Module = @import("Package/Module.zig"); pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { if (!build_options.have_llvm) { @@ -195,44 +196,71 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "-DTSAN_CONTAINS_UBSAN=0", }; + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .strip = strip, + .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, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .pic = true, + .cc_argv = &common_flags, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .thread_pool = comp.thread_pool, + .self_exe_path = comp.self_exe_path, .cache_mode = .whole, - .target = target, + .config = 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 = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), - .link_mode = link_mode, - .want_sanitize_c = false, - .want_stack_check = false, - .want_stack_protector = 0, - .want_valgrind = false, - .want_tsan = false, - .want_pic = true, - .want_pie = null, .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.items, .verbose_cc = comp.verbose_cc, - .verbose_link = comp.bin_file.options.verbose_link, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_bc = comp.verbose_llvm_bc, .verbose_cimport = comp.verbose_cimport, .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, - .link_libc = true, .skip_linker_dependencies = true, - .clang_argv = &common_flags, }); defer sub_compilation.destroy(); @@ -240,8 +268,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { assert(comp.tsan_static_lib == null); comp.tsan_static_lib = 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(), }; From 92b54e50c85488459df0c6579086494e31d9d52a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 14:43:39 -0700 Subject: [PATCH 048/133] glibc: update to new Compilation API --- src/Compilation.zig | 2 ++ src/glibc.zig | 68 ++++++++++++++++++++++++++++++++------------- src/libcxx.zig | 2 ++ src/libtsan.zig | 1 + src/libunwind.zig | 1 + src/musl.zig | 1 + 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 2a2ef3e3296a..7b7e85d0f7d6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6158,6 +6158,7 @@ fn buildOutputFromZig( }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = comp.compilerRtStrip(), .stack_check = false, .stack_protector = 0, @@ -6269,6 +6270,7 @@ pub fn build_crt_file( }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = comp.compilerRtStrip(), .stack_check = false, .stack_protector = 0, diff --git a/src/glibc.zig b/src/glibc.zig index d719dab491f9..0502bc3799f2 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -12,7 +12,7 @@ const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); const trace = @import("tracy.zig").trace; const Cache = std.Build.Cache; -const Package = @import("Package.zig"); +const Module = @import("Package/Module.zig"); pub const Lib = struct { name: []const u8, @@ -1067,34 +1067,62 @@ fn buildSharedLib( .src_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, asm_file_basename }), }, }; + + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + const config = try Compilation.Config.resolve(.{ + .output_mode = .Lib, + .link_mode = .Dynamic, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = false, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .strip = strip, + .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, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = zig_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, + .thread_pool = comp.thread_pool, + .self_exe_path = comp.self_exe_path, .cache_mode = .whole, - .target = comp.getTarget(), + .config = config, + .root_mod = root_mod, .root_name = lib.name, - .main_mod = null, - .output_mode = .Lib, - .link_mode = .Dynamic, - .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.libc_installation, + .libc_installation = comp.libc_installation, .emit_bin = emit_bin, - .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, .emit_h = null, - .strip = comp.compilerRtStrip(), - .is_native_os = false, - .is_native_abi = false, - .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_llvm_ir = comp.verbose_llvm_ir, .verbose_llvm_bc = comp.verbose_llvm_bc, diff --git a/src/libcxx.zig b/src/libcxx.zig index 1f78b867a324..0625d033bfa2 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -251,6 +251,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = strip, .stack_check = false, .stack_protector = 0, @@ -439,6 +440,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = strip, .stack_check = false, .stack_protector = 0, diff --git a/src/libtsan.zig b/src/libtsan.zig index 745a947153df..6220f00e8fd1 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -219,6 +219,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = strip, .stack_check = false, .stack_protector = 0, diff --git a/src/libunwind.zig b/src/libunwind.zig index baf24d850827..5b963c96c966 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -40,6 +40,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = comp.compilerRtStrip(), .stack_check = false, .stack_protector = 0, diff --git a/src/musl.zig b/src/musl.zig index 249753d4156e..953c5687e909 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -222,6 +222,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr }, .fully_qualified_name = "root", .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, .strip = strip, .stack_check = false, .stack_protector = 0, From b54ad9317591873159594e673953088a21d66e7b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 19:12:06 -0700 Subject: [PATCH 049/133] update codegen.llvm references to bin_file.options --- src/codegen/llvm.zig | 494 ++++++++++++++++++------------------- src/link.zig | 46 ++++ src/link/Coff.zig | 17 +- src/link/Elf.zig | 47 ++-- src/link/Elf/Symbol.zig | 6 +- src/link/Elf/ZigObject.zig | 6 +- src/link/MachO.zig | 21 +- src/link/Wasm.zig | 21 +- 8 files changed, 354 insertions(+), 304 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 75fb373d9be5..42180c6529ef 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -822,7 +822,7 @@ pub const Object = struct { type_map: TypeMap, di_type_map: DITypeMap, /// The LLVM global table which holds the names corresponding to Zig errors. - /// Note that the values are not added until flushModule, when all errors in + /// Note that the values are not added until `emit`, when all errors in /// the compilation are known. error_name_table: Builder.Variable.Index, /// This map is usually very close to empty. It tracks only the cases when a @@ -850,7 +850,7 @@ pub const Object = struct { pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); - /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we + /// This is an ArrayHashMap as opposed to a HashMap because in `emit` we /// want to iterate over it while adding entries to it. pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr); @@ -1026,17 +1026,6 @@ pub const Object = struct { self.* = undefined; } - fn locPath( - arena: Allocator, - opt_loc: ?Compilation.EmitLoc, - cache_directory: Compilation.Directory, - ) !?[*:0]u8 { - const loc = opt_loc orelse return null; - const directory = loc.directory orelse cache_directory; - const slice = try directory.joinZ(arena, &[_][]const u8{loc.basename}); - return slice.ptr; - } - fn genErrorNameTable(o: *Object) Allocator.Error!void { // If o.error_name_table is null, then it was not referenced by any instructions. if (o.error_name_table == .none) return; @@ -1175,12 +1164,22 @@ pub const Object = struct { } } - pub fn flushModule(self: *Object, comp: *Compilation, prog_node: *std.Progress.Node) !void { - var sub_prog_node = prog_node.start("LLVM Emit Object", 0); - sub_prog_node.activate(); - sub_prog_node.context.refresh(); - defer sub_prog_node.end(); + pub const EmitOptions = struct { + pre_ir_path: ?[]const u8, + pre_bc_path: ?[]const u8, + bin_path: ?[*:0]const u8, + emit_asm: ?[*:0]const u8, + post_ir_path: ?[*:0]const u8, + post_bc_path: ?[*:0]const u8, + + is_debug: bool, + is_small: bool, + time_report: bool, + sanitize_thread: bool, + lto: bool, + }; + pub fn emit(self: *Object, options: EmitOptions) !void { try self.resolveExportExternCollisions(); try self.genErrorNameTable(); try self.genCmpLtErrorsLenFunction(); @@ -1206,7 +1205,7 @@ pub const Object = struct { dib.finalize(); } - if (comp.verbose_llvm_ir) |path| { + if (options.pre_ir_path) |path| { if (std.mem.eql(u8, path, "-")) { self.builder.dump(); } else { @@ -1214,91 +1213,72 @@ pub const Object = struct { } } - if (comp.verbose_llvm_bc) |path| _ = try self.builder.writeBitcodeToFile(path); - - var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const mod = comp.module.?; - const cache_dir = mod.zig_cache_artifact_directory; + if (options.pre_bc_path) |path| _ = try self.builder.writeBitcodeToFile(path); if (std.debug.runtime_safety and !try self.builder.verify()) { - if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| - _ = self.builder.printToFileZ(emit_llvm_ir_path); @panic("LLVM module verification failed"); } - var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| - try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) - else - null; - - const emit_asm_path = try locPath(arena, comp.emit_asm, cache_dir); - var emit_llvm_ir_path = try locPath(arena, comp.emit_llvm_ir, cache_dir); - const emit_llvm_bc_path = try locPath(arena, comp.emit_llvm_bc, cache_dir); - - const emit_asm_msg = emit_asm_path orelse "(none)"; - const emit_bin_msg = emit_bin_path orelse "(none)"; - const emit_llvm_ir_msg = emit_llvm_ir_path orelse "(none)"; - const emit_llvm_bc_msg = emit_llvm_bc_path orelse "(none)"; + const emit_asm_msg = options.asm_path orelse "(none)"; + const emit_bin_msg = options.bin_path orelse "(none)"; + const post_llvm_ir_msg = options.post_ir_path orelse "(none)"; + const post_llvm_bc_msg = options.post_bc_path orelse "(none)"; log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{ - emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, + emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, }); - if (emit_asm_path == null and emit_bin_path == null and - emit_llvm_ir_path == null and emit_llvm_bc_path == null) return; + if (options.asm_path == null and options.bin_path == null and + options.post_ir_path == null and options.post_bc_path == null) return; - if (!self.builder.useLibLlvm()) { - log.err("emitting without libllvm not implemented", .{}); - return error.FailedToEmit; - } + if (!self.builder.useLibLlvm()) unreachable; // caught in Compilation.Config.resolve // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. // So we call the entire pipeline multiple times if this is requested. var error_message: [*:0]const u8 = undefined; - if (emit_asm_path != null and emit_bin_path != null) { + var emit_bin_path = options.bin_path; + var post_ir_path = options.post_ir_path; + if (options.asm_path != null and options.bin_path != null) { if (self.target_machine.emitToFile( self.builder.llvm.module.?, &error_message, - comp.bin_file.options.optimize_mode == .Debug, - comp.bin_file.options.optimize_mode == .ReleaseSmall, - comp.time_report, - comp.bin_file.options.tsan, - comp.bin_file.options.lto, + options.is_debug, + options.is_small, + options.time_report, + options.sanitize_thread, + options.lto, null, emit_bin_path, - emit_llvm_ir_path, + post_ir_path, null, )) { defer llvm.disposeMessage(error_message); log.err("LLVM failed to emit bin={s} ir={s}: {s}", .{ - emit_bin_msg, emit_llvm_ir_msg, error_message, + emit_bin_msg, post_llvm_ir_msg, error_message, }); return error.FailedToEmit; } emit_bin_path = null; - emit_llvm_ir_path = null; + post_ir_path = null; } if (self.target_machine.emitToFile( self.builder.llvm.module.?, &error_message, - comp.bin_file.options.optimize_mode == .Debug, - comp.bin_file.options.optimize_mode == .ReleaseSmall, - comp.time_report, - comp.bin_file.options.tsan, - comp.bin_file.options.lto, - emit_asm_path, + options.is_debug, + options.is_small, + options.time_report, + options.sanitize_thread, + options.lto, + options.asm_path, emit_bin_path, - emit_llvm_ir_path, - emit_llvm_bc_path, + post_ir_path, + options.post_bc_path, )) { defer llvm.disposeMessage(error_message); log.err("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{ - emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, + emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, error_message, }); return error.FailedToEmit; @@ -1307,17 +1287,19 @@ pub const Object = struct { pub fn updateFunc( o: *Object, - mod: *Module, + zcu: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness, ) !void { - const func = mod.funcInfo(func_index); + const func = zcu.funcInfo(func_index); const decl_index = func.owner_decl; - const decl = mod.declPtr(decl_index); - const fn_info = mod.typeToFunc(decl.ty).?; - const target = mod.getTarget(); - const ip = &mod.intern_pool; + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const owner_mod = namespace.file_scope.mod; + const fn_info = zcu.typeToFunc(decl.ty).?; + const target = zcu.getTarget(); + const ip = &zcu.intern_pool; var dg: DeclGen = .{ .object = o, @@ -1352,7 +1334,7 @@ pub const Object = struct { } // TODO: disable this if safety is off for the function scope - const ssp_buf_size = mod.comp.bin_file.options.stack_protector; + const ssp_buf_size = owner_mod.stack_protector; if (ssp_buf_size != 0) { try attributes.addFnAttr(.sspstrong, &o.builder); try attributes.addFnAttr(.{ .string = .{ @@ -1362,7 +1344,7 @@ pub const Object = struct { } // TODO: disable this if safety is off for the function scope - if (mod.comp.bin_file.options.stack_check) { + if (owner_mod.stack_check) { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("probe-stack"), .value = try o.builder.string("__zig_probe_stack"), @@ -1385,20 +1367,22 @@ pub const Object = struct { var llvm_arg_i: u32 = 0; // This gets the LLVM values from the function and stores them in `dg.args`. - const sret = firstParamSRet(fn_info, mod); + const sret = firstParamSRet(fn_info, zcu); const ret_ptr: Builder.Value = if (sret) param: { const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; break :param param; } else .none; - if (ccAbiPromoteInt(fn_info.cc, mod, Type.fromInterned(fn_info.return_type))) |s| switch (s) { + if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) { .signed => try attributes.addRetAttr(.signext, &o.builder), .unsigned => try attributes.addRetAttr(.zeroext, &o.builder), }; - const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.config.any_error_tracing; + const comp = zcu.comp; + + const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and + comp.config.any_error_tracing; const err_ret_trace: Builder.Value = if (err_return_tracing) param: { const param = wip.arg(llvm_arg_i); @@ -1426,8 +1410,8 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); const param = wip.arg(llvm_arg_i); - if (isByRef(param_ty, mod)) { - const alignment = param_ty.abiAlignment(mod).toLlvm(); + if (isByRef(param_ty, zcu)) { + const alignment = param_ty.abiAlignment(zcu).toLlvm(); const param_llvm_ty = param.typeOfWip(&wip); const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); _ = try wip.store(.normal, param, arg_ptr, alignment); @@ -1443,12 +1427,12 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); - const alignment = param_ty.abiAlignment(mod).toLlvm(); + const alignment = param_ty.abiAlignment(zcu).toLlvm(); try o.addByRefParamAttrs(&attributes, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); llvm_arg_i += 1; - if (isByRef(param_ty, mod)) { + if (isByRef(param_ty, zcu)) { args.appendAssumeCapacity(param); } else { args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); @@ -1458,12 +1442,12 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); - const alignment = param_ty.abiAlignment(mod).toLlvm(); + const alignment = param_ty.abiAlignment(zcu).toLlvm(); try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); llvm_arg_i += 1; - if (isByRef(param_ty, mod)) { + if (isByRef(param_ty, zcu)) { args.appendAssumeCapacity(param); } else { args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, param, alignment, "")); @@ -1476,11 +1460,11 @@ pub const Object = struct { llvm_arg_i += 1; const param_llvm_ty = try o.lowerType(param_ty); - const alignment = param_ty.abiAlignment(mod).toLlvm(); + const alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); _ = try wip.store(.normal, param, arg_ptr, alignment); - args.appendAssumeCapacity(if (isByRef(param_ty, mod)) + args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) arg_ptr else try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); @@ -1488,14 +1472,14 @@ pub const Object = struct { .slice => { assert(!it.byval_attr); const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const ptr_info = param_ty.ptrInfo(mod); + const ptr_info = param_ty.ptrInfo(zcu); if (math.cast(u5, it.zig_index - 1)) |i| { if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) { try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); } } - if (param_ty.zigTypeTag(mod) != .Optional) { + if (param_ty.zigTypeTag(zcu) != .Optional) { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); } if (ptr_info.flags.is_const) { @@ -1504,7 +1488,7 @@ pub const Object = struct { const elem_align = (if (ptr_info.flags.alignment != .none) @as(InternPool.Alignment, ptr_info.flags.alignment) else - Type.fromInterned(ptr_info.child).abiAlignment(mod).max(.@"1")).toLlvm(); + Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); const ptr_param = wip.arg(llvm_arg_i); llvm_arg_i += 1; @@ -1521,7 +1505,7 @@ pub const Object = struct { const field_types = it.types_buffer[0..it.types_len]; const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); const param_llvm_ty = try o.lowerType(param_ty); - const param_alignment = param_ty.abiAlignment(mod).toLlvm(); + const param_alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, param_alignment, target); const llvm_ty = try o.builder.structType(.normal, field_types); for (0..field_types.len) |field_i| { @@ -1533,7 +1517,7 @@ pub const Object = struct { _ = try wip.store(.normal, param, field_ptr, alignment); } - const is_by_ref = isByRef(param_ty, mod); + const is_by_ref = isByRef(param_ty, zcu); args.appendAssumeCapacity(if (is_by_ref) arg_ptr else @@ -1551,11 +1535,11 @@ pub const Object = struct { const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; - const alignment = param_ty.abiAlignment(mod).toLlvm(); + const alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); _ = try wip.store(.normal, param, arg_ptr, alignment); - args.appendAssumeCapacity(if (isByRef(param_ty, mod)) + args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) arg_ptr else try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); @@ -1566,11 +1550,11 @@ pub const Object = struct { const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; - const alignment = param_ty.abiAlignment(mod).toLlvm(); + const alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, false, param_llvm_ty, alignment, target); _ = try wip.store(.normal, param, arg_ptr, alignment); - args.appendAssumeCapacity(if (isByRef(param_ty, mod)) + args.appendAssumeCapacity(if (isByRef(param_ty, zcu)) arg_ptr else try wip.load(.normal, param_llvm_ty, arg_ptr, alignment, "")); @@ -1584,14 +1568,12 @@ pub const Object = struct { var di_file: ?if (build_options.have_llvm) *llvm.DIFile else noreturn = null; var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; - const namespace = mod.namespacePtr(decl.src_namespace); - if (o.di_builder) |dib| { di_file = try o.getDIFile(gpa, namespace.file_scope); const line_number = decl.src_line + 1; - const is_internal_linkage = decl.val.getExternFunc(mod) == null and - !mod.decl_exports.contains(decl_index); + const is_internal_linkage = decl.val.getExternFunc(zcu) == null and + !zcu.decl_exports.contains(decl_index); const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type) llvm.DIFlags.NoReturn else @@ -1608,7 +1590,7 @@ pub const Object = struct { true, // is definition line_number + func.lbrace_line, // scope line llvm.DIFlags.StaticMember | noret_bit, - mod.comp.bin_file.options.optimize_mode != .Debug, + owner_mod.optimize_mode != .Debug, null, // decl_subprogram ); try o.di_map.put(gpa, decl, subprogram.toNode()); @@ -1618,8 +1600,6 @@ pub const Object = struct { di_scope = subprogram.toScope(); } - const single_threaded = namespace.file_scope.mod.single_threaded; - var fg: FuncGen = .{ .gpa = gpa, .air = air, @@ -1631,7 +1611,7 @@ pub const Object = struct { .arg_index = 0, .func_inst_table = .{}, .blocks = .{}, - .sync_scope = if (single_threaded) .singlethread else .system, + .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, .di_scope = di_scope, .di_file = di_file, .base_line = dg.decl.src_line, @@ -1645,7 +1625,7 @@ pub const Object = struct { fg.genBody(air.getMainBody()) catch |err| switch (err) { error.CodegenFail => { decl.analysis = .codegen_failure; - try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?); + try zcu.failed_decls.put(zcu.gpa, decl_index, dg.err_msg.?); dg.err_msg = null; return; }, @@ -1654,7 +1634,7 @@ pub const Object = struct { try fg.wip.finish(); - try o.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); + try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index)); } pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { @@ -2933,22 +2913,24 @@ pub const Object = struct { o: *Object, decl_index: InternPool.DeclIndex, ) Allocator.Error!Builder.Function.Index { - const mod = o.module; - const ip = &mod.intern_pool; + const zcu = o.module; + const ip = &zcu.intern_pool; const gpa = o.gpa; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const owner_mod = namespace.file_scope.mod; const zig_fn_type = decl.ty; const gop = try o.decl_map.getOrPut(gpa, decl_index); if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; assert(decl.has_tv); - const fn_info = mod.typeToFunc(zig_fn_type).?; - const target = mod.getTarget(); - const sret = firstParamSRet(fn_info, mod); + const fn_info = zcu.typeToFunc(zig_fn_type).?; + const target = owner_mod.resolved_target.result; + const sret = firstParamSRet(fn_info, zcu); const function_index = try o.builder.addFunction( try o.lowerType(zig_fn_type), - try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(mod))), + try o.builder.string(ip.stringToSlice(try decl.getFullyQualifiedName(zcu))), toLlvmAddressSpace(decl.@"addrspace", target), ); gop.value_ptr.* = function_index.ptrConst(&o.builder).global; @@ -2956,7 +2938,7 @@ pub const Object = struct { var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - const is_extern = decl.isExtern(mod); + const is_extern = decl.isExtern(zcu); if (!is_extern) { function_index.setLinkage(.internal, &o.builder); function_index.setUnnamedAddr(.unnamed_addr, &o.builder); @@ -2966,7 +2948,7 @@ pub const Object = struct { .kind = try o.builder.string("wasm-import-name"), .value = try o.builder.string(ip.stringToSlice(decl.name)), } }, &o.builder); - if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { + if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("wasm-import-module"), .value = try o.builder.string(lib_name), @@ -2987,8 +2969,8 @@ pub const Object = struct { llvm_arg_i += 1; } - const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.config.any_error_tracing; + const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and + zcu.comp.config.any_error_tracing; if (err_return_tracing) { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); @@ -3009,7 +2991,7 @@ pub const Object = struct { function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder); // Function attributes that are independent of analysis results of the function body. - try o.addCommonFnAttributes(&attributes); + try o.addCommonFnAttributes(&attributes, owner_mod); if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); @@ -3022,14 +3004,14 @@ pub const Object = struct { .byval => { const param_index = it.zig_index - 1; const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); - if (!isByRef(param_ty, mod)) { + if (!isByRef(param_ty, zcu)) { try o.addByValParamAttrs(&attributes, param_ty, param_index, fn_info, it.llvm_index - 1); } }, .byref => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); const param_llvm_ty = try o.lowerType(param_ty); - const alignment = param_ty.abiAlignment(mod); + const alignment = param_ty.abiAlignment(zcu); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); }, .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), @@ -3055,13 +3037,14 @@ pub const Object = struct { fn addCommonFnAttributes( o: *Object, attributes: *Builder.FunctionAttributes.Wip, + owner_mod: *Package.Module, ) Allocator.Error!void { const comp = o.module.comp; - if (!comp.bin_file.options.red_zone) { + if (!owner_mod.red_zone) { try attributes.addFnAttr(.noredzone, &o.builder); } - if (comp.bin_file.options.omit_frame_pointer) { + if (owner_mod.omit_frame_pointer) { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("frame-pointer"), .value = try o.builder.string("none"), @@ -3073,7 +3056,7 @@ pub const Object = struct { } }, &o.builder); } try attributes.addFnAttr(.nounwind, &o.builder); - if (comp.unwind_tables) { + if (owner_mod.unwind_tables) { try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); } if (comp.skip_linker_dependencies or comp.no_builtin) { @@ -3084,26 +3067,27 @@ pub const Object = struct { // overflow instead of performing memcpy. try attributes.addFnAttr(.nobuiltin, &o.builder); } - if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { + if (owner_mod.optimize_mode == .ReleaseSmall) { try attributes.addFnAttr(.minsize, &o.builder); try attributes.addFnAttr(.optsize, &o.builder); } - if (comp.bin_file.options.tsan) { + if (owner_mod.sanitize_thread) { try attributes.addFnAttr(.sanitize_thread, &o.builder); } - if (comp.getTarget().cpu.model.llvm_name) |s| { + const target = owner_mod.resolved_target.result; + if (target.cpu.model.llvm_name) |s| { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("target-cpu"), .value = try o.builder.string(s), } }, &o.builder); } - if (comp.bin_file.options.llvm_cpu_features) |s| { + if (owner_mod.resolved_target.llvm_cpu_features) |s| { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("target-features"), .value = try o.builder.string(std.mem.span(s)), } }, &o.builder); } - if (comp.getTarget().cpu.arch.isBpf()) { + if (target.cpu.arch.isBpf()) { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("no-builtins"), .value = .empty, @@ -4646,6 +4630,100 @@ pub const Object = struct { .field_index = @intCast(field_index), }); } + + fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index { + const name = try o.builder.string(lt_errors_fn_name); + if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; + + const zcu = o.module; + const target = zcu.root_mod.resolved_target.result; + const function_index = try o.builder.addFunction( + try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal), + name, + toLlvmAddressSpace(.generic, target), + ); + + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCommonFnAttributes(&attributes, zcu.root_mod); + + function_index.setLinkage(.internal, &o.builder); + function_index.setCallConv(.fastcc, &o.builder); + function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + return function_index; + } + + fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { + const zcu = o.module; + const ip = &zcu.intern_pool; + const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type; + + // TODO: detect when the type changes and re-emit this function. + const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); + if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; + errdefer assert(o.decl_map.remove(enum_type.decl)); + + const usize_ty = try o.lowerType(Type.usize); + const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); + const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu); + const target = zcu.root_mod.resolved_target.result; + const function_index = try o.builder.addFunction( + try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), + try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), + toLlvmAddressSpace(.generic, target), + ); + + var attributes: Builder.FunctionAttributes.Wip = .{}; + defer attributes.deinit(&o.builder); + try o.addCommonFnAttributes(&attributes, zcu.root_mod); + + function_index.setLinkage(.internal, &o.builder); + function_index.setCallConv(.fastcc, &o.builder); + function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); + gop.value_ptr.* = function_index.ptrConst(&o.builder).global; + + var wip = try Builder.WipFunction.init(&o.builder, function_index); + defer wip.deinit(); + wip.cursor = .{ .block = try wip.block(0, "Entry") }; + + const bad_value_block = try wip.block(1, "BadValue"); + const tag_int_value = wip.arg(0); + var wip_switch = + try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len)); + defer wip_switch.finish(&wip); + + for (0..enum_type.names.len) |field_index| { + const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index])); + const name_init = try o.builder.stringNullConst(name); + const name_variable_index = + try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); + try name_variable_index.setInitializer(name_init, &o.builder); + name_variable_index.setLinkage(.private, &o.builder); + name_variable_index.setMutability(.constant, &o.builder); + name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); + name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); + + const name_val = try o.builder.structValue(ret_ty, &.{ + name_variable_index.toConst(&o.builder), + try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), + }); + + const return_block = try wip.block(1, "Name"); + const this_tag_int_value = try o.lowerValue( + (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), + ); + try wip_switch.addCase(this_tag_int_value, return_block, &wip); + + wip.cursor = .{ .block = return_block }; + _ = try wip.ret(name_val); + } + + wip.cursor = .{ .block = bad_value_block }; + _ = try wip.@"unreachable"(); + + try wip.finish(); + return function_index; + } }; pub const DeclGen = struct { @@ -4654,6 +4732,13 @@ pub const DeclGen = struct { decl_index: InternPool.DeclIndex, err_msg: ?*Module.ErrorMsg, + fn ownerModule(dg: DeclGen) *Package.Module { + const o = dg.object; + const zcu = o.module; + const namespace = zcu.namespacePtr(dg.decl.src_namespace); + return namespace.file_scope.mod; + } + fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { @setCold(true); assert(dg.err_msg == null); @@ -5614,7 +5699,7 @@ pub const FuncGen = struct { const o = self.dg.object; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); - const llvm_fn = try self.getCmpLtErrorsLenFunction(); + const llvm_fn = try o.getCmpLtErrorsLenFunction(); return self.wip.call( .normal, .fastcc, @@ -6547,11 +6632,13 @@ pub const FuncGen = struct { const dib = o.di_builder orelse return .none; const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn; - const mod = o.module; - const func = mod.funcInfo(ty_fn.func); + const zcu = o.module; + const func = zcu.funcInfo(ty_fn.func); const decl_index = func.owner_decl; - const decl = mod.declPtr(decl_index); - const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); + const decl = zcu.declPtr(decl_index); + const namespace = zcu.namespacePtr(decl.src_namespace); + const owner_mod = namespace.file_scope.mod; + const di_file = try o.getDIFile(self.gpa, zcu.namespacePtr(decl.src_namespace).file_scope); self.di_file = di_file; const line_number = decl.src_line + 1; const cur_debug_location = self.wip.llvm.builder.getCurrentDebugLocation2(); @@ -6562,18 +6649,18 @@ pub const FuncGen = struct { .base_line = self.base_line, }); - const fqn = try decl.getFullyQualifiedName(mod); + const fqn = try decl.getFullyQualifiedName(zcu); - const is_internal_linkage = !mod.decl_exports.contains(decl_index); - const fn_ty = try mod.funcType(.{ + const is_internal_linkage = !zcu.decl_exports.contains(decl_index); + const fn_ty = try zcu.funcType(.{ .param_types = &.{}, .return_type = .void_type, }); const fn_di_ty = try o.lowerDebugType(fn_ty, .full); const subprogram = dib.createFunction( di_file.toScope(), - mod.intern_pool.stringToSlice(decl.name), - mod.intern_pool.stringToSlice(fqn), + zcu.intern_pool.stringToSlice(decl.name), + zcu.intern_pool.stringToSlice(fqn), di_file, line_number, fn_di_ty, @@ -6581,7 +6668,7 @@ pub const FuncGen = struct { true, // is definition line_number + func.lbrace_line, // scope line llvm.DIFlags.StaticMember, - mod.comp.bin_file.options.optimize_mode != .Debug, + owner_mod.optimize_mode != .Debug, null, // decl_subprogram ); @@ -6676,11 +6763,12 @@ pub const FuncGen = struct { null; const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); const insert_block = self.wip.cursor.block.toLlvm(&self.wip); - const mod = o.module; - if (isByRef(operand_ty, mod)) { + const zcu = o.module; + const owner_mod = self.dg.ownerModule(); + if (isByRef(operand_ty, zcu)) { _ = dib.insertDeclareAtEnd(operand.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); - } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { - const alignment = operand_ty.abiAlignment(mod).toLlvm(); + } else if (owner_mod.optimize_mode == .Debug) { + const alignment = operand_ty.abiAlignment(zcu).toLlvm(); const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); _ = try self.wip.store(.normal, operand, alloca, alignment); _ = dib.insertDeclareAtEnd(alloca.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); @@ -8729,9 +8817,10 @@ pub const FuncGen = struct { const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null); const insert_block = self.wip.cursor.block.toLlvm(&self.wip); + const owner_mod = self.dg.ownerModule(); if (isByRef(inst_ty, mod)) { _ = dib.insertDeclareAtEnd(arg_val.toLlvm(&self.wip), di_local_var, debug_loc, insert_block); - } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { + } else if (owner_mod.optimize_mode == .Debug) { const alignment = inst_ty.abiAlignment(mod).toLlvm(); const alloca = try self.buildAlloca(arg_val.typeOfWip(&self.wip), alignment); _ = try self.wip.store(.normal, arg_val, alloca, alignment); @@ -8821,7 +8910,8 @@ pub const FuncGen = struct { len, if (ptr_ty.isVolatilePtr(mod)) .@"volatile" else .normal, ); - if (safety and mod.comp.bin_file.options.valgrind) { + const owner_mod = self.dg.ownerModule(); + if (safety and owner_mod.valgrind) { try self.valgrindMarkUndef(dest_ptr, len); } return .none; @@ -9137,7 +9227,8 @@ pub const FuncGen = struct { } else { _ = try self.wip.callMemSet(dest_ptr, dest_ptr_align, fill_byte, len, access_kind); } - if (safety and mod.comp.bin_file.options.valgrind) { + const owner_mod = self.dg.ownerModule(); + if (safety and owner_mod.valgrind) { try self.valgrindMarkUndef(dest_ptr, len); } return .none; @@ -9488,24 +9579,25 @@ pub const FuncGen = struct { fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { const o = self.dg.object; - const mod = o.module; - const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; + const zcu = o.module; + const enum_type = zcu.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; // TODO: detect when the type changes and re-emit this function. const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.named_enum_map.remove(enum_type.decl)); - const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); + const fqn = try zcu.declPtr(enum_type.decl).getFullyQualifiedName(zcu); + const target = zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), - try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}), - toLlvmAddressSpace(.generic, mod.getTarget()), + try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}), + toLlvmAddressSpace(.generic, target), ); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - try o.addCommonFnAttributes(&attributes); + try o.addCommonFnAttributes(&attributes, zcu.root_mod); function_index.setLinkage(.internal, &o.builder); function_index.setCallConv(.fastcc, &o.builder); @@ -9524,7 +9616,7 @@ pub const FuncGen = struct { for (0..enum_type.names.len) |field_index| { const this_tag_int_value = try o.lowerValue( - (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), + (try zcu.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), ); try wip_switch.addCase(this_tag_int_value, named_block, &wip); } @@ -9544,7 +9636,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const enum_ty = self.typeOf(un_op); - const llvm_fn = try self.getEnumTagNameFunction(enum_ty); + const llvm_fn = try o.getEnumTagNameFunction(enum_ty); return self.wip.call( .normal, .fastcc, @@ -9556,100 +9648,6 @@ pub const FuncGen = struct { ); } - fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { - const o = self.dg.object; - const mod = o.module; - const ip = &mod.intern_pool; - const enum_type = ip.indexToKey(enum_ty.toIntern()).enum_type; - - // TODO: detect when the type changes and re-emit this function. - const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); - if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; - errdefer assert(o.decl_map.remove(enum_type.decl)); - - const usize_ty = try o.lowerType(Type.usize); - const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); - const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); - const function_index = try o.builder.addFunction( - try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), - try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), - toLlvmAddressSpace(.generic, mod.getTarget()), - ); - - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - try o.addCommonFnAttributes(&attributes); - - function_index.setLinkage(.internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); - gop.value_ptr.* = function_index.ptrConst(&o.builder).global; - - var wip = try Builder.WipFunction.init(&o.builder, function_index); - defer wip.deinit(); - wip.cursor = .{ .block = try wip.block(0, "Entry") }; - - const bad_value_block = try wip.block(1, "BadValue"); - const tag_int_value = wip.arg(0); - var wip_switch = - try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len)); - defer wip_switch.finish(&wip); - - for (0..enum_type.names.len) |field_index| { - const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index])); - const name_init = try o.builder.stringNullConst(name); - const name_variable_index = - try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); - try name_variable_index.setInitializer(name_init, &o.builder); - name_variable_index.setLinkage(.private, &o.builder); - name_variable_index.setMutability(.constant, &o.builder); - name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); - - const name_val = try o.builder.structValue(ret_ty, &.{ - name_variable_index.toConst(&o.builder), - try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len), - }); - - const return_block = try wip.block(1, "Name"); - const this_tag_int_value = try o.lowerValue( - (try mod.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), - ); - try wip_switch.addCase(this_tag_int_value, return_block, &wip); - - wip.cursor = .{ .block = return_block }; - _ = try wip.ret(name_val); - } - - wip.cursor = .{ .block = bad_value_block }; - _ = try wip.@"unreachable"(); - - try wip.finish(); - return function_index; - } - - fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index { - const o = self.dg.object; - - const name = try o.builder.string(lt_errors_fn_name); - if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; - - const function_index = try o.builder.addFunction( - try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal), - name, - toLlvmAddressSpace(.generic, o.module.getTarget()), - ); - - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - try o.addCommonFnAttributes(&attributes); - - function_index.setLinkage(.internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); - return function_index; - } - fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const o = self.dg.object; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; diff --git a/src/link.zig b/src/link.zig index ce12e922d7f5..77169afa2919 100644 --- a/src/link.zig +++ b/src/link.zig @@ -18,6 +18,7 @@ const Module = @import("Module.zig"); const InternPool = @import("InternPool.zig"); const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); +const LlvmObject = @import("codegen/llvm.zig").Object; /// When adding a new field, remember to update `hashAddSystemLibs`. /// These are *always* dynamically linked. Static libraries will be @@ -1046,6 +1047,51 @@ pub const File = struct { return output_mode == .Lib and !self.isStatic(); } + pub fn resolveEmitLoc( + base: File, + arena: Allocator, + opt_loc: ?Compilation.EmitLoc, + ) Allocator.Error!?[*:0]u8 { + const loc = opt_loc orelse return null; + const slice = if (loc.directory) |directory| + try directory.joinZ(arena, &.{loc.basename}) + else + try base.emit.basenamePath(arena, loc.basename); + return slice.ptr; + } + + pub fn emitLlvmObject( + base: File, + arena: Allocator, + llvm_object: *LlvmObject, + prog_node: *std.Progress.Node, + ) !void { + const comp = base.comp; + + var sub_prog_node = prog_node.start("LLVM Emit Object", 0); + sub_prog_node.activate(); + sub_prog_node.context.refresh(); + defer sub_prog_node.end(); + + try llvm_object.emit(comp, .{ + .pre_ir_path = comp.verbose_llvm_ir, + .pre_bc_path = comp.verbose_llvm_bc, + .bin_path = try base.resolveEmitLoc(arena, .{ + .directory = null, + .basename = base.intermediary_basename.?, + }), + .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm), + .post_llvm_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), + .post_llvm_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), + + .is_debug = comp.root_mod.optimize_mode == .Debug, + .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, + .time_report = comp.time_report, + .sanitize_thread = comp.config.any_sanitize_thread, + .lto = comp.config.lto, + }); + } + pub const C = @import("link/C.zig"); pub const Coff = @import("link/Coff.zig"); pub const Plan9 = @import("link/Plan9.zig"); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 762591442b15..52ca7e554ccf 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -3,7 +3,7 @@ //! LLD for traditional linking (linking relocatable object files). //! LLD is also the default linker for LLVM. -/// If this is not null, an object file is created by LLVM and linked with LLD afterwards. +/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. llvm_object: ?*LlvmObject = null, base: link.File, @@ -1711,17 +1711,22 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const tracy = trace(@src()); defer tracy.end(); + const gpa = comp.gpa; + if (self.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + try self.base.emitLlvmObject(arena, llvm_object, prog_node); + return; } var sub_prog_node = prog_node.start("COFF Flush", 0); sub_prog_node.activate(); defer sub_prog_node.end(); - const gpa = self.base.comp.gpa; - - const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; if (self.lazy_syms.getPtr(.none)) |metadata| { // Most lazy symbols can be updated on first use, but @@ -1822,7 +1827,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try self.writeDataDirectoriesHeaders(); try self.writeSectionHeaders(); - if (self.entry_addr == null and self.base.comp.config.output_mode == .Exe) { + if (self.entry_addr == null and comp.config.output_mode == .Exe) { log.debug("flushing. no_entry_point_found = true\n", .{}); self.base.error_flags.no_entry_point_found = true; } else { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3e237fe4944e..fe89a6321fc7 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -27,7 +27,7 @@ version_script: ?[]const u8, ptr_width: PtrWidth, -/// If this is not null, an object file is created by LLVM and linked with LLD afterwards. +/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. llvm_object: ?*LlvmObject = null, /// A list of all input files. @@ -1031,24 +1031,23 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node const tracy = trace(@src()); defer tracy.end(); - if (self.llvm_object) |llvm_object| { - try llvm_object.flushModule(comp, prog_node); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); - const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; + if (self.llvm_object) |llvm_object| { + try self.base.emitLlvmObject(arena, llvm_object, prog_node); + const use_lld = build_options.have_llvm and comp.config.use_lld; if (use_lld) return; } - const gpa = self.base.comp.gpa; var sub_prog_node = prog_node.start("ELF Flush", 0); sub_prog_node.activate(); defer sub_prog_node.end(); - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const target = self.base.comp.root_mod.resolved_target.result; - const link_mode = self.base.comp.config.link_mode; + const target = comp.root_mod.resolved_target.result; + const link_mode = comp.config.link_mode; const directory = self.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { @@ -1060,7 +1059,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } else null; // --verbose-link - if (self.base.comp.verbose_link) try self.dumpArgv(comp); + if (comp.verbose_link) try self.dumpArgv(comp); const csu = try CsuObjects.init(arena, comp); const compiler_rt_path: ?[]const u8 = blk: { @@ -1082,8 +1081,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (csu.crti) |v| try positionals.append(.{ .path = v }); if (csu.crtbegin) |v| try positionals.append(.{ .path = v }); - try positionals.ensureUnusedCapacity(self.base.comp.objects.len); - positionals.appendSliceAssumeCapacity(self.base.comp.objects); + try positionals.ensureUnusedCapacity(comp.objects.len); + positionals.appendSliceAssumeCapacity(comp.objects); // This is a set of object files emitted by clang in a single `build-exe` invocation. // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up @@ -1106,13 +1105,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node var test_path = std.ArrayList(u8).init(gpa); defer test_path.deinit(); for (self.lib_dirs) |lib_dir_path| { - for (self.base.comp.system_libs.keys()) |link_lib| { + for (comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; _ = try rpath_table.put(lib_dir_path, {}); } } - for (self.base.comp.objects) |obj| { + for (comp.objects) |obj| { if (Compilation.classifyFileExt(obj.path) == .shared_library) { const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; if (obj.loption) continue; @@ -1122,7 +1121,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // TSAN - if (self.base.comp.config.any_sanitize_thread) { + if (comp.config.any_sanitize_thread) { try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path }); } @@ -1146,27 +1145,27 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node var system_libs = std.ArrayList(SystemLib).init(arena); - try system_libs.ensureUnusedCapacity(self.base.comp.system_libs.values().len); - for (self.base.comp.system_libs.values()) |lib_info| { + try system_libs.ensureUnusedCapacity(comp.system_libs.values().len); + for (comp.system_libs.values()) |lib_info| { system_libs.appendAssumeCapacity(.{ .needed = lib_info.needed, .path = lib_info.path.? }); } // libc++ dep - if (self.base.comp.config.link_libcpp) { + if (comp.config.link_libcpp) { try system_libs.ensureUnusedCapacity(2); system_libs.appendAssumeCapacity(.{ .path = comp.libcxxabi_static_lib.?.full_object_path }); system_libs.appendAssumeCapacity(.{ .path = comp.libcxx_static_lib.?.full_object_path }); } // libunwind dep - if (self.base.comp.config.link_libunwind) { + if (comp.config.link_libunwind) { try system_libs.append(.{ .path = comp.libunwind_static_lib.?.full_object_path }); } // libc dep self.base.error_flags.missing_libc = false; - if (self.base.comp.config.link_libc) { - if (self.base.comp.libc_installation) |lc| { + if (comp.config.link_libc) { + if (comp.libc_installation) |lc| { const flags = target_util.libcFullLinkFlags(target); try system_libs.ensureUnusedCapacity(flags.len); @@ -1305,7 +1304,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Look for entry address in objects if not set by the incremental compiler. if (self.entry_index == null) { const entry: ?[]const u8 = entry: { - if (self.base.comp.config.entry) |entry| break :entry entry; + if (comp.config.entry) |entry| break :entry entry; if (!self.base.isDynLib()) break :entry "_start"; break :entry null; }; diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 3dd35dfe63a0..7c7d3fd17c95 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -43,7 +43,7 @@ pub fn outputShndx(symbol: Symbol) ?u16 { } pub fn isLocal(symbol: Symbol, elf_file: *Elf) bool { - if (elf_file.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL; + if (elf_file.base.isRelocatable()) return symbol.elfSym(elf_file).st_bind() == elf.STB_LOCAL; return !(symbol.flags.import or symbol.flags.@"export"); } @@ -186,7 +186,7 @@ const GetOrCreateZigGotEntryResult = struct { }; pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult { - assert(!elf_file.isRelocatable()); + assert(!elf_file.base.isRelocatable()); assert(symbol.flags.needs_zig_got); if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got }; const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file); @@ -237,7 +237,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { const st_shndx = blk: { if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?; if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; - if (elf_file.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; + if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; break :blk symbol.outputShndx() orelse elf.SHN_UNDEF; }; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 75bc53bb48d4..b6be4013ce5f 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -926,7 +926,7 @@ fn updateDeclCode( sym.value = atom_ptr.value; esym.st_value = atom_ptr.value; - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { log.debug(" (writing new offset table entry)", .{}); assert(sym.flags.has_zig_got); const extra = sym.extra(elf_file).?; @@ -944,7 +944,7 @@ fn updateDeclCode( sym.flags.needs_zig_got = true; esym.st_value = atom_ptr.value; - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file); try elf_file.zig_got.writeOne(elf_file, gop.index); } @@ -1262,7 +1262,7 @@ fn updateLazySymbol( local_sym.flags.needs_zig_got = true; local_esym.st_value = atom_ptr.value; - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file); try elf_file.zig_got.writeOne(elf_file, gop.index); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 104c83b3574e..9af563b047c0 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1,6 +1,6 @@ base: File, -/// If this is not null, an object file is created by LLVM and linked with LLD afterwards. +/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. llvm_object: ?*LlvmObject = null, /// Debug symbols bundle (or dSym). @@ -352,22 +352,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No const tracy = trace(@src()); defer tracy.end(); - if (self.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); - } - - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); + if (self.llvm_object) |llvm_object| { + try self.base.emitLlvmObject(arena, llvm_object, prog_node); + return; + } + var sub_prog_node = prog_node.start("MachO Flush", 0); sub_prog_node.activate(); defer sub_prog_node.end(); - const output_mode = self.base.comp.config.output_mode; - const module = self.base.comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; - const target = self.base.comp.root_mod.resolved_target.result; + const output_mode = comp.config.output_mode; + const module = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; + const target = comp.root_mod.resolved_target.result; if (self.lazy_syms.getPtr(.none)) |metadata| { // Most lazy symbols can be updated on first use, but @@ -619,7 +620,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No .stacksize = self.base.stack_size, }); }, - .Lib => if (self.base.comp.config.link_mode == .Dynamic) { + .Lib => if (comp.config.link_mode == .Dynamic) { try load_commands.writeDylibIdLC(self, lc_writer); }, else => {}, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 8f63e7c6fd51..6488231afa60 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3700,8 +3700,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod const tracy = trace(@src()); defer tracy.end(); + const gpa = comp.gpa; + // Used for all temporary memory allocated during flushin + var arena_instance = std.heap.ArenaAllocator.init(gpa); + defer arena_instance.deinit(); + const arena = arena_instance.allocator(); + if (wasm.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); + try wasm.base.emitLlvmObject(arena, llvm_object, prog_node); + return; } var sub_prog_node = prog_node.start("Wasm Flush", 0); @@ -3711,13 +3718,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod // ensure the error names table is populated when an error name is referenced try wasm.populateErrorNameTable(); - // Used for all temporary memory allocated during flushin - const gpa = wasm.base.comp.gpa; - var arena_instance = std.heap.ArenaAllocator.init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - - const objects = wasm.base.comp.objects; + const objects = comp.objects; // Positional arguments to the linker such as object files and static archives. var positionals = std.ArrayList([]const u8).init(arena); @@ -3755,7 +3756,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try wasm.markReferences(); try wasm.setupErrorsLen(); try wasm.setupImports(); - if (wasm.base.comp.module) |mod| { + if (comp.module) |mod| { var decl_it = wasm.decls.iterator(); while (decl_it.next()) |entry| { const decl = mod.declPtr(entry.key_ptr.*); @@ -3810,7 +3811,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } if (wasm.dwarf) |*dwarf| { - try dwarf.flushModule(wasm.base.comp.module.?); + try dwarf.flushModule(comp.module.?); } } From 638db680f4c6380bb193da520f29a7c587bfb719 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 19:25:34 -0700 Subject: [PATCH 050/133] move dll_export_fns and rdynamic to Compilation.Config --- src/Compilation.zig | 13 +++---------- src/Compilation/Config.zig | 17 +++++++++++++++++ src/codegen/llvm.zig | 17 ++++++++--------- src/link.zig | 2 -- src/link/Coff.zig | 2 -- src/link/Elf.zig | 10 ++++------ src/link/Wasm.zig | 13 ++++++------- src/main.zig | 16 ++++++---------- 8 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 7b7e85d0f7d6..c742e59af5e7 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -956,7 +956,6 @@ pub const InitOptions = struct { emit_docs: ?EmitLoc = null, /// `null` means to not emit an import lib. emit_implib: ?EmitLoc = null, - dll_export_fns: ?bool = false, /// Normally when using LLD to link, Zig uses a file named "lld.id" in the /// same directory as the output binary which contains the hash of the link /// operation, allowing Zig to skip linking when the hash would be unchanged. @@ -989,7 +988,6 @@ pub const InitOptions = struct { want_compiler_rt: ?bool = null, want_lto: ?bool = null, formatted_panics: ?bool = null, - rdynamic: bool = false, function_sections: bool = false, data_sections: bool = false, no_builtin: bool = false, @@ -1200,8 +1198,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const link_libc = options.config.link_libc; - const dll_export_fns = options.dll_export_fns orelse (is_dyn_lib or options.rdynamic); - const libc_dirs = try detectLibCIncludeDirs( arena, options.zig_lib_directory.path.?, @@ -1524,10 +1520,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .gc_sections = options.linker_gc_sections, .eh_frame_hdr = link_eh_frame_hdr, .emit_relocs = options.link_emit_relocs, - .rdynamic = options.rdynamic, .soname = options.soname, .compatibility_version = options.compatibility_version, - .dll_export_fns = dll_export_fns, .each_lib_rpath = each_lib_rpath, .build_id = build_id, .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, @@ -1555,7 +1549,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // Synchronize with other matching comments: ZigOnlyHashStuff hash.add(use_llvm); hash.add(options.config.use_lib_llvm); - hash.add(dll_export_fns); + hash.add(options.config.dll_export_fns); hash.add(options.config.is_test); hash.add(options.config.test_evented_io); hash.addOptionalBytes(options.test_filter); @@ -2430,6 +2424,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.config.import_memory); man.hash.add(comp.config.export_memory); man.hash.add(comp.config.shared_memory); + man.hash.add(comp.config.dll_export_fns); + man.hash.add(comp.config.rdynamic); if (comp.bin_file) |lf| { man.hash.add(lf.stack_size); @@ -2442,7 +2438,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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); @@ -2468,7 +2463,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes }, .wasm => { const wasm = lf.cast(link.File.Wasm).?; - man.hash.add(wasm.rdynamic); man.hash.addOptional(wasm.initial_memory); man.hash.addOptional(wasm.max_memory); man.hash.addOptional(wasm.global_base); @@ -2485,7 +2479,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes }, .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); diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 44ace55ae486..442b7a1b9af8 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -41,6 +41,8 @@ entry: ?[]const u8, debug_format: DebugFormat, root_strip: bool, root_error_tracing: bool, +dll_export_fns: bool, +rdynamic: bool, pub const CFrontend = enum { clang, aro }; @@ -93,6 +95,8 @@ pub const Options = struct { shared_memory: ?bool = null, test_evented_io: bool = false, debug_format: ?Config.DebugFormat = null, + dll_export_fns: ?bool = null, + rdynamic: ?bool = null, }; pub fn resolve(options: Options) !Config { @@ -415,6 +419,17 @@ pub fn resolve(options: Options) !Config { const any_error_tracing = root_error_tracing or options.any_error_tracing; + const rdynamic = options.rdynamic orelse false; + + const dll_export_fns = b: { + if (options.dll_export_fns) |x| break :b x; + if (rdynamic) break :b true; + break :b switch (options.output_mode) { + .Obj, .Exe => false, + .Lib => link_mode == .Dynamic, + }; + }; + return .{ .output_mode = options.output_mode, .have_zcu = options.have_zcu, @@ -443,6 +458,8 @@ pub fn resolve(options: Options) !Config { .wasi_exec_model = wasi_exec_model, .debug_format = debug_format, .root_strip = root_strip, + .dll_export_fns = dll_export_fns, + .rdynamic = rdynamic, }; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 42180c6529ef..7e25a4b59b0e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1672,6 +1672,7 @@ pub const Object = struct { // because we call `updateExports` at the end of `updateFunc` and `updateDecl`. const global_index = self.decl_map.get(decl_index) orelse return; const decl = mod.declPtr(decl_index); + const comp = mod.comp; if (decl.isExtern(mod)) { const decl_name = decl_name: { const decl_name = mod.intern_pool.stringToSlice(decl.name); @@ -1696,7 +1697,8 @@ pub const Object = struct { try global_index.rename(decl_name, &self.builder); global_index.setLinkage(.external, &self.builder); global_index.setUnnamedAddr(.default, &self.builder); - if (wantDllExports(mod)) global_index.setDllStorageClass(.default, &self.builder); + if (comp.config.dll_export_fns) + global_index.setDllStorageClass(.default, &self.builder); if (self.di_map.get(decl)) |di_node| { const decl_name_slice = decl_name.slice(&self.builder).?; if (try decl.isFunction(mod)) { @@ -1762,7 +1764,8 @@ pub const Object = struct { ); try global_index.rename(fqn, &self.builder); global_index.setLinkage(.internal, &self.builder); - if (wantDllExports(mod)) global_index.setDllStorageClass(.default, &self.builder); + if (comp.config.dll_export_fns) + global_index.setDllStorageClass(.default, &self.builder); global_index.setUnnamedAddr(.unnamed_addr, &self.builder); if (decl.val.getVariable(mod)) |decl_var| { const decl_namespace = mod.namespacePtr(decl.src_namespace); @@ -1821,7 +1824,9 @@ pub const Object = struct { exports: []const *Module.Export, ) link.File.UpdateExportsError!void { global_index.setUnnamedAddr(.default, &o.builder); - if (wantDllExports(mod)) global_index.setDllStorageClass(.dllexport, &o.builder); + const comp = mod.comp; + if (comp.config.dll_export_fns) + global_index.setDllStorageClass(.dllexport, &o.builder); global_index.setLinkage(switch (exports[0].opts.linkage) { .Internal => unreachable, .Strong => .external, @@ -11758,9 +11763,3 @@ fn constraintAllowsRegister(constraint: []const u8) bool { } } else return false; } - -fn wantDllExports(zcu: *const Zcu) bool { - const lf = zcu.bin_file.?; - const coff = lf.cast(link.File.Coff) orelse return false; - return coff.dll_export_fns; -} diff --git a/src/link.zig b/src/link.zig index 77169afa2919..14b180ed2acf 100644 --- a/src/link.zig +++ b/src/link.zig @@ -88,7 +88,6 @@ pub const File = struct { image_base: ?u64, eh_frame_hdr: bool, emit_relocs: bool, - rdynamic: bool, z_nodelete: bool, z_notext: bool, z_defs: bool, @@ -110,7 +109,6 @@ pub const File = struct { max_memory: ?u64, export_symbol_names: []const []const u8, global_base: ?u64, - dll_export_fns: bool, each_lib_rpath: bool, build_id: std.zig.BuildId, disable_lld_caching: bool, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 52ca7e554ccf..c02aecf2db36 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -8,7 +8,6 @@ llvm_object: ?*LlvmObject = null, base: link.File, image_base: u64, -dll_export_fns: bool, subsystem: ?std.Target.SubSystem, tsaware: bool, nxcompat: bool, @@ -416,7 +415,6 @@ pub fn createEmpty( .Obj => 0, }, - .dll_export_fns = options.dll_export_fns, .subsystem = options.subsystem, .tsaware = options.tsaware, .nxcompat = options.nxcompat, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index fe89a6321fc7..47b4712b57bf 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,6 +1,5 @@ base: link.File, image_base: u64, -rdynamic: bool, eh_frame_hdr: bool, emit_relocs: bool, z_nodelete: bool, @@ -370,7 +369,7 @@ pub fn createEmpty( else => 0x1000, }; const is_dyn_lib = output_mode == .Lib and link_mode == .Dynamic; - const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or options.rdynamic) + const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or comp.config.rdynamic) elf.VER_NDX_GLOBAL else elf.VER_NDX_LOCAL; @@ -402,7 +401,6 @@ pub fn createEmpty( }; }, - .rdynamic = options.rdynamic, .eh_frame_hdr = options.eh_frame_hdr, .emit_relocs = options.emit_relocs, .z_nodelete = options.z_nodelete, @@ -1725,7 +1723,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("--eh-frame-hdr"); } - if (self.rdynamic) { + if (comp.config.rdynamic) { try argv.append("--export-dynamic"); } @@ -2434,7 +2432,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addOptional(self.sort_section); man.hash.add(self.eh_frame_hdr); man.hash.add(self.emit_relocs); - man.hash.add(self.rdynamic); + man.hash.add(comp.config.rdynamic); man.hash.addListOfBytes(self.lib_dirs); man.hash.addListOfBytes(self.base.rpath_list); man.hash.add(self.each_lib_rpath); @@ -2637,7 +2635,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--emit-relocs"); } - if (self.rdynamic) { + if (comp.config.rdynamic) { try argv.append("--export-dynamic"); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 6488231afa60..874cc2d9b378 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -39,7 +39,6 @@ pub const base_tag: link.File.Tag = .wasm; base: link.File, import_symbols: bool, export_symbol_names: []const []const u8, -rdynamic: bool, global_base: ?u64, initial_memory: ?u64, max_memory: ?u64, @@ -563,7 +562,6 @@ pub fn createEmpty( .export_table = options.export_table, .import_symbols = options.import_symbols, .export_symbol_names = options.export_symbol_names, - .rdynamic = options.rdynamic, .global_base = options.global_base, .initial_memory = options.initial_memory, .max_memory = options.max_memory, @@ -2973,8 +2971,9 @@ fn mergeTypes(wasm: *Wasm) !void { } fn setupExports(wasm: *Wasm) !void { - const gpa = wasm.base.comp.gpa; - if (wasm.base.comp.config.output_mode == .Obj) return; + const comp = wasm.base.comp; + const gpa = comp.gpa; + if (comp.config.output_mode == .Obj) return; log.debug("Building exports from symbols", .{}); const force_exp_names = wasm.export_symbol_names; @@ -2999,7 +2998,7 @@ fn setupExports(wasm: *Wasm) !void { for (wasm.resolved_symbols.keys()) |sym_loc| { const symbol = sym_loc.getSymbol(wasm); - if (!symbol.isExported(wasm.rdynamic)) continue; + if (!symbol.isExported(comp.config.rdynamic)) continue; const sym_name = sym_loc.getName(wasm); const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: { @@ -4789,7 +4788,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(arg); } - if (wasm.rdynamic) { + if (comp.config.rdynamic) { try argv.append("--export-dynamic"); } @@ -5288,7 +5287,7 @@ fn markReferences(wasm: *Wasm) !void { for (wasm.resolved_symbols.keys()) |sym_loc| { const sym = sym_loc.getSymbol(wasm); - if (sym.isExported(wasm.rdynamic) or sym.isNoStrip() or !do_garbage_collect) { + if (sym.isExported(comp.config.rdynamic) or sym.isNoStrip() or !do_garbage_collect) { try wasm.mark(sym_loc); continue; } diff --git a/src/main.zig b/src/main.zig index b73023e5b35f..ee6468d41f28 100644 --- a/src/main.zig +++ b/src/main.zig @@ -786,7 +786,6 @@ fn buildOutputType( arg_mode: ArgMode, ) !void { var provided_name: ?[]const u8 = null; - var dll_export_fns: ?bool = null; var root_src_file: ?[]const u8 = null; var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 }; var have_version = false; @@ -824,7 +823,6 @@ fn buildOutputType( var soname: SOName = undefined; var want_native_include_dirs = false; var want_compiler_rt: ?bool = null; - var rdynamic: bool = false; var linker_script: ?[]const u8 = null; var version_script: ?[]const u8 = null; var disable_c_depfile = false; @@ -1411,7 +1409,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-error-tracing")) { mod_opts.error_tracing = false; } else if (mem.eql(u8, arg, "-rdynamic")) { - rdynamic = true; + create_module.opts.rdynamic = true; } else if (mem.eql(u8, arg, "-fsoname")) { soname = .yes_default_value; } else if (mem.startsWith(u8, arg, "-fsoname=")) { @@ -1472,9 +1470,9 @@ fn buildOutputType( lib_preferred_mode = .Static; lib_search_strategy = .no_fallback; } else if (mem.eql(u8, arg, "-fdll-export-fns")) { - dll_export_fns = true; + create_module.opts.dll_export_fns = true; } else if (mem.eql(u8, arg, "-fno-dll-export-fns")) { - dll_export_fns = false; + create_module.opts.dll_export_fns = false; } else if (mem.eql(u8, arg, "--show-builtin")) { show_builtin = true; emit_bin = .no; @@ -1882,7 +1880,7 @@ fn buildOutputType( create_module.opts.link_mode = .Dynamic; is_shared_lib = true; }, - .rdynamic => rdynamic = true, + .rdynamic => create_module.opts.rdynamic = true, .wl => { var split_it = mem.splitScalar(u8, it.only_arg, ','); while (split_it.next()) |linker_arg| { @@ -2136,7 +2134,7 @@ fn buildOutputType( mem.eql(u8, arg, "--export-dynamic") or mem.eql(u8, arg, "-export-dynamic")) { - rdynamic = true; + create_module.opts.rdynamic = true; } 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")) { @@ -2295,7 +2293,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--high-entropy-va")) { // This option does not do anything. } else if (mem.eql(u8, arg, "--export-all-symbols")) { - rdynamic = true; + create_module.opts.rdynamic = true; } else if (mem.eql(u8, arg, "--color-diagnostics") or mem.eql(u8, arg, "--color-diagnostics=always")) { @@ -3365,7 +3363,6 @@ fn buildOutputType( .emit_llvm_bc = emit_llvm_bc_resolved.data, .emit_docs = emit_docs_resolved.data, .emit_implib = emit_implib_resolved.data, - .dll_export_fns = dll_export_fns, .lib_dirs = lib_dirs.items, .rpath_list = rpath_list.items, .symbol_wrap_set = symbol_wrap_set, @@ -3381,7 +3378,6 @@ fn buildOutputType( .wasi_emulated_libs = create_module.wasi_emulated_libs.items, .want_compiler_rt = want_compiler_rt, .hash_style = hash_style, - .rdynamic = rdynamic, .linker_script = linker_script, .version_script = version_script, .disable_c_depfile = disable_c_depfile, From 48d5861f9256dfd1c5357dd6f2a023e700de16e4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 20:28:51 -0700 Subject: [PATCH 051/133] fix more compilation errors introduced by this branch --- src/Compilation.zig | 44 +++++++++++++---- src/arch/aarch64/CodeGen.zig | 2 +- src/arch/arm/CodeGen.zig | 2 +- src/arch/riscv64/CodeGen.zig | 2 +- src/arch/sparc64/CodeGen.zig | 2 +- src/arch/x86_64/CodeGen.zig | 9 ++-- src/arch/x86_64/Emit.zig | 6 +-- src/arch/x86_64/Lower.zig | 11 +++-- src/libcxx.zig | 14 +----- src/libtsan.zig | 7 +-- src/libunwind.zig | 7 +-- src/link/Elf/synthetic_sections.zig | 73 ++++++++++++++++++++--------- src/main.zig | 17 ------- src/musl.zig | 2 +- 14 files changed, 113 insertions(+), 85 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index c742e59af5e7..a39d85256305 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -893,6 +893,12 @@ const CacheUse = union(CacheMode) { whole.lock = null; } } + + fn moveLock(whole: *Whole) Cache.Lock { + const result = whole.lock.?; + whole.lock = null; + return result; + } }; const Incremental = struct { @@ -939,7 +945,9 @@ pub const InitOptions = struct { main_mod: ?*Package.Module = null, /// This is provided so that the API user has a chance to tweak the /// per-module settings of the standard library. - std_mod: *Package.Module, + /// When this is null, a default configuration of the std lib is created + /// based on the settings of root_mod. + std_mod: ?*Package.Module = null, root_name: []const u8, sysroot: ?[]const u8 = null, /// `null` means to not emit a binary file. @@ -1381,13 +1389,30 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { break :eh eh; } else null; + const std_mod = options.std_mod orelse try Package.Module.create(arena, .{ + .global_cache_directory = options.global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = options.zig_lib_directory, + .sub_path = "std", + }, + .root_src_path = "std.zig", + }, + .fully_qualified_name = "std", + .cc_argv = &.{}, + .inherited = .{}, + .global = options.config, + .parent = options.root_mod, + .builtin_mod = options.root_mod.deps.get("builtin").?, + }); + const zcu = try arena.create(Module); zcu.* = .{ .gpa = gpa, .comp = comp, .main_mod = options.main_mod orelse options.root_mod, .root_mod = options.root_mod, - .std_mod = options.std_mod, + .std_mod = std_mod, .global_zir_cache = global_zir_cache, .local_zir_cache = local_zir_cache, .emit_h = emit_h, @@ -6215,7 +6240,7 @@ fn buildOutputFromZig( .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &.{ sub_compilation.bin_file.?.emit.sub_path, }), - .lock = sub_compilation.bin_file.toOwnedLock(), + .lock = sub_compilation.bin_file.?.toOwnedLock(), }; } @@ -6317,13 +6342,16 @@ pub fn build_crt_file( try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); try comp.crt_files.ensureUnusedCapacity(gpa, 1); + comp.crt_files.putAssumeCapacityNoClobber(basename, try sub_compilation.toCrtFile()); +} - comp.crt_files.putAssumeCapacityNoClobber(basename, .{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &.{ - sub_compilation.bin_file.?.emit.sub_path, +pub fn toCrtFile(comp: *Compilation) Allocator.Error!CRTFile { + return .{ + .full_object_path = try comp.local_cache_directory.join(comp.gpa, &.{ + comp.cache_use.whole.bin_sub_path.?, }), - .lock = sub_compilation.bin_file.toOwnedLock(), - }); + .lock = comp.cache_use.whole.moveLock(), + }; } pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 341e4bef008c..ee5e58ae05e9 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -6332,7 +6332,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. fn wantSafety(self: *Self) bool { - return switch (self.bin_file.options.optimize_mode) { + return switch (self.bin_file.comp.root_mod.optimize_mode) { .Debug => true, .ReleaseSafe => true, .ReleaseFast => false, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index c9d6a3aef462..7227347e1b9e 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -6281,7 +6281,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. fn wantSafety(self: *Self) bool { - return switch (self.bin_file.options.optimize_mode) { + return switch (self.bin_file.comp.root_mod.optimize_mode) { .Debug => true, .ReleaseSafe => true, .ReleaseFast => false, diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 80daa8fd3a51..7d3b0cd1a0ac 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -2708,7 +2708,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. fn wantSafety(self: *Self) bool { - return switch (self.bin_file.options.optimize_mode) { + return switch (self.bin_file.comp.root_mod.optimize_mode) { .Debug => true, .ReleaseSafe => true, .ReleaseFast => false, diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index e58206ac1635..e7db3be8b020 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -4857,7 +4857,7 @@ fn truncRegister( /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. fn wantSafety(self: *Self) bool { - return switch (self.bin_file.options.optimize_mode) { + return switch (self.bin_file.comp.root_mod.optimize_mode) { .Debug => true, .ReleaseSafe => true, .ReleaseFast => false, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 5056bc32fd3e..dbb87fa56687 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -25,7 +25,9 @@ const Emit = @import("Emit.zig"); const Liveness = @import("../../Liveness.zig"); const Lower = @import("Lower.zig"); const Mir = @import("Mir.zig"); +const Package = @import("../../Package.zig"); const Module = @import("../../Module.zig"); +const Zcu = Module; const InternPool = @import("../../InternPool.zig"); const Alignment = InternPool.Alignment; const Target = std.Target; @@ -56,6 +58,7 @@ bin_file: *link.File, debug_output: DebugInfoOutput, target: *const std.Target, owner: Owner, +mod: *Package.Module, err_msg: ?*ErrorMsg, args: []MCValue, va_info: union { @@ -10906,7 +10909,7 @@ fn genCall(self: *Self, info: union(enum) { if (self.bin_file.cast(link.File.Elf)) |elf_file| { const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); const sym = elf_file.symbol(sym_index); - if (self.bin_file.options.pic) { + if (self.mod.pic) { const callee_reg: Register = switch (resolved_cc) { .SysV => callee: { if (!fn_info.is_var_args) break :callee .rax; @@ -13819,7 +13822,7 @@ fn genLazySymbolRef( const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err| return self.fail("{s} creating lazy symbol", .{@errorName(err)}); const sym = elf_file.symbol(sym_index); - if (self.bin_file.options.pic) { + if (self.mod.pic) { switch (tag) { .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = .{ .sym = sym.esym_index }, @@ -16062,7 +16065,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { const const_mcv = try self.genTypedValue(.{ .ty = ty, .val = Value.fromInterned(ip_index) }); switch (const_mcv) { .lea_tlv => |tlv_sym| if (self.bin_file.cast(link.File.Elf)) |_| { - if (self.bin_file.options.pic) { + if (self.mod.pic) { try self.spillRegisters(&.{ .rdi, .rax }); } else { try self.spillRegisters(&.{.rax}); diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index b3a5316104fb..e8668e82f4a7 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -103,10 +103,10 @@ pub fn emitMir(emit: *Emit) Error!void { }); }, .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| { - const is_obj_or_static_lib = switch (emit.lower.bin_file.options.output_mode) { + const is_obj_or_static_lib = switch (emit.lower.output_mode) { .Exe => false, .Obj => true, - .Lib => emit.lower.bin_file.options.link_mode == .Static, + .Lib => emit.lower.link_mode == .Static, }; const atom = elf_file.symbol(data.atom_index).atom(elf_file).?; const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index); @@ -114,7 +114,7 @@ pub fn emitMir(emit: *Emit) Error!void { if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); } - if (emit.lower.bin_file.options.pic) { + if (emit.lower.pic) { const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) link.File.Elf.R_X86_64_ZIG_GOTPCREL else if (sym.flags.needs_got) diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index 0c309991f6b0..cc5ae7712bb1 100644 --- a/src/arch/x86_64/Lower.zig +++ b/src/arch/x86_64/Lower.zig @@ -1,6 +1,9 @@ //! This file contains the functionality for lowering x86_64 MIR to Instructions bin_file: *link.File, +output_mode: std.builtin.OutputMode, +link_mode: std.builtin.LinkMode, +pic: bool, allocator: Allocator, mir: Mir, cc: std.builtin.CallingConvention, @@ -336,10 +339,10 @@ fn isTls(sym: bits.Symbol, ctx: *link.File) bool { } fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { - const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) { + const is_obj_or_static_lib = switch (lower.output_mode) { .Exe => false, .Obj => true, - .Lib => lower.bin_file.options.link_mode == .Static, + .Lib => lower.link_mode == .Static, }; const emit_prefix = prefix; @@ -358,7 +361,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) if (isTls(sym, lower.bin_file)) { // TODO handle extern TLS vars, i.e., emit GD model - if (lower.bin_file.options.pic) { + if (lower.pic) { // Here, we currently assume local dynamic TLS vars, and so // we emit LD model. _ = lower.reloc(.{ .linker_tlsld = sym }); @@ -403,7 +406,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) } _ = lower.reloc(.{ .linker_reloc = sym }); - break :op if (lower.bin_file.options.pic) switch (mnemonic) { + break :op if (lower.pic) switch (mnemonic) { .lea => { break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; }, diff --git a/src/libcxx.zig b/src/libcxx.zig index 0625d033bfa2..aedb1f3930af 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -299,12 +299,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { try comp.updateSubCompilation(sub_compilation, .libcxx, prog_node); assert(comp.libcxx_static_lib == null); - comp.libcxx_static_lib = Compilation.CRTFile{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(comp.gpa, &.{ - sub_compilation.bin_file.?.emit.sub_path, - }), - .lock = sub_compilation.bin_file.toOwnedLock(), - }; + comp.libcxx_static_lib = try sub_compilation.toCrtFile(); } pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { @@ -489,10 +484,5 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { try comp.updateSubCompilation(sub_compilation, .libcxxabi, prog_node); assert(comp.libcxxabi_static_lib == null); - comp.libcxxabi_static_lib = Compilation.CRTFile{ - .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(), - }; + comp.libcxxabi_static_lib = try sub_compilation.toCrtFile(); } diff --git a/src/libtsan.zig b/src/libtsan.zig index 6220f00e8fd1..553597e48515 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -268,12 +268,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { try comp.updateSubCompilation(sub_compilation, .libtsan, prog_node); assert(comp.tsan_static_lib == null); - comp.tsan_static_lib = Compilation.CRTFile{ - .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(), - }; + comp.tsan_static_lib = try sub_compilation.toCrtFile(); } const tsan_sources = [_][]const u8{ diff --git a/src/libunwind.zig b/src/libunwind.zig index 5b963c96c966..c59b5255d209 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -151,12 +151,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { assert(comp.libunwind_static_lib == null); - comp.libunwind_static_lib = Compilation.CRTFile{ - .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(), - }; + comp.libunwind_static_lib = try sub_compilation.toOwnedLock(); } const unwind_src_list = [_][]const u8{ diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 92d5318c0219..29cf8e2bc70e 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -8,14 +8,16 @@ pub const DynamicSection = struct { } pub fn addNeeded(dt: *DynamicSection, shared: *SharedObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const off = try elf_file.insertDynString(shared.soname()); try dt.needed.append(gpa, off); } pub fn setRpath(dt: *DynamicSection, rpath_list: []const []const u8, elf_file: *Elf) !void { if (rpath_list.len == 0) return; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var rpath = std.ArrayList(u8).init(gpa); defer rpath.deinit(); for (rpath_list, 0..) |path, i| { @@ -248,7 +250,8 @@ pub const ZigGotSection = struct { pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { const comp = elf_file.base.comp; - const index = try zig_got.allocateEntry(elf_file.base.allocator); + const gpa = comp.gpa; + const index = try zig_got.allocateEntry(gpa); const entry = &zig_got.entries.items[index]; entry.* = sym_index; const symbol = elf_file.symbol(sym_index); @@ -349,7 +352,9 @@ pub const ZigGotSection = struct { } pub fn addRela(zig_got: ZigGotSection, elf_file: *Elf) !void { - try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, zig_got.numRela()); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela()); for (zig_got.entries.items) |entry| { const symbol = elf_file.symbol(entry); const offset = symbol.zigGotAddress(elf_file); @@ -481,7 +486,8 @@ pub const GotSection = struct { pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { const comp = elf_file.base.comp; - const index = try got.allocateEntry(elf_file.base.allocator); + const gpa = comp.gpa; + const index = try got.allocateEntry(gpa); const entry = &got.entries.items[index]; entry.tag = .got; entry.symbol_index = sym_index; @@ -501,8 +507,10 @@ pub const GotSection = struct { } pub fn addTlsLdSymbol(got: *GotSection, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; assert(got.flags.needs_tlsld); - const index = try got.allocateEntry(elf_file.base.allocator); + const index = try got.allocateEntry(gpa); const entry = &got.entries.items[index]; entry.tag = .tlsld; entry.symbol_index = undefined; // unused @@ -511,7 +519,9 @@ pub const GotSection = struct { } pub fn addTlsGdSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { - const index = try got.allocateEntry(elf_file.base.allocator); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const index = try got.allocateEntry(gpa); const entry = &got.entries.items[index]; entry.tag = .tlsgd; entry.symbol_index = sym_index; @@ -526,7 +536,9 @@ pub const GotSection = struct { } pub fn addGotTpSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { - const index = try got.allocateEntry(elf_file.base.allocator); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const index = try got.allocateEntry(gpa); const entry = &got.entries.items[index]; entry.tag = .gottp; entry.symbol_index = sym_index; @@ -541,7 +553,9 @@ pub const GotSection = struct { } pub fn addTlsDescSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { - const index = try got.allocateEntry(elf_file.base.allocator); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const index = try got.allocateEntry(gpa); const entry = &got.entries.items[index]; entry.tag = .tlsdesc; entry.symbol_index = sym_index; @@ -628,8 +642,9 @@ pub const GotSection = struct { pub fn addRela(got: GotSection, elf_file: *Elf) !void { const comp = elf_file.base.comp; + const gpa = comp.gpa; const is_dyn_lib = elf_file.isDynLib(); - try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file)); + try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file)); for (got.entries.items) |entry| { const symbol = switch (entry.tag) { @@ -847,6 +862,8 @@ pub const PltSection = struct { } pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const index = @as(u32, @intCast(plt.symbols.items.len)); const symbol = elf_file.symbol(sym_index); symbol.flags.has_plt = true; @@ -855,7 +872,7 @@ pub const PltSection = struct { new_extra.plt = index; symbol.setExtra(new_extra, elf_file); } else try symbol.addExtra(.{ .plt = index }, elf_file); - try plt.symbols.append(elf_file.base.allocator, sym_index); + try plt.symbols.append(gpa, sym_index); } pub fn size(plt: PltSection) usize { @@ -895,7 +912,9 @@ pub const PltSection = struct { } pub fn addRela(plt: PltSection, elf_file: *Elf) !void { - try elf_file.rela_plt.ensureUnusedCapacity(elf_file.base.allocator, plt.numRela()); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela()); for (plt.symbols.items) |sym_index| { const sym = elf_file.symbol(sym_index); assert(sym.flags.import); @@ -1010,6 +1029,8 @@ pub const PltGotSection = struct { } pub fn addSymbol(plt_got: *PltGotSection, sym_index: Symbol.Index, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const index = @as(u32, @intCast(plt_got.symbols.items.len)); const symbol = elf_file.symbol(sym_index); symbol.flags.has_plt = true; @@ -1019,7 +1040,7 @@ pub const PltGotSection = struct { new_extra.plt_got = index; symbol.setExtra(new_extra, elf_file); } else try symbol.addExtra(.{ .plt_got = index }, elf_file); - try plt_got.symbols.append(elf_file.base.allocator, sym_index); + try plt_got.symbols.append(gpa, sym_index); } pub fn size(plt_got: PltGotSection) usize { @@ -1077,6 +1098,8 @@ pub const CopyRelSection = struct { } pub fn addSymbol(copy_rel: *CopyRelSection, sym_index: Symbol.Index, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const index = @as(u32, @intCast(copy_rel.symbols.items.len)); const symbol = elf_file.symbol(sym_index); symbol.flags.import = true; @@ -1089,7 +1112,7 @@ pub const CopyRelSection = struct { new_extra.copy_rel = index; symbol.setExtra(new_extra, elf_file); } else try symbol.addExtra(.{ .copy_rel = index }, elf_file); - try copy_rel.symbols.append(elf_file.base.allocator, sym_index); + try copy_rel.symbols.append(gpa, sym_index); const shared_object = symbol.file(elf_file).?.shared_object; if (shared_object.aliases == null) { @@ -1129,7 +1152,9 @@ pub const CopyRelSection = struct { } pub fn addRela(copy_rel: CopyRelSection, elf_file: *Elf) !void { - try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, copy_rel.numRela()); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela()); for (copy_rel.symbols.items) |sym_index| { const sym = elf_file.symbol(sym_index); assert(sym.flags.import and sym.flags.has_copy_rel); @@ -1162,7 +1187,8 @@ pub const DynsymSection = struct { } pub fn addSymbol(dynsym: *DynsymSection, sym_index: Symbol.Index, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const index = @as(u32, @intCast(dynsym.entries.items.len + 1)); const sym = elf_file.symbol(sym_index); sym.flags.has_dynamic = true; @@ -1244,7 +1270,8 @@ pub const HashSection = struct { pub fn generate(hs: *HashSection, elf_file: *Elf) !void { if (elf_file.dynsym.count() == 1) return; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const nsyms = elf_file.dynsym.count(); var buckets = try gpa.alloc(u32, nsyms); @@ -1332,7 +1359,8 @@ pub const GnuHashSection = struct { try cwriter.writeInt(u32, hash.num_bloom, .little); try cwriter.writeInt(u32, bloom_shift, .little); - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const hashes = try gpa.alloc(u32, exports.len); defer gpa.free(hashes); const indices = try gpa.alloc(u32, exports.len); @@ -1434,7 +1462,8 @@ pub const VerneedSection = struct { } }; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var verneed = std.ArrayList(VersionedSymbol).init(gpa); defer verneed.deinit(); try verneed.ensureTotalCapacity(dynsyms.len); @@ -1490,7 +1519,8 @@ pub const VerneedSection = struct { } fn addVerneed(vern: *VerneedSection, soname: []const u8, elf_file: *Elf) !*elf.Elf64_Verneed { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const sym = try vern.verneed.addOne(gpa); sym.* = .{ .vn_version = 1, @@ -1508,7 +1538,8 @@ pub const VerneedSection = struct { version: [:0]const u8, elf_file: *Elf, ) !elf.Elf64_Vernaux { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const sym = try vern.vernaux.addOne(gpa); sym.* = .{ .vna_hash = HashSection.hasher(version), diff --git a/src/main.zig b/src/main.zig index ee6468d41f28..26e1d79a7b0f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5242,22 +5242,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi }); const builtin_mod = root_mod.getBuiltinDependency(); - const std_mod = try Package.Module.create(arena, .{ - .global_cache_directory = global_cache_directory, - .paths = .{ - .root = .{ - .root_dir = zig_lib_directory, - .sub_path = "std", - }, - .root_src_path = "std.zig", - }, - .fully_qualified_name = "std", - .cc_argv = &.{}, - .inherited = .{}, - .global = config, - .parent = root_mod, - .builtin_mod = builtin_mod, - }); const build_mod = try Package.Module.create(arena, .{ .global_cache_directory = global_cache_directory, @@ -5425,7 +5409,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .config = config, .root_mod = root_mod, .main_mod = build_mod, - .std_mod = std_mod, .emit_bin = emit_bin, .emit_h = null, .self_exe_path = self_exe_path, diff --git a/src/musl.zig b/src/musl.zig index 953c5687e909..2ba9e4485c48 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -280,7 +280,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(comp.gpa, &.{ sub_compilation.bin_file.?.emit.sub_path, }), - .lock = sub_compilation.bin_file.toOwnedLock(), + .lock = sub_compilation.bin_file.?.toOwnedLock(), }); }, } From 46297087871dec88c2b632d057f1e55b662126df Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Dec 2023 20:34:42 -0700 Subject: [PATCH 052/133] linker: fix some allocator references --- src/link/Elf/Archive.zig | 6 ++++-- src/link/Elf/LdScript.zig | 3 ++- src/link/Elf/LinkerDefined.zig | 3 ++- src/link/Elf/Object.zig | 33 +++++++++++++++++++---------- src/link/Elf/SharedObject.zig | 12 +++++++---- src/link/Elf/eh_frame.zig | 16 ++++++++++---- src/link/Elf/gc.zig | 3 ++- src/link/Elf/synthetic_sections.zig | 26 +++++++++++------------ 8 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index 686647a290fe..65135abbc77a 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -20,7 +20,8 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { } pub fn parse(self: *Archive, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var stream = std.io.fixedBufferStream(self.data); const reader = stream.reader(); @@ -150,7 +151,8 @@ pub const ArSymtab = struct { const hdr = setArHdr(.{ .name = .symtab, .size = @intCast(ar.size(.p64)) }); try writer.writeAll(mem.asBytes(&hdr)); - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var offsets = std.AutoHashMap(File.Index, u64).init(gpa); defer offsets.deinit(); try offsets.ensureUnusedCapacity(@intCast(elf_file.objects.items.len + 1)); diff --git a/src/link/Elf/LdScript.zig b/src/link/Elf/LdScript.zig index 803e2e146946..34cecf587993 100644 --- a/src/link/Elf/LdScript.zig +++ b/src/link/Elf/LdScript.zig @@ -14,7 +14,8 @@ pub const Error = error{ }; pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var tokenizer = Tokenizer{ .source = data }; var tokens = std.ArrayList(Token).init(gpa); defer tokens.deinit(); diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index bc51cfc1f17d..b9fffa1a4a65 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -12,7 +12,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void { } pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; try self.symtab.ensureUnusedCapacity(gpa, 1); try self.symbols.ensureUnusedCapacity(gpa, 1); const name_off = @as(u32, @intCast(self.strtab.items.len)); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 0bf1e837e352..35df214b182b 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -66,7 +66,8 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { if (self.header.?.e_shnum == 0) return; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; if (self.data.len < self.header.?.e_shoff or self.data.len < self.header.?.e_shoff + @as(u64, @intCast(self.header.?.e_shnum)) * @sizeOf(elf.Elf64_Shdr)) @@ -149,8 +150,10 @@ pub fn init(self: *Object, elf_file: *Elf) !void { } fn initAtoms(self: *Object, elf_file: *Elf) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; const shdrs = self.shdrs.items; - try self.atoms.resize(elf_file.base.allocator, shdrs.len); + try self.atoms.resize(gpa, shdrs.len); @memset(self.atoms.items, 0); for (shdrs, 0..) |shdr, i| { @@ -185,7 +188,6 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void { continue; } - const gpa = elf_file.base.allocator; const gop = try elf_file.getOrCreateComdatGroupOwner(group_signature); const comdat_group_index = try elf_file.addComdatGroup(); const comdat_group = elf_file.comdatGroup(comdat_group_index); @@ -308,7 +310,8 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { } fn initSymtab(self: *Object, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const first_global = self.first_global orelse self.symtab.items.len; try self.symbols.ensureTotalCapacityPrecise(gpa, self.symtab.items.len); @@ -340,7 +343,8 @@ fn parseEhFrame(self: *Object, shndx: u16, elf_file: *Elf) !void { return; }; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const raw = self.shdrContents(shndx); const relocs = self.getRelocs(relocs_shndx); const fdes_start = self.fdes.items.len; @@ -440,6 +444,8 @@ fn filterRelocs( } pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; for (self.atoms.items) |atom_index| { const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; @@ -450,7 +456,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { // TODO ideally, we don't have to decompress at this stage (should already be done) // and we just fetch the code slice. const code = try self.codeDecompressAlloc(elf_file, atom_index); - defer elf_file.base.allocator.free(code); + defer gpa.free(code); try atom.scanRelocs(elf_file, code, undefs); } else try atom.scanRelocs(elf_file, null, undefs); } @@ -623,7 +629,8 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { continue; } - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const atom_index = try elf_file.addAtom(); try self.atoms.append(gpa, atom_index); @@ -682,7 +689,8 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { const shdr = atom.inputShdr(elf_file); atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index); if (!gop.found_existing) gop.value_ptr.* = .{}; try gop.value_ptr.append(gpa, atom_index); @@ -742,7 +750,8 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { shdr.sh_info = atom.outputShndx().?; shdr.sh_link = elf_file.symtab_section_index.?; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?); if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx }; try gop.value_ptr.atom_list.append(gpa, atom_index); @@ -750,7 +759,8 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { } pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const start = self.first_global orelse self.symtab.items.len; try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.symtab.items.len - start); @@ -857,7 +867,8 @@ pub fn shdrContents(self: Object, index: u32) []const u8 { /// Returns atom's code and optionally uncompresses data if required (for compressed sections). /// Caller owns the memory. pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const atom_ptr = elf_file.atom(atom_index).?; assert(atom_ptr.file_index == self.index); const data = self.shdrContents(atom_ptr.input_section_index); diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 6675f4994146..e5e87cc51e6d 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -47,7 +47,8 @@ pub fn deinit(self: *SharedObject, allocator: Allocator) void { } pub fn parse(self: *SharedObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var stream = std.io.fixedBufferStream(self.data); const reader = stream.reader(); @@ -101,7 +102,8 @@ pub fn parse(self: *SharedObject, elf_file: *Elf) !void { } fn parseVersions(self: *SharedObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const symtab = self.getSymtabRaw(); try self.verstrings.resize(gpa, 2); @@ -146,7 +148,8 @@ fn parseVersions(self: *SharedObject, elf_file: *Elf) !void { } pub fn init(self: *SharedObject, elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const symtab = self.getSymtabRaw(); const strtab = self.getStrtabRaw(); @@ -295,7 +298,8 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void { } }; - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; var aliases = std.ArrayList(Symbol.Index).init(gpa); defer aliases.deinit(); try aliases.ensureTotalCapacityPrecise(self.globals().len); diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 1d24285b30c0..e8500e8aa92b 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -233,9 +233,12 @@ pub const Iterator = struct { }; pub fn calcEhFrameSize(elf_file: *Elf) !usize { + const comp = elf_file.base.comp; + const gpa = comp.gpa; + var offset: usize = 0; - var cies = std.ArrayList(Cie).init(elf_file.base.allocator); + var cies = std.ArrayList(Cie).init(gpa); defer cies.deinit(); for (elf_file.objects.items) |index| { @@ -327,7 +330,8 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: } pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr}); @@ -378,7 +382,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { } pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; for (elf_file.objects.items) |index| { const object = elf_file.file(index).?.object; @@ -467,6 +472,9 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { } pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { + const comp = elf_file.base.comp; + const gpa = comp.gpa; + try writer.writeByte(1); // version try writer.writeByte(EH_PE.pcrel | EH_PE.sdata4); try writer.writeByte(EH_PE.udata4); @@ -495,7 +503,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { } }; - var entries = std.ArrayList(Entry).init(elf_file.base.allocator); + var entries = std.ArrayList(Entry).init(gpa); defer entries.deinit(); try entries.ensureTotalCapacityPrecise(num_fdes); diff --git a/src/link/Elf/gc.zig b/src/link/Elf/gc.zig index ade2b75782a8..d95dd78b331f 100644 --- a/src/link/Elf/gc.zig +++ b/src/link/Elf/gc.zig @@ -1,5 +1,6 @@ pub fn gcAtoms(elf_file: *Elf) !void { - const gpa = elf_file.base.allocator; + const comp = elf_file.base.comp; + const gpa = comp.gpa; const num_files = elf_file.objects.items.len + @intFromBool(elf_file.zig_object_index != null); var files = try std.ArrayList(File.Index).initCapacity(gpa, num_files); defer files.deinit(); diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 29cf8e2bc70e..68a36e14ce4e 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -57,7 +57,7 @@ pub const DynamicSection = struct { if (elf_file.z_now) { flags_1 |= elf.DF_1_NOW; } - if (elf_file.isExe() and comp.config.pie) { + if (elf_file.base.isExe() and comp.config.pie) { flags_1 |= elf.DF_1_PIE; } // if (elf_file.z_nodlopen) { @@ -89,7 +89,7 @@ pub const DynamicSection = struct { if (elf_file.verneed_section_index != null) nentries += 2; // VERNEED if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_1 - if (!elf_file.isDynLib()) nentries += 1; // DEBUG + if (!elf_file.base.isDynLib()) nentries += 1; // DEBUG nentries += 1; // NULL return nentries * @sizeOf(elf.Elf64_Dyn); } @@ -216,7 +216,7 @@ pub const DynamicSection = struct { } // DEBUG - if (!elf_file.isDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 }); + if (!elf_file.base.isDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 }); // NULL try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 }); @@ -256,7 +256,7 @@ pub const ZigGotSection = struct { entry.* = sym_index; const symbol = elf_file.symbol(sym_index); symbol.flags.has_zig_got = true; - if (elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) { + if (elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) { zig_got.flags.needs_rela = true; } if (symbol.extra(elf_file)) |extra| { @@ -494,7 +494,7 @@ pub const GotSection = struct { const symbol = elf_file.symbol(sym_index); symbol.flags.has_got = true; if (symbol.flags.import or symbol.isIFunc(elf_file) or - ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file))) + ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file))) { got.flags.needs_rela = true; } @@ -527,7 +527,7 @@ pub const GotSection = struct { entry.symbol_index = sym_index; const symbol = elf_file.symbol(sym_index); symbol.flags.has_tlsgd = true; - if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true; + if (symbol.flags.import or elf_file.base.isDynLib()) got.flags.needs_rela = true; if (symbol.extra(elf_file)) |extra| { var new_extra = extra; new_extra.tlsgd = index; @@ -544,7 +544,7 @@ pub const GotSection = struct { entry.symbol_index = sym_index; const symbol = elf_file.symbol(sym_index); symbol.flags.has_gottp = true; - if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true; + if (symbol.flags.import or elf_file.base.isDynLib()) got.flags.needs_rela = true; if (symbol.extra(elf_file)) |extra| { var new_extra = extra; new_extra.gottp = index; @@ -579,7 +579,7 @@ pub const GotSection = struct { pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void { const comp = elf_file.base.comp; - const is_dyn_lib = elf_file.isDynLib(); + const is_dyn_lib = elf_file.base.isDynLib(); const apply_relocs = true; // TODO add user option for this for (got.entries.items) |entry| { @@ -594,7 +594,7 @@ pub const GotSection = struct { if (symbol.?.flags.import) break :blk 0; if (symbol.?.isIFunc(elf_file)) break :blk if (apply_relocs) value else 0; - if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and + if ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file)) { break :blk if (apply_relocs) value else 0; @@ -643,7 +643,7 @@ pub const GotSection = struct { pub fn addRela(got: GotSection, elf_file: *Elf) !void { const comp = elf_file.base.comp; const gpa = comp.gpa; - const is_dyn_lib = elf_file.isDynLib(); + const is_dyn_lib = elf_file.base.isDynLib(); try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file)); for (got.entries.items) |entry| { @@ -672,7 +672,7 @@ pub const GotSection = struct { }); continue; } - if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and + if ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file)) { elf_file.addRelaDynAssumeCapacity(.{ @@ -746,7 +746,7 @@ pub const GotSection = struct { pub fn numRela(got: GotSection, elf_file: *Elf) usize { const comp = elf_file.base.comp; - const is_dyn_lib = elf_file.isDynLib(); + const is_dyn_lib = elf_file.base.isDynLib(); var num: usize = 0; for (got.entries.items) |entry| { const symbol = switch (entry.tag) { @@ -755,7 +755,7 @@ pub const GotSection = struct { }; switch (entry.tag) { .got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or - ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and + ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file))) { num += 1; From 2047a6b82d2e6cdbddde3e7f1c93df9e72216052 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 00:39:36 -0700 Subject: [PATCH 053/133] fix remaining compile errors except one --- src/Compilation.zig | 8 +- src/Module.zig | 11 +- src/Sema.zig | 2 +- src/arch/x86_64/CodeGen.zig | 46 +++-- src/codegen/llvm.zig | 2 +- src/link.zig | 298 +++++++++++++------------------ src/link/C.zig | 1 + src/link/Coff.zig | 15 +- src/link/Coff/lld.zig | 45 ++--- src/link/Dwarf.zig | 6 +- src/link/Elf.zig | 12 +- src/link/Elf/Atom.zig | 6 +- src/link/Elf/Object.zig | 6 +- src/link/Elf/ZigObject.zig | 2 +- src/link/Elf/eh_frame.zig | 2 +- src/link/MachO.zig | 34 ++-- src/link/MachO/Object.zig | 16 +- src/link/MachO/dead_strip.zig | 3 +- src/link/MachO/eh_frame.zig | 9 +- src/link/MachO/load_commands.zig | 33 ++-- src/link/MachO/thunks.zig | 6 +- src/link/MachO/zld.zig | 42 +++-- src/link/NvPtx.zig | 3 +- src/link/Plan9.zig | 11 +- src/link/SpirV.zig | 19 +- src/link/Wasm.zig | 9 +- src/link/Wasm/Object.zig | 10 +- src/main.zig | 24 ++- 28 files changed, 340 insertions(+), 341 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index a39d85256305..14a39f1bb327 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -229,7 +229,7 @@ pub const Emit = struct { /// Returns the full path to `basename` if it were in the same directory as the /// `Emit` sub_path. - pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 { + pub fn basenamePath(emit: Emit, arena: Allocator, basename: []const u8) ![:0]const u8 { const full_path = if (emit.directory.path) |p| try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path }) else @@ -238,7 +238,7 @@ pub const Emit = struct { if (std.fs.path.dirname(full_path)) |dirname| { return try std.fs.path.joinZ(arena, &.{ dirname, basename }); } else { - return basename; + return try arena.dupeZ(u8, basename); } } }; @@ -1038,8 +1038,8 @@ pub const InitOptions = struct { linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null, linker_module_definition_file: ?[]const u8 = null, linker_sort_section: ?link.File.Elf.SortSection = null, - major_subsystem_version: ?u32 = null, - minor_subsystem_version: ?u32 = null, + major_subsystem_version: ?u16 = null, + minor_subsystem_version: ?u16 = null, clang_passthrough_mode: bool = false, verbose_cc: bool = false, verbose_link: bool = false, diff --git a/src/Module.zig b/src/Module.zig index 571301c8e68d..6d5a2f78a6a0 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4309,14 +4309,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err decl.has_linksection_or_addrspace = has_linksection_or_addrspace; decl.zir_decl_index = @enumFromInt(decl_sub_index); if (decl.getOwnedFunction(mod) != null) { - switch (comp.bin_file.tag) { - .coff, .elf, .macho, .plan9 => { - // TODO Look into detecting when this would be unnecessary by storing enough state - // in `Decl` to notice that the line number did not change. - comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); - }, - .c, .wasm, .spirv, .nvptx => {}, - } + // TODO Look into detecting when this would be unnecessary by storing enough state + // in `Decl` to notice that the line number did not change. + comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); } } diff --git a/src/Sema.zig b/src/Sema.zig index 6d14deb0953f..26afd285c7e9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -20043,7 +20043,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { if (sema.owner_func_index != .none and ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and - mod.ownerModule().error_tracing and + block.ownerModule().error_tracing and mod.backendSupportsFeature(.error_return_trace)) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index dbb87fa56687..55e241cbd4c3 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -800,19 +800,20 @@ pub fn generate( ) CodeGenError!Result { const comp = bin_file.comp; const gpa = comp.gpa; - const mod = comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const zcu = comp.module.?; + const func = zcu.funcInfo(func_index); + const fn_owner_decl = zcu.declPtr(func.owner_decl); assert(fn_owner_decl.has_tv); const fn_type = fn_owner_decl.ty; - const namespace = mod.namespacePtr(fn_owner_decl.src_namespace); - const target = namespace.file_scope.mod.resolved_target.result; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const mod = namespace.file_scope.mod; var function = Self{ .gpa = gpa, .air = air, .liveness = liveness, - .target = target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .func_index = func_index }, @@ -843,7 +844,7 @@ pub fn generate( wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); - const ip = &mod.intern_pool; + const ip = &zcu.intern_pool; try function.frame_allocs.resize(gpa, FrameIndex.named_count); function.frame_allocs.set( @@ -858,7 +859,7 @@ pub fn generate( FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }), ); - const fn_info = mod.typeToFunc(fn_type).?; + const fn_info = zcu.typeToFunc(fn_type).?; const cc = abi.resolveCallingConvention(fn_info.cc, function.target.*); var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, @@ -877,14 +878,14 @@ pub fn generate( function.args = call_info.args; function.ret_mcv = call_info.return_value; function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(mod), - .alignment = Type.usize.abiAlignment(mod).min(call_info.stack_align), + .size = Type.usize.abiSize(zcu), + .alignment = Type.usize.abiAlignment(zcu).min(call_info.stack_align), })); function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(mod), + .size = Type.usize.abiSize(zcu), .alignment = Alignment.min( call_info.stack_align, - Alignment.fromNonzeroByteUnits(target.stackAlignment()), + Alignment.fromNonzeroByteUnits(function.target.stackAlignment()), ), })); function.frame_allocs.set( @@ -927,6 +928,9 @@ pub fn generate( .mir = mir, .cc = cc, .src_loc = src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -970,16 +974,14 @@ pub fn generateLazy( ) CodeGenError!Result { const comp = bin_file.comp; const gpa = comp.gpa; - const zcu = comp.module.?; - const decl_index = lazy_sym.ty.getOwnerDecl(zcu); - const decl = zcu.declPtr(decl_index); - const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.resolved_target.result; + // This function is for generating global code, so we use the root module. + const mod = comp.root_mod; var function = Self{ .gpa = gpa, .air = undefined, .liveness = undefined, - .target = target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .lazy_sym = lazy_sym }, @@ -1020,6 +1022,9 @@ pub fn generateLazy( .mir = mir, .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), .src_loc = src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -1104,6 +1109,8 @@ fn formatWipMir( _: std.fmt.FormatOptions, writer: anytype, ) @TypeOf(writer).Error!void { + const comp = data.self.bin_file.comp; + const mod = comp.root_mod; var lower = Lower{ .bin_file = data.self.bin_file, .allocator = data.self.gpa, @@ -1114,6 +1121,9 @@ fn formatWipMir( }, .cc = .Unspecified, .src_loc = data.self.src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }; var first = true; for ((lower.lowerMir(data.inst) catch |err| switch (err) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7e25a4b59b0e..3a53bddcb8a4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1168,7 +1168,7 @@ pub const Object = struct { pre_ir_path: ?[]const u8, pre_bc_path: ?[]const u8, bin_path: ?[*:0]const u8, - emit_asm: ?[*:0]const u8, + asm_path: ?[*:0]const u8, post_ir_path: ?[*:0]const u8, post_bc_path: ?[*:0]const u8, diff --git a/src/link.zig b/src/link.zig index 14b180ed2acf..3e5caf9fc1ea 100644 --- a/src/link.zig +++ b/src/link.zig @@ -61,6 +61,7 @@ pub const File = struct { intermediary_basename: ?[]const u8 = null, disable_lld_caching: bool, gc_sections: bool, + print_gc_sections: bool, build_id: std.zig.BuildId, rpath_list: []const []const u8, /// List of symbols forced as undefined in the symbol table @@ -114,8 +115,8 @@ pub const File = struct { disable_lld_caching: bool, hash_style: Elf.HashStyle, sort_section: ?Elf.SortSection, - major_subsystem_version: ?u32, - minor_subsystem_version: ?u32, + major_subsystem_version: ?u16, + minor_subsystem_version: ?u16, gc_sections: ?bool, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, @@ -181,9 +182,15 @@ pub const File = struct { emit: Compilation.Emit, options: OpenOptions, ) !*File { - switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { - inline else => |tag| { - const ptr = try tag.Type().open(arena, comp, emit, options); + const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); + switch (tag) { + .c => { + const ptr = try C.open(arena, comp, emit, options); + return &ptr.base; + }, + inline else => |t| { + if (build_options.only_c) unreachable; + const ptr = try t.Type().open(arena, comp, emit, options); return &ptr.base; }, } @@ -195,9 +202,15 @@ pub const File = struct { emit: Compilation.Emit, options: OpenOptions, ) !*File { - switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { - inline else => |tag| { - const ptr = try tag.Type().createEmpty(arena, comp, emit, options); + const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); + switch (tag) { + .c => { + const ptr = try C.createEmpty(arena, comp, emit, options); + return &ptr.base; + }, + inline else => |t| { + if (build_options.only_c) unreachable; + const ptr = try t.Type().createEmpty(arena, comp, emit, options); return &ptr.base; }, } @@ -360,16 +373,12 @@ pub const File = struct { pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).lowerUnnamedConst(tv, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).lowerUnnamedConst(tv, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerUnnamedConst(tv, decl_index), .spirv => unreachable, - .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).lowerUnnamedConst(tv, decl_index), + .c => unreachable, .nvptx => unreachable, - // zig fmt: on + inline else => |t| { + return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(tv, decl_index); + }, } } @@ -382,16 +391,13 @@ pub const File = struct { if (build_options.only_c) @compileError("unreachable"); log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name }); switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).getGlobalSymbol(name, lib_name), - .elf => return @fieldParentPtr(Elf, "base", base).getGlobalSymbol(name, lib_name), - .macho => return @fieldParentPtr(MachO, "base", base).getGlobalSymbol(name, lib_name), .plan9 => unreachable, .spirv => unreachable, - .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getGlobalSymbol(name, lib_name), + .c => unreachable, .nvptx => unreachable, - // zig fmt: on + inline else => |t| { + return @fieldParentPtr(t.Type(), "base", base).getGlobalSymbol(name, lib_name); + }, } } @@ -399,59 +405,48 @@ pub const File = struct { pub fn updateDecl(base: *File, module: *Module, decl_index: InternPool.DeclIndex) UpdateDeclError!void { const decl = module.declPtr(decl_index); assert(decl.has_tv); - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index); - } switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl_index), - .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl_index), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateDecl(module, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDecl(module, decl_index), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDecl(module, decl_index), - // zig fmt: on + .c => { + return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateDecl(module, decl_index); + }, } } /// May be called before or after updateExports for any given Decl. - pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); - } + pub fn updateFunc( + base: *File, + module: *Module, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, + ) UpdateDeclError!void { switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness), - .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness), - .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness), - .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness), - // zig fmt: on + .c => { + return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateFunc(module, func_index, air, liveness); + }, } } pub fn updateDeclLineNumber(base: *File, module: *Module, decl_index: InternPool.DeclIndex) UpdateDeclError!void { const decl = module.declPtr(decl_index); assert(decl.has_tv); - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl_index), - .c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclLineNumber(module, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDeclLineNumber(module, decl_index), .spirv, .nvptx => {}, + .c => { + return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateDeclLineNumber(module, decl_index); + }, } } @@ -477,44 +472,11 @@ pub const File = struct { base.misc_errors.deinit(gpa); } switch (base.tag) { - .coff => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Coff, "base", base); - parent.deinit(); - }, - .elf => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Elf, "base", base); - parent.deinit(); - }, - .macho => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(MachO, "base", base); - parent.deinit(); - }, - .c => { - const parent = @fieldParentPtr(C, "base", base); - parent.deinit(); - }, - .wasm => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Wasm, "base", base); - parent.deinit(); - }, - .spirv => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(SpirV, "base", base); - parent.deinit(); - }, - .plan9 => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Plan9, "base", base); - parent.deinit(); - }, - .nvptx => { + .c => @fieldParentPtr(C, "base", base).deinit(), + + inline else => |tag| { if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(NvPtx, "base", base); - parent.deinit(); + @fieldParentPtr(tag.Type(), "base", base).deinit(); }, } } @@ -619,51 +581,36 @@ pub const File = struct { return base.linkAsArchive(comp, prog_node); } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).flush(comp, prog_node), - .elf => return @fieldParentPtr(Elf, "base", base).flush(comp, prog_node), - .macho => return @fieldParentPtr(MachO, "base", base).flush(comp, prog_node), - .c => return @fieldParentPtr(C, "base", base).flush(comp, prog_node), - .wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp, prog_node), - .spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp, prog_node), - .plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp, prog_node), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp, prog_node), + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).flush(comp, prog_node); + }, } } /// Commit pending changes and write headers. Works based on `effectiveOutputMode` /// rather than final output mode. pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node), - .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node), - .macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp, prog_node), - .c => return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node), - .wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp, prog_node), - .spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp, prog_node), - .plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp, prog_node), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp, prog_node), + .c => { + return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).flushModule(comp, prog_node); + }, } } /// Called when a Decl is deleted from the Module. pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).freeDecl(decl_index); - } switch (base.tag) { - .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl_index), - .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl_index), - .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl_index), - .c => @fieldParentPtr(C, "base", base).freeDecl(decl_index), - .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl_index), - .spirv => @fieldParentPtr(SpirV, "base", base).freeDecl(decl_index), - .plan9 => @fieldParentPtr(Plan9, "base", base).freeDecl(decl_index), - .nvptx => @fieldParentPtr(NvPtx, "base", base).freeDecl(decl_index), + .c => { + @fieldParentPtr(C, "base", base).freeDecl(decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + @fieldParentPtr(tag.Type(), "base", base).freeDecl(decl_index); + }, } } @@ -682,19 +629,14 @@ pub const File = struct { exported: Module.Exported, exports: []const *Module.Export, ) UpdateExportsError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).updateExports(module, exported, exports), - .elf => return @fieldParentPtr(Elf, "base", base).updateExports(module, exported, exports), - .macho => return @fieldParentPtr(MachO, "base", base).updateExports(module, exported, exports), - .c => return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateExports(module, exported, exports), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateExports(module, exported, exports), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateExports(module, exported, exports), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateExports(module, exported, exports), + .c => { + return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateExports(module, exported, exports); + }, } } @@ -711,60 +653,64 @@ pub const File = struct { /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate /// the block/atom. pub fn getDeclVAddr(base: *File, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) unreachable; + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl_index, reloc_info), - .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl_index, reloc_info), - .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl_index, reloc_info), - .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl_index, reloc_info), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl_index, reloc_info), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).getDeclVAddr(decl_index, reloc_info); + }, } } pub const LowerResult = @import("codegen.zig").Result; - pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !LowerResult { - if (build_options.only_c) unreachable; + pub fn lowerAnonDecl( + base: *File, + decl_val: InternPool.Index, + decl_align: InternPool.Alignment, + src_loc: Module.SrcLoc, + ) !LowerResult { + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).lowerAnonDecl(decl_val, decl_align, src_loc); + }, } } pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) unreachable; + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .elf => return @fieldParentPtr(Elf, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .macho => return @fieldParentPtr(MachO, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .plan9 => return @fieldParentPtr(Plan9, "base", base).getAnonDeclVAddr(decl_val, reloc_info), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getAnonDeclVAddr(decl_val, reloc_info), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).getAnonDeclVAddr(decl_val, reloc_info); + }, } } - pub fn deleteDeclExport(base: *File, decl_index: InternPool.DeclIndex, name: InternPool.NullTerminatedString) !void { - if (build_options.only_c) unreachable; + pub fn deleteDeclExport( + base: *File, + decl_index: InternPool.DeclIndex, + name: InternPool.NullTerminatedString, + ) !void { + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).deleteDeclExport(decl_index, name), - .elf => return @fieldParentPtr(Elf, "base", base).deleteDeclExport(decl_index, name), - .macho => return @fieldParentPtr(MachO, "base", base).deleteDeclExport(decl_index, name), - .plan9 => {}, - .c => {}, - .wasm => return @fieldParentPtr(Wasm, "base", base).deleteDeclExport(decl_index), - .spirv => {}, - .nvptx => {}, + .plan9, + .c, + .spirv, + .nvptx, + => {}, + + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).deleteDeclExport(decl_index, name); + }, } } @@ -1049,7 +995,7 @@ pub const File = struct { base: File, arena: Allocator, opt_loc: ?Compilation.EmitLoc, - ) Allocator.Error!?[*:0]u8 { + ) Allocator.Error!?[*:0]const u8 { const loc = opt_loc orelse return null; const slice = if (loc.directory) |directory| try directory.joinZ(arena, &.{loc.basename}) @@ -1071,7 +1017,7 @@ pub const File = struct { sub_prog_node.context.refresh(); defer sub_prog_node.end(); - try llvm_object.emit(comp, .{ + try llvm_object.emit(.{ .pre_ir_path = comp.verbose_llvm_ir, .pre_bc_path = comp.verbose_llvm_bc, .bin_path = try base.resolveEmitLoc(arena, .{ @@ -1079,8 +1025,8 @@ pub const File = struct { .basename = base.intermediary_basename.?, }), .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm), - .post_llvm_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), - .post_llvm_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), + .post_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), + .post_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), .is_debug = comp.root_mod.optimize_mode == .Debug, .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, diff --git a/src/link/C.zig b/src/link/C.zig index 3592052cf804..669587bda9ec 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -135,6 +135,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = file, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index c02aecf2db36..98c649ca84b1 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -14,9 +14,10 @@ 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, +major_subsystem_version: u16, +minor_subsystem_version: u16, lib_dirs: []const []const u8, +entry_addr: ?u32, ptr_width: PtrWidth, page_size: u32, @@ -238,7 +239,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Coff { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .coff); @@ -390,6 +390,7 @@ pub fn createEmpty( .emit = emit, .stack_size = options.stack_size orelse 16777216, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, .disable_lld_caching = options.disable_lld_caching, @@ -422,6 +423,8 @@ pub fn createEmpty( .major_subsystem_version = options.major_subsystem_version orelse 6, .minor_subsystem_version = options.minor_subsystem_version orelse 0, .lib_dirs = options.lib_dirs, + .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse + return error.EntryAddressTooBig, }; const use_llvm = comp.config.use_llvm; @@ -2329,8 +2332,8 @@ fn writeHeader(self: *Coff) !void { .minor_operating_system_version = 0, .major_image_version = 0, .minor_image_version = 0, - .major_subsystem_version = self.major_subsystem_version, - .minor_subsystem_version = self.minor_subsystem_version, + .major_subsystem_version = @intCast(self.major_subsystem_version), + .minor_subsystem_version = @intCast(self.minor_subsystem_version), .win32_version_value = 0, .size_of_image = size_of_image, .size_of_headers = size_of_headers, @@ -2342,7 +2345,7 @@ fn writeHeader(self: *Coff) !void { .size_of_heap_reserve = default_size_of_heap_reserve, .size_of_heap_commit = default_size_of_heap_commit, .loader_flags = 0, - .number_of_rva_and_sizes = @as(u32, @intCast(self.data_directories.len)), + .number_of_rva_and_sizes = @intCast(self.data_directories.len), }; writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; }, diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index ad9e18fa2262..a94644a41e23 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -21,7 +21,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -30,7 +31,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: { + const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -45,12 +46,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_lib = self.base.comp.config.output_mode == .Lib; - const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; - const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; + const is_lib = comp.config.output_mode == .Lib; + const is_dyn_lib = comp.config.link_mode == .Dynamic and is_lib; + const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe; const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib; - const target = self.base.comp.root_mod.resolved_target.result; - const optimize_mode = self.base.comp.root_mod.optimize_mode; + const target = comp.root_mod.resolved_target.result; + const optimize_mode = comp.root_mod.optimize_mode; // See link/Elf.zig for comments on how this mechanism works. const id_symlink_basename = "lld.id"; @@ -85,8 +86,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man.hash.addListOfBytes(self.lib_dirs); man.hash.add(comp.skip_linker_dependencies); if (comp.config.link_libc) { - man.hash.add(self.base.comp.libc_installation != null); - if (self.base.comp.libc_installation) |libc_installation| { + man.hash.add(comp.libc_installation != null); + if (comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); if (target.abi == .msvc) { man.hash.addBytes(libc_installation.msvc_lib_dir.?); @@ -94,7 +95,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } } - try link.hashAddSystemLibs(&man, self.base.comp.system_libs); + try link.hashAddSystemLibs(&man, comp.system_libs); man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); man.hash.addOptional(self.subsystem); man.hash.add(comp.config.is_test); @@ -136,7 +137,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod }; } - if (self.base.comp.config.output_mode == .Obj) { + if (comp.config.output_mode == .Obj) { // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. @@ -161,7 +162,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } else { // Create an LLD command line and invoke it. - var argv = std.ArrayList([]const u8).init(self.base.allocator); + var argv = std.ArrayList([]const u8).init(gpa); defer argv.deinit(); // We will invoke ourselves as a child process to gain access to LLD. // This is necessary because LLD does not behave properly as a library - @@ -192,7 +193,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), } } - if (self.base.comp.config.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{self.image_base})); @@ -242,7 +243,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } if (comp.config.link_libc) { - if (self.base.comp.libc_installation) |libc_installation| { + if (comp.libc_installation) |libc_installation| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?})); if (target.abi == .msvc) { @@ -287,7 +288,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.subsystem) |explicit| break :blk explicit; switch (target.os.tag) { .windows => { - if (self.base.comp.module) |module| { + if (comp.module) |module| { if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib) break :blk null; if (module.stage1_flags.have_c_main or comp.config.is_test or @@ -415,13 +416,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib")); for (mingw.always_link_libs) |name| { - if (!self.base.comp.system_libs.contains(name)) { + if (!comp.system_libs.contains(name)) { const lib_basename = try allocPrint(arena, "{s}.lib", .{name}); try argv.append(try comp.get_libc_crt_file(arena, lib_basename)); } } } else { - const lib_str = switch (self.base.comp.config.link_mode) { + const lib_str = switch (comp.config.link_mode) { .Dynamic => "", .Static => "lib", }; @@ -429,7 +430,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .Debug => "d", else => "", }; - switch (self.base.comp.config.link_mode) { + switch (comp.config.link_mode) { .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})), .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})), } @@ -448,7 +449,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } else { try argv.append("-NODEFAULTLIB"); if (!is_lib and comp.config.entry == null) { - if (self.base.comp.module) |module| { + if (comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); } else { @@ -485,8 +486,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); } - try argv.ensureUnusedCapacity(self.base.comp.system_libs.count()); - for (self.base.comp.system_libs.keys()) |key| { + try argv.ensureUnusedCapacity(comp.system_libs.count()); + for (comp.system_libs.keys()) |key| { const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); if (comp.crt_files.get(lib_basename)) |crt_file| { argv.appendAssumeCapacity(crt_file.full_object_path); @@ -512,7 +513,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod return error.DllImportLibraryNotFound; } - if (self.base.comp.verbose_link) { + if (comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index faaf5100a4a2..cabaed1addc7 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1745,6 +1745,7 @@ pub fn freeDecl(self: *Dwarf, decl_index: InternPool.DeclIndex) void { } pub fn writeDbgAbbrev(self: *Dwarf) !void { + const gpa = self.allocator; // These are LEB encoded but since the values are all less than 127 // we can simply append these bytes. // zig fmt: off @@ -1887,7 +1888,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { .wasm => { const wasm_file = self.bin_file.cast(File.Wasm).?; const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code; - try debug_abbrev.resize(wasm_file.base.allocator, needed_size); + try debug_abbrev.resize(gpa, needed_size); debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf; }, else => unreachable, @@ -2236,6 +2237,7 @@ fn writeDbgInfoNopsToArrayList( pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { const comp = self.bin_file.comp; + const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; const target_endian = target.cpu.arch.endian(); const ptr_width_bytes = self.ptrWidthBytes(); @@ -2301,7 +2303,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { .wasm => { const wasm_file = self.bin_file.cast(File.Wasm).?; const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code; - try debug_ranges.resize(wasm_file.base.allocator, needed_size); + try debug_ranges.resize(gpa, needed_size); @memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items); }, else => unreachable, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 47b4712b57bf..67478a59e876 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -230,7 +230,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Elf { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .elf); @@ -380,6 +379,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, .file = null, @@ -1175,7 +1175,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node const lib_name = flag["-l".len..]; success: { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lc.crt_dir.?, lib_name, .Dynamic)) break :success; } @@ -1664,7 +1664,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append(p); } } else { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (target.dynamic_linker.get()) |path| { try argv.append("-dynamic-linker"); try argv.append(path); @@ -1742,7 +1742,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("now"); } - if (self.isStatic()) { + if (self.base.isStatic()) { try argv.append("-static"); } else if (self.base.isDynLib()) { try argv.append("-shared"); @@ -2023,7 +2023,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { // TODO I think technically we should re-use the mechanism used by the frontend here. // Maybe we should hoist search-strategy all the way here? for (self.lib_dirs) |lib_dir| { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic)) break :success; } @@ -3598,7 +3598,7 @@ fn initSyntheticSections(self: *Elf) !void { // In this case, if we do generate .interp section and segment, we will get // a segfault in the dynamic linker trying to load a binary that is static // and doesn't contain .dynamic section. - if (self.isStatic() and !comp.config.pie) break :blk false; + if (self.base.isStatic() and !comp.config.pie) break :blk false; break :blk target.dynamic_linker.get() != null; }; if (needs_interp) { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 9f57dab28371..a7b876f619a2 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -377,8 +377,8 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { } pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { - const is_static = elf_file.isStatic(); - const is_dyn_lib = elf_file.isDynLib(); + const is_static = elf_file.base.isStatic(); + const is_dyn_lib = elf_file.base.isDynLib(); const file_ptr = self.file(elf_file).?; const rels = self.relocs(elf_file); var i: usize = 0; @@ -660,7 +660,7 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { fn outputType(elf_file: *Elf) u2 { const comp = elf_file.base.comp; - assert(!elf_file.isRelocatable()); + assert(!elf_file.base.isRelocatable()); return switch (elf_file.base.comp.config.output_mode) { .Obj => unreachable, .Lib => 0, diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 35df214b182b..b6dced258ce0 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -250,7 +250,7 @@ fn addAtom(self: *Object, shdr: ElfShdr, shndx: u16, elf_file: *Elf) error{OutOf fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMemory}!u16 { const name = blk: { const name = self.getString(shdr.sh_name); - if (elf_file.isRelocatable()) break :blk name; + if (elf_file.base.isRelocatable()) break :blk name; if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name; const sh_name_prefixes: []const [:0]const u8 = &.{ ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", @@ -278,7 +278,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem }; const flags = blk: { var flags = shdr.sh_flags; - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); } break :blk switch (@"type") { @@ -520,7 +520,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { } const is_import = blk: { - if (!elf_file.isDynLib()) break :blk false; + if (!elf_file.base.isDynLib()) break :blk false; const vis = @as(elf.STV, @enumFromInt(esym.st_other)); if (vis == .HIDDEN) break :blk false; break :blk true; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index b6be4013ce5f..3a8a77de68cf 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -370,7 +370,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { } const is_import = blk: { - if (!elf_file.isDynLib()) break :blk false; + if (!elf_file.base.isDynLib()) break :blk false; const vis = @as(elf.STV, @enumFromInt(esym.st_other)); if (vis == .HIDDEN) break :blk false; break :blk true; diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index e8500e8aa92b..75401824abe5 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -271,7 +271,7 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { } } - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { offset += 4; // NULL terminator } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 9af563b047c0..35d5c85c2d45 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -155,6 +155,7 @@ frameworks: []const Framework, install_name: ?[]const u8, /// Path to entitlements file. entitlements: ?[]const u8, +compatibility_version: ?std.SemanticVersion, /// When adding a new field, remember to update `hashAddFrameworks`. pub const Framework = struct { @@ -185,7 +186,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*MachO { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -295,6 +295,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -315,6 +316,7 @@ pub fn createEmpty( .frameworks = options.frameworks, .install_name = options.install_name, .entitlements = options.entitlements, + .compatibility_version = options.compatibility_version, }; if (use_llvm and comp.module != null) { @@ -632,7 +634,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No }); { const platform = Platform.fromTarget(target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(self); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else if (platform.isVersionMinCompatible()) { @@ -2237,10 +2239,10 @@ fn allocateGlobal(self: *MachO) !u32 { return index; } -pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.got_table.lookup.contains(target)) return; +pub fn addGotEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.got_table.lookup.contains(reloc_target)) return; const gpa = self.base.comp.gpa; - const got_index = try self.got_table.allocateEntry(gpa, target); + const got_index = try self.got_table.allocateEntry(gpa, reloc_target); if (self.got_section_index == null) { self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{ .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, @@ -2249,20 +2251,22 @@ pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.mode == .incremental) { try self.writeOffsetTableEntry(got_index); self.got_table_count_dirty = true; - self.markRelocsDirtyByTarget(target); + self.markRelocsDirtyByTarget(reloc_target); } } -pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.stub_table.lookup.contains(target)) return; - const gpa = self.base.comp.gpa; - const stub_index = try self.stub_table.allocateEntry(gpa, target); +pub fn addStubEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.stub_table.lookup.contains(reloc_target)) return; + const comp = self.base.comp; + const gpa = comp.gpa; + const cpu_arch = comp.root_mod.resolved_target.result.cpu.arch; + const stub_index = try self.stub_table.allocateEntry(gpa, reloc_target); if (self.stubs_section_index == null) { self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{ .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, - .reserved2 = stubs.stubSize(target.cpu.arch), + .reserved2 = stubs.stubSize(cpu_arch), }); self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ .flags = macho.S_REGULAR | @@ -2276,14 +2280,14 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.mode == .incremental) { try self.writeStubTableEntry(stub_index); self.stub_table_count_dirty = true; - self.markRelocsDirtyByTarget(target); + self.markRelocsDirtyByTarget(reloc_target); } } -pub fn addTlvPtrEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.tlv_ptr_table.lookup.contains(target)) return; +pub fn addTlvPtrEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.tlv_ptr_table.lookup.contains(reloc_target)) return; const gpa = self.base.comp.gpa; - _ = try self.tlv_ptr_table.allocateEntry(gpa, target); + _ = try self.tlv_ptr_table.allocateEntry(gpa, reloc_target); if (self.tlv_ptr_section_index == null) { self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{ .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5185b933860e..ad069b845e4d 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -342,19 +342,22 @@ pub const SplitIntoAtomsError = error{ }; pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) SplitIntoAtomsError!void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; log.debug("splitting object({d}, {s}) into atoms", .{ object_id, self.name }); try self.splitRegularSections(macho_file, object_id); try self.parseEhFrameSection(macho_file, object_id); try self.parseUnwindInfo(macho_file, object_id); - try self.parseDataInCode(macho_file.base.allocator); + try self.parseDataInCode(gpa); } /// Splits input regular sections into Atoms. /// If the Object was compiled with `MH_SUBSECTIONS_VIA_SYMBOLS`, splits section /// into subsections where each subsection then represents an Atom. pub fn splitRegularSections(self: *Object, macho_file: *MachO, object_id: u32) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const sections = self.getSourceSections(); @@ -555,7 +558,8 @@ fn createAtomFromSubsection( alignment: Alignment, out_sect_id: u8, ) !Atom.Index { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const atom_index = try macho_file.createAtom(sym_index, .{ .size = size, .alignment = alignment, @@ -671,7 +675,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void log.debug("parsing __TEXT,__eh_frame section", .{}); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; if (macho_file.eh_frame_section_index == null) { macho_file.eh_frame_section_index = try macho_file.initSection("__TEXT", "__eh_frame", .{}); @@ -767,7 +772,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void } fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const sect_id = self.unwind_info_sect_id orelse { diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index a92126c07ec8..02cf68e46ee8 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -1,7 +1,8 @@ //! An algorithm for dead stripping of unreferenced Atoms. pub fn gcAtoms(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var arena = std.heap.ArenaAllocator.init(gpa); defer arena.deinit(); diff --git a/src/link/MachO/eh_frame.zig b/src/link/MachO/eh_frame.zig index 8223c830e00d..4b51d09683d5 100644 --- a/src/link/MachO/eh_frame.zig +++ b/src/link/MachO/eh_frame.zig @@ -1,5 +1,6 @@ pub fn scanRelocs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; for (macho_file.objects.items, 0..) |*object, object_id| { var cies = std.AutoHashMap(u32, void).init(gpa); @@ -37,7 +38,8 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) error const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var size: u32 = 0; for (macho_file.objects.items, 0..) |*object, object_id| { @@ -89,7 +91,8 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void { const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var eh_records = std.AutoArrayHashMap(u32, EhFrameRecord(true)).init(gpa); defer { diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 8bcf43935442..e155a7a8ed34 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -63,7 +63,7 @@ fn calcLCsSize(m: *MachO, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 { } // LC_RPATH { - var it = RpathIterator.init(gpa, m.rpath_list); + var it = RpathIterator.init(gpa, m.base.rpath_list); defer it.deinit(); while (try it.next()) |rpath| { sizeofcmds += calcInstallNameLen( @@ -189,17 +189,20 @@ fn writeDylibLC(ctx: WriteDylibLCCtx, lc_writer: anytype) !void { } } -pub fn writeDylibIdLC(gpa: Allocator, options: *const link.Options, lc_writer: anytype) !void { - assert(options.output_mode == .Lib and options.link_mode == .Dynamic); - const emit = options.emit.?; - const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path}); - defer if (options.install_name == null) gpa.free(install_name); - const curr = options.version orelse std.SemanticVersion{ +pub fn writeDylibIdLC(macho_file: *MachO, lc_writer: anytype) !void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + assert(comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic); + const emit = macho_file.base.emit; + const install_name = macho_file.install_name orelse + try emit.directory.join(gpa, &.{emit.sub_path}); + defer if (macho_file.install_name == null) gpa.free(install_name); + const curr = comp.version orelse std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0, }; - const compat = options.compatibility_version orelse std.SemanticVersion{ + const compat = macho_file.compatibility_version orelse std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0, @@ -237,8 +240,11 @@ const RpathIterator = struct { } }; -pub fn writeRpathLCs(gpa: Allocator, options: *const link.Options, lc_writer: anytype) !void { - var it = RpathIterator.init(gpa, options.rpath_list); +pub fn writeRpathLCs(macho_file: *MachO, lc_writer: anytype) !void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + + var it = RpathIterator.init(gpa, macho_file.base.rpath_list); defer it.deinit(); while (try it.next()) |rpath| { @@ -467,13 +473,14 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { }; } -pub fn inferSdkVersion(gpa: Allocator, comp: *const Compilation) ?std.SemanticVersion { +pub fn inferSdkVersion(macho_file: *MachO) ?std.SemanticVersion { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const macho_file = comp.bin_file.cast(MachO).?; - const sdk_layout = macho_file.sdk_layout orelse return null; const sdk_dir = switch (sdk_layout) { .sdk => comp.sysroot.?, diff --git a/src/link/MachO/thunks.zig b/src/link/MachO/thunks.zig index 774a8f73449c..f080de7f80df 100644 --- a/src/link/MachO/thunks.zig +++ b/src/link/MachO/thunks.zig @@ -68,7 +68,8 @@ pub fn createThunks(macho_file: *MachO, sect_id: u8) !void { const header = &macho_file.sections.items(.header)[sect_id]; if (header.size == 0) return; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const first_atom_index = macho_file.sections.items(.first_atom_index)[sect_id].?; header.size = 0; @@ -245,7 +246,8 @@ fn scanRelocs( macho_file.getSymbol(target).n_value, }); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target_sym = macho_file.getSymbol(target); const thunk = &macho_file.thunks.items[thunk_index]; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 06fede6e1b3e..f8715aa447dd 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -15,7 +15,7 @@ pub fn linkWithZld( const arena = arena_allocator.allocator(); const directory = emit.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{emit.?.sub_path}); + const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path}); const opt_zcu = macho_file.base.comp.module; // If there is no Zig code to compile, then we should skip flushing the output file because it @@ -71,14 +71,14 @@ pub fn linkWithZld( // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.add(stack_size); - man.hash.addOptional(macho_file.pagezero_vmsize); - man.hash.addOptional(macho_file.headerpad_size); + man.hash.add(macho_file.pagezero_vmsize); + man.hash.add(macho_file.headerpad_size); man.hash.add(macho_file.headerpad_max_install_names); man.hash.add(macho_file.base.gc_sections); man.hash.add(macho_file.dead_strip_dylibs); man.hash.add(macho_file.base.comp.root_mod.strip); try MachO.hashAddFrameworks(&man, macho_file.frameworks); - man.hash.addListOfBytes(macho_file.rpath_list); + man.hash.addListOfBytes(macho_file.base.rpath_list); if (is_dyn_lib) { man.hash.addOptionalBytes(macho_file.install_name); man.hash.addOptional(comp.version); @@ -151,7 +151,7 @@ pub fn linkWithZld( try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); } } else { - const sub_path = emit.?.sub_path; + const sub_path = emit.sub_path; const old_file = macho_file.base.file; // TODO is this needed at all? defer macho_file.base.file = old_file; @@ -241,7 +241,7 @@ pub fn linkWithZld( try argv.append(@tagName(platform.os_tag)); try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(macho_file); if (sdk_version) |ver| { try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); } else { @@ -254,13 +254,13 @@ pub fn linkWithZld( try argv.append(syslibroot); } - for (macho_file.rpath_list) |rpath| { + for (macho_file.base.rpath_list) |rpath| { try argv.append("-rpath"); try argv.append(rpath); } try argv.appendSlice(&.{ - "-pagezero_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.pagezero_size}), + "-pagezero_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.pagezero_vmsize}), "-headerpad_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.headerpad_size}), }); @@ -558,7 +558,7 @@ pub fn linkWithZld( }); { const platform = Platform.fromTarget(target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(macho_file); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else { @@ -609,7 +609,8 @@ pub fn linkWithZld( } fn createSegments(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const page_size = MachO.getPageSize(target.cpu.arch); const aligned_pagezero_vmsize = mem.alignBackward(u64, macho_file.pagezero_vmsize, page_size); @@ -683,7 +684,8 @@ fn createSegments(macho_file: *MachO) !void { } fn writeAtoms(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const slice = macho_file.sections.slice(); for (slice.items(.first_atom_index), 0..) |first_atom_index, sect_id| { @@ -758,7 +760,8 @@ fn writeDyldPrivateAtom(macho_file: *MachO) !void { fn writeThunks(macho_file: *MachO) !void { const target = macho_file.base.comp.root_mod.resolved_target.result; assert(target.cpu.arch == .aarch64); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const sect_id = macho_file.text_section_index orelse return; const header = macho_file.sections.items(.header)[sect_id]; @@ -778,7 +781,8 @@ fn writeThunks(macho_file: *MachO) !void { } fn writePointerEntries(macho_file: *MachO, sect_id: u8, table: anytype) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const header = macho_file.sections.items(.header)[sect_id]; const capacity = math.cast(usize, header.size) orelse return error.Overflow; var buffer = try std.ArrayList(u8).initCapacity(gpa, capacity); @@ -792,7 +796,8 @@ fn writePointerEntries(macho_file: *MachO, sect_id: u8, table: anytype) !void { } fn writeStubs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const stubs_header = macho_file.sections.items(.header)[macho_file.stubs_section_index.?]; @@ -815,7 +820,8 @@ fn writeStubs(macho_file: *MachO) !void { } fn writeStubHelpers(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const stub_helper_header = macho_file.sections.items(.header)[macho_file.stub_helper_section_index.?]; @@ -859,7 +865,8 @@ fn writeStubHelpers(macho_file: *MachO) !void { } fn writeLaSymbolPtrs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const la_symbol_ptr_header = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_section_index.?]; @@ -892,7 +899,8 @@ fn pruneAndSortSections(macho_file: *MachO) !void { } }; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var entries = try std.ArrayList(Entry).initCapacity(gpa, macho_file.sections.slice().len); defer entries.deinit(); diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index b59a527c5a1d..2025372323a7 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -31,8 +31,6 @@ pub fn createEmpty( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*NvPtx { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -55,6 +53,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse false, + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 3fe6aee00959..ceabfe2864f1 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -318,6 +318,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -1314,8 +1315,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Plan9 { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -1525,7 +1524,13 @@ pub fn getDeclVAddr( return undefined; } -pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { +pub fn lowerAnonDecl( + self: *Plan9, + decl_val: InternPool.Index, + explicit_alignment: InternPool.Alignment, + src_loc: Module.SrcLoc, +) !codegen.Result { + _ = explicit_alignment; // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 853d97b0142b..5124ff19f619 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -24,7 +24,6 @@ const SpirV = @This(); const std = @import("std"); const Allocator = std.mem.Allocator; -const ArenaAllocator = std.heap.ArenaAllocator; const assert = std.debug.assert; const log = std.log.scoped(.link); @@ -65,6 +64,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse false, + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -98,8 +98,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*SpirV { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -194,7 +192,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No const spv = &self.object.spv; + const gpa = comp.gpa; const target = comp.getTarget(); + try writeCapabilities(spv, target); try writeMemoryModel(spv, target); @@ -214,11 +214,11 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. // We're using : as separator, which is a reserved character. - const escaped_name = try std.Uri.escapeString(self.base.allocator, name); - defer self.base.allocator.free(escaped_name); + const escaped_name = try std.Uri.escapeString(gpa, name); + defer gpa.free(escaped_name); try error_info.writer().print(":{s}", .{escaped_name}); } - try spv.sections.debug_strings.emit(spv.gpa, .OpSourceExtension, .{ + try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{ .extension = error_info.items, }); @@ -226,6 +226,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No } fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { + const gpa = spv.gpa; // TODO: Integrate with a hypothetical feature system const caps: []const spec.Capability = switch (target.os.tag) { .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .GenericPointer }, @@ -235,13 +236,15 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { }; for (caps) |cap| { - try spv.sections.capabilities.emit(spv.gpa, .OpCapability, .{ + try spv.sections.capabilities.emit(gpa, .OpCapability, .{ .capability = cap, }); } } fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { + const gpa = spv.gpa; + const addressing_model = switch (target.os.tag) { .opencl => switch (target.cpu.arch) { .spirv32 => spec.AddressingModel.Physical32, @@ -260,7 +263,7 @@ fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { }; // TODO: Put this in a proper section. - try spv.sections.extensions.emit(spv.gpa, .OpMemoryModel, .{ + try spv.sections.extensions.emit(gpa, .OpMemoryModel, .{ .addressing_model = addressing_model, .memory_model = memory_model, }); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 874cc2d9b378..7ec950675127 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -378,7 +378,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Wasm { - if (build_options.only_c) unreachable; const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .wasm); @@ -549,6 +548,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -1893,7 +1893,12 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin return target_symbol_index; } -pub fn deleteDeclExport(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { +pub fn deleteDeclExport( + wasm: *Wasm, + decl_index: InternPool.DeclIndex, + name: InternPool.NullTerminatedString, +) void { + _ = name; if (wasm.llvm_object) |_| return; const atom_index = wasm.decls.get(decl_index) orelse return; const sym_index = wasm.getAtom(atom_index).sym_index; diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 610c534c8875..f0c21b8c89c8 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -883,6 +883,8 @@ fn assertEnd(reader: anytype) !void { /// Parses an object file into atoms, for code and data sections pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32, wasm: *Wasm) !Atom.Index { + const comp = wasm.base.comp; + const gpa = comp.gpa; const symbol = &object.symtable[symbol_index]; const relocatable_data: RelocatableData = switch (symbol.tag) { .function => object.relocatable_data.get(.code).?[symbol.index - object.importedCountByKind(.function)], @@ -900,7 +902,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 }; const final_index = try wasm.getMatchingSegment(object_index, symbol_index); const atom_index = @as(Atom.Index, @intCast(wasm.managed_atoms.items.len)); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); + const atom = try wasm.managed_atoms.addOne(gpa); atom.* = Atom.empty; try wasm.appendAtomAtIndex(final_index, atom_index); @@ -910,7 +912,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 atom.alignment = relocatable_data.getAlignment(object); atom.code = std.ArrayListUnmanaged(u8).fromOwnedSlice(relocatable_data.data[0..relocatable_data.size]); atom.original_offset = relocatable_data.offset; - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom_index); + try wasm.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom_index); const segment: *Wasm.Segment = &wasm.segments.items[final_index]; if (relocatable_data.type == .data) { //code section and custom sections are 1-byte aligned segment.alignment = segment.alignment.max(atom.alignment); @@ -927,7 +929,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 .R_WASM_TABLE_INDEX_SLEB, .R_WASM_TABLE_INDEX_SLEB64, => { - try wasm.function_table.put(wasm.base.allocator, .{ + try wasm.function_table.put(gpa, .{ .file = object_index, .index = reloc.index, }, 0); @@ -938,7 +940,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 const sym = object.symtable[reloc.index]; if (sym.tag != .global) { try wasm.got_symbols.append( - wasm.base.allocator, + gpa, .{ .file = object_index, .index = reloc.index }, ); } diff --git a/src/main.zig b/src/main.zig index 26e1d79a7b0f..f412658a6701 100644 --- a/src/main.zig +++ b/src/main.zig @@ -874,8 +874,8 @@ fn buildOutputType( var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; - var major_subsystem_version: ?u32 = null; - var minor_subsystem_version: ?u32 = null; + var major_subsystem_version: ?u16 = null; + var minor_subsystem_version: ?u16 = null; var enable_link_snapshots: bool = false; var debug_incremental: bool = false; var install_name: ?[]const u8 = null; @@ -2321,21 +2321,17 @@ fn buildOutputType( _ = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "--major-subsystem-version")) { const major = linker_args_it.nextOrFatal(); - major_subsystem_version = std.fmt.parseUnsigned( - u32, - major, - 10, - ) catch |err| { - fatal("unable to parse major subsystem version '{s}': {s}", .{ major, @errorName(err) }); + major_subsystem_version = std.fmt.parseUnsigned(u16, major, 10) catch |err| { + fatal("unable to parse major subsystem version '{s}': {s}", .{ + major, @errorName(err), + }); }; } else if (mem.eql(u8, arg, "--minor-subsystem-version")) { const minor = linker_args_it.nextOrFatal(); - minor_subsystem_version = std.fmt.parseUnsigned( - u32, - minor, - 10, - ) catch |err| { - fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) }); + minor_subsystem_version = std.fmt.parseUnsigned(u16, minor, 10) catch |err| { + fatal("unable to parse minor subsystem version '{s}': {s}", .{ + minor, @errorName(err), + }); }; } else if (mem.eql(u8, arg, "-framework")) { try frameworks.put(arena, linker_args_it.nextOrFatal(), .{}); From b6dd5ad3578c69ad4a4b596477ccb86f087a99e6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 00:43:11 -0700 Subject: [PATCH 054/133] MachO: rip out the caching mechanism This is redundant with CacheMode.whole which caches everything, including linking output. Linker code does not need to concern itself with caching like this. --- src/link/MachO.zig | 124 +++++++++------------------------------------ 1 file changed, 24 insertions(+), 100 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 35d5c85c2d45..1706dc55acf8 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -74,12 +74,6 @@ stub_table_count_dirty: bool = false, stub_table_contents_dirty: bool = false, stub_helper_preamble_allocated: bool = false, -/// A helper var to indicate if we are at the start of the incremental updates, or -/// already somewhere further along the update-and-run chain. -/// TODO once we add opening a prelinked output binary from file, this will become -/// obsolete as we will carry on where we left off. -cold_start: bool = true, - /// List of atoms that are either synthetic or map directly to the Zig source program. atoms: std.ArrayListUnmanaged(Atom) = .{}, @@ -404,91 +398,38 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No var libs = std.StringArrayHashMap(link.SystemLib).init(arena); try self.resolveLibSystem(arena, comp, &libs); - const id_symlink_basename = "link.id"; - - const cache_dir_handle = module.zig_cache_artifact_directory.handle; - var man: Cache.Manifest = undefined; - defer man.deinit(); - - var digest: [Cache.hex_digest_len]u8 = undefined; - man = comp.cache_parent.obtain(); - man.want_shared_lock = false; self.base.releaseLock(); - man.hash.addListOfBytes(libs.keys()); - - _ = try man.hit(); - digest = man.final(); - - var prev_digest_buf: [digest.len]u8 = undefined; - const prev_digest: []u8 = Cache.readSmallFile( - cache_dir_handle, - id_symlink_basename, - &prev_digest_buf, - ) catch |err| blk: { - log.debug("MachO Zld new_digest={s} error: {s}", .{ - std.fmt.fmtSliceHexLower(&digest), - @errorName(err), - }); - // Handle this as a cache miss. - break :blk prev_digest_buf[0..0]; - }; - const cache_miss: bool = cache_miss: { - if (mem.eql(u8, prev_digest, &digest)) { - log.debug("MachO Zld digest={s} match", .{ - std.fmt.fmtSliceHexLower(&digest), - }); - if (!self.cold_start) { - log.debug(" skipping parsing linker line objects", .{}); - break :cache_miss false; - } else { - log.debug(" TODO parse prelinked binary and continue linking where we left off", .{}); - } - } - log.debug("MachO Zld prev_digest={s} new_digest={s}", .{ - std.fmt.fmtSliceHexLower(prev_digest), - std.fmt.fmtSliceHexLower(&digest), - }); - // We are about to change the output file to be different, so we invalidate the build hash now. - cache_dir_handle.deleteFile(id_symlink_basename) catch |err| switch (err) { - error.FileNotFound => {}, - else => |e| return e, - }; - break :cache_miss true; - }; - - if (cache_miss) { - for (self.dylibs.items) |*dylib| { - dylib.deinit(gpa); - } - self.dylibs.clearRetainingCapacity(); - self.dylibs_map.clearRetainingCapacity(); - self.referenced_dylibs.clearRetainingCapacity(); - - var dependent_libs = std.fifo.LinearFifo(DylibReExportInfo, .Dynamic).init(arena); + for (self.dylibs.items) |*dylib| { + dylib.deinit(gpa); + } + self.dylibs.clearRetainingCapacity(); + self.dylibs_map.clearRetainingCapacity(); + self.referenced_dylibs.clearRetainingCapacity(); - for (libs.keys(), libs.values()) |path, lib| { - const in_file = try std.fs.cwd().openFile(path, .{}); - defer in_file.close(); + var dependent_libs = std.fifo.LinearFifo(DylibReExportInfo, .Dynamic).init(arena); - var parse_ctx = ParseErrorCtx.init(gpa); - defer parse_ctx.deinit(); + for (libs.keys(), libs.values()) |path, lib| { + const in_file = try std.fs.cwd().openFile(path, .{}); + defer in_file.close(); - self.parseLibrary( - in_file, - path, - lib, - false, - false, - null, - &dependent_libs, - &parse_ctx, - ) catch |err| try self.handleAndReportParseError(path, err, &parse_ctx); - } + var parse_ctx = ParseErrorCtx.init(gpa); + defer parse_ctx.deinit(); - try self.parseDependentLibs(&dependent_libs); + self.parseLibrary( + in_file, + path, + lib, + false, + false, + null, + &dependent_libs, + &parse_ctx, + ) catch |err| try self.handleAndReportParseError(path, err, &parse_ctx); } + try self.parseDependentLibs(&dependent_libs); + try self.resolveSymbols(); if (self.getEntryPoint() == null) { @@ -666,23 +607,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No // Flush debug symbols bundle. try d_sym.flushModule(self); } - - if (cache_miss) { - // Update the file with the digest. If it fails we can continue; it only - // means that the next invocation will have an unnecessary cache miss. - Cache.writeSmallFile(cache_dir_handle, id_symlink_basename, &digest) catch |err| { - log.debug("failed to save linking hash digest file: {s}", .{@errorName(err)}); - }; - // Again failure here only means an unnecessary cache miss. - man.writeManifest() catch |err| { - log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)}); - }; - // We hang on to this lock so that the output file path can be used without - // other processes clobbering it. - self.base.lock = man.toOwnedLock(); - } - - self.cold_start = false; } /// XNU starting with Big Sur running on arm64 is caching inodes of running binaries. From 971593647205da15f4174ddd7e4039b1c2756ccc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 00:52:27 -0700 Subject: [PATCH 055/133] Compilation: oops! used comp before init --- src/Compilation.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 14a39f1bb327..fb6e5a44b0b0 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1184,7 +1184,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { // We put the `Compilation` itself in the arena. Freeing the arena will free the module. // It's initialized later after we prepare the initialization options. - const comp = try arena.create(Compilation); const root_name = try arena.dupeZ(u8, options.root_name); const use_llvm = options.config.use_llvm; @@ -1280,7 +1279,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const sysroot = options.sysroot orelse libc_dirs.sysroot; const include_compiler_rt = options.want_compiler_rt orelse - (!comp.skip_linker_dependencies and is_exe_or_dyn_lib); + (!options.skip_linker_dependencies and is_exe_or_dyn_lib); if (include_compiler_rt and output_mode == .Obj) { // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");` @@ -1357,7 +1356,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.config.link_libcpp); cache.hash.add(options.config.link_libunwind); cache.hash.add(output_mode); - cache_helpers.addDebugFormat(&cache.hash, comp.config.debug_format); + cache_helpers.addDebugFormat(&cache.hash, options.config.debug_format); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs); @@ -1365,6 +1364,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.config.wasi_exec_model); // TODO audit this and make sure everything is in it + const comp = try arena.create(Compilation); const opt_zcu: ?*Module = if (have_zcu) blk: { // Pre-open the directory handles for cached ZIR code so that it does not need // to redundantly happen for each AstGen operation. From d71e6273b6acd766eea6c37b8f53ae03cb2bd9f6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 01:49:06 -0700 Subject: [PATCH 056/133] std.fs.Dir.atomicFile: provide an option for make path It's useful for the API to support creating the parent directory. --- lib/std/fs/Dir.zig | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index b637e664f1ee..4a45975ccc18 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -2416,15 +2416,21 @@ fn copy_file(fd_in: posix.fd_t, fd_out: posix.fd_t, maybe_size: ?u64) CopyFileRa pub const AtomicFileOptions = struct { mode: File.Mode = File.default_mode, + make_path: bool = false, }; -/// Directly access the `.file` field, and then call `AtomicFile.finish` -/// to atomically replace `dest_path` with contents. -/// Always call `AtomicFile.deinit` to clean up, regardless of whether `AtomicFile.finish` succeeded. -/// `dest_path` must remain valid until `AtomicFile.deinit` is called. +/// Directly access the `.file` field, and then call `AtomicFile.finish` to +/// atomically replace `dest_path` with contents. +/// Always call `AtomicFile.deinit` to clean up, regardless of whether +/// `AtomicFile.finish` succeeded. `dest_path` must remain valid until +/// `AtomicFile.deinit` is called. pub fn atomicFile(self: Dir, dest_path: []const u8, options: AtomicFileOptions) !AtomicFile { if (fs.path.dirname(dest_path)) |dirname| { - const dir = try self.openDir(dirname, .{}); + const dir = if (options.make_path) + try self.makeOpenPath(dirname, .{}) + else + try self.openDir(dirname, .{}); + return AtomicFile.init(fs.path.basename(dest_path), options.mode, dir, true); } else { return AtomicFile.init(dest_path, options.mode, self, false); From 0be97b5ae3d32ca9cd7fbb68d5972538b48d8c76 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 01:49:57 -0700 Subject: [PATCH 057/133] fix population of builtin.zig not making the parent dir --- src/Builtin.zig | 2 +- src/Compilation.zig | 9 ++++++++- src/Package.zig | 10 ++++++++++ src/Package/Module.zig | 2 +- src/codegen/llvm.zig | 12 ++++++++++-- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Builtin.zig b/src/Builtin.zig index 4c8038019c10..f80f4663024c 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -276,7 +276,7 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { } fn writeFile(file: *File, mod: *Module) !void { - var af = try mod.root.atomicFile(mod.root_src_path, .{}); + var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }); defer af.deinit(); try af.file.writeAll(file.source); try af.finish(); diff --git a/src/Compilation.zig b/src/Compilation.zig index fb6e5a44b0b0..20e2d1ce5301 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1119,6 +1119,11 @@ fn addModuleTableToCacheHash( var i: usize = 0; while (i < seen_table.count()) : (i += 1) { const mod = seen_table.keys()[i]; + if (mod.isBuiltin()) { + // Skip builtin.zig; it is useless as an input, and we don't want to + // have to write it before checking for a cache hit. + continue; + } cache_helpers.addResolvedTarget(hash, mod.resolved_target); hash.add(mod.optimize_mode); @@ -1133,6 +1138,8 @@ fn addModuleTableToCacheHash( hash.add(mod.red_zone); hash.add(mod.sanitize_c); hash.add(mod.sanitize_thread); + hash.add(mod.unwind_tables); + hash.add(mod.structured_cfg); switch (hash_type) { .path_bytes => { @@ -2371,7 +2378,6 @@ pub const link_hash_implementation_version = 10; fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { const gpa = comp.gpa; - const target = comp.getTarget(); var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); @@ -2432,6 +2438,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.include_compiler_rt); if (comp.config.link_libc) { man.hash.add(comp.libc_installation != null); + const target = comp.root_mod.resolved_target.result; if (comp.libc_installation) |libc_installation| { man.hash.addOptionalBytes(libc_installation.crt_dir); if (target.abi == .msvc) { diff --git a/src/Package.zig b/src/Package.zig index ab06ca985208..373b46e495a7 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -108,6 +108,16 @@ pub const Path = struct { return p.root_dir.handle.access(joined_path, flags); } + pub fn makePath(p: Path, sub_path: []const u8) !void { + var buf: [fs.MAX_PATH_BYTES]u8 = undefined; + const joined_path = if (p.sub_path.len == 0) sub_path else p: { + break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ + p.sub_path, sub_path, + }) catch return error.NameTooLong; + }; + return p.root_dir.handle.makePath(joined_path); + } + pub fn format( self: Path, comptime fmt_string: []const u8, diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 4ce0f0a8569f..2d54c9296cc2 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -40,7 +40,7 @@ builtin_file: ?*File, pub const Deps = std.StringArrayHashMapUnmanaged(*Module); pub fn isBuiltin(m: Module) bool { - return m.file != null; + return m.builtin_file != null; } pub const Tree = struct { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3a53bddcb8a4..91c4faffcc27 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -898,14 +898,22 @@ pub const Object = struct { // very location dependent. // TODO: the only concern I have with this is WASI as either host or target, should // we leave the paths as relative then? + // TODO: This is totally wrong. In dwarf, paths are encoded as relative to + // a particular directory, and then the directory path is specified elsewhere. + // In the compiler frontend we have it stored correctly in this + // way already, but here we throw all that sweet information + // into the garbage can by converting into absolute paths. What + // a terrible tragedy. const compile_unit_dir_z = blk: { if (comp.module) |zcu| m: { const d = try zcu.root_mod.root.joinStringZ(arena, ""); if (d.len == 0) break :m; if (std.fs.path.isAbsolute(d)) break :blk d; - break :blk std.fs.realpathAlloc(arena, d) catch d; + const realpath = std.fs.realpathAlloc(arena, d) catch break :blk d; + break :blk try arena.dupeZ(u8, realpath); } - break :blk try std.process.getCwdAlloc(arena); + const cwd = try std.process.getCwdAlloc(arena); + break :blk try arena.dupeZ(u8, cwd); }; builder.llvm.di_compile_unit = builder.llvm.di_builder.?.createCompileUnit( From e3409c0bce4a0aaa2ec3f536eabf31061919dde4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 13:48:06 -0700 Subject: [PATCH 058/133] Elf: fix createEmpty not creating the file --- src/link/Elf.zig | 157 ++++++++++++++++++++++------------------------- 1 file changed, 75 insertions(+), 82 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 67478a59e876..52e08af6656b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -224,7 +224,7 @@ pub const HashStyle = enum { sysv, gnu, both }; pub const CompressDebugSections = enum { none, zlib, zstd }; pub const SortSection = enum { name, alignment }; -pub fn open( +pub fn createEmpty( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, @@ -238,8 +238,79 @@ pub fn open( const opt_zcu = comp.module; const output_mode = comp.config.output_mode; const link_mode = comp.config.link_mode; + const optimize_mode = comp.root_mod.optimize_mode; + const is_native_os = comp.root_mod.resolved_target.is_native_os; + const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { + 0...32 => .p32, + 33...64 => .p64, + else => return error.UnsupportedELFArchitecture, + }; + + const page_size: u32 = switch (target.cpu.arch) { + .powerpc64le => 0x10000, + .sparc64 => 0x2000, + else => 0x1000, + }; + const is_dyn_lib = output_mode == .Lib and link_mode == .Dynamic; + const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or comp.config.rdynamic) + elf.VER_NDX_GLOBAL + else + elf.VER_NDX_LOCAL; + + const self = try arena.create(Elf); + self.* = .{ + .base = .{ + .tag = .elf, + .comp = comp, + .emit = emit, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, + .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + }, + .ptr_width = ptr_width, + .page_size = page_size, + .default_sym_version = default_sym_version, + + .image_base = b: { + if (is_dyn_lib) break :b 0; + if (output_mode == .Exe and comp.config.pie) break :b 0; + break :b options.image_base orelse switch (ptr_width) { + .p32 => 0x1000, + .p64 => 0x1000000, + }; + }, - const self = try createEmpty(arena, comp, emit, options); + .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, comp); + } errdefer self.base.destroy(); if (use_lld and use_llvm) { @@ -343,91 +414,13 @@ pub fn open( return self; } -pub fn createEmpty( +pub fn open( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Elf { - const use_llvm = comp.config.use_llvm; - const optimize_mode = comp.root_mod.optimize_mode; - const target = comp.root_mod.resolved_target.result; - const output_mode = comp.config.output_mode; - const link_mode = comp.config.link_mode; - const is_native_os = comp.root_mod.resolved_target.is_native_os; - const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { - 0...32 => .p32, - 33...64 => .p64, - else => return error.UnsupportedELFArchitecture, - }; - const self = try arena.create(Elf); - - const page_size: u32 = switch (target.cpu.arch) { - .powerpc64le => 0x10000, - .sparc64 => 0x2000, - else => 0x1000, - }; - const is_dyn_lib = output_mode == .Lib and link_mode == .Dynamic; - const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or comp.config.rdynamic) - elf.VER_NDX_GLOBAL - else - elf.VER_NDX_LOCAL; - - self.* = .{ - .base = .{ - .tag = .elf, - .comp = comp, - .emit = emit, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), - .print_gc_sections = options.print_gc_sections, - .stack_size = options.stack_size orelse 16777216, - .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, - .file = null, - .disable_lld_caching = options.disable_lld_caching, - .build_id = options.build_id, - .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, - }, - .ptr_width = ptr_width, - .page_size = page_size, - .default_sym_version = default_sym_version, - - .image_base = b: { - if (is_dyn_lib) break :b 0; - if (output_mode == .Exe and comp.config.pie) break :b 0; - break :b options.image_base orelse switch (ptr_width) { - .p32 => 0x1000, - .p64 => 0x1000000, - }; - }, - - .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, comp); - } - - return self; + return createEmpty(arena, comp, emit, options); } pub fn deinit(self: *Elf) void { From b1fc3fe1c42d50a40eee985f059a4f43a5f1ce1a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 13:48:43 -0700 Subject: [PATCH 059/133] Elf: fix invalid free of path field It's now arena-allocated so no need to free it with gpa --- src/link/Elf/ZigObject.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 3a8a77de68cf..a29c3ab69c48 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -4,6 +4,7 @@ //! Think about this as fake in-memory Object file for the Zig module. data: std.ArrayListUnmanaged(u8) = .{}, +/// Externally owned memory. path: []const u8, index: File.Index, @@ -109,7 +110,6 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void { pub fn deinit(self: *ZigObject, allocator: Allocator) void { self.data.deinit(allocator); - allocator.free(self.path); self.local_esyms.deinit(allocator); self.global_esyms.deinit(allocator); self.strtab.deinit(allocator); From 57afdfc8fae667e69850650ebb8606805d0d2272 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 13:49:03 -0700 Subject: [PATCH 060/133] compilation: fix build artifact communication from sub-compilation in whole cache mode, build artifacts are communicated by accessing the whole cache information, for which there is a helper method called toCrtFile --- src/Compilation.zig | 12 +----------- src/musl.zig | 7 +------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 20e2d1ce5301..7f3d696ecbe2 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2336,11 +2336,6 @@ fn wholeCacheModeSetBinFilePath( if (whole.bin_sub_path) |sub_path| { @memcpy(sub_path[digest_start..][0..digest.len], digest); - - comp.bin_file.?.emit = .{ - .directory = comp.local_cache_directory, - .sub_path = sub_path, - }; } if (whole.implib_sub_path) |sub_path| { @@ -6243,12 +6238,7 @@ fn buildOutputFromZig( try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); assert(out.* == null); - out.* = .{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(gpa, &.{ - sub_compilation.bin_file.?.emit.sub_path, - }), - .lock = sub_compilation.bin_file.?.toOwnedLock(), - }; + out.* = try sub_compilation.toCrtFile(); } pub fn build_crt_file( diff --git a/src/musl.zig b/src/musl.zig index 2ba9e4485c48..ce5c5b23ddff 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -276,12 +276,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr const basename = try comp.gpa.dupe(u8, "libc.so"); errdefer comp.gpa.free(basename); - comp.crt_files.putAssumeCapacityNoClobber(basename, .{ - .full_object_path = try sub_compilation.bin_file.?.emit.directory.join(comp.gpa, &.{ - sub_compilation.bin_file.?.emit.sub_path, - }), - .lock = sub_compilation.bin_file.?.toOwnedLock(), - }); + comp.crt_files.putAssumeCapacityNoClobber(basename, try sub_compilation.toCrtFile()); }, } } From f2564318385ea90b08af044ae32ddef26e6346bd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 15:22:31 -0700 Subject: [PATCH 061/133] fix compilation errors when enabling llvm --- src/Compilation.zig | 57 +++++++++---- src/Module.zig | 2 +- src/Package/Module.zig | 76 +++++++++-------- src/Sema.zig | 37 +++++++-- src/glibc.zig | 23 ++++-- src/libcxx.zig | 182 +++++++++++++++++++++-------------------- src/libtsan.zig | 102 ++++++++++++----------- src/libunwind.zig | 10 ++- src/link/Coff.zig | 4 + src/link/Coff/lld.zig | 23 ++---- src/link/Elf.zig | 20 +++-- src/main.zig | 2 +- src/mingw.zig | 21 ++++- src/musl.zig | 39 ++++++--- src/wasi_libc.zig | 20 ++++- 15 files changed, 363 insertions(+), 255 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 7f3d696ecbe2..7314da3960db 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1410,7 +1410,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .inherited = .{}, .global = options.config, .parent = options.root_mod, - .builtin_mod = options.root_mod.deps.get("builtin").?, + .builtin_mod = options.root_mod.getBuiltinDependency(), }); const zcu = try arena.create(Module); @@ -3830,6 +3830,7 @@ pub fn obtainCObjectCacheManifest( // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. man.hash.add(owner_mod.sanitize_c); + man.hash.add(owner_mod.sanitize_thread); man.hash.addListOfBytes(owner_mod.cc_argv); man.hash.add(comp.config.link_libcpp); @@ -3970,10 +3971,13 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module const dep_basename = std.fs.path.basename(out_dep_path); try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); - if (comp.whole_cache_manifest) |whole_cache_manifest| { - comp.whole_cache_manifest_mutex.lock(); - defer comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + }, + .incremental => {}, } const digest = man.final(); @@ -4425,10 +4429,15 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P const dep_basename = std.fs.path.basename(dep_file_path); // Add the files depended on to the cache system. try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); - if (comp.whole_cache_manifest) |whole_cache_manifest| { - comp.whole_cache_manifest_mutex.lock(); - defer comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + switch (comp.cache_use) { + .whole => |whole| { + if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + } + }, + .incremental => {}, } // Just to save disk space, we delete the file because it is never needed again. zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { @@ -4724,10 +4733,13 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const dep_basename = std.fs.path.basename(out_dep_path); // Add the files depended on to the cache system. try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); - if (comp.whole_cache_manifest) |whole_cache_manifest| { - comp.whole_cache_manifest_mutex.lock(); - defer comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); + }, + .incremental => {}, } // Just to save disk space, we delete the file because it is never needed again. zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { @@ -4799,10 +4811,13 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 for (dependencies_list.items) |dep_file_path| { try man.addFilePost(dep_file_path); - if (comp.whole_cache_manifest) |whole_cache_manifest| { - comp.whole_cache_manifest_mutex.lock(); - defer comp.whole_cache_manifest_mutex.unlock(); - try whole_cache_manifest.addFilePost(dep_file_path); + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addFilePost(dep_file_path); + }, + .incremental => {}, } } @@ -6247,7 +6262,9 @@ pub fn build_crt_file( output_mode: std.builtin.OutputMode, misc_task_tag: MiscTask, prog_node: *std.Progress.Node, - c_source_files: []const CSourceFile, + /// These elements have to get mutated to add the owner module after it is + /// created within this function. + c_source_files: []CSourceFile, ) !void { const tracy_trace = trace(@src()); defer tracy_trace.end(); @@ -6305,6 +6322,10 @@ pub fn build_crt_file( .builtin_mod = null, }); + for (c_source_files) |*item| { + item.owner = root_mod; + } + const sub_compilation = try Compilation.create(gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, diff --git a/src/Module.zig b/src/Module.zig index 6d5a2f78a6a0..f2049df378a5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5275,7 +5275,7 @@ pub fn populateTestFunctions( ) !void { const gpa = mod.gpa; const ip = &mod.intern_pool; - const builtin_mod = mod.main_mod.deps.get("builtin").?; + const builtin_mod = mod.main_mod.getBuiltinDependency(); const builtin_file = (mod.importPkg(builtin_mod) catch unreachable).file; const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); const builtin_namespace = mod.namespacePtr(root_decl.src_namespace); diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 2d54c9296cc2..0ebd951cc66d 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -310,7 +310,39 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { break :b buf.items[0 .. buf.items.len - 1 :0].ptr; }; - const builtin_mod = options.builtin_mod orelse b: { + const mod = try arena.create(Module); + mod.* = .{ + .root = options.paths.root, + .root_src_path = options.paths.root_src_path, + .fully_qualified_name = options.fully_qualified_name, + .resolved_target = .{ + .result = target, + .is_native_os = resolved_target.is_native_os, + .is_native_abi = resolved_target.is_native_abi, + .llvm_cpu_features = llvm_cpu_features, + }, + .optimize_mode = optimize_mode, + .single_threaded = single_threaded, + .error_tracing = error_tracing, + .valgrind = valgrind, + .pic = pic, + .strip = strip, + .omit_frame_pointer = omit_frame_pointer, + .stack_check = stack_check, + .stack_protector = stack_protector, + .code_model = code_model, + .red_zone = red_zone, + .sanitize_c = sanitize_c, + .sanitize_thread = sanitize_thread, + .unwind_tables = unwind_tables, + .cc_argv = options.cc_argv, + .structured_cfg = structured_cfg, + .builtin_file = null, + }; + + const opt_builtin_mod = options.builtin_mod orelse b: { + if (!options.global.have_zcu) break :b null; + const generated_builtin_source = try Builtin.generate(.{ .target = target, .zig_backend = zig_backend, @@ -388,38 +420,10 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { break :b new; }; - const mod = try arena.create(Module); - mod.* = .{ - .root = options.paths.root, - .root_src_path = options.paths.root_src_path, - .fully_qualified_name = options.fully_qualified_name, - .resolved_target = .{ - .result = target, - .is_native_os = resolved_target.is_native_os, - .is_native_abi = resolved_target.is_native_abi, - .llvm_cpu_features = llvm_cpu_features, - }, - .optimize_mode = optimize_mode, - .single_threaded = single_threaded, - .error_tracing = error_tracing, - .valgrind = valgrind, - .pic = pic, - .strip = strip, - .omit_frame_pointer = omit_frame_pointer, - .stack_check = stack_check, - .stack_protector = stack_protector, - .code_model = code_model, - .red_zone = red_zone, - .sanitize_c = sanitize_c, - .sanitize_thread = sanitize_thread, - .unwind_tables = unwind_tables, - .cc_argv = options.cc_argv, - .structured_cfg = structured_cfg, - .builtin_file = null, - }; - - try mod.deps.ensureUnusedCapacity(arena, 1); - mod.deps.putAssumeCapacityNoClobber("builtin", builtin_mod); + if (opt_builtin_mod) |builtin_mod| { + try mod.deps.ensureUnusedCapacity(arena, 1); + mod.deps.putAssumeCapacityNoClobber("builtin", builtin_mod); + } return mod; } @@ -462,8 +466,10 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P return mod; } -pub fn getBuiltinDependency(m: *Module) *Module { - return m.deps.values()[0]; +pub fn getBuiltinDependency(m: Module) *Module { + const result = m.deps.values()[0]; + assert(result.isBuiltin()); + return result; } const Module = @This(); diff --git a/src/Sema.zig b/src/Sema.zig index 26afd285c7e9..c2e05e4a2c0d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5759,14 +5759,39 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr }; return sema.failWithOwnedErrorMsg(&child_block, msg); } - const c_import_mod = try Package.Module.create(comp.arena.allocator(), .{ - .root = .{ - .root_dir = Compilation.Directory.cwd(), - .sub_path = std.fs.path.dirname(c_import_res.out_zig_path) orelse "", + const parent_mod = parent_block.ownerModule(); + const c_import_mod = Package.Module.create(comp.arena.allocator(), .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ + .root_dir = Compilation.Directory.cwd(), + .sub_path = std.fs.path.dirname(c_import_res.out_zig_path) orelse "", + }, + .root_src_path = std.fs.path.basename(c_import_res.out_zig_path), }, - .root_src_path = std.fs.path.basename(c_import_res.out_zig_path), .fully_qualified_name = c_import_res.out_zig_path, - }); + .cc_argv = parent_mod.cc_argv, + .inherited = .{}, + .global = comp.config, + .parent = parent_mod, + .builtin_mod = parent_mod.getBuiltinDependency(), + }) catch |err| switch (err) { + // None of these are possible because we are creating a package with + // the exact same configuration as the parent package, which already + // passed these checks. + error.ValgrindUnsupportedOnTarget => unreachable, + error.TargetRequiresSingleThreaded => unreachable, + error.BackendRequiresSingleThreaded => unreachable, + error.TargetRequiresPic => unreachable, + error.PieRequiresPic => unreachable, + error.DynamicLinkingRequiresPic => unreachable, + error.TargetHasNoRedZone => unreachable, + error.StackCheckUnsupportedByTarget => unreachable, + error.StackProtectorUnsupportedByTarget => unreachable, + error.StackProtectorUnavailableWithoutLibC => unreachable, + + else => |e| return e, + }; const result = mod.importPkg(c_import_mod) catch |err| return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); diff --git a/src/glibc.zig b/src/glibc.zig index 0502bc3799f2..d478c6e939a7 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -170,7 +170,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const target = comp.getTarget(); + const target = comp.root_mod.resolved_target.result; const target_ver = target.os.version_range.linux.glibc; const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt; @@ -196,12 +196,14 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-DASSEMBLER", "-Wa,--noexecstack", }); - return comp.build_crt_file("crti", .Obj, .@"glibc crti.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try start_asm_path(comp, arena, "crti.S"), .cache_exempt_flags = args.items, + .owner = comp.root_mod, }, - }); + }; + return comp.build_crt_file("crti", .Obj, .@"glibc crti.o", prog_node, &files); }, .crtn_o => { var args = std.ArrayList([]const u8).init(arena); @@ -215,12 +217,14 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-DASSEMBLER", "-Wa,--noexecstack", }); - return comp.build_crt_file("crtn", .Obj, .@"glibc crtn.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try start_asm_path(comp, arena, "crtn.S"), .cache_exempt_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crtn", .Obj, .@"glibc crtn.o", prog_node, &files); }, .scrt1_o => { const start_o: Compilation.CSourceFile = blk: { @@ -244,6 +248,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr break :blk .{ .src_path = try start_asm_path(comp, arena, src_path), .cache_exempt_flags = args.items, + .owner = undefined, }; }; const abi_note_o: Compilation.CSourceFile = blk: { @@ -263,11 +268,11 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr break :blk .{ .src_path = try lib_path(comp, arena, lib_libc_glibc ++ "csu" ++ path.sep_str ++ "abi-note.S"), .cache_exempt_flags = args.items, + .owner = undefined, }; }; - return comp.build_crt_file("Scrt1", .Obj, .@"glibc Scrt1.o", prog_node, &.{ - start_o, abi_note_o, - }); + var files = [_]Compilation.CSourceFile{ start_o, abi_note_o }; + return comp.build_crt_file("Scrt1", .Obj, .@"glibc Scrt1.o", prog_node, &files); }, .libc_nonshared_a => { const s = path.sep_str; @@ -364,6 +369,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr files_buf[files_index] = .{ .src_path = try lib_path(comp, arena, dep.path), .cache_exempt_flags = args.items, + .owner = undefined, }; files_index += 1; } @@ -1065,6 +1071,7 @@ fn buildSharedLib( const c_source_files = [1]Compilation.CSourceFile{ .{ .src_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, asm_file_basename }), + .owner = undefined, }, }; diff --git a/src/libcxx.zig b/src/libcxx.zig index aedb1f3930af..abcbc0187ec2 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -138,6 +138,50 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { const abi_namespace_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{ @intFromEnum(comp.libcxx_abi_version), }); + + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + .lto = comp.config.lto, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .strip = strip, + .stack_check = false, + .stack_protector = 0, + .sanitize_c = false, + .sanitize_thread = comp.config.any_sanitize_thread, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .pic = comp.root_mod.pic, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxx_files.len); for (libcxx_files) |cxx_src| { @@ -224,52 +268,10 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", cxx_src }), .extra_flags = cflags.items, .cache_exempt_flags = cache_exempt_flags.items, + .owner = root_mod, }); } - const optimize_mode = comp.compilerRtOptMode(); - const strip = comp.compilerRtStrip(); - - const config = try Compilation.Config.resolve(.{ - .output_mode = output_mode, - .link_mode = link_mode, - .resolved_target = comp.root_mod.resolved_target, - .is_test = false, - .have_zcu = false, - .emit_bin = true, - .root_optimize_mode = optimize_mode, - .root_strip = strip, - .link_libc = true, - .lto = comp.config.lto, - }); - - const root_mod = try Module.create(arena, .{ - .global_cache_directory = comp.global_cache_directory, - .paths = .{ - .root = .{ .root_dir = comp.zig_lib_directory }, - .root_src_path = "", - }, - .fully_qualified_name = "root", - .inherited = .{ - .resolved_target = comp.root_mod.resolved_target, - .strip = strip, - .stack_check = false, - .stack_protector = 0, - .sanitize_c = false, - .sanitize_thread = comp.config.any_sanitize_thread, - .red_zone = comp.root_mod.red_zone, - .omit_frame_pointer = comp.root_mod.omit_frame_pointer, - .valgrind = false, - .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, - .pic = comp.root_mod.pic, - }, - .global = config, - .cc_argv = &.{}, - .parent = null, - .builtin_mod = null, - }); - const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, @@ -339,6 +341,53 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { const abi_namespace_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{ @intFromEnum(comp.libcxx_abi_version), }); + + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + const unwind_tables = true; + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + .any_unwind_tables = unwind_tables, + .lto = comp.config.lto, + }); + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .strip = strip, + .stack_check = false, + .stack_protector = 0, + .sanitize_c = false, + .sanitize_thread = comp.config.any_sanitize_thread, + .red_zone = comp.root_mod.red_zone, + .omit_frame_pointer = comp.root_mod.omit_frame_pointer, + .valgrind = false, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .unwind_tables = unwind_tables, + .pic = comp.root_mod.pic, + }, + .global = config, + .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, + }); + var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len); for (libcxxabi_files) |cxxabi_src| { @@ -406,55 +455,10 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }), .extra_flags = cflags.items, .cache_exempt_flags = cache_exempt_flags.items, + .owner = root_mod, }); } - const optimize_mode = comp.compilerRtOptMode(); - const strip = comp.compilerRtStrip(); - const unwind_tables = true; - - const config = try Compilation.Config.resolve(.{ - .output_mode = output_mode, - .link_mode = link_mode, - .resolved_target = comp.root_mod.resolved_target, - .is_test = false, - .have_zcu = false, - .emit_bin = true, - .root_optimize_mode = optimize_mode, - .root_strip = strip, - .link_libc = true, - .any_unwind_tables = unwind_tables, - .lto = comp.config.lto, - }); - - const root_mod = try Module.create(arena, .{ - .global_cache_directory = comp.global_cache_directory, - .paths = .{ - .root = .{ .root_dir = comp.zig_lib_directory }, - .root_src_path = "", - }, - .fully_qualified_name = "root", - .inherited = .{ - .resolved_target = comp.root_mod.resolved_target, - .strip = strip, - .stack_check = false, - .stack_protector = 0, - .sanitize_c = false, - .sanitize_thread = comp.config.any_sanitize_thread, - .red_zone = comp.root_mod.red_zone, - .omit_frame_pointer = comp.root_mod.omit_frame_pointer, - .valgrind = false, - .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, - .unwind_tables = unwind_tables, - .pic = comp.root_mod.pic, - }, - .global = config, - .cc_argv = &.{}, - .parent = null, - .builtin_mod = null, - }); - const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, diff --git a/src/libtsan.zig b/src/libtsan.zig index 553597e48515..a736c3271315 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -34,6 +34,52 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { .basename = basename, }; + const optimize_mode = comp.compilerRtOptMode(); + const strip = comp.compilerRtStrip(); + + const config = try Compilation.Config.resolve(.{ + .output_mode = output_mode, + .link_mode = link_mode, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = false, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = true, + }); + + const common_flags = [_][]const u8{ + "-DTSAN_CONTAINS_UBSAN=0", + }; + + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, + .paths = .{ + .root = .{ .root_dir = comp.zig_lib_directory }, + .root_src_path = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .strip = strip, + .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, + .optimize_mode = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + .pic = true, + }, + .global = config, + .cc_argv = &common_flags, + .parent = null, + .builtin_mod = null, + }); + var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena); try c_source_files.ensureUnusedCapacity(tsan_sources.len); @@ -50,8 +96,9 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { try cflags.append("-fno-rtti"); c_source_files.appendAssumeCapacity(.{ - .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "tsan", tsan_src }), + .src_path = try comp.zig_lib_directory.join(arena, &.{ "tsan", tsan_src }), .extra_flags = cflags.items, + .owner = root_mod, }); } @@ -74,6 +121,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { c_source_files.appendAssumeCapacity(.{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "tsan", tsan_src }), .extra_flags = cflags.items, + .owner = root_mod, }); } { @@ -94,6 +142,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { c_source_files.appendAssumeCapacity(.{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "tsan", asm_source }), .extra_flags = cflags.items, + .owner = root_mod, }); } @@ -117,6 +166,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "tsan", "sanitizer_common", common_src, }), .extra_flags = cflags.items, + .owner = root_mod, }); } @@ -141,6 +191,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "tsan", "sanitizer_common", c_src, }), .extra_flags = cflags.items, + .owner = root_mod, }); } @@ -161,6 +212,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "tsan", "sanitizer_common", c_src, }), .extra_flags = cflags.items, + .owner = root_mod, }); } @@ -189,56 +241,10 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "tsan", "interception", c_src, }), .extra_flags = cflags.items, + .owner = root_mod, }); } - const common_flags = [_][]const u8{ - "-DTSAN_CONTAINS_UBSAN=0", - }; - - const optimize_mode = comp.compilerRtOptMode(); - const strip = comp.compilerRtStrip(); - - const config = try Compilation.Config.resolve(.{ - .output_mode = output_mode, - .link_mode = link_mode, - .resolved_target = comp.root_mod.resolved_target, - .is_test = false, - .have_zcu = false, - .emit_bin = true, - .root_optimize_mode = optimize_mode, - .root_strip = strip, - .link_libc = true, - }); - - const root_mod = try Module.create(arena, .{ - .global_cache_directory = comp.global_cache_directory, - .paths = .{ - .root = .{ .root_dir = comp.zig_lib_directory }, - .root_src_path = "", - }, - .fully_qualified_name = "root", - .inherited = .{ - .resolved_target = comp.root_mod.resolved_target, - .strip = strip, - .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, - .optimize_mode = optimize_mode, - .structured_cfg = comp.root_mod.structured_cfg, - .pic = true, - .cc_argv = &common_flags, - }, - .global = config, - .cc_argv = &.{}, - .parent = null, - .builtin_mod = null, - }); - const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, diff --git a/src/libunwind.zig b/src/libunwind.zig index c59b5255d209..0f23f8b352a7 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -33,7 +33,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 .lto = false, }); - const root_mod = Module.create(.{ + const root_mod = try Module.create(arena, .{ + .global_cache_directory = comp.global_cache_directory, .paths = .{ .root = .{ .root_dir = comp.zig_lib_directory }, .root_src_path = "", @@ -55,6 +56,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { }, .global = config, .cc_argv = &.{}, + .parent = null, + .builtin_mod = null, }); const root_name = "unwind"; @@ -117,6 +120,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { c_source_files[i] = .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{unwind_src}), .extra_flags = cflags.items, + .owner = root_mod, }; } const sub_compilation = try Compilation.create(comp.gpa, .{ @@ -132,7 +136,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.libc_installation, .emit_bin = emit_bin, - .link_mode = link_mode, .function_sections = comp.function_sections, .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, @@ -150,8 +153,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { try comp.updateSubCompilation(sub_compilation, .libunwind, prog_node); assert(comp.libunwind_static_lib == null); - - comp.libunwind_static_lib = try sub_compilation.toOwnedLock(); + comp.libunwind_static_lib = try sub_compilation.toCrtFile(); } const unwind_src_list = [_][]const u8{ diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 98c649ca84b1..b6a3979122da 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -18,6 +18,8 @@ major_subsystem_version: u16, minor_subsystem_version: u16, lib_dirs: []const []const u8, entry_addr: ?u32, +module_definition_file: ?[]const u8, +pdb_out_path: ?[]const u8, ptr_width: PtrWidth, page_size: u32, @@ -425,6 +427,8 @@ pub fn createEmpty( .lib_dirs = options.lib_dirs, .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse return error.EntryAddressTooBig, + .module_definition_file = options.module_definition_file, + .pdb_out_path = options.pdb_out_path, }; const use_llvm = comp.config.use_llvm; diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index a94644a41e23..39e6d5288d8f 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -82,7 +82,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try man.addOptionalFile(module_obj_path); man.hash.addOptionalBytes(comp.config.entry); man.hash.add(self.base.stack_size); - man.hash.addOptional(self.image_base); + man.hash.add(self.image_base); man.hash.addListOfBytes(self.lib_dirs); man.hash.add(comp.skip_linker_dependencies); if (comp.config.link_libc) { @@ -102,10 +102,10 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man.hash.add(self.tsaware); man.hash.add(self.nxcompat); man.hash.add(self.dynamicbase); - man.hash.addOptional(self.base.allow_shlib_undefined); + man.hash.add(self.base.allow_shlib_undefined); // strip does not need to go into the linker hash because it is part of the hash namespace - man.hash.addOptional(self.major_subsystem_version); - man.hash.addOptional(self.minor_subsystem_version); + man.hash.add(self.major_subsystem_version); + man.hash.add(self.minor_subsystem_version); man.hash.addOptional(comp.version); try man.addOptionalFile(self.module_definition_file); @@ -237,7 +237,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); - if (self.implib_emit) |emit| { + if (comp.implib_emit) |emit| { const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path}); try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path})); } @@ -310,16 +310,9 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const Mode = enum { uefi, win32 }; const mode: Mode = mode: { if (resolved_subsystem) |subsystem| { - const subsystem_suffix = ss: { - if (self.major_subsystem_version) |major| { - if (self.minor_subsystem_version) |minor| { - break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); - } else { - break :ss try allocPrint(arena, ",{d}", .{major}); - } - } - break :ss ""; - }; + const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{ + self.major_subsystem_version, self.minor_subsystem_version, + }); switch (subsystem) { .Console => { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 52e08af6656b..e5e5c98ec0e1 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -23,6 +23,8 @@ soname: ?[]const u8, bind_global_refs_locally: bool, linker_script: ?[]const u8, version_script: ?[]const u8, +print_icf_sections: bool, +print_map: bool, ptr_width: PtrWidth, @@ -307,6 +309,8 @@ pub fn createEmpty( .bind_global_refs_locally = options.bind_global_refs_locally, .linker_script = options.linker_script, .version_script = options.version_script, + .print_icf_sections = options.print_icf_sections, + .print_map = options.print_map, }; if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, comp); @@ -1294,12 +1298,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Look for entry address in objects if not set by the incremental compiler. if (self.entry_index == null) { - const entry: ?[]const u8 = entry: { - if (comp.config.entry) |entry| break :entry entry; - if (!self.base.isDynLib()) break :entry "_start"; - break :entry null; - }; - self.entry_index = if (entry) |name| self.globalByName(name) else null; + if (comp.config.entry) |name| { + self.entry_index = self.globalByName(name); + } } if (self.base.gc_sections) { @@ -2420,7 +2421,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.addOptionalBytes(comp.config.entry); - man.hash.addOptional(self.image_base); + man.hash.add(self.image_base); man.hash.add(self.base.gc_sections); man.hash.addOptional(self.sort_section); man.hash.add(self.eh_frame_hdr); @@ -5896,7 +5897,7 @@ pub fn addSymbol(self: *Elf) !Symbol.Index { break :blk index; } else { log.debug(" (allocating symbol index {d})", .{self.symbols.items.len}); - const index = @as(Symbol.Index, @intCast(self.symbols.items.len)); + const index: Symbol.Index = @intCast(self.symbols.items.len); _ = self.symbols.addOneAssumeCapacity(); break :blk index; } @@ -5961,6 +5962,7 @@ pub fn getOrPutGlobal(self: *Elf, name: []const u8) !GetOrPutGlobalResult { const gop = try self.resolver.getOrPut(gpa, name_off); if (!gop.found_existing) { const index = try self.addSymbol(); + log.debug("added symbol '{s}' at index {d}", .{ name, index }); const global = self.symbol(index); global.name_offset = name_off; global.flags.global = true; @@ -5996,7 +5998,7 @@ pub fn getOrCreateComdatGroupOwner(self: *Elf, name: [:0]const u8) !GetOrCreateC const off = try self.strings.insert(gpa, name); const gop = try self.comdat_groups_table.getOrPut(gpa, off); if (!gop.found_existing) { - const index = @as(ComdatGroupOwner.Index, @intCast(self.comdat_groups_owners.items.len)); + const index: ComdatGroupOwner.Index = @intCast(self.comdat_groups_owners.items.len); const owner = try self.comdat_groups_owners.addOne(gpa); owner.* = .{}; gop.value_ptr.* = index; diff --git a/src/main.zig b/src/main.zig index f412658a6701..a65c8959b328 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3481,7 +3481,7 @@ fn buildOutputType( defer if (!comp_destroyed) comp.destroy(); if (show_builtin) { - const builtin_mod = comp.root_mod.deps.get("builtin").?; + const builtin_mod = comp.root_mod.getBuiltinDependency(); const source = builtin_mod.builtin_file.?.source; return std.io.getStdOut().writeAll(source); } diff --git a/src/mingw.zig b/src/mingw.zig index 5a36e0082401..fb8972df21c9 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -41,14 +41,16 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr //"-D_UNICODE", //"-DWPRFLAG=1", }); - return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "crt", "crtexe.c", }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files); }, .dllcrt2_o => { @@ -60,14 +62,16 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-U__CRTDLL__", "-D__MSVCRT__", }); - return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "crt", "crtdll.c", }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files); }, .mingw32_lib => { @@ -97,6 +101,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", "crt", dep, }), .extra_flags = args.items, + .owner = undefined, }; } return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, &c_source_files); @@ -125,6 +130,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr (try c_source_files.addOne()).* = .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", dep }), .extra_flags = extra_flags, + .owner = undefined, }; } if (comp.getTarget().cpu.arch == .x86) { @@ -134,6 +140,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } } else { @@ -143,6 +150,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } } @@ -175,6 +183,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } const target = comp.getTarget(); @@ -185,6 +194,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } } else if (target.cpu.arch.isARM()) { @@ -194,6 +204,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } } else if (target.cpu.arch.isAARCH64()) { @@ -203,6 +214,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } } else { @@ -238,6 +250,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", "mingw", "libsrc", dep, }), .extra_flags = extra_flags, + .owner = undefined, }; } return comp.build_crt_file("uuid", .Lib, .@"mingw-w64 uuid.lib", prog_node, &c_source_files); diff --git a/src/musl.zig b/src/musl.zig index ce5c5b23ddff..4a62d5ededd7 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -34,12 +34,14 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr try args.appendSlice(&[_][]const u8{ "-Qunused-arguments", }); - return comp.build_crt_file("crti", .Obj, .@"musl crti.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try start_asm_path(comp, arena, "crti.s"), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crti", .Obj, .@"musl crti.o", prog_node, &files); }, .crtn_o => { var args = std.ArrayList([]const u8).init(arena); @@ -47,12 +49,14 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr try args.appendSlice(&[_][]const u8{ "-Qunused-arguments", }); - return comp.build_crt_file("crtn", .Obj, .@"musl crtn.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try start_asm_path(comp, arena, "crtn.s"), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crtn", .Obj, .@"musl crtn.o", prog_node, &files); }, .crt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -61,14 +65,16 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-fno-stack-protector", "-DCRT", }); - return comp.build_crt_file("crt1", .Obj, .@"musl crt1.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "crt", "crt1.c", }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crt1", .Obj, .@"musl crt1.o", prog_node, &files); }, .rcrt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -78,14 +84,16 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-fno-stack-protector", "-DCRT", }); - return comp.build_crt_file("rcrt1", .Obj, .@"musl rcrt1.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "crt", "rcrt1.c", }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("rcrt1", .Obj, .@"musl rcrt1.o", prog_node, &files); }, .scrt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -95,14 +103,16 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-fno-stack-protector", "-DCRT", }); - return comp.build_crt_file("Scrt1", .Obj, .@"musl Scrt1.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "crt", "Scrt1.c", }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("Scrt1", .Obj, .@"musl Scrt1.o", prog_node, &files); }, .libc_a => { // When there is a src//foo.* then it should substitute for src/foo.* @@ -186,6 +196,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr c_source_file.* = .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", src_file }), .extra_flags = args.items, + .owner = undefined, }; } return comp.build_crt_file("c", .Lib, .@"musl libc.a", prog_node, c_source_files.items); @@ -235,7 +246,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, - .cc_argv = &.{}, + .cc_argv = cc_argv, .parent = null, .builtin_mod = null, }); @@ -261,9 +272,11 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, .clang_passthrough_mode = comp.clang_passthrough_mode, .c_source_files = &[_]Compilation.CSourceFile{ - .{ .src_path = try comp.zig_lib_directory.join(arena, &.{ "libc", "musl", "libc.S" }) }, + .{ + .src_path = try comp.zig_lib_directory.join(arena, &.{ "libc", "musl", "libc.S" }), + .owner = root_mod, + }, }, - .cc_argv = cc_argv, .skip_linker_dependencies = true, .soname = "libc.so", }); diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 2d5f0bc685de..3c0ff26314f3 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -74,27 +74,31 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, .{}); try addLibcBottomHalfIncludes(comp, arena, &args); - return comp.build_crt_file("crt1-reactor", .Obj, .@"wasi crt1-reactor.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", try sanitize(arena, crt1_reactor_src_file), }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crt1-reactor", .Obj, .@"wasi crt1-reactor.o", prog_node, &files); }, .crt1_command_o => { var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, .{}); try addLibcBottomHalfIncludes(comp, arena, &args); - return comp.build_crt_file("crt1-command", .Obj, .@"wasi crt1-command.o", prog_node, &.{ + var files = [_]Compilation.CSourceFile{ .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", try sanitize(arena, crt1_command_src_file), }), .extra_flags = args.items, + .owner = undefined, }, - }); + }; + return comp.build_crt_file("crt1-command", .Obj, .@"wasi crt1-command.o", prog_node, &files); }, .libc_a => { var libc_sources = std.ArrayList(Compilation.CSourceFile).init(arena); @@ -109,6 +113,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } } @@ -125,6 +130,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } } @@ -141,6 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } } @@ -159,6 +166,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } try comp.build_crt_file("wasi-emulated-process-clocks", .Lib, .@"libwasi-emulated-process-clocks.a", prog_node, emu_clocks_sources.items); @@ -175,6 +183,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } try comp.build_crt_file("wasi-emulated-getpid", .Lib, .@"libwasi-emulated-getpid.a", prog_node, emu_getpid_sources.items); @@ -191,6 +200,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } try comp.build_crt_file("wasi-emulated-mman", .Lib, .@"libwasi-emulated-mman.a", prog_node, emu_mman_sources.items); @@ -208,6 +218,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } } @@ -224,6 +235,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "libc", try sanitize(arena, file_path), }), .extra_flags = args.items, + .owner = undefined, }); } } From 9b98d33d0b76a8c8b23958c89ab7e952893697be Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 15:49:08 -0700 Subject: [PATCH 062/133] Compilation: don't store arena until it's done being used --- src/Compilation.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 7314da3960db..d8d8bbc39d1e 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1443,7 +1443,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { comp.* = .{ .gpa = gpa, - .arena = arena_allocator, + .arena = undefined, // populated after we are finished with `arena` .module = opt_zcu, .cache_use = undefined, // populated below .bin_file = null, // populated below @@ -1667,6 +1667,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { }, } + comp.arena = arena_allocator; break :comp comp; }; errdefer comp.destroy(); From 2d2a18831e9821e22d23b4a15ffd20e30e24b27b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 16 Dec 2023 15:49:25 -0700 Subject: [PATCH 063/133] linker: rename intermediary_basname to zcu_object_sub_path --- src/link.zig | 10 +++++----- src/link/Coff.zig | 4 ++-- src/link/Coff/lld.zig | 4 ++-- src/link/Elf.zig | 37 ++++++++++++++++++++++--------------- src/link/MachO.zig | 6 +++--- src/link/MachO/zld.zig | 4 ++-- src/link/Wasm.zig | 10 +++++----- 7 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/link.zig b/src/link.zig index 3e5caf9fc1ea..8fc1e8cc917f 100644 --- a/src/link.zig +++ b/src/link.zig @@ -58,7 +58,7 @@ pub const File = struct { file: ?fs.File, /// When linking with LLD, this linker code will output an object file only at /// this location, and then this path can be placed on the LLD linker line. - intermediary_basename: ?[]const u8 = null, + zcu_object_sub_path: ?[]const u8 = null, disable_lld_caching: bool, gc_sections: bool, print_gc_sections: bool, @@ -289,7 +289,7 @@ pub const File = struct { switch (base.tag) { .elf => if (base.file) |f| { if (build_options.only_c) unreachable; - if (base.intermediary_basename != null and use_lld) { + if (base.zcu_object_sub_path != null and use_lld) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. return; @@ -308,7 +308,7 @@ pub const File = struct { }, .coff, .macho, .plan9, .wasm => if (base.file) |f| { if (build_options.only_c) unreachable; - if (base.intermediary_basename != null) { + if (base.zcu_object_sub_path != null) { // The file we have open is not the final file that we want to // make executable, so we don't have to close it. return; @@ -734,7 +734,7 @@ pub const File = struct { try base.flushModule(comp, prog_node); const dirname = fs.path.dirname(full_out_path_z) orelse "."; - break :blk try fs.path.join(arena, &.{ dirname, base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? }); } else null; log.debug("zcu_obj_path={s}", .{if (zcu_obj_path) |s| s else "(null)"}); @@ -1022,7 +1022,7 @@ pub const File = struct { .pre_bc_path = comp.verbose_llvm_bc, .bin_path = try base.resolveEmitLoc(arena, .{ .directory = null, - .basename = base.intermediary_basename.?, + .basename = base.zcu_object_sub_path.?, }), .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm), .post_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), diff --git a/src/link/Coff.zig b/src/link/Coff.zig index b6a3979122da..75feeeab4637 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -3,7 +3,7 @@ //! LLD for traditional linking (linking relocatable object files). //! LLD is also the default linker for LLVM. -/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. +/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. llvm_object: ?*LlvmObject = null, base: link.File, @@ -261,7 +261,7 @@ pub fn open( const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); - self.base.intermediary_basename = o_file_path; + self.base.zcu_object_sub_path = o_file_path; break :p o_file_path; }; diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 39e6d5288d8f..5b01f6364543 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -35,9 +35,9 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { - break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? }); } else { - break :blk self.base.intermediary_basename.?; + break :blk self.base.zcu_object_sub_path.?; } } else null; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index e5e5c98ec0e1..6cb6a98250de 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -28,7 +28,7 @@ print_map: bool, ptr_width: PtrWidth, -/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. +/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. llvm_object: ?*LlvmObject = null, /// A list of all input files. @@ -259,12 +259,25 @@ pub fn createEmpty( else elf.VER_NDX_LOCAL; + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + // If using LLVM to generate the object file for the zig compilation unit, + // we need a place to put the object file so that it can be subsequently + // handled. + const zcu_object_sub_path = if (!use_lld and !use_llvm) null else p: { + const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ + emit.sub_path, target.ofmt.fileExt(target.cpu.arch), + }); + break :p o_file_path; + }; + const self = try arena.create(Elf); self.* = .{ .base = .{ .tag = .elf, .comp = comp, .emit = emit, + .zcu_object_sub_path = zcu_object_sub_path, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, @@ -325,16 +338,10 @@ pub fn createEmpty( const is_obj = output_mode == .Obj; const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static); - const sub_path = if (!use_lld) emit.sub_path else p: { - // Open a temporary object file, not the final output file because we - // want to link with LLD. - const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - emit.sub_path, target.ofmt.fileExt(target.cpu.arch), - }); - self.base.intermediary_basename = o_file_path; - break :p o_file_path; - }; - + // What path should this ELF linker code output to? + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; self.base.file = try emit.directory.handle.createFile(sub_path, .{ .truncate = false, .read = true, @@ -1045,7 +1052,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node const link_mode = comp.config.link_mode; const directory = self.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); - const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { + const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); } else { @@ -1613,7 +1620,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { const link_mode = self.base.comp.config.link_mode; const directory = self.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); - const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { + const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); } else { @@ -2356,9 +2363,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { - break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? }); } else { - break :blk self.base.intermediary_basename.?; + break :blk self.base.zcu_object_sub_path.?; } } else null; diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 1706dc55acf8..0964859c284a 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1,6 +1,6 @@ base: File, -/// If this is not null, an object file is created by LLVM and emitted to intermediary_basename. +/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. llvm_object: ?*LlvmObject = null, /// Debug symbols bundle (or dSym). @@ -208,10 +208,10 @@ pub fn open( errdefer self.base.destroy(); if (mode == .zld) { - // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`, + // TODO this zcu_object_sub_path isn't enough; in the case of `zig build-exe`, // we also want to put the intermediary object file in the cache while the // main emit directory is the cwd. - self.base.intermediary_basename = sub_path; + self.base.zcu_object_sub_path = sub_path; return self; } diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index f8715aa447dd..fa6aa152e4b3 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -24,9 +24,9 @@ pub fn linkWithZld( try macho_file.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { - break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? }); } else { - break :blk macho_file.base.intermediary_basename.?; + break :blk macho_file.base.zcu_object_sub_path.?; } } else null; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 7ec950675127..cf41110307f3 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -401,7 +401,7 @@ pub fn open( const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ emit.sub_path, target.ofmt.fileExt(target.cpu.arch), }); - wasm.base.intermediary_basename = o_file_path; + wasm.base.zcu_object_sub_path = o_file_path; break :p o_file_path; }; @@ -3511,9 +3511,9 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try wasm.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { - break :blk try fs.path.join(arena, &.{ dirname, wasm.base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? }); } else { - break :blk wasm.base.intermediary_basename.?; + break :blk wasm.base.zcu_object_sub_path.?; } } else null; @@ -4604,9 +4604,9 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try wasm.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { - break :blk try fs.path.join(arena, &.{ dirname, wasm.base.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? }); } else { - break :blk wasm.base.intermediary_basename.?; + break :blk wasm.base.zcu_object_sub_path.?; } } else null; From a3ff4d9b4584b872289f67e94ffa2f0aba9c4257 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 15:20:47 -0700 Subject: [PATCH 064/133] fix entry symbol name on mips --- src/target.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/target.zig b/src/target.zig index 68777945a9b3..4adc26aff8fc 100644 --- a/src/target.zig +++ b/src/target.zig @@ -673,7 +673,10 @@ pub fn defaultEntrySymbolName( return switch (target.ofmt) { .coff => "wWinMainCRTStartup", .macho => "_main", - .elf, .plan9 => "_start", + .elf, .plan9 => switch (target.cpu.arch) { + .mips, .mipsel, .mips64, .mips64el => "__start", + else => "_start", + }, .wasm => switch (wasi_exec_model) { .reactor => "_initialize", .command => "_start", From 38f2172b0a31ec09a39c3222fd7cde2f2802ae8e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 15:21:03 -0700 Subject: [PATCH 065/133] fix memory leak in addModuleTableToCacheHash --- src/Compilation.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index d8d8bbc39d1e..10f9572192fd 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1104,6 +1104,7 @@ fn addModuleTableToCacheHash( hash_type: union(enum) { path_bytes, files: *Cache.Manifest }, ) (error{OutOfMemory} || std.os.GetCwdError)!void { var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{}; + defer seen_table.deinit(gpa); try seen_table.put(gpa, root_mod, {}); const SortByName = struct { @@ -6172,6 +6173,8 @@ fn buildOutputFromZig( const lf = comp.bin_file.?; const unwind_tables = if (lf.cast(link.File.Elf)) |elf| elf.eh_frame_hdr else false; + const strip = comp.compilerRtStrip(); + const optimize_mode = comp.compilerRtOptMode(); const config = try Config.resolve(.{ .output_mode = output_mode, @@ -6180,8 +6183,8 @@ fn buildOutputFromZig( .is_test = false, .have_zcu = true, .emit_bin = true, - .root_optimize_mode = comp.compilerRtOptMode(), - .root_strip = comp.compilerRtStrip(), + .root_optimize_mode = optimize_mode, + .root_strip = strip, .link_libc = comp.config.link_libc, .any_unwind_tables = unwind_tables, }); @@ -6195,14 +6198,14 @@ fn buildOutputFromZig( .fully_qualified_name = "root", .inherited = .{ .resolved_target = comp.root_mod.resolved_target, - .strip = comp.compilerRtStrip(), + .strip = strip, .stack_check = false, .stack_protector = 0, .red_zone = comp.root_mod.red_zone, .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .unwind_tables = unwind_tables, .pic = comp.root_mod.pic, - .optimize_mode = comp.compilerRtOptMode(), + .optimize_mode = optimize_mode, .structured_cfg = comp.root_mod.structured_cfg, }, .global = config, From 90cc408c1479e5e7ccd82369253d19f79d2812a5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 15:21:18 -0700 Subject: [PATCH 066/133] fix --show-builtin when no positional argument is provided --- src/main.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.zig b/src/main.zig index a65c8959b328..3b3eb8941ec5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2511,6 +2511,13 @@ fn buildOutputType( fatal("`zig test` expects a zig source file argument", .{}); } + if (show_builtin and root_src_file == null) { + // Without this, there will be no main module created and no zig + // compilation unit, and therefore also no builtin.zig contents + // created. + root_src_file = "dummy.zig"; + } + if (root_src_file) |unresolved_src_path| { if (create_module.modules.count() != 0) { fatal("main module provided both by '--mod {s} {}{s}' and by positional argument '{s}'", .{ From fe87bae7e39657c96015aa7f3c7a35a0b01da1ad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 17:10:28 -0700 Subject: [PATCH 067/133] frontend: fix handling of special builtin module it's allocated differently and imported differently --- src/Builtin.zig | 6 ++++- src/Module.zig | 64 +++++++++++++++++++++++++++++++++---------------- src/codegen.zig | 5 +--- src/main.zig | 18 +------------- 4 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/Builtin.zig b/src/Builtin.zig index f80f4663024c..8a3a1ecf4b21 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -266,11 +266,14 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { else => |e| return e, } + log.debug("parsing and generating '{s}'", .{mod.root_src_path}); + file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig); - file.tree_loaded = true; assert(file.tree.errors.len == 0); // builtin.zig must parse + file.tree_loaded = true; file.zir = try AstGen.generate(comp.gpa, file.tree); + assert(!file.zir.hasCompileErrors()); // builtin.zig must not have astgen errors file.zir_loaded = true; file.status = .success_zir; } @@ -296,3 +299,4 @@ const assert = std.debug.assert; const AstGen = @import("AstGen.zig"); const File = @import("Module.zig").File; const Compilation = @import("Compilation.zig"); +const log = std.log.scoped(.builtin); diff --git a/src/Module.zig b/src/Module.zig index f2049df378a5..d7b82d15a24c 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -14,7 +14,9 @@ const BigIntMutable = std.math.big.int.Mutable; const Target = std.Target; const Ast = std.zig.Ast; -const Module = @This(); +/// Deprecated, use `Zcu`. +const Module = Zcu; +const Zcu = @This(); const Compilation = @import("Compilation.zig"); const Cache = std.Build.Cache; const Value = @import("value.zig").Value; @@ -947,15 +949,21 @@ pub const File = struct { pub fn deinit(file: *File, mod: *Module) void { const gpa = mod.gpa; + const is_builtin = file.mod.isBuiltin(); log.debug("deinit File {s}", .{file.sub_file_path}); + if (is_builtin) { + file.unloadTree(gpa); + file.unloadZir(gpa); + } else { + gpa.free(file.sub_file_path); + file.unload(gpa); + } file.deleted_decls.deinit(gpa); file.outdated_decls.deinit(gpa); file.references.deinit(gpa); if (file.root_decl.unwrap()) |root_decl| { mod.destroyDecl(root_decl); } - gpa.free(file.sub_file_path); - file.unload(gpa); if (file.prev_zir) |prev_zir| { prev_zir.deinit(gpa); gpa.destroy(prev_zir); @@ -1017,8 +1025,9 @@ pub const File = struct { pub fn destroy(file: *File, mod: *Module) void { const gpa = mod.gpa; + const is_builtin = file.mod.isBuiltin(); file.deinit(mod); - gpa.destroy(file); + if (!is_builtin) gpa.destroy(file); } pub fn renderFullyQualifiedName(file: File, writer: anytype) !void { @@ -3408,6 +3417,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { if (file.root_decl != .none) return; const gpa = mod.gpa; + log.debug("semaFile mod={s} sub_file_path={s}", .{ + file.mod.fully_qualified_name, file.sub_file_path, + }); // Because these three things each reference each other, `undefined` // placeholders are used before being set after the struct type gains an @@ -3523,6 +3535,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { defer tracy.end(); const decl = mod.declPtr(decl_index); + const ip = &mod.intern_pool; if (decl.getFileScope(mod).status != .success_zir) { return error.AnalysisFail; @@ -3532,7 +3545,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const zir = decl.getFileScope(mod).zir; const zir_datas = zir.instructions.items(.data); - // TODO: figure out how this works under incremental changes to builtin.zig! const builtin_type_target_index: InternPool.Index = blk: { const std_mod = mod.std_mod; if (decl.getFileScope(mod).mod != std_mod) break :blk .none; @@ -3540,12 +3552,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const std_file = (try mod.importPkg(std_mod)).file; const std_decl = mod.declPtr(std_file.root_decl.unwrap().?); const std_namespace = std_decl.getInnerNamespace(mod).?; - const builtin_str = try mod.intern_pool.getOrPutString(gpa, "builtin"); + const builtin_str = try ip.getOrPutString(gpa, "builtin"); const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .mod = mod }) orelse break :blk .none); const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none; if (decl.src_namespace != builtin_namespace) break :blk .none; // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. - const decl_name = mod.intern_pool.stringToSlice(decl.name); for ([_]struct { []const u8, InternPool.Index }{ .{ "AtomicOrder", .atomic_order_type }, .{ "AtomicRmwOp", .atomic_rmw_op_type }, @@ -3559,6 +3570,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { .{ "ExternOptions", .extern_options_type }, .{ "Type", .type_info_type }, }) |pair| { + const decl_name = ip.stringToSlice(decl.name); if (std.mem.eql(u8, decl_name, pair[0])) { break :blk pair[1]; } @@ -3654,7 +3666,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { return true; } - const ip = &mod.intern_pool; switch (ip.indexToKey(decl_tv.val.toIntern())) { .func => |func| { const owns_tv = func.owner_decl == decl_index; @@ -3798,25 +3809,24 @@ pub const ImportFileResult = struct { is_pkg: bool, }; -/// https://github.com/ziglang/zig/issues/14307 -pub fn importPkg(mod: *Module, pkg: *Package.Module) !ImportFileResult { - const gpa = mod.gpa; +pub fn importPkg(zcu: *Zcu, mod: *Package.Module) !ImportFileResult { + const gpa = zcu.gpa; // The resolved path is used as the key in the import table, to detect if // an import refers to the same as another, despite different relative paths // or differently mapped package names. const resolved_path = try std.fs.path.resolve(gpa, &.{ - pkg.root.root_dir.path orelse ".", - pkg.root.sub_path, - pkg.root_src_path, + mod.root.root_dir.path orelse ".", + mod.root.sub_path, + mod.root_src_path, }); var keep_resolved_path = false; defer if (!keep_resolved_path) gpa.free(resolved_path); - const gop = try mod.import_table.getOrPut(gpa, resolved_path); - errdefer _ = mod.import_table.pop(); + const gop = try zcu.import_table.getOrPut(gpa, resolved_path); + errdefer _ = zcu.import_table.pop(); if (gop.found_existing) { - try gop.value_ptr.*.addReference(mod.*, .{ .root = pkg }); + try gop.value_ptr.*.addReference(zcu.*, .{ .root = mod }); return ImportFileResult{ .file = gop.value_ptr.*, .is_new = false, @@ -3824,7 +3834,18 @@ pub fn importPkg(mod: *Module, pkg: *Package.Module) !ImportFileResult { }; } - const sub_file_path = try gpa.dupe(u8, pkg.root_src_path); + if (mod.builtin_file) |builtin_file| { + keep_resolved_path = true; // It's now owned by import_table. + gop.value_ptr.* = builtin_file; + try builtin_file.addReference(zcu.*, .{ .root = mod }); + return .{ + .file = builtin_file, + .is_new = false, + .is_pkg = true, + }; + } + + const sub_file_path = try gpa.dupe(u8, mod.root_src_path); errdefer gpa.free(sub_file_path); const new_file = try gpa.create(File); @@ -3842,10 +3863,10 @@ pub fn importPkg(mod: *Module, pkg: *Package.Module) !ImportFileResult { .tree = undefined, .zir = undefined, .status = .never_loaded, - .mod = pkg, + .mod = mod, .root_decl = .none, }; - try new_file.addReference(mod.*, .{ .root = pkg }); + try new_file.addReference(zcu.*, .{ .root = mod }); return ImportFileResult{ .file = new_file, .is_new = true, @@ -4267,6 +4288,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err }, }; if (want_analysis) { + log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{s}' decl_index={d}", .{ + namespace.file_scope.sub_file_path, ip.stringToSlice(decl_name), new_decl_index, + }); comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index }); } new_decl.is_pub = is_pub; diff --git a/src/codegen.zig b/src/codegen.zig index 65af8236deb9..1ac8626a7959 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -119,10 +119,7 @@ pub fn generateLazySymbol( const comp = bin_file.comp; const zcu = comp.module.?; - const decl_index = lazy_sym.ty.getOwnerDecl(zcu); - const decl = zcu.declPtr(decl_index); - const namespace = zcu.namespacePtr(decl.src_namespace); - const target = namespace.file_scope.mod.resolved_target.result; + const target = comp.root_mod.resolved_target.result; const endian = target.cpu.arch.endian(); const gpa = comp.gpa; diff --git a/src/main.zig b/src/main.zig index 3b3eb8941ec5..3f5eab801b6b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2662,23 +2662,7 @@ fn buildOutputType( const std_mod = m: { if (main_mod_is_std) break :m main_mod; if (create_module.modules.get("std")) |cli_mod| break :m cli_mod.resolved.?; - - break :m try Package.Module.create(arena, .{ - .global_cache_directory = global_cache_directory, - .paths = .{ - .root = .{ - .root_dir = zig_lib_directory, - .sub_path = "std", - }, - .root_src_path = "std.zig", - }, - .fully_qualified_name = "std", - .cc_argv = &.{}, - .inherited = .{}, - .global = create_module.resolved_options, - .parent = main_mod, - .builtin_mod = main_mod.getBuiltinDependency(), - }); + break :m null; }; const root_mod = if (arg_mode == .zig_test) root_mod: { From 4b667e736201d9fbe2e440863ce1e631a2d3b4e7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 18:17:45 -0700 Subject: [PATCH 068/133] fix compilations without zig compilation units --- src/Compilation.zig | 2 +- src/main.zig | 86 ++++++++++++++++++++++++--------------------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 10f9572192fd..fa674e28fa3d 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1180,7 +1180,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { return error.ExportTableAndImportTableConflict; } - const have_zcu = options.root_mod.root_src_path.len != 0; + const have_zcu = options.config.have_zcu; const comp: *Compilation = comp: { // For allocations that have the same lifetime as Compilation. This diff --git a/src/main.zig b/src/main.zig index 3f5eab801b6b..0533201a4de7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2515,21 +2515,48 @@ fn buildOutputType( // Without this, there will be no main module created and no zig // compilation unit, and therefore also no builtin.zig contents // created. - root_src_file = "dummy.zig"; + root_src_file = "builtin.zig"; } - if (root_src_file) |unresolved_src_path| { - if (create_module.modules.count() != 0) { - fatal("main module provided both by '--mod {s} {}{s}' and by positional argument '{s}'", .{ - create_module.modules.keys()[0], - create_module.modules.values()[0].paths.root, - create_module.modules.values()[0].paths.root_src_path, - unresolved_src_path, - }); - } + implicit_root_mod: { + const unresolved_src_path = b: { + if (root_src_file) |src_path| { + if (create_module.modules.count() != 0) { + fatal("main module provided both by '--mod {s} {}{s}' and by positional argument '{s}'", .{ + create_module.modules.keys()[0], + create_module.modules.values()[0].paths.root, + create_module.modules.values()[0].paths.root_src_path, + src_path, + }); + } + create_module.opts.have_zcu = true; + break :b src_path; + } + + if (create_module.modules.count() != 0) + break :implicit_root_mod; + + if (create_module.c_source_files.items.len >= 1) + break :b create_module.c_source_files.items[0].src_path; + + if (link_objects.items.len >= 1) + break :b link_objects.items[0].path; + + if (emit_bin == .yes) + break :b emit_bin.yes; + + if (create_module.rc_source_files.items.len >= 1) + break :b create_module.rc_source_files.items[0].src_path; + + if (arg_mode == .run) + fatal("`zig run` expects at least one positional argument", .{}); + + fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{}); + + break :implicit_root_mod; + }; // See duplicate logic: ModCreationGlobalFlags - create_module.opts.have_zcu = true; if (mod_opts.single_threaded == false) create_module.opts.any_non_single_threaded = true; if (mod_opts.sanitize_thread == true) @@ -2542,7 +2569,12 @@ fn buildOutputType( create_module.opts.any_error_tracing = true; const src_path = try introspect.resolvePath(arena, unresolved_src_path); - try create_module.modules.put(arena, "main", .{ + const name = if (arg_mode == .zig_test) + "test" + else + fs.path.stem(fs.path.basename(src_path)); + + try create_module.modules.put(arena, name, .{ .paths = .{ .root = .{ .root_dir = Cache.Directory.cwd(), @@ -2718,35 +2750,7 @@ fn buildOutputType( } } - const root_name = if (provided_name) |n| n else blk: { - if (arg_mode == .zig_test) { - break :blk "test"; - } else if (root_src_file) |file| { - const basename = fs.path.basename(file); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (create_module.c_source_files.items.len >= 1) { - const basename = fs.path.basename(create_module.c_source_files.items[0].src_path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (link_objects.items.len >= 1) { - const basename = fs.path.basename(link_objects.items[0].path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (emit_bin == .yes) { - const basename = fs.path.basename(emit_bin.yes); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (create_module.rc_source_files.items.len >= 1) { - const basename = fs.path.basename(create_module.rc_source_files.items[0].src_path); - break :blk basename[0 .. basename.len - fs.path.extension(basename).len]; - } else if (show_builtin) { - break :blk "builtin"; - } else if (arg_mode == .run) { - fatal("`zig run` expects at least one positional argument", .{}); - // TODO once the attempt to unwrap error: LinkingWithoutZigSourceUnimplemented - // is solved, remove the above fatal() and uncomment the `break` below. - //break :blk "run"; - } else { - fatal("expected a positional argument, -femit-bin=[path], --show-builtin, or --name [name]", .{}); - } - }; + const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name; // Resolve the library path arguments with respect to sysroot. var lib_dirs: std.ArrayListUnmanaged([]const u8) = .{}; From ca77c3bacc971b92f4fcfc783224af51d16174bd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 18:18:02 -0700 Subject: [PATCH 069/133] std.Build.Step.Compile: restore previous step name Print using the target query rather than the resolved target. This makes it print "native" when compiling for the native target. --- lib/std/Build/Step/Compile.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index a984b1618992..683648856a0e 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -251,7 +251,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile { else owner.fmt("{s} ", .{name}); - const target = options.root_module.target.?.result; + const resolved_target = options.root_module.target.?; + const target = resolved_target.result; const step_name = owner.fmt("{s} {s}{s} {s}", .{ switch (options.kind) { @@ -262,7 +263,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { }, name_adjusted, @tagName(options.root_module.optimize orelse .Debug), - target.zigTriple(owner.allocator) catch @panic("OOM"), + resolved_target.query.zigTriple(owner.allocator) catch @panic("OOM"), }); const out_filename = std.zig.binNameAlloc(owner.allocator, .{ From db2ca2ca0005b73e1a7df42de77a06c5506f3aaf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2023 18:40:00 -0700 Subject: [PATCH 070/133] CLI: mark any_dyn_libs=true when encountering a shared object --- src/main.zig | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main.zig b/src/main.zig index 0533201a4de7..aee670756fb0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1666,7 +1666,11 @@ fn buildOutputType( fatal("unrecognized parameter: '{s}'", .{arg}); } } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { - .object, .static_library, .shared_library => { + .shared_library => { + try link_objects.append(arena, .{ .path = arg }); + create_module.opts.any_dyn_libs = true; + }, + .object, .static_library => { try link_objects.append(arena, .{ .path = arg }); }, .res => { @@ -1781,7 +1785,14 @@ fn buildOutputType( .ext = file_ext, // duped while parsing the args. }); }, - .unknown, .shared_library, .object, .static_library => { + .shared_library => { + try link_objects.append(arena, .{ + .path = it.only_arg, + .must_link = must_link, + }); + create_module.opts.any_dyn_libs = true; + }, + .unknown, .object, .static_library => { try link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, From 8944dea23fb554290a4b54ca40b0594f6e3f77a9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 15:03:55 -0700 Subject: [PATCH 071/133] CLI: fix regressed logic for any_dyn_libs This value needs access to the fully resolved set of system libraries, which required restructuring a bunch of CLI logic. --- src/Compilation.zig | 11 + src/main.zig | 621 +++++++++++++++++++++++--------------------- 2 files changed, 329 insertions(+), 303 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index fa674e28fa3d..f825d8c93079 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -86,6 +86,7 @@ skip_linker_dependencies: bool, no_builtin: bool, function_sections: bool, data_sections: bool, +native_system_include_paths: []const []const u8, c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = @@ -1065,6 +1066,7 @@ pub const InitOptions = struct { version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation = null, + native_system_include_paths: []const []const u8 = &.{}, clang_preprocessor_mode: ClangPreprocessorMode = .no, /// This is for stage1 and should be deleted upon completion of self-hosting. color: Color = .auto, @@ -1508,6 +1510,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .job_queued_update_builtin_zig = have_zcu, .function_sections = options.function_sections, .data_sections = options.data_sections, + .native_system_include_paths = options.native_system_include_paths, }; const lf_open_opts: link.File.OpenOptions = .{ @@ -5296,6 +5299,14 @@ pub fn addCCArgs( try argv.append("-ffreestanding"); } + if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) { + try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2); + for (comp.native_system_include_paths) |include_path| { + argv.appendAssumeCapacity("-isystem"); + argv.appendAssumeCapacity(include_path); + } + } + try argv.appendSlice(mod.cc_argv); } diff --git a/src/main.zig b/src/main.zig index aee670756fb0..8a1286bc8ea4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -821,7 +821,6 @@ fn buildOutputType( var target_mcpu: ?[]const u8 = null; var emit_h: Emit = .no; var soname: SOName = undefined; - var want_native_include_dirs = false; var want_compiler_rt: ?bool = null; var linker_script: ?[]const u8 = null; var version_script: ?[]const u8 = null; @@ -863,8 +862,6 @@ fn buildOutputType( var link_emit_relocs = false; var each_lib_rpath: ?bool = null; var build_id: ?std.zig.BuildId = null; - var sysroot: ?[]const u8 = null; - var libc_paths_file: ?[]const u8 = try EnvVar.ZIG_LIBC.get(arena); var runtime_args_start: ?usize = null; var test_filter: ?[]const u8 = null; var test_name_prefix: ?[]const u8 = null; @@ -892,16 +889,11 @@ fn buildOutputType( var pdb_out_path: ?[]const u8 = null; var error_limit: ?Module.ErrorInt = null; // These are before resolving sysroot. - var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{}; var extra_cflags: std.ArrayListUnmanaged([]const u8) = .{}; var extra_rcflags: std.ArrayListUnmanaged([]const u8) = .{}; var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}; - var rpath_list: std.ArrayListUnmanaged([]const u8) = .{}; var rc_includes: Compilation.RcIncludes = .any; var manifest_file: ?[]const u8 = null; - var link_objects: std.ArrayListUnmanaged(Compilation.LinkObject) = .{}; - var framework_dirs: std.ArrayListUnmanaged([]const u8) = .{}; - var frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{}; var linker_export_symbol_names: std.ArrayListUnmanaged([]const u8) = .{}; // Tracks the position in c_source_files which have already their owner populated. @@ -951,7 +943,6 @@ fn buildOutputType( .resolved_options = undefined, .system_libs = .{}, - .external_system_libs = .{}, .resolved_system_libs = .{}, .wasi_emulated_libs = .{}, @@ -959,6 +950,17 @@ fn buildOutputType( .rc_source_files = .{}, .llvm_m_args = .{}, + .sysroot = null, + .lib_dirs = .{}, // populated by createModule() + .lib_dir_args = .{}, // populated from CLI arg parsing + .libc_installation = null, + .want_native_include_dirs = false, + .frameworks = .{}, + .framework_dirs = .{}, + .rpath_list = .{}, + .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena), + .link_objects = .{}, + .native_system_include_paths = &.{}, }; // before arg parsing, check for the NO_COLOR environment variable @@ -1137,17 +1139,17 @@ fn buildOutputType( if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?))) fatal("invalid package name '{s}': cannot contain folder separators", .{provided_name.?}); } else if (mem.eql(u8, arg, "-rpath")) { - try rpath_list.append(arena, args_iter.nextOrFatal()); + try create_module.rpath_list.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - try lib_dir_args.append(arena, args_iter.nextOrFatal()); + try create_module.lib_dir_args.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-F")) { - try framework_dirs.append(arena, args_iter.nextOrFatal()); + try create_module.framework_dirs.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-framework")) { - try frameworks.put(arena, args_iter.nextOrFatal(), .{}); + try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{}); } else if (mem.eql(u8, arg, "-weak_framework")) { - try frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true }); + try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .weak = true }); } else if (mem.eql(u8, arg, "-needed_framework")) { - try frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true }); + try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{ .needed = true }); } else if (mem.eql(u8, arg, "-install_name")) { install_name = args_iter.nextOrFatal(); } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) { @@ -1236,11 +1238,11 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-iframework")) { const path = args_iter.nextOrFatal(); try cssan.addIncludePath(arena, &clang_argv, .iframework, arg, path, false); - try framework_dirs.append(arena, path); // Forward to the backend as -F + try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) { const path = args_iter.nextOrFatal(); try cssan.addIncludePath(arena, &clang_argv, .iframeworkwithsysroot, arg, path, false); - try framework_dirs.append(arena, path); // Forward to the backend as -F + try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "--version")) { const next_arg = args_iter.nextOrFatal(); version = std.SemanticVersion.parse(next_arg) catch |err| { @@ -1265,10 +1267,10 @@ fn buildOutputType( create_module.dynamic_linker = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--sysroot")) { const next_arg = args_iter.nextOrFatal(); - sysroot = next_arg; + create_module.sysroot = next_arg; try clang_argv.appendSlice(arena, &.{ "-isysroot", next_arg }); } else if (mem.eql(u8, arg, "--libc")) { - libc_paths_file = args_iter.nextOrFatal(); + create_module.libc_paths_file = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--test-filter")) { test_filter = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--test-name-prefix")) { @@ -1620,9 +1622,9 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-T")) { linker_script = arg[2..]; } else if (mem.startsWith(u8, arg, "-L")) { - try lib_dir_args.append(arena, arg[2..]); + try create_module.lib_dir_args.append(arena, arg[2..]); } else if (mem.startsWith(u8, arg, "-F")) { - try framework_dirs.append(arena, arg[2..]); + try create_module.framework_dirs.append(arena, arg[2..]); } else if (mem.startsWith(u8, arg, "-l")) { // We don't know whether this library is part of libc // or libc++ until we resolve the target, so we append @@ -1667,14 +1669,14 @@ fn buildOutputType( } } else switch (file_ext orelse Compilation.classifyFileExt(arg)) { .shared_library => { - try link_objects.append(arena, .{ .path = arg }); + try create_module.link_objects.append(arena, .{ .path = arg }); create_module.opts.any_dyn_libs = true; }, .object, .static_library => { - try link_objects.append(arena, .{ .path = arg }); + try create_module.link_objects.append(arena, .{ .path = arg }); }, .res => { - try link_objects.append(arena, .{ .path = arg }); + try create_module.link_objects.append(arena, .{ .path = arg }); contains_res_file = true; }, .manifest => { @@ -1721,7 +1723,7 @@ fn buildOutputType( soname = .no; create_module.opts.ensure_libc_on_non_freestanding = true; create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp; - want_native_include_dirs = true; + create_module.want_native_include_dirs = true; // Clang's driver enables this switch unconditionally. // Disabling the emission of .eh_frame_hdr can unexpectedly break // some functionality that depend on it, such as C++ exceptions and @@ -1786,20 +1788,20 @@ fn buildOutputType( }); }, .shared_library => { - try link_objects.append(arena, .{ + try create_module.link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, }); create_module.opts.any_dyn_libs = true; }, .unknown, .object, .static_library => { - try link_objects.append(arena, .{ + try create_module.link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, }); }, .res => { - try link_objects.append(arena, .{ + try create_module.link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, }); @@ -1835,7 +1837,7 @@ fn buildOutputType( // more control over what's in the resulting // binary: no extra rpaths and DSO filename exactly // as provided. Hello, Go. - try link_objects.append(arena, .{ + try create_module.link_objects.append(arena, .{ .path = it.only_arg, .must_link = must_link, .loption = true, @@ -2036,7 +2038,7 @@ fn buildOutputType( try linker_args.append("-z"); try linker_args.append(it.only_arg); }, - .lib_dir => try lib_dir_args.append(arena, it.only_arg), + .lib_dir => try create_module.lib_dir_args.append(arena, it.only_arg), .mcpu => target_mcpu = it.only_arg, .m => try create_module.llvm_m_args.append(arena, it.only_arg), .dep_file => { @@ -2050,15 +2052,15 @@ fn buildOutputType( disable_c_depfile = true; try clang_argv.appendSlice(arena, it.other_args); }, - .framework_dir => try framework_dirs.append(arena, it.only_arg), - .framework => try frameworks.put(arena, it.only_arg, .{}), - .nostdlibinc => want_native_include_dirs = false, + .framework_dir => try create_module.framework_dirs.append(arena, it.only_arg), + .framework => try create_module.frameworks.put(arena, it.only_arg, .{}), + .nostdlibinc => create_module.want_native_include_dirs = false, .strip => mod_opts.strip = true, .exec_model => { create_module.opts.wasi_exec_model = parseWasiExecModel(it.only_arg); }, .sysroot => { - sysroot = it.only_arg; + create_module.sysroot = it.only_arg; }, .entry => { create_module.opts.entry = .{ .named = it.only_arg }; @@ -2072,7 +2074,7 @@ fn buildOutputType( .preferred_mode = lib_preferred_mode, .search_strategy = lib_search_strategy, }), - .weak_framework => try frameworks.put(arena, it.only_arg, .{ .weak = true }), + .weak_framework => try create_module.frameworks.put(arena, it.only_arg, .{ .weak = true }), .headerpad_max_install_names => headerpad_max_install_names = true, .compress_debug_sections => { if (it.only_arg.len == 0) { @@ -2133,7 +2135,7 @@ fn buildOutputType( } provided_name = name[prefix..end]; } else if (mem.eql(u8, arg, "-rpath")) { - try rpath_list.append(arena, linker_args_it.nextOrFatal()); + try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--subsystem")) { subsystem = try parseSubSystem(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "-I") or @@ -2345,11 +2347,11 @@ fn buildOutputType( }); }; } else if (mem.eql(u8, arg, "-framework")) { - try frameworks.put(arena, linker_args_it.nextOrFatal(), .{}); + try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{}); } else if (mem.eql(u8, arg, "-weak_framework")) { - try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true }); + try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .weak = true }); } else if (mem.eql(u8, arg, "-needed_framework")) { - try frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true }); + try create_module.frameworks.put(arena, linker_args_it.nextOrFatal(), .{ .needed = true }); } else if (mem.eql(u8, arg, "-needed_library")) { try create_module.system_libs.put(arena, linker_args_it.nextOrFatal(), .{ .weak = false, @@ -2399,7 +2401,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-install_name")) { install_name = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "-force_load")) { - try link_objects.append(arena, .{ + try create_module.link_objects.append(arena, .{ .path = linker_args_it.nextOrFatal(), .must_link = true, }); @@ -2504,7 +2506,7 @@ fn buildOutputType( }, } if (create_module.c_source_files.items.len == 0 and - link_objects.items.len == 0 and + create_module.link_objects.items.len == 0 and root_src_file == null) { // For example `zig cc` and no args should print the "no input files" message. @@ -2550,8 +2552,8 @@ fn buildOutputType( if (create_module.c_source_files.items.len >= 1) break :b create_module.c_source_files.items[0].src_path; - if (link_objects.items.len >= 1) - break :b link_objects.items[0].path; + if (create_module.link_objects.items.len >= 1) + break :b create_module.link_objects.items[0].path; if (emit_bin == .yes) break :b emit_bin.yes; @@ -2761,250 +2763,10 @@ fn buildOutputType( } } - const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name; - - // Resolve the library path arguments with respect to sysroot. - var lib_dirs: std.ArrayListUnmanaged([]const u8) = .{}; - if (sysroot) |root| { - try lib_dirs.ensureUnusedCapacity(arena, lib_dir_args.items.len * 2); - for (lib_dir_args.items) |dir| { - if (fs.path.isAbsolute(dir)) { - const stripped_dir = dir[fs.path.diskDesignator(dir).len..]; - const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); - lib_dirs.appendAssumeCapacity(full_path); - } - lib_dirs.appendAssumeCapacity(dir); - } - } else { - lib_dirs = lib_dir_args; - } - lib_dir_args = undefined; // From here we use lib_dirs instead. - - if (main_mod.resolved_target.is_native_os and target.isDarwin()) { - // If we want to link against frameworks, we need system headers. - if (framework_dirs.items.len > 0 or frameworks.count() > 0) - want_native_include_dirs = true; - } - - // Trigger native system library path detection if necessary. - if (sysroot == null and - main_mod.resolved_target.is_native_os and - main_mod.resolved_target.is_native_abi and - (create_module.external_system_libs.len != 0 or want_native_include_dirs)) - { - const paths = std.zig.system.NativePaths.detect(arena, target) catch |err| { - fatal("unable to detect native system paths: {s}", .{@errorName(err)}); - }; - for (paths.warnings.items) |warning| { - warn("{s}", .{warning}); - } - - try clang_argv.ensureUnusedCapacity(arena, paths.include_dirs.items.len * 2); - for (paths.include_dirs.items) |include_dir| { - clang_argv.appendAssumeCapacity("-isystem"); - clang_argv.appendAssumeCapacity(include_dir); - } - - try framework_dirs.appendSlice(arena, paths.framework_dirs.items); - try lib_dirs.appendSlice(arena, paths.lib_dirs.items); - try rpath_list.appendSlice(arena, paths.rpaths.items); - } - - var libc_installation: ?LibCInstallation = null; - if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { - fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); - }; - } - - if (builtin.target.os.tag == .windows and - target.abi == .msvc and - create_module.external_system_libs.len != 0) - { - if (libc_installation == null) { - libc_installation = try LibCInstallation.findNative(.{ - .allocator = arena, - .verbose = true, - .target = target, - }); - - try lib_dirs.appendSlice(arena, &.{ - libc_installation.?.msvc_lib_dir.?, - libc_installation.?.kernel32_lib_dir.?, - }); - } - } - - // If any libs in this list are statically provided, we omit them from the - // resolved list and populate the link_objects array instead. - { - var test_path = std.ArrayList(u8).init(gpa); - defer test_path.deinit(); - - var checked_paths = std.ArrayList(u8).init(gpa); - defer checked_paths.deinit(); - - var failed_libs = std.ArrayList(struct { - name: []const u8, - strategy: SystemLib.SearchStrategy, - checked_paths: []const u8, - preferred_mode: std.builtin.LinkMode, - }).init(arena); - - syslib: for (create_module.external_system_libs.items(.name), create_module.external_system_libs.items(.info)) |lib_name, info| { - // Checked in the first pass above while looking for libc libraries. - assert(!fs.path.isAbsolute(lib_name)); - - checked_paths.clearRetainingCapacity(); - - switch (info.search_strategy) { - .mode_first, .no_fallback => { - // check for preferred mode - for (lib_dirs.items) |lib_dir_path| { - if (try accessLibPath( - &test_path, - &checked_paths, - lib_dir_path, - lib_name, - target, - info.preferred_mode, - )) { - const path = try arena.dupe(u8, test_path.items); - switch (info.preferred_mode) { - .Static => try link_objects.append(arena, .{ .path = path }), - .Dynamic => try create_module.resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = info.needed, - .weak = info.weak, - .path = path, - }, - }), - } - continue :syslib; - } - } - // check for fallback mode - if (info.search_strategy == .no_fallback) { - try failed_libs.append(.{ - .name = lib_name, - .strategy = info.search_strategy, - .checked_paths = try arena.dupe(u8, checked_paths.items), - .preferred_mode = info.preferred_mode, - }); - continue :syslib; - } - for (lib_dirs.items) |lib_dir_path| { - if (try accessLibPath( - &test_path, - &checked_paths, - lib_dir_path, - lib_name, - target, - info.fallbackMode(), - )) { - const path = try arena.dupe(u8, test_path.items); - switch (info.fallbackMode()) { - .Static => try link_objects.append(arena, .{ .path = path }), - .Dynamic => try create_module.resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = info.needed, - .weak = info.weak, - .path = path, - }, - }), - } - continue :syslib; - } - } - try failed_libs.append(.{ - .name = lib_name, - .strategy = info.search_strategy, - .checked_paths = try arena.dupe(u8, checked_paths.items), - .preferred_mode = info.preferred_mode, - }); - continue :syslib; - }, - .paths_first => { - for (lib_dirs.items) |lib_dir_path| { - // check for preferred mode - if (try accessLibPath( - &test_path, - &checked_paths, - lib_dir_path, - lib_name, - target, - info.preferred_mode, - )) { - const path = try arena.dupe(u8, test_path.items); - switch (info.preferred_mode) { - .Static => try link_objects.append(arena, .{ .path = path }), - .Dynamic => try create_module.resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = info.needed, - .weak = info.weak, - .path = path, - }, - }), - } - continue :syslib; - } - - // check for fallback mode - if (try accessLibPath( - &test_path, - &checked_paths, - lib_dir_path, - lib_name, - target, - info.fallbackMode(), - )) { - const path = try arena.dupe(u8, test_path.items); - switch (info.fallbackMode()) { - .Static => try link_objects.append(arena, .{ .path = path }), - .Dynamic => try create_module.resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = info.needed, - .weak = info.weak, - .path = path, - }, - }), - } - continue :syslib; - } - } - try failed_libs.append(.{ - .name = lib_name, - .strategy = info.search_strategy, - .checked_paths = try arena.dupe(u8, checked_paths.items), - .preferred_mode = info.preferred_mode, - }); - continue :syslib; - }, - } - @compileError("unreachable"); - } - - if (failed_libs.items.len > 0) { - for (failed_libs.items) |f| { - const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; - std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{ - @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths, - }); - } - process.exit(1); - } - } - // After this point, create_module.resolved_system_libs is used instead of - // create_module.external_system_libs. - // We now repeat part of the process for frameworks. var resolved_frameworks = std.ArrayList(Compilation.Framework).init(arena); - if (frameworks.keys().len > 0) { + if (create_module.frameworks.keys().len > 0) { var test_path = std.ArrayList(u8).init(gpa); defer test_path.deinit(); @@ -3016,10 +2778,10 @@ fn buildOutputType( checked_paths: []const u8, }).init(arena); - framework: for (frameworks.keys(), frameworks.values()) |framework_name, info| { + framework: for (create_module.frameworks.keys(), create_module.frameworks.values()) |framework_name, info| { checked_paths.clearRetainingCapacity(); - for (framework_dirs.items) |framework_dir_path| { + for (create_module.framework_dirs.items) |framework_dir_path| { if (try accessFrameworkPath( &test_path, &checked_paths, @@ -3054,11 +2816,13 @@ fn buildOutputType( } // After this point, resolved_frameworks is used instead of frameworks. - if (create_module.opts.output_mode == .Obj and (target.ofmt == .coff or target.ofmt == .macho)) { + if (create_module.resolved_options.output_mode == .Obj and + (target.ofmt == .coff or target.ofmt == .macho)) + { const total_obj_count = create_module.c_source_files.items.len + @intFromBool(root_src_file != null) + create_module.rc_source_files.items.len + - link_objects.items.len; + create_module.link_objects.items.len; if (total_obj_count > 1) { fatal("{s} does not support linking multiple objects into one", .{@tagName(target.ofmt)}); } @@ -3070,6 +2834,8 @@ fn buildOutputType( const output_to_cache = listen != .none; const optional_version = if (have_version) version else null; + const root_name = if (provided_name) |n| n else main_mod.fully_qualified_name; + const resolved_soname: ?[]const u8 = switch (soname) { .yes => |explicit| explicit, .no => null, @@ -3105,8 +2871,8 @@ fn buildOutputType( .basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, .target = target, - .output_mode = create_module.opts.output_mode, - .link_mode = create_module.opts.link_mode, + .output_mode = create_module.resolved_options.output_mode, + .link_mode = create_module.resolved_options.link_mode, .version = optional_version, }), }, @@ -3224,9 +2990,9 @@ fn buildOutputType( }; defer emit_docs_resolved.deinit(); - const is_exe_or_dyn_lib = switch (create_module.opts.output_mode) { + const is_exe_or_dyn_lib = switch (create_module.resolved_options.output_mode) { .Obj => false, - .Lib => (create_module.opts.link_mode orelse .Static) == .Dynamic, + .Lib => create_module.resolved_options.link_mode == .Dynamic, .Exe => true, }; // Note that cmake when targeting Windows will try to execute @@ -3354,7 +3120,7 @@ fn buildOutputType( .self_exe_path = self_exe_path, .config = create_module.resolved_options, .root_name = root_name, - .sysroot = sysroot, + .sysroot = create_module.sysroot, .main_mod = main_mod, .root_mod = root_mod, .std_mod = std_mod, @@ -3365,15 +3131,15 @@ fn buildOutputType( .emit_llvm_bc = emit_llvm_bc_resolved.data, .emit_docs = emit_docs_resolved.data, .emit_implib = emit_implib_resolved.data, - .lib_dirs = lib_dirs.items, - .rpath_list = rpath_list.items, + .lib_dirs = create_module.lib_dirs.items, + .rpath_list = create_module.rpath_list.items, .symbol_wrap_set = symbol_wrap_set, .c_source_files = create_module.c_source_files.items, .rc_source_files = create_module.rc_source_files.items, .manifest_file = manifest_file, .rc_includes = rc_includes, - .link_objects = link_objects.items, - .framework_dirs = framework_dirs.items, + .link_objects = create_module.link_objects.items, + .framework_dirs = create_module.framework_dirs.items, .frameworks = resolved_frameworks.items, .system_lib_names = create_module.resolved_system_libs.items(.name), .system_lib_infos = create_module.resolved_system_libs.items(.lib), @@ -3427,7 +3193,7 @@ fn buildOutputType( .clang_passthrough_mode = clang_passthrough_mode, .clang_preprocessor_mode = clang_preprocessor_mode, .version = optional_version, - .libc_installation = if (libc_installation) |*lci| lci else null, + .libc_installation = if (create_module.libc_installation) |*lci| lci else null, .verbose_cc = verbose_cc, .verbose_link = verbose_link, .verbose_air = verbose_air, @@ -3458,6 +3224,7 @@ fn buildOutputType( .reference_trace = reference_trace, .pdb_out_path = pdb_out_path, .error_limit = error_limit, + .native_system_include_paths = create_module.native_system_include_paths, }) catch |err| switch (err) { error.LibCUnavailable => { const triple_name = try target.zigTriple(arena); @@ -3626,10 +3393,6 @@ const CreateModule = struct { /// link_libcpp, and then the libraries are filtered into /// `external_system_libs` and `resolved_system_libs`. system_libs: std.StringArrayHashMapUnmanaged(SystemLib), - external_system_libs: std.MultiArrayList(struct { - name: []const u8, - info: SystemLib, - }), resolved_system_libs: std.MultiArrayList(struct { name: []const u8, lib: Compilation.SystemLib, @@ -3643,6 +3406,17 @@ const CreateModule = struct { // This array is populated by zig cc frontend and then has to be converted to zig-style // CPU features. llvm_m_args: std.ArrayListUnmanaged([]const u8), + sysroot: ?[]const u8, + lib_dirs: std.ArrayListUnmanaged([]const u8), + lib_dir_args: std.ArrayListUnmanaged([]const u8), + libc_installation: ?LibCInstallation, + want_native_include_dirs: bool, + frameworks: std.StringArrayHashMapUnmanaged(Framework), + native_system_include_paths: []const []const u8, + framework_dirs: std.ArrayListUnmanaged([]const u8), + rpath_list: std.ArrayListUnmanaged([]const u8), + libc_paths_file: ?[]const u8, + link_objects: std.ArrayListUnmanaged(Compilation.LinkObject), }; fn createModule( @@ -3749,6 +3523,10 @@ fn createModule( // First, remove libc, libc++, and compiler_rt libraries from the system libraries list. // We need to know whether the set of system libraries contains anything besides these // to decide whether to trigger native path detection logic. + var external_system_libs: std.MultiArrayList(struct { + name: []const u8, + info: SystemLib, + }) = .{}; for (create_module.system_libs.keys(), create_module.system_libs.values()) |lib_name, info| { if (target.is_libc_lib_name(lib_name)) { create_module.opts.link_libc = true; @@ -3800,12 +3578,249 @@ fn createModule( } } - try create_module.external_system_libs.append(arena, .{ + try external_system_libs.append(arena, .{ .name = lib_name, .info = info, }); } // After this point, external_system_libs is used instead of system_libs. + if (external_system_libs.len != 0) + create_module.want_native_include_dirs = true; + + // Resolve the library path arguments with respect to sysroot. + if (create_module.sysroot) |root| { + try create_module.lib_dirs.ensureUnusedCapacity(arena, create_module.lib_dir_args.items.len * 2); + for (create_module.lib_dir_args.items) |dir| { + if (fs.path.isAbsolute(dir)) { + const stripped_dir = dir[fs.path.diskDesignator(dir).len..]; + const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); + create_module.lib_dirs.appendAssumeCapacity(full_path); + } + create_module.lib_dirs.appendAssumeCapacity(dir); + } + } else { + create_module.lib_dirs = create_module.lib_dir_args; + } + create_module.lib_dir_args = undefined; // From here we use lib_dirs instead. + + if (resolved_target.is_native_os and target.isDarwin()) { + // If we want to link against frameworks, we need system headers. + if (create_module.frameworks.count() > 0) + create_module.want_native_include_dirs = true; + } + + // Trigger native system library path detection if necessary. + if (create_module.sysroot == null and + resolved_target.is_native_os and resolved_target.is_native_abi and + create_module.want_native_include_dirs) + { + var paths = std.zig.system.NativePaths.detect(arena, target) catch |err| { + fatal("unable to detect native system paths: {s}", .{@errorName(err)}); + }; + for (paths.warnings.items) |warning| { + warn("{s}", .{warning}); + } + + create_module.native_system_include_paths = try paths.include_dirs.toOwnedSlice(arena); + + try create_module.framework_dirs.appendSlice(arena, paths.framework_dirs.items); + try create_module.lib_dirs.appendSlice(arena, paths.lib_dirs.items); + try create_module.rpath_list.appendSlice(arena, paths.rpaths.items); + } + + if (create_module.libc_paths_file) |paths_file| { + create_module.libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| { + fatal("unable to parse libc paths file at path {s}: {s}", .{ + paths_file, @errorName(err), + }); + }; + } + + if (builtin.target.os.tag == .windows and target.abi == .msvc and + external_system_libs.len != 0) + { + if (create_module.libc_installation == null) { + create_module.libc_installation = try LibCInstallation.findNative(.{ + .allocator = arena, + .verbose = true, + .target = target, + }); + + try create_module.lib_dirs.appendSlice(arena, &.{ + create_module.libc_installation.?.msvc_lib_dir.?, + create_module.libc_installation.?.kernel32_lib_dir.?, + }); + } + } + + // If any libs in this list are statically provided, we omit them from the + // resolved list and populate the link_objects array instead. + { + var test_path = std.ArrayList(u8).init(gpa); + defer test_path.deinit(); + + var checked_paths = std.ArrayList(u8).init(gpa); + defer checked_paths.deinit(); + + var failed_libs = std.ArrayList(struct { + name: []const u8, + strategy: SystemLib.SearchStrategy, + checked_paths: []const u8, + preferred_mode: std.builtin.LinkMode, + }).init(arena); + + syslib: for (external_system_libs.items(.name), external_system_libs.items(.info)) |lib_name, info| { + // Checked in the first pass above while looking for libc libraries. + assert(!fs.path.isAbsolute(lib_name)); + + checked_paths.clearRetainingCapacity(); + + switch (info.search_strategy) { + .mode_first, .no_fallback => { + // check for preferred mode + for (create_module.lib_dirs.items) |lib_dir_path| { + if (try accessLibPath( + &test_path, + &checked_paths, + lib_dir_path, + lib_name, + target, + info.preferred_mode, + )) { + const path = try arena.dupe(u8, test_path.items); + switch (info.preferred_mode) { + .Static => try create_module.link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = info.needed, + .weak = info.weak, + .path = path, + }, + }), + } + continue :syslib; + } + } + // check for fallback mode + if (info.search_strategy == .no_fallback) { + try failed_libs.append(.{ + .name = lib_name, + .strategy = info.search_strategy, + .checked_paths = try arena.dupe(u8, checked_paths.items), + .preferred_mode = info.preferred_mode, + }); + continue :syslib; + } + for (create_module.lib_dirs.items) |lib_dir_path| { + if (try accessLibPath( + &test_path, + &checked_paths, + lib_dir_path, + lib_name, + target, + info.fallbackMode(), + )) { + const path = try arena.dupe(u8, test_path.items); + switch (info.fallbackMode()) { + .Static => try create_module.link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = info.needed, + .weak = info.weak, + .path = path, + }, + }), + } + continue :syslib; + } + } + try failed_libs.append(.{ + .name = lib_name, + .strategy = info.search_strategy, + .checked_paths = try arena.dupe(u8, checked_paths.items), + .preferred_mode = info.preferred_mode, + }); + continue :syslib; + }, + .paths_first => { + for (create_module.lib_dirs.items) |lib_dir_path| { + // check for preferred mode + if (try accessLibPath( + &test_path, + &checked_paths, + lib_dir_path, + lib_name, + target, + info.preferred_mode, + )) { + const path = try arena.dupe(u8, test_path.items); + switch (info.preferred_mode) { + .Static => try create_module.link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = info.needed, + .weak = info.weak, + .path = path, + }, + }), + } + continue :syslib; + } + + // check for fallback mode + if (try accessLibPath( + &test_path, + &checked_paths, + lib_dir_path, + lib_name, + target, + info.fallbackMode(), + )) { + const path = try arena.dupe(u8, test_path.items); + switch (info.fallbackMode()) { + .Static => try create_module.link_objects.append(arena, .{ .path = path }), + .Dynamic => try create_module.resolved_system_libs.append(arena, .{ + .name = lib_name, + .lib = .{ + .needed = info.needed, + .weak = info.weak, + .path = path, + }, + }), + } + continue :syslib; + } + } + try failed_libs.append(.{ + .name = lib_name, + .strategy = info.search_strategy, + .checked_paths = try arena.dupe(u8, checked_paths.items), + .preferred_mode = info.preferred_mode, + }); + continue :syslib; + }, + } + @compileError("unreachable"); + } + + if (failed_libs.items.len > 0) { + for (failed_libs.items) |f| { + const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths; + std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{ + @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths, + }); + } + process.exit(1); + } + } + // After this point, create_module.resolved_system_libs is used instead of + // create_module.external_system_libs. + + if (create_module.resolved_system_libs.len != 0) + create_module.opts.any_dyn_libs = true; create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) { else => fatal("unable to resolve compilation options: {s}", .{@errorName(err)}), From 529d01c2baf695c2844b5dd42642a74749bef0d0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 15:22:47 -0700 Subject: [PATCH 072/133] resolve error tracing logic at module creation time rather than checking multiple conditions in Sema --- src/Compilation/Config.zig | 10 ++++++++++ src/Module.zig | 11 +---------- src/Sema.zig | 14 ++++---------- src/target.zig | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 442b7a1b9af8..fc4b774baad7 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -408,9 +408,17 @@ pub fn resolve(options: Options) !Config { }; }; + const backend_supports_error_tracing = target_util.backendSupportsFeature( + target.cpu.arch, + target.ofmt, + use_llvm, + .error_return_trace, + ); + const root_error_tracing = b: { if (options.root_error_tracing) |x| break :b x; if (root_strip) break :b false; + if (!backend_supports_error_tracing) break :b false; break :b switch (root_optimize_mode) { .Debug => true, .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, @@ -418,6 +426,8 @@ pub fn resolve(options: Options) !Config { }; const any_error_tracing = root_error_tracing or options.any_error_tracing; + if (any_error_tracing and !backend_supports_error_tracing) + return error.BackendLacksErrorTracing; const rdynamic = options.rdynamic orelse false; diff --git a/src/Module.zig b/src/Module.zig index d7b82d15a24c..86c124e3b57f 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5589,16 +5589,7 @@ pub fn backendSupportsFeature(zcu: Module, feature: Feature) bool { const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch; const ofmt = zcu.root_mod.resolved_target.result.ofmt; const use_llvm = zcu.comp.config.use_llvm; - return switch (feature) { - .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64, - .panic_unwrap_error => ofmt == .c or use_llvm, - .safety_check_formatted => ofmt == .c or use_llvm, - .error_return_trace => use_llvm, - .is_named_enum_value => use_llvm, - .error_set_has_value => use_llvm or cpu_arch.isWasm(), - .field_reordering => use_llvm, - .safety_checked_instructions => use_llvm, - }; + return target_util.backendSupportsFeature(cpu_arch, ofmt, use_llvm, feature); } /// Shortcut for calling `intern_pool.get`. diff --git a/src/Sema.zig b/src/Sema.zig index c2e05e4a2c0d..3a54b20ea4c2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2045,9 +2045,10 @@ fn analyzeAsType( pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { const mod = sema.mod; + const comp = mod.comp; const gpa = sema.gpa; const ip = &mod.intern_pool; - if (!mod.backendSupportsFeature(.error_return_trace)) return; + if (!comp.config.any_error_tracing) return; assert(!block.is_comptime); var err_trace_block = block.makeSubBlock(); @@ -6543,7 +6544,6 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref const gpa = sema.gpa; const src = sema.src; - if (!mod.backendSupportsFeature(.error_return_trace)) return .none; if (!block.ownerModule().error_tracing) return .none; if (block.is_comptime) @@ -6728,7 +6728,7 @@ fn zirCall( input_is_error = false; } - if (mod.backendSupportsFeature(.error_return_trace) and block.ownerModule().error_tracing and + if (block.ownerModule().error_tracing and !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) { const return_ty = sema.typeOf(call_inst); @@ -18759,8 +18759,6 @@ fn retWithErrTracing( fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool { const mod = sema.mod; - if (!mod.backendSupportsFeature(.error_return_trace)) return false; - return fn_ret_ty.isError(mod) and mod.comp.config.any_error_tracing; } @@ -18768,8 +18766,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index; - // TODO: replace all of these checks with logic in module creation - if (!mod.backendSupportsFeature(.error_return_trace)) return; if (!block.ownerModule().error_tracing) return; // This is only relevant at runtime. @@ -18795,7 +18791,6 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) const mod = sema.mod; const ip = &mod.intern_pool; - if (!mod.backendSupportsFeature(.error_return_trace)) return; if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return; if (!start_block.ownerModule().error_tracing) return; @@ -20068,8 +20063,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { if (sema.owner_func_index != .none and ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and - block.ownerModule().error_tracing and - mod.backendSupportsFeature(.error_return_trace)) + block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); } diff --git a/src/target.zig b/src/target.zig index 4adc26aff8fc..d1a98601cf22 100644 --- a/src/target.zig +++ b/src/target.zig @@ -2,6 +2,7 @@ const std = @import("std"); const Type = @import("type.zig").Type; const AddressSpace = std.builtin.AddressSpace; const Alignment = @import("InternPool.zig").Alignment; +const Feature = @import("Module.zig").Feature; pub const default_stack_protector_buffer_size = 4; @@ -665,6 +666,24 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken }; } +pub fn backendSupportsFeature( + cpu_arch: std.Target.Cpu.Arch, + ofmt: std.Target.ObjectFormat, + use_llvm: bool, + feature: Feature, +) bool { + return switch (feature) { + .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64, + .panic_unwrap_error => ofmt == .c or use_llvm, + .safety_check_formatted => ofmt == .c or use_llvm, + .error_return_trace => use_llvm, + .is_named_enum_value => use_llvm, + .error_set_has_value => use_llvm or cpu_arch.isWasm(), + .field_reordering => use_llvm, + .safety_checked_instructions => use_llvm, + }; +} + pub fn defaultEntrySymbolName( target: std.Target, /// May be `undefined` when `target` is not WASI. From 76c47815789148eb6a95e5bd6b719fde52280e4a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 15:54:46 -0700 Subject: [PATCH 073/133] std.Build.Step.Options: update unit test to new API --- lib/std/Build/Step/Options.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 938649d83ff8..7f334a2e69c5 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -296,7 +296,7 @@ test Options { const host: std.Build.ResolvedTarget = .{ .query = .{}, - .target = try std.zig.system.resolveTargetQuery(.{}), + .result = try std.zig.system.resolveTargetQuery(.{}), }; var cache: std.Build.Cache = .{ From fad35835aac7d6ac1a3654eba631febbf8d4e82b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 15:55:04 -0700 Subject: [PATCH 074/133] CLI: better error messages for bad args --- src/main.zig | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main.zig b/src/main.zig index 8a1286bc8ea4..cf5d95f40cc6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3823,7 +3823,32 @@ fn createModule( create_module.opts.any_dyn_libs = true; create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) { - else => fatal("unable to resolve compilation options: {s}", .{@errorName(err)}), + error.WasiExecModelRequiresWasi => fatal("execution model only allowed for WASI OS targets", .{}), + error.SharedMemoryIsWasmOnly => fatal("shared memory only allowed for WebAssembly CPU targets", .{}), + error.ObjectFilesCannotShareMemory => fatal("object files cannot share memory", .{}), + error.SharedMemoryRequiresAtomicsAndBulkMemory => fatal("shared memory requires atomics and bulk_memory CPU features", .{}), + error.ThreadsRequireSharedMemory => fatal("threads require shared memory", .{}), + error.UnknownTargetEntryPoint => fatal("unknown target entry point", .{}), + error.NonExecutableEntryPoint => fatal("entry points only allowed for executables", .{}), + error.EmittingLlvmModuleRequiresLlvmBackend => fatal("emitting an LLVM module requires using the LLVM backend", .{}), + error.LlvmLacksTargetSupport => fatal("LLVM lacks support for the specified target", .{}), + error.ZigLacksTargetSupport => fatal("compiler backend unavailable for the specified target", .{}), + error.EmittingBinaryRequiresLlvmLibrary => fatal("producing machine code via LLVM requires using the LLVM library", .{}), + error.LldIncompatibleObjectFormat => fatal("using LLD to link {s} files is unsupported", .{@tagName(target.ofmt)}), + error.LtoRequiresLld => fatal("LTO requires using LLD", .{}), + error.SanitizeThreadRequiresLibCpp => fatal("thread sanitization is (for now) implemented in C++, so it requires linking libc++", .{}), + error.LibCppRequiresLibUnwind => fatal("libc++ requires linking libunwind", .{}), + error.OsRequiresLibC => fatal("the target OS requires using libc as the stable syscall interface", .{}), + error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}), + error.LibUnwindRequiresLibC => fatal("libunwind requires linking libc", .{}), + error.TargetCannotDynamicLink => fatal("dynamic linking unavailable on the specified target", .{}), + error.LibCRequiresDynamicLinking => fatal("libc of the specified target requires dynamic linking", .{}), + error.SharedLibrariesRequireDynamicLinking => fatal("using shared libraries requires dynamic linking", .{}), + error.ExportMemoryAndDynamicIncompatible => fatal("exporting memory is incompatible with dynamic linking", .{}), + error.DynamicLibraryPrecludesPie => fatal("dynamic libraries cannot be position independent executables", .{}), + error.TargetRequiresPie => fatal("the specified target requires position independent executables", .{}), + error.SanitizeThreadRequiresPie => fatal("thread sanitization requires position independent executables", .{}), + error.BackendLacksErrorTracing => fatal("the selected backend has not yet implemented error return tracing", .{}), }; } From 056f04c1ff71fe6e4cf18d7b46bc821b12d874f1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 15:59:49 -0700 Subject: [PATCH 075/133] CLI: rename clang_argv to cc_argv The args apply to Aro as well. --- src/main.zig | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main.zig b/src/main.zig index cf5d95f40cc6..577a3d3c35ab 100644 --- a/src/main.zig +++ b/src/main.zig @@ -911,7 +911,7 @@ fn buildOutputType( // These get appended to by CLI flags and then slurped when a `--mod` flag // is encountered. var cssan: ClangSearchSanitizer = .{}; - var clang_argv: std.ArrayListUnmanaged([]const u8) = .{}; + var cc_argv: std.ArrayListUnmanaged([]const u8) = .{}; var deps: std.ArrayListUnmanaged(CliModule.Dep) = .{}; // Contains every module specified via --mod. The dependencies are added @@ -1067,7 +1067,7 @@ fn buildOutputType( }, .root_src_path = fs.path.basename(root_src), }, - .cc_argv = try clang_argv.toOwnedSlice(arena), + .cc_argv = try cc_argv.toOwnedSlice(arena), .inherited = mod_opts, .target_arch_os_abi = target_arch_os_abi, .target_mcpu = target_mcpu, @@ -1226,22 +1226,22 @@ fn buildOutputType( .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-D")) { - try clang_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() }); + try cc_argv.appendSlice(arena, &.{ arg, args_iter.nextOrFatal() }); } else if (mem.eql(u8, arg, "-I")) { - try cssan.addIncludePath(arena, &clang_argv, .I, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &cc_argv, .I, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-isystem")) { - try cssan.addIncludePath(arena, &clang_argv, .isystem, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &cc_argv, .isystem, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-iwithsysroot")) { - try cssan.addIncludePath(arena, &clang_argv, .iwithsysroot, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &cc_argv, .iwithsysroot, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-idirafter")) { - try cssan.addIncludePath(arena, &clang_argv, .idirafter, arg, args_iter.nextOrFatal(), false); + try cssan.addIncludePath(arena, &cc_argv, .idirafter, arg, args_iter.nextOrFatal(), false); } else if (mem.eql(u8, arg, "-iframework")) { const path = args_iter.nextOrFatal(); - try cssan.addIncludePath(arena, &clang_argv, .iframework, arg, path, false); + try cssan.addIncludePath(arena, &cc_argv, .iframework, arg, path, false); try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "-iframeworkwithsysroot")) { const path = args_iter.nextOrFatal(); - try cssan.addIncludePath(arena, &clang_argv, .iframeworkwithsysroot, arg, path, false); + try cssan.addIncludePath(arena, &cc_argv, .iframeworkwithsysroot, arg, path, false); try create_module.framework_dirs.append(arena, path); // Forward to the backend as -F } else if (mem.eql(u8, arg, "--version")) { const next_arg = args_iter.nextOrFatal(); @@ -1268,7 +1268,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--sysroot")) { const next_arg = args_iter.nextOrFatal(); create_module.sysroot = next_arg; - try clang_argv.appendSlice(arena, &.{ "-isysroot", next_arg }); + try cc_argv.appendSlice(arena, &.{ "-isysroot", next_arg }); } else if (mem.eql(u8, arg, "--libc")) { create_module.libc_paths_file = args_iter.nextOrFatal(); } else if (mem.eql(u8, arg, "--test-filter")) { @@ -1650,9 +1650,9 @@ fn buildOutputType( .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-D")) { - try clang_argv.append(arena, arg); + try cc_argv.append(arena, arg); } else if (mem.startsWith(u8, arg, "-I")) { - try cssan.addIncludePath(arena, &clang_argv, .I, arg, arg[2..], true); + try cssan.addIncludePath(arena, &cc_argv, .I, arg, arg[2..], true); } else if (mem.eql(u8, arg, "-x")) { const lang = args_iter.nextOrFatal(); if (mem.eql(u8, lang, "none")) { @@ -1776,7 +1776,7 @@ fn buildOutputType( } }, .other => { - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); }, .positional => switch (file_ext orelse Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) { .assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .m, .mm, .cu => { @@ -1985,7 +1985,7 @@ fn buildOutputType( { mod_opts.optimize_mode = .Debug; } else { - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); } }, .debug => { @@ -1996,9 +1996,9 @@ fn buildOutputType( mem.eql(u8, it.only_arg, "gline-tables-only")) { // We handled with strip = false above. but we also want reduced debug info. - try clang_argv.append(arena, "-gline-tables-only"); + try cc_argv.append(arena, "-gline-tables-only"); } else { - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); } }, .gdwarf32 => { @@ -2015,7 +2015,7 @@ fn buildOutputType( } else if (mem.eql(u8, it.only_arg, "thread")) { mod_opts.sanitize_thread = true; } else { - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); } }, .linker_script => linker_script = it.only_arg, @@ -2024,14 +2024,14 @@ fn buildOutputType( // Have Clang print more infos, some tools such as CMake // parse this to discover any implicit include and // library dir to look-up into. - try clang_argv.append(arena, "-v"); + try cc_argv.append(arena, "-v"); }, .dry_run => { // This flag means "dry run". Clang will not actually output anything // to the file system. verbose_link = true; disable_c_depfile = true; - try clang_argv.append(arena, "-###"); + try cc_argv.append(arena, "-###"); }, .for_linker => try linker_args.append(it.only_arg), .linker_input_z => { @@ -2043,14 +2043,14 @@ fn buildOutputType( .m => try create_module.llvm_m_args.append(arena, it.only_arg), .dep_file => { disable_c_depfile = true; - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); }, .dep_file_to_stdout => { // -M, -MM // "Like -MD, but also implies -E and writes to stdout by default" // "Like -MMD, but also implies -E and writes to stdout by default" c_out_mode = .preprocessor; disable_c_depfile = true; - try clang_argv.appendSlice(arena, it.other_args); + try cc_argv.appendSlice(arena, it.other_args); }, .framework_dir => try create_module.framework_dirs.append(arena, it.only_arg), .framework => try create_module.frameworks.put(arena, it.only_arg, .{}), @@ -2595,7 +2595,7 @@ fn buildOutputType( }, .root_src_path = fs.path.basename(src_path), }, - .cc_argv = try clang_argv.toOwnedSlice(arena), + .cc_argv = try cc_argv.toOwnedSlice(arena), .inherited = mod_opts, .target_arch_os_abi = target_arch_os_abi, .target_mcpu = target_mcpu, From 3b36c4d0b30285ceb3576e621a4dc2b98a30d424 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 16:01:15 -0700 Subject: [PATCH 076/133] zig build: pass resolved_target to Module.create it's now required to pass this for the root module --- src/main.zig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.zig b/src/main.zig index 577a3d3c35ab..04cf9db12ae4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5234,11 +5234,15 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi gimmeMoreOfThoseSweetSweetFileDescriptors(); const target_query: std.Target.Query = .{}; - const target = resolveTargetQueryOrFatal(target_query); + const resolved_target: Package.Module.ResolvedTarget = .{ + .result = resolveTargetQueryOrFatal(target_query), + .is_native_os = true, + .is_native_abi = true, + }; const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", - .target = target, + .target = resolved_target.result, .output_mode = .Exe, }); const emit_bin: Compilation.EmitLoc = .{ @@ -5262,11 +5266,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi const config = try Compilation.Config.resolve(.{ .output_mode = .Exe, - .resolved_target = .{ - .result = target, - .is_native_os = true, - .is_native_abi = true, - }, + .resolved_target = resolved_target, .have_zcu = true, .emit_bin = true, .is_test = false, @@ -5277,7 +5277,9 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .paths = main_mod_paths, .fully_qualified_name = "root", .cc_argv = &.{}, - .inherited = .{}, + .inherited = .{ + .resolved_target = resolved_target, + }, .global = config, .parent = null, .builtin_mod = null, From 3262e9cceee21279f1327e36bac1b5a9a7989cea Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2023 16:21:20 -0700 Subject: [PATCH 077/133] zig build: fix logic for extracting executable file from Compilation --- src/main.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.zig b/src/main.zig index 04cf9db12ae4..c165f724b893 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5478,10 +5478,12 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi error.SemanticAnalyzeFail => process.exit(2), else => |e| return e, }; - try comp.makeBinFileExecutable(); - const emit = comp.bin_file.?.emit; - child_argv.items[argv_index_exe] = try emit.directory.join(arena, &.{emit.sub_path}); + // Since incremental compilation isn't done yet, we use cache_mode = whole + // above, and thus the output file is already closed. + //try comp.makeBinFileExecutable(); + child_argv.items[argv_index_exe] = + try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); break :argv child_argv.items; }; From e12e29630664a78a32103d56175162381443b574 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 23 Dec 2023 23:52:16 -0700 Subject: [PATCH 078/133] CLI: fix not respecting module remappings --- src/main.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.zig b/src/main.zig index c165f724b893..4da79536e0de 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1059,7 +1059,7 @@ fn buildOutputType( create_module.opts.any_error_tracing = true; const root_src = try introspect.resolvePath(arena, root_src_orig); - try create_module.modules.put(arena, mod_name, .{ + gop.value_ptr.* = .{ .paths = .{ .root = .{ .root_dir = Cache.Directory.cwd(), @@ -1077,7 +1077,7 @@ fn buildOutputType( .c_source_files_end = create_module.c_source_files.items.len, .rc_source_files_start = rc_source_files_owner_index, .rc_source_files_end = create_module.rc_source_files.items.len, - }); + }; cssan.reset(); mod_opts = .{}; target_arch_os_abi = null; @@ -3882,7 +3882,7 @@ fn createModule( for (create_module.rc_source_files.items[cli_mod.rc_source_files_start..cli_mod.rc_source_files_end]) |*item| item.owner = mod; for (cli_mod.deps) |dep| { - const dep_index = create_module.modules.getIndex(dep.key) orelse + const dep_index = create_module.modules.getIndex(dep.value) orelse fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key }); const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory); try mod.deps.put(arena, dep.key, dep_mod); From 9141e1a29c8e1b3334a1ea3cdf85fe6df9cac2b4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 18:30:38 -0700 Subject: [PATCH 079/133] CLI: fix logic for sending output file path via the compiler protocol --- src/Compilation.zig | 14 ++------ src/main.zig | 78 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index f825d8c93079..c24868560143 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1198,16 +1198,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const use_llvm = options.config.use_llvm; - // TODO: once we support incremental compilation for the LLVM backend via - // saving the LLVM module into a bitcode file and restoring it, along with - // compiler state, the second clause here can be removed so that incremental - // cache mode is used for LLVM backend too. We need some fuzz testing before - // that can be enabled. - const cache_mode = if ((use_llvm or !have_zcu) and !options.disable_lld_caching) - CacheMode.whole - else - options.cache_mode; - const any_unwind_tables = options.config.any_unwind_tables; const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; @@ -1560,7 +1550,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .compatibility_version = options.compatibility_version, .each_lib_rpath = each_lib_rpath, .build_id = build_id, - .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, + .disable_lld_caching = options.disable_lld_caching or options.cache_mode == .whole, .subsystem = options.subsystem, .hash_style = options.hash_style, .enable_link_snapshots = options.enable_link_snapshots, @@ -1576,7 +1566,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .entry_addr = null, // CLI does not expose this option (yet?) }; - switch (cache_mode) { + switch (options.cache_mode) { .incremental => { // Options that are specific to zig source files, that cannot be // modified between incremental updates. diff --git a/src/main.zig b/src/main.zig index 4da79536e0de..50743b92f083 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3110,6 +3110,21 @@ fn buildOutputType( else => false, }; + const disable_lld_caching = !output_to_cache; + + const cache_mode: Compilation.CacheMode = b: { + if (disable_lld_caching) break :b .incremental; + if (!create_module.resolved_options.have_zcu) break :b .whole; + + // TODO: once we support incremental compilation for the LLVM backend + // via saving the LLVM module into a bitcode file and restoring it, + // along with compiler state, this clause can be removed so that + // incremental cache mode is used for LLVM backend too. + if (create_module.resolved_options.use_llvm) break :b .whole; + + break :b .incremental; + }; + gimmeMoreOfThoseSweetSweetFileDescriptors(); const comp = Compilation.create(gpa, .{ @@ -3211,7 +3226,8 @@ fn buildOutputType( .test_filter = test_filter, .test_name_prefix = test_name_prefix, .test_runner_path = test_runner_path, - .disable_lld_caching = !output_to_cache, + .disable_lld_caching = disable_lld_caching, + .cache_mode = cache_mode, .subsystem = subsystem, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, @@ -3942,7 +3958,7 @@ fn serve( const hdr = try server.receiveMessage(); switch (hdr.tag) { - .exit => return, + .exit => return cleanExit(), .update => { assert(main_progress_node.recently_updated_child == null); tracy.frameMark(); @@ -4104,25 +4120,63 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { try s.serveErrorBundle(error_bundle); return; } - // This logic is a bit counter-intuitive because the protocol implies that - // each emitted artifact could possibly be in a different location, when in - // reality, there is only one artifact output directory, and the build - // system depends on that fact. So, until the protocol is changed to - // reflect this, this logic only needs to ensure that emit_bin_path is - // emitted for at least one thing, if there are any artifacts. - if (comp.bin_file) |lf| { - const emit = lf.emit; + + // This logic is counter-intuitive because the protocol accounts for each + // emitted artifact possibly being in a different location, which correctly + // matches the behavior of the compiler, however, the build system + // currently always passes flags that makes all build artifacts output to + // the same local cache directory, and relies on them all being in the same + // directory. + // + // So, until the build system and protocol are changed to reflect this, + // this logic must ensure that emit_bin_path is emitted for at least one + // thing, if there are any artifacts. + + switch (comp.cache_use) { + .incremental => if (comp.bin_file) |lf| { + const full_path = try lf.emit.directory.join(gpa, &.{lf.emit.sub_path}); + defer gpa.free(full_path); + try s.serveEmitBinPath(full_path, .{ + .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, + }); + return; + }, + .whole => |whole| if (whole.bin_sub_path) |sub_path| { + const full_path = try comp.local_cache_directory.join(gpa, &.{sub_path}); + defer gpa.free(full_path); + try s.serveEmitBinPath(full_path, .{ + .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, + }); + return; + }, + } + + for ([_]?Compilation.Emit{ + comp.docs_emit, + comp.implib_emit, + }) |opt_emit| { + const emit = opt_emit orelse continue; const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); defer gpa.free(full_path); try s.serveEmitBinPath(full_path, .{ .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, }); - } else if (comp.docs_emit) |emit| { - const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); + return; + } + + for ([_]?Compilation.EmitLoc{ + comp.emit_asm, + comp.emit_llvm_ir, + comp.emit_llvm_bc, + }) |opt_emit_loc| { + const emit_loc = opt_emit_loc orelse continue; + const directory = emit_loc.directory orelse continue; + const full_path = try directory.join(gpa, &.{emit_loc.basename}); defer gpa.free(full_path); try s.serveEmitBinPath(full_path, .{ .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, }); + return; } } From 24eec48f60c2002e491d78a5c199a4c39d50e48a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 18:42:26 -0700 Subject: [PATCH 080/133] CLI: update main usage text * Organize and reword some stuff * Add missing usage for `zig reduce` --- src/main.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.zig b/src/main.zig index 50743b92f083..1811399da31e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -87,13 +87,15 @@ const normal_usage = \\ fetch Copy a package into global cache and print its hash \\ init Initialize a Zig package in the current directory \\ - \\ ast-check Look for simple compile errors in any set of files \\ build-exe Create executable from source or object files \\ build-lib Create library from source or object files \\ build-obj Create object from source or object files - \\ fmt Reformat Zig source into canonical form + \\ test Perform unit testing \\ run Create executable and run immediately - \\ test Create and run a test build + \\ + \\ ast-check Look for simple compile errors in any set of files + \\ fmt Reformat Zig source into canonical form + \\ reduce Minimize a bug report \\ translate-c Convert C code to Zig code \\ \\ ar Use Zig as a drop-in archiver From 8cf2cfc52c23fec8de2fa8ca54c2589daed2135b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:18:52 -0700 Subject: [PATCH 081/133] update bootstrap scripts to new zig CLI Now they use the new --mod --dep parameters. --- CMakeLists.txt | 41 +++++++++++++++++++++++++---------------- bootstrap.c | 36 ++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 202c5d1861aa..0108f448dfb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -810,18 +810,26 @@ endif() set(BUILD_ZIG2_ARGS "${CMAKE_SOURCE_DIR}/lib" - build-exe src/main.zig -ofmt=c -lc - -OReleaseSmall - --name zig2 -femit-bin="${ZIG2_C_SOURCE}" - --mod "build_options::${ZIG_CONFIG_ZIG_OUT}" - --mod "aro_options::src/stubs/aro_options.zig" - --mod "Builtins/Builtin.def::src/stubs/aro_builtins.zig" - --mod "Attribute/names.def::src/stubs/aro_names.zig" - --mod "Diagnostics/messages.def::src/stubs/aro_messages.zig" - --mod "aro_backend:build_options=aro_options:deps/aro/backend.zig" - --mod "aro:Builtins/Builtin.def,Attribute/names.def,Diagnostics/messages.def,build_options=aro_options,backend=aro_backend:deps/aro/aro.zig" - --deps build_options,aro + build-exe -ofmt=c -lc -OReleaseSmall + --name zig2 + -femit-bin="${ZIG2_C_SOURCE}" -target "${ZIG_HOST_TARGET_TRIPLE}" + --dep "build_options" + --dep "aro" + --mod "root" "src/main.zig" + --mod "build_options" "${ZIG_CONFIG_ZIG_OUT}" + --mod "aro_options" "src/stubs/aro_options.zig" + --mod "Builtins/Builtin.def" "src/stubs/aro_builtins.zig" + --mod "Attribute/names.def" "src/stubs/aro_names.zig" + --mod "Diagnostics/messages.def" "src/stubs/aro_messages.zig" + --dep "build_options=aro_options" + --mod "aro_backend" "deps/aro/backend.zig" + --dep "Builtins/Builtin.def" + --dep "Attribute/names.def" + --dep "Diagnostics/messages.def" + --dep "build_options=aro_options" + --dep "backend=aro_backend" + --mod "aro" "deps/aro/aro.zig" ) add_custom_command( @@ -834,12 +842,13 @@ add_custom_command( set(BUILD_COMPILER_RT_ARGS "${CMAKE_SOURCE_DIR}/lib" - build-obj lib/compiler_rt.zig -ofmt=c - -OReleaseSmall - --name compiler_rt -femit-bin="${ZIG_COMPILER_RT_C_SOURCE}" - --mod "build_options::${ZIG_CONFIG_ZIG_OUT}" - --deps build_options + build-obj -ofmt=c -OReleaseSmall + --name compiler_rt + -femit-bin="${ZIG_COMPILER_RT_C_SOURCE}" -target "${ZIG_HOST_TARGET_TRIPLE}" + --dep "build_options" + --mod "root" "lib/compiler_rt.zig" + --mod "build_options" "${ZIG_CONFIG_ZIG_OUT}" ) add_custom_command( diff --git a/bootstrap.c b/bootstrap.c index 08fff00b2d06..c6236b3d2772 100644 --- a/bootstrap.c +++ b/bootstrap.c @@ -138,18 +138,29 @@ int main(int argc, char **argv) { { const char *child_argv[] = { - "./zig1", "lib", "build-exe", "src/main.zig", + "./zig1", "lib", "build-exe", "-ofmt=c", "-lc", "-OReleaseSmall", "--name", "zig2", "-femit-bin=zig2.c", - "--mod", "build_options::config.zig", - "--mod", "aro_options::src/stubs/aro_options.zig", - "--mod", "Builtins/Builtin.def::src/stubs/aro_builtins.zig", - "--mod", "Attribute/names.def::src/stubs/aro_names.zig", - "--mod", "Diagnostics/messages.def::src/stubs/aro_messages.zig", - "--mod", "aro_backend:build_options=aro_options:deps/aro/backend.zig", - "--mod", "aro:Builtins/Builtin.def,Attribute/names.def,Diagnostics/messages.def,build_options=aro_options,backend=aro_backend:deps/aro/aro.zig", - "--deps", "build_options,aro", "-target", host_triple, + "--dep", "build_options", + "--dep", "aro", + "--mod", "root", "src/main.zig", + + "--mod", "build_options", "config.zig", + "--mod", "aro_options", "src/stubs/aro_options.zig", + "--mod", "Builtins/Builtin.def", "src/stubs/aro_builtins.zig", + "--mod", "Attribute/names.def", "src/stubs/aro_names.zig", + "--mod", "Diagnostics/messages.def", "src/stubs/aro_messages.zig", + + "--dep", "build_options=aro_options", + "--mod", "aro_backend", "deps/aro/backend.zig", + + "--dep", "Builtins/Builtin.def", + "--dep", "Attribute/names.def", + "--dep", "Diagnostics/messages.def", + "--dep", "build_options=aro_options", + "--dep", "backend=aro_backend", + "--mod", "aro", "deps/aro/aro.zig", NULL, }; print_and_run(child_argv); @@ -157,12 +168,13 @@ int main(int argc, char **argv) { { const char *child_argv[] = { - "./zig1", "lib", "build-obj", "lib/compiler_rt.zig", + "./zig1", "lib", "build-obj", "-ofmt=c", "-OReleaseSmall", "--name", "compiler_rt", "-femit-bin=compiler_rt.c", - "--mod", "build_options::config.zig", - "--deps", "build_options", "-target", host_triple, + "--dep", "build_options", + "--mod", "root", "lib/compiler_rt.zig", + "--mod", "build_options", "config.zig", NULL, }; print_and_run(child_argv); From 41ab64c3eb7a104e78ca96cfe861a03f3a150d47 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:20:03 -0700 Subject: [PATCH 082/133] Compilation.Config.resolve: explicit error set Some logic has comptime-known conditions, causing the inferred error set to be different on different compiler build configurations. --- src/Compilation/Config.zig | 34 +++++++++++++++++++++++++++++++++- src/main.zig | 3 +++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index fc4b774baad7..4abc27029d67 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -99,7 +99,39 @@ pub const Options = struct { rdynamic: ?bool = null, }; -pub fn resolve(options: Options) !Config { +pub const ResolveError = error{ + WasiExecModelRequiresWasi, + SharedMemoryIsWasmOnly, + ObjectFilesCannotShareMemory, + SharedMemoryRequiresAtomicsAndBulkMemory, + ThreadsRequireSharedMemory, + UnknownTargetEntryPoint, + NonExecutableEntryPoint, + EmittingLlvmModuleRequiresLlvmBackend, + LlvmLacksTargetSupport, + ZigLacksTargetSupport, + EmittingBinaryRequiresLlvmLibrary, + LldIncompatibleObjectFormat, + LtoRequiresLld, + SanitizeThreadRequiresLibCpp, + LibCppRequiresLibUnwind, + OsRequiresLibC, + LibCppRequiresLibC, + LibUnwindRequiresLibC, + TargetCannotDynamicLink, + LibCRequiresDynamicLinking, + SharedLibrariesRequireDynamicLinking, + ExportMemoryAndDynamicIncompatible, + DynamicLibraryPrecludesPie, + TargetRequiresPie, + SanitizeThreadRequiresPie, + BackendLacksErrorTracing, + LlvmLibraryUnavailable, + LldUnavailable, + ClangUnavailable, +}; + +pub fn resolve(options: Options) ResolveError!Config { const target = options.resolved_target.result; // WASI-only. Resolve the optional exec-model option, defaults to command. diff --git a/src/main.zig b/src/main.zig index 1811399da31e..8f235e12334a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3867,6 +3867,9 @@ fn createModule( error.TargetRequiresPie => fatal("the specified target requires position independent executables", .{}), error.SanitizeThreadRequiresPie => fatal("thread sanitization requires position independent executables", .{}), error.BackendLacksErrorTracing => fatal("the selected backend has not yet implemented error return tracing", .{}), + error.LlvmLibraryUnavailable => fatal("zig was compiled without LLVM libraries", .{}), + error.LldUnavailable => fatal("zig was compiled without LLD libraries", .{}), + error.ClangUnavailable => fatal("zig was compiled without Clang libraries", .{}), }; } From edccd68adf58273f44c57ef0d609ec09cc3fb41e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:20:41 -0700 Subject: [PATCH 083/133] Package.Module: fix typo in default red-zone setting oops, this was supposed to return true, not false. --- src/Package/Module.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 0ebd951cc66d..3c3a1c81e6da 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -187,7 +187,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { if (!target_util.hasRedZone(target)) { if (options.inherited.red_zone == true) return error.TargetHasNoRedZone; - break :b true; + break :b false; } if (options.inherited.red_zone) |x| break :b x; if (options.parent) |p| break :b p.red_zone; From 4d28db7329c32d7a2b7915d7a5da7f93c4088ccd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:21:18 -0700 Subject: [PATCH 084/133] Zcu: mark outdated decl handling as unreachable from only_c builds This way we don't drag in linker code into only_c builds that doesn't need to be there. --- src/Module.zig | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index 86c124e3b57f..bf278fb9b58b 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3167,6 +3167,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { .complete => return, .outdated => blk: { + if (build_options.only_c) unreachable; // The exports this Decl performs will be re-discovered, so we remove them here // prior to re-analysis. try mod.deleteDeclExports(decl_index); @@ -4678,25 +4679,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato }; } -fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { - const decl = mod.declPtr(decl_index); - try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index }); - if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| { - kv.value.destroy(mod.gpa); - } - if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| { - var errors = kv.value; - errors.deinit(mod.gpa); - } - if (mod.emit_h) |emit_h| { - if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { - kv.value.destroy(mod.gpa); - } - } - _ = mod.compile_log_decls.swapRemove(decl_index); - decl.analysis = .outdated; -} - pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { return mod.intern_pool.createNamespace(mod.gpa, initialization); } From 981166e33f967c62971de1aee79779fcfb3e37b7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:47:34 -0700 Subject: [PATCH 085/133] link.Elf: truncate=true in createEmpty --- src/link/Elf.zig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 6cb6a98250de..eb08fe2855ca 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -264,12 +264,10 @@ pub fn createEmpty( // If using LLVM to generate the object file for the zig compilation unit, // we need a place to put the object file so that it can be subsequently // handled. - const zcu_object_sub_path = if (!use_lld and !use_llvm) null else p: { - const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - emit.sub_path, target.ofmt.fileExt(target.cpu.arch), - }); - break :p o_file_path; - }; + const zcu_object_sub_path = if (!use_lld and !use_llvm) + null + else + try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); const self = try arena.create(Elf); self.* = .{ @@ -343,7 +341,7 @@ pub fn createEmpty( // can be passed to LLD. const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; self.base.file = try emit.directory.handle.createFile(sub_path, .{ - .truncate = false, + .truncate = true, .read = true, .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); @@ -431,6 +429,8 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Elf { + // TODO: restore saved linker state, don't truncate the file, and + // participate in incremental compilation. return createEmpty(arena, comp, emit, options); } From 1edcea9ec80d9ca6fd9700ef605cfa9c3722817b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:48:01 -0700 Subject: [PATCH 086/133] link.Wasm: fix relationship between createEmpty/open --- src/link/Wasm.zig | 108 +++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index cf41110307f3..edc4ada40527 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -377,6 +377,17 @@ pub fn open( comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, +) !*Wasm { + // TODO: restore saved linker state, don't truncate the file, and + // participate in incremental compilation. + return createEmpty(arena, comp, emit, options); +} + +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, ) !*Wasm { const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; @@ -387,7 +398,46 @@ pub fn open( const output_mode = comp.config.output_mode; const shared_memory = comp.config.shared_memory; - const wasm = try createEmpty(arena, comp, emit, options); + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + // If using LLVM to generate the object file for the zig compilation unit, + // we need a place to put the object file so that it can be subsequently + // handled. + const zcu_object_sub_path = if (!use_lld and !use_llvm) + null + else + try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); + + const wasm = try arena.create(Wasm); + wasm.* = .{ + .base = .{ + .tag = .wasm, + .comp = comp, + .emit = emit, + .zcu_object_sub_path = zcu_object_sub_path, + .gc_sections = options.gc_sections orelse (output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, + .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, + .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + }, + .name = undefined, + .import_table = options.import_table, + .export_table = options.export_table, + .import_symbols = options.import_symbols, + .export_symbol_names = options.export_symbol_names, + .global_base = options.global_base, + .initial_memory = options.initial_memory, + .max_memory = options.max_memory, + .wasi_emulated_libs = options.wasi_emulated_libs, + }; + if (use_llvm and comp.config.have_zcu) { + wasm.llvm_object = try LlvmObject.create(arena, comp); + } errdefer wasm.base.destroy(); if (use_lld and use_llvm) { @@ -395,17 +445,11 @@ pub fn open( return wasm; } - const sub_path = if (!use_lld) emit.sub_path else p: { - // Open a temporary object file, not the final output file because we - // want to link with LLD. - const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - emit.sub_path, target.ofmt.fileExt(target.cpu.arch), - }); - wasm.base.zcu_object_sub_path = o_file_path; - break :p o_file_path; - }; + // What path should this Wasm linker code output to? + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; - // TODO: read the file and keep valid parts instead of truncating const file = try emit.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, @@ -532,48 +576,6 @@ pub fn open( return wasm; } -pub fn createEmpty( - arena: Allocator, - comp: *Compilation, - emit: Compilation.Emit, - options: link.File.OpenOptions, -) !*Wasm { - const use_llvm = comp.config.use_llvm; - const output_mode = comp.config.output_mode; - - const wasm = try arena.create(Wasm); - wasm.* = .{ - .base = .{ - .tag = .wasm, - .comp = comp, - .emit = emit, - .gc_sections = options.gc_sections orelse (output_mode != .Obj), - .print_gc_sections = options.print_gc_sections, - .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB - .allow_shlib_undefined = options.allow_shlib_undefined orelse false, - .file = null, - .disable_lld_caching = options.disable_lld_caching, - .build_id = options.build_id, - .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, - }, - .name = undefined, - .import_table = options.import_table, - .export_table = options.export_table, - .import_symbols = options.import_symbols, - .export_symbol_names = options.export_symbol_names, - .global_base = options.global_base, - .initial_memory = options.initial_memory, - .max_memory = options.max_memory, - .wasi_emulated_libs = options.wasi_emulated_libs, - }; - - if (use_llvm) { - wasm.llvm_object = try LlvmObject.create(arena, comp); - } - return wasm; -} - /// For a given name, creates a new global synthetic symbol. /// Leaves index undefined and the default flags (0). fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc { From 44e2dbe117fe79b99a970990878a061bdd26ff55 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 20:11:58 -0700 Subject: [PATCH 087/133] fix logic for default entry point when linking libc, the entry point is within libc. when producing C code, the entry point is decided when compiling the C code and does not need to be known up front. fixes a false positive "error: unknown target entry point" when using -ofmt=c. --- src/Compilation/Config.zig | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 4abc27029d67..811d37a2db9f 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -161,20 +161,6 @@ pub fn resolve(options: Options) ResolveError!Config { break :b options.shared_memory orelse false; }; - const entry: ?[]const u8 = switch (options.entry) { - .disabled => null, - .default => b: { - if (options.output_mode != .Exe) break :b null; - break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse - return error.UnknownTargetEntryPoint; - }, - .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse - return error.UnknownTargetEntryPoint, - .named => |name| name, - }; - if (entry != null and options.output_mode != .Exe) - return error.NonExecutableEntryPoint; - // *If* the LLVM backend were to be selected, should Zig use the LLVM // library to build the LLVM module? const use_lib_llvm = b: { @@ -348,6 +334,29 @@ pub fn resolve(options: Options) ResolveError!Config { break :b false; }; + const entry: ?[]const u8 = switch (options.entry) { + .disabled => null, + .default => b: { + if (options.output_mode != .Exe) break :b null; + + // When linking libc, the entry point is inside libc and not in the + // zig compilation unit. + if (link_libc) break :b null; + + // When producing C source code, the decision of entry point is made + // when compiling the C code, not when producing the C code. + if (target.ofmt == .c) break :b null; + + break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse + return error.UnknownTargetEntryPoint; + }, + .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse + return error.UnknownTargetEntryPoint, + .named => |name| name, + }; + if (entry != null and options.output_mode != .Exe) + return error.NonExecutableEntryPoint; + const any_unwind_tables = options.any_unwind_tables or link_libunwind or target_util.needUnwindTables(target); From 4f8a44cd0f636f3ffe008b2cedafa1e51a4a3796 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 21:50:37 -0700 Subject: [PATCH 088/133] compiler: fix UAF when writing builtin.zig --- src/Builtin.zig | 3 ++- src/Package.zig | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Builtin.zig b/src/Builtin.zig index 8a3a1ecf4b21..dc9ccc22c4df 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -279,7 +279,8 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { } fn writeFile(file: *File, mod: *Module) !void { - var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }); + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); defer af.deinit(); try af.file.writeAll(file.source); try af.finish(); diff --git a/src/Package.zig b/src/Package.zig index 373b46e495a7..da2e214154b4 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -88,10 +88,10 @@ pub const Path = struct { p: Path, sub_path: []const u8, options: fs.Dir.AtomicFileOptions, + buf: *[fs.MAX_PATH_BYTES]u8, ) !fs.AtomicFile { - var buf: [fs.MAX_PATH_BYTES]u8 = undefined; const joined_path = if (p.sub_path.len == 0) sub_path else p: { - break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ + break :p std.fmt.bufPrint(buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ p.sub_path, sub_path, }) catch return error.NameTooLong; }; From 98dd4f7847c0d50c3367a3bf12a80d5bf7b1fed2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 21:51:11 -0700 Subject: [PATCH 089/133] frontend: skip astgen for builtin.zig since it's already done ahead of time and always unchanging --- src/Compilation.zig | 7 +++---- src/Module.zig | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index c24868560143..00d6ec3193cb 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2131,11 +2131,10 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Put a work item in for every known source file to detect if // it changed, and, if so, re-compute ZIR and then queue the job // to update it. - // We still want AstGen work items for stage1 so that we expose compile errors - // that are implemented in stage2 but not stage1. try comp.astgen_work_queue.ensureUnusedCapacity(module.import_table.count()); - for (module.import_table.values()) |value| { - comp.astgen_work_queue.writeItemAssumeCapacity(value); + for (module.import_table.values()) |file| { + if (file.mod.isBuiltin()) continue; + comp.astgen_work_queue.writeItemAssumeCapacity(file); } // Put a work item in for checking if any files used with `@embedFile` changed. diff --git a/src/Module.zig b/src/Module.zig index bf278fb9b58b..9d5f4a69d2fa 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2637,6 +2637,8 @@ comptime { } pub fn astGenFile(mod: *Module, file: *File) !void { + assert(!file.mod.isBuiltin()); + const tracy = trace(@src()); defer tracy.end(); From 944b0ef5188a066c9fe11a297c743bfb3301a02a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 23:02:39 -0700 Subject: [PATCH 090/133] link.File.Coff: fix relationship between createEmpty/open similar commit to b0c433c80f2e4edd7b60e444b4ea56dacb727051 --- src/link/Coff.zig | 170 +++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 75feeeab4637..6db49713fcef 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -235,7 +235,7 @@ const ideal_factor = 3; const minimum_text_block_size = 64; pub const min_text_capacity = padToIdeal(minimum_text_block_size); -pub fn open( +pub fn createEmpty( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, @@ -243,36 +243,96 @@ pub fn open( ) !*Coff { const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .coff); + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const use_llvm = comp.config.use_llvm; + const use_lld = build_options.have_llvm and comp.config.use_lld; - const self = try createEmpty(arena, comp, emit, options); - errdefer self.base.destroy(); + const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { + 0...32 => .p32, + 33...64 => .p64, + else => return error.UnsupportedCOFFArchitecture, + }; + const page_size: u32 = switch (target.cpu.arch) { + else => 0x1000, + }; - const use_lld = build_options.have_llvm and comp.config.use_lld; - const use_llvm = comp.config.use_llvm; + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + // If using LLVM to generate the object file for the zig compilation unit, + // we need a place to put the object file so that it can be subsequently + // handled. + const zcu_object_sub_path = if (!use_lld and !use_llvm) + null + else + try std.fmt.allocPrint(arena, "{s}.obj", .{emit.sub_path}); + + const self = try arena.create(Coff); + self.* = .{ + .base = .{ + .tag = .coff, + .comp = comp, + .emit = emit, + .zcu_object_sub_path = zcu_object_sub_path, + .stack_size = options.stack_size orelse 16777216, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, + .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + }, + .ptr_width = ptr_width, + .page_size = page_size, + + .data_directories = [1]coff.ImageDataDirectory{.{ + .virtual_address = 0, + .size = 0, + }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, + + .image_base = options.image_base orelse switch (output_mode) { + .Exe => switch (target.cpu.arch) { + .aarch64 => 0x140000000, + .x86_64, .x86 => 0x400000, + else => unreachable, + }, + .Lib => 0x10000000, + .Obj => 0, + }, + + .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, + .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse + return error.EntryAddressTooBig, + .module_definition_file = options.module_definition_file, + .pdb_out_path = options.pdb_out_path, + }; + if (use_llvm and comp.config.have_zcu) { + self.llvm_object = try LlvmObject.create(arena, comp); + } + errdefer self.base.destroy(); if (use_lld and use_llvm) { // LLVM emits the object file; LLD links it into the final product. return self; } - const sub_path = if (!use_lld) emit.sub_path else p: { - // Open a temporary object file, not the final output file because we - // want to link with LLD. - const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ - emit.sub_path, target.ofmt.fileExt(target.cpu.arch), - }); - self.base.zcu_object_sub_path = o_file_path; - break :p o_file_path; - }; - + // What path should this COFF linker code output to? + // If using LLD to link, this code should produce an object file so that it + // can be passed to LLD. + const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; self.base.file = try emit.directory.handle.createFile(sub_path, .{ - .truncate = false, + .truncate = true, .read = true, - .mode = link.File.determineMode( - use_lld, - comp.config.output_mode, - comp.config.link_mode, - ), + .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); assert(self.llvm_object == null); @@ -367,75 +427,15 @@ pub fn open( return self; } -pub fn createEmpty( +pub fn open( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Coff { - const target = comp.root_mod.resolved_target.result; - const optimize_mode = comp.root_mod.optimize_mode; - const output_mode = comp.config.output_mode; - const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { - 0...32 => .p32, - 33...64 => .p64, - else => return error.UnsupportedCOFFArchitecture, - }; - const page_size: u32 = switch (target.cpu.arch) { - else => 0x1000, - }; - const self = try arena.create(Coff); - self.* = .{ - .base = .{ - .tag = .coff, - .comp = comp, - .emit = emit, - .stack_size = options.stack_size orelse 16777216, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), - .print_gc_sections = options.print_gc_sections, - .allow_shlib_undefined = options.allow_shlib_undefined orelse false, - .file = null, - .disable_lld_caching = options.disable_lld_caching, - .build_id = options.build_id, - .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, - }, - .ptr_width = ptr_width, - .page_size = page_size, - - .data_directories = [1]coff.ImageDataDirectory{.{ - .virtual_address = 0, - .size = 0, - }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, - - .image_base = options.image_base orelse switch (output_mode) { - .Exe => switch (target.cpu.arch) { - .aarch64 => 0x140000000, - .x86_64, .x86 => 0x400000, - else => unreachable, - }, - .Lib => 0x10000000, - .Obj => 0, - }, - - .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, - .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse - return error.EntryAddressTooBig, - .module_definition_file = options.module_definition_file, - .pdb_out_path = options.pdb_out_path, - }; - - const use_llvm = comp.config.use_llvm; - if (use_llvm and comp.config.have_zcu) { - self.llvm_object = try LlvmObject.create(arena, comp); - } - return self; + // TODO: restore saved linker state, don't truncate the file, and + // participate in incremental compilation. + return createEmpty(arena, comp, emit, options); } pub fn deinit(self: *Coff) void { From b36659c972fb7d75b1e34cb668770353de27db7d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 25 Dec 2023 00:01:52 -0700 Subject: [PATCH 091/133] fix MachO linking * fix relationship between createEmpty/open (similar logic as 607111aa758002bc51914b7dc800b23927c931b8) * still resolve the start symbol when linking libc because when zig is the linker it still needs to know the entry symbol. * make use_llvm=false when there is no zig compilation unit. --- src/Compilation/Config.zig | 12 ++-- src/link/Coff.zig | 4 +- src/link/Elf.zig | 4 +- src/link/MachO.zig | 143 +++++++++++++++++-------------------- src/link/Wasm.zig | 4 +- 5 files changed, 75 insertions(+), 92 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 811d37a2db9f..367187b6588d 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -178,6 +178,9 @@ pub fn resolve(options: Options) ResolveError!Config { // For example, Zig can emit .bc and .ll files directly, and this is still considered // using "the LLVM backend". const use_llvm = b: { + // If we have no zig code to compile, no need for LLVM. + if (!options.have_zcu) break :b false; + // If emitting to LLVM bitcode object format, must use LLVM backend. if (options.emit_llvm_ir or options.emit_llvm_bc) { if (options.use_llvm == false) @@ -202,13 +205,10 @@ pub fn resolve(options: Options) ResolveError!Config { if (options.use_llvm) |x| break :b x; - // If we have no zig code to compile, no need for LLVM. - if (!options.have_zcu) break :b false; - // If we cannot use LLVM libraries, then our own backends will be a // better default since the LLVM backend can only produce bitcode // and not an object file or executable. - if (!use_lib_llvm) break :b false; + if (!use_lib_llvm and options.emit_bin) break :b false; // Prefer LLVM for release builds. if (root_optimize_mode != .Debug) break :b true; @@ -339,10 +339,6 @@ pub fn resolve(options: Options) ResolveError!Config { .default => b: { if (options.output_mode != .Exe) break :b null; - // When linking libc, the entry point is inside libc and not in the - // zig compilation unit. - if (link_libc) break :b null; - // When producing C source code, the decision of entry point is made // when compiling the C code, not when producing the C code. if (target.ofmt == .c) break :b null; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 6db49713fcef..861ec030b36d 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -320,8 +320,8 @@ pub fn createEmpty( } errdefer self.base.destroy(); - if (use_lld and use_llvm) { - // LLVM emits the object file; LLD links it into the final product. + if (use_lld and (use_llvm or !comp.config.have_zcu)) { + // LLVM emits the object file (if any); LLD links it into the final product. return self; } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index eb08fe2855ca..378c8cbd5a65 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -328,8 +328,8 @@ pub fn createEmpty( } errdefer self.base.destroy(); - if (use_lld and use_llvm) { - // LLVM emits the object file; LLD links it into the final product. + if (use_lld and (use_llvm or !comp.config.have_zcu)) { + // LLVM emits the object file (if any); LLD links it into the final product. return self; } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 0964859c284a..d8fc71c0f07b 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -174,72 +174,97 @@ pub const SdkLayout = enum { vendored, }; -pub fn open( +pub fn createEmpty( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, ) !*MachO { const target = comp.root_mod.resolved_target.result; - const use_lld = build_options.have_llvm and comp.config.use_lld; - const use_llvm = comp.config.use_llvm; assert(target.ofmt == .macho); - + const use_llvm = comp.config.use_llvm; const gpa = comp.gpa; - const mode: Mode = mode: { - if (use_llvm or comp.module == null or comp.cache_use == .whole) - break :mode .zld; - break :mode .incremental; - }; - const sub_path = if (mode == .zld) blk: { - if (comp.module == null) { - // No point in opening a file, we would not write anything to it. - // Initialize with empty. - return createEmpty(arena, comp, emit, options); - } - // Open a temporary object file, not the final output file because we - // want to link with LLD. - break :blk try std.fmt.allocPrint(arena, "{s}{s}", .{ - emit.sub_path, target.ofmt.fileExt(target.cpu.arch), - }); - } else emit.sub_path; + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; - const self = try createEmpty(arena, comp, emit, options); + // TODO: get rid of zld mode + const mode: Mode = if (use_llvm or !comp.config.have_zcu or comp.cache_use == .whole) + .zld + else + .incremental; + + // If using "zld mode" to link, this code should produce an object file so that it + // can be passed to "zld mode". TODO: get rid of "zld mode". + // If using LLVM to generate the object file for the zig compilation unit, + // we need a place to put the object file so that it can be subsequently + // handled. + const zcu_object_sub_path = if (mode != .zld and !use_llvm) + null + else + try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path}); + + const self = try arena.create(MachO); + self.* = .{ + .base = .{ + .tag = .macho, + .comp = comp, + .emit = emit, + .zcu_object_sub_path = zcu_object_sub_path, + .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, + .stack_size = options.stack_size orelse 16777216, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, + .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, + .force_undefined_symbols = options.force_undefined_symbols, + }, + .mode = mode, + .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, + .headerpad_size = options.headerpad_size orelse default_headerpad_size, + .headerpad_max_install_names = options.headerpad_max_install_names, + .dead_strip_dylibs = options.dead_strip_dylibs, + .sdk_layout = options.darwin_sdk_layout, + .frameworks = options.frameworks, + .install_name = options.install_name, + .entitlements = options.entitlements, + .compatibility_version = options.compatibility_version, + }; + if (use_llvm and comp.config.have_zcu) { + self.llvm_object = try LlvmObject.create(arena, comp); + } errdefer self.base.destroy(); + log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); + if (mode == .zld) { - // TODO this zcu_object_sub_path isn't enough; in the case of `zig build-exe`, - // we also want to put the intermediary object file in the cache while the - // main emit directory is the cwd. - self.base.zcu_object_sub_path = sub_path; + // TODO: get rid of zld mode return self; } - const file = try emit.directory.handle.createFile(sub_path, .{ - .truncate = false, + const file = try emit.directory.handle.createFile(emit.sub_path, .{ + .truncate = true, .read = true, - .mode = link.File.determineMode( - use_lld, - comp.config.output_mode, - comp.config.link_mode, - ), + .mode = link.File.determineMode(false, output_mode, link_mode), }); self.base.file = file; if (comp.config.debug_format != .strip and comp.module != null) { // Create dSYM bundle. - log.debug("creating {s}.dSYM bundle", .{sub_path}); + log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); const d_sym_path = try std.fmt.allocPrint( arena, "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", - .{sub_path}, + .{emit.sub_path}, ); var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); defer d_sym_bundle.close(); - const d_sym_file = try d_sym_bundle.createFile(sub_path, .{ + const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ .truncate = false, .read = true, }); @@ -273,53 +298,15 @@ pub fn open( return self; } -pub fn createEmpty( +pub fn open( arena: Allocator, comp: *Compilation, emit: Compilation.Emit, options: link.File.OpenOptions, ) !*MachO { - const optimize_mode = comp.root_mod.optimize_mode; - const use_llvm = comp.config.use_llvm; - - const self = try arena.create(MachO); - self.* = .{ - .base = .{ - .tag = .macho, - .comp = comp, - .emit = emit, - .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), - .print_gc_sections = options.print_gc_sections, - .stack_size = options.stack_size orelse 16777216, - .allow_shlib_undefined = options.allow_shlib_undefined orelse false, - .file = null, - .disable_lld_caching = options.disable_lld_caching, - .build_id = options.build_id, - .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, - }, - .mode = if (use_llvm or comp.module == null or comp.cache_use == .whole) - .zld - else - .incremental, - .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, - .headerpad_size = options.headerpad_size orelse default_headerpad_size, - .headerpad_max_install_names = options.headerpad_max_install_names, - .dead_strip_dylibs = options.dead_strip_dylibs, - .sdk_layout = options.darwin_sdk_layout, - .frameworks = options.frameworks, - .install_name = options.install_name, - .entitlements = options.entitlements, - .compatibility_version = options.compatibility_version, - }; - - if (use_llvm and comp.module != null) { - self.llvm_object = try LlvmObject.create(arena, comp); - } - - log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); - - return self; + // TODO: restore saved linker state, don't truncate the file, and + // participate in incremental compilation. + return createEmpty(arena, comp, emit, options); } pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index edc4ada40527..b4b0f16d4a8d 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -440,8 +440,8 @@ pub fn createEmpty( } errdefer wasm.base.destroy(); - if (use_lld and use_llvm) { - // LLVM emits the object file; LLD links it into the final product. + if (use_lld and (use_llvm or !comp.config.have_zcu)) { + // LLVM emits the object file (if any); LLD links it into the final product. return wasm; } From 4c07d41b52d3acdfe81e4712526e60cef78484ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 25 Dec 2023 00:11:53 -0700 Subject: [PATCH 092/133] CLI: fix logic for zig test error message When using the build system to do unit testing, it lowers to --mod arguments which were incorrectly tripping a "zig test requires a source file argument" error. --- src/main.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 8f235e12334a..16bd32b45e88 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2522,10 +2522,6 @@ fn buildOutputType( fatal("translate-c expects exactly 1 source file (found {d})", .{create_module.c_source_files.items.len}); } - if (root_src_file == null and arg_mode == .zig_test) { - fatal("`zig test` expects a zig source file argument", .{}); - } - if (show_builtin and root_src_file == null) { // Without this, there will be no main module created and no zig // compilation unit, and therefore also no builtin.zig contents @@ -2616,6 +2612,10 @@ fn buildOutputType( rc_source_files_owner_index = create_module.rc_source_files.items.len; } + if (!create_module.opts.have_zcu and arg_mode == .zig_test) { + fatal("`zig test` expects a zig source file argument", .{}); + } + if (c_source_files_owner_index != create_module.c_source_files.items.len) { fatal("C source file '{s}' has no parent module", .{ create_module.c_source_files.items[c_source_files_owner_index].src_path, From b8a8fb927b791b369234012a3d4ff5e2c4c466c9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 17:08:14 -0700 Subject: [PATCH 093/133] link.File.Elf: bump 32-bit image_base default to 64K Now that we always pass --image-base to LLD, including when Zig chooses the default value, LLD is complaining about 32-bit architectures because it requires being at least equal to the max page size, which is 64K. --- src/link/Elf.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 378c8cbd5a65..ea8454490cc8 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -294,7 +294,7 @@ pub fn createEmpty( if (is_dyn_lib) break :b 0; if (output_mode == .Exe and comp.config.pie) break :b 0; break :b options.image_base orelse switch (ptr_width) { - .p32 => 0x1000, + .p32 => 0x10000, .p64 => 0x1000000, }; }, From 951c5b3f67e086c50ba8d0cd9318cb770fd3f724 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 17:09:40 -0700 Subject: [PATCH 094/133] frontend: fix "any" default resolution ambiguity In Compilation.create, update the resolved config to account for the default resolution of the root module. This makes it so that, for example, reading comp.config.any_non_single_threaded is valid in order to determine whether any module has single_threaded=false. --- src/Compilation.zig | 13 ++++++++++++- src/Compilation/Config.zig | 28 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 00d6ec3193cb..15b507b7a498 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1198,7 +1198,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const use_llvm = options.config.use_llvm; - const any_unwind_tables = options.config.any_unwind_tables; + // The "any" values provided by resolved config only account for + // explicitly-provided settings. We now make them additionally account + // for default setting resolution. + const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables; + const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded; + const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread; const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; const build_id = options.build_id orelse .none; @@ -1503,6 +1508,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .native_system_include_paths = options.native_system_include_paths, }; + // Prevent some footguns by making the "any" fields of config reflect + // the default Module settings. + comp.config.any_unwind_tables = any_unwind_tables; + comp.config.any_non_single_threaded = any_non_single_threaded; + comp.config.any_sanitize_thread = any_sanitize_thread; + const lf_open_opts: link.File.OpenOptions = .{ .linker_script = options.linker_script, .z_nodelete = options.linker_z_nodelete, diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 367187b6588d..dcf908ef2fe3 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -1,4 +1,7 @@ -//! User-specified settings that have all the defaults resolved into concrete values. +//! User-specified settings that have all the defaults resolved into concrete +//! values. These values are observable before calling Compilation.create for +//! the benefit of Module creation API, which needs access to these details in +//! order to resolve per-Module defaults. have_zcu: bool, output_mode: std.builtin.OutputMode, @@ -6,12 +9,27 @@ link_mode: std.builtin.LinkMode, link_libc: bool, link_libcpp: bool, link_libunwind: bool, -any_unwind_tables: bool, +/// True if and only if the c_source_files field will have nonzero length when +/// calling Compilation.create. any_c_source_files: bool, +/// This is true if any Module has unwind_tables set explicitly to true. Until +/// Compilation.create is called, it is possible for this to be false while in +/// fact all Module instances have unwind_tables=true due to the default +/// being unwind_tables=true. After Compilation.create is called this will +/// also take into account the default setting, making this value true if and +/// only if any Module has unwind_tables set to true. +any_unwind_tables: bool, +/// This is true if any Module has single_threaded set explicitly to false. Until +/// Compilation.create is called, it is possible for this to be false while in +/// fact all Module instances have single_threaded=false due to the default +/// being non-single-threaded. After Compilation.create is called this will +/// also take into account the default setting, making this value true if and +/// only if any Module has single_threaded set to false. any_non_single_threaded: bool, -/// This is true if any Module has error_tracing set to true. Function types -/// and function calling convention depend on this global value, however, other -/// kinds of error tracing are omitted depending on the per-Module setting. +/// This is true if and only if any Module has error_tracing set to true. +/// Function types and function calling convention depend on this global value, +/// however, other kinds of error tracing are omitted depending on the +/// per-Module setting. any_error_tracing: bool, any_sanitize_thread: bool, pie: bool, From 6beae6c061a650ea2d695e6902683641df920aa8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 19:58:05 -0700 Subject: [PATCH 095/133] frontend: avoid spurious error when no zcu use_llvm=false does not always mean there needs to be a zig compiler backend available. In particular, when there is no zig compilation unit, use_llvm=false and yet no zig backend will be used to produce code. --- src/Compilation/Config.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index dcf908ef2fe3..d5f3b2ef955b 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -237,7 +237,7 @@ pub fn resolve(options: Options) ResolveError!Config { break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target); }; - if (options.emit_bin) { + if (options.emit_bin and options.have_zcu) { if (!use_lib_llvm and use_llvm) { // Explicit request to use LLVM to produce an object file, but without // using LLVM libraries. Impossible. From c9fe43679f8d8f0db6250cc881b59cc68daaf128 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 20:32:40 -0700 Subject: [PATCH 096/133] frontend: remove deprecated field from Compilation --- src/Compilation.zig | 8 -------- src/main.zig | 14 +++++++------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 15b507b7a498..d8c59f4f1b5b 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -35,7 +35,6 @@ const c_codegen = @import("codegen/c.zig"); const libtsan = @import("libtsan.zig"); const Zir = @import("Zir.zig"); const Autodoc = @import("Autodoc.zig"); -const Color = @import("main.zig").Color; const resinator = @import("resinator.zig"); const Builtin = @import("Builtin.zig"); @@ -197,10 +196,6 @@ glibc_so_files: ?glibc.BuiltSharedObjects = null, /// The key is the basename, and the value is the absolute path to the completed build artifact. crt_files: std.StringHashMapUnmanaged(CRTFile) = .{}, -/// This is for stage1 and should be deleted upon completion of self-hosting. -/// Don't use this for anything other than stage1 compatibility. -color: Color = .auto, - /// How many lines of reference trace should be included per compile error. /// Null means only show snippet on first error. reference_trace: ?u32 = null, @@ -1068,8 +1063,6 @@ pub const InitOptions = struct { libc_installation: ?*const LibCInstallation = null, native_system_include_paths: []const []const u8 = &.{}, clang_preprocessor_mode: ClangPreprocessorMode = .no, - /// This is for stage1 and should be deleted upon completion of self-hosting. - color: Color = .auto, reference_trace: ?u32 = null, test_filter: ?[]const u8 = null, test_name_prefix: ?[]const u8 = null, @@ -1481,7 +1474,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, .verbose_link = options.verbose_link, .disable_c_depfile = options.disable_c_depfile, - .color = options.color, .reference_trace = options.reference_trace, .formatted_panics = formatted_panics, .time_report = options.time_report, diff --git a/src/main.zig b/src/main.zig index 16bd32b45e88..0822557158bb 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3220,7 +3220,6 @@ fn buildOutputType( .verbose_llvm_bc = verbose_llvm_bc, .verbose_cimport = verbose_cimport, .verbose_llvm_cpu_features = verbose_llvm_cpu_features, - .color = color, .time_report = time_report, .stack_report = stack_report, .each_lib_rpath = each_lib_rpath, @@ -3323,7 +3322,7 @@ fn buildOutputType( return cmdTranslateC(comp, arena, null); } - updateModule(comp) catch |err| switch (err) { + updateModule(comp, color) catch |err| switch (err) { error.SemanticAnalyzeFail => { assert(listen == .none); saveState(comp, debug_incremental); @@ -4436,13 +4435,13 @@ fn runOrTestHotSwap( } } -fn updateModule(comp: *Compilation) !void { +fn updateModule(comp: *Compilation, color: Color) !void { { // If the terminal is dumb, we dont want to show the user all the output. var progress: std.Progress = .{ .dont_print_on_dumb = true }; const main_progress_node = progress.start("", 0); defer main_progress_node.end(); - switch (comp.color) { + switch (color) { .off => { progress.terminal = null; }, @@ -4460,13 +4459,14 @@ fn updateModule(comp: *Compilation) !void { defer errors.deinit(comp.gpa); if (errors.errorMessageCount() > 0) { - errors.renderToStdErr(renderOptions(comp.color)); + errors.renderToStdErr(renderOptions(color)); return error.SemanticAnalyzeFail; } } fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilation.CImportResult) !void { if (build_options.only_core_functionality) @panic("@translate-c is not available in a zig2.c build"); + const color: Color = .auto; assert(comp.c_source_files.len == 1); const c_source_file = comp.c_source_files[0]; @@ -4559,7 +4559,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati p.errors = errors; return; } else { - errors.renderToStdErr(renderOptions(comp.color)); + errors.renderToStdErr(renderOptions(color)); process.exit(1); } }, @@ -5533,7 +5533,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi }; defer comp.destroy(); - updateModule(comp) catch |err| switch (err) { + updateModule(comp, color) catch |err| switch (err) { error.SemanticAnalyzeFail => process.exit(2), else => |e| return e, }; From 57562c8d507667b6fefcb7fbc7a305fbd610b5dd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 21:39:39 -0700 Subject: [PATCH 097/133] compiler: push entry symbol name resolution into the linker This is necessary because on COFF, the entry symbol name is not known until the linker has looked at the set of global symbol names to determine which of the four possible main entry points is present. --- src/Compilation.zig | 9 ++++--- src/Compilation/Config.zig | 29 ---------------------- src/link.zig | 9 +++++++ src/link/Coff.zig | 21 +++++++++++++++- src/link/Coff/lld.zig | 15 ++++++++--- src/link/Elf.zig | 29 ++++++++++++++++------ src/link/MachO.zig | 17 ++++++++++--- src/link/MachO/zld.zig | 5 ++-- src/link/Wasm.zig | 51 ++++++++++++++++++++++++-------------- src/main.zig | 18 +++++++------- src/target.zig | 20 --------------- 11 files changed, 124 insertions(+), 99 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index d8c59f4f1b5b..9029d8ecbcbc 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -924,7 +924,7 @@ pub const LinkObject = struct { loption: bool = false, }; -pub const InitOptions = struct { +pub const CreateOptions = struct { zig_lib_directory: Directory, local_cache_directory: Directory, global_cache_directory: Directory, @@ -1054,7 +1054,7 @@ pub const InitOptions = struct { /// infinite recursion. skip_linker_dependencies: bool = false, hash_style: link.File.Elf.HashStyle = .both, - entry: ?[]const u8 = null, + entry: Entry = .default, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, stack_size: ?u64 = null, image_base: ?u64 = null, @@ -1089,6 +1089,8 @@ pub const InitOptions = struct { /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, error_limit: ?Compilation.Module.ErrorInt = null, + + pub const Entry = link.File.OpenOptions.Entry; }; fn addModuleTableToCacheHash( @@ -1159,7 +1161,7 @@ fn addModuleTableToCacheHash( } } -pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { +pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { const output_mode = options.config.output_mode; const is_dyn_lib = switch (output_mode) { .Obj, .Exe => false, @@ -1543,6 +1545,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .dynamicbase = options.linker_dynamicbase, .major_subsystem_version = options.major_subsystem_version, .minor_subsystem_version = options.minor_subsystem_version, + .entry = options.entry, .stack_size = options.stack_size, .image_base = options.image_base, .version_script = options.version_script, diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index d5f3b2ef955b..4abf3e88d4ac 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -55,7 +55,6 @@ export_memory: bool, shared_memory: bool, is_test: bool, test_evented_io: bool, -entry: ?[]const u8, debug_format: DebugFormat, root_strip: bool, root_error_tracing: bool, @@ -100,12 +99,6 @@ pub const Options = struct { use_lld: ?bool = null, use_clang: ?bool = null, lto: ?bool = null, - entry: union(enum) { - default, - disabled, - enabled, - named: []const u8, - } = .default, /// WASI-only. Type of WASI execution model ("command" or "reactor"). wasi_exec_model: ?std.builtin.WasiExecModel = null, import_memory: ?bool = null, @@ -123,8 +116,6 @@ pub const ResolveError = error{ ObjectFilesCannotShareMemory, SharedMemoryRequiresAtomicsAndBulkMemory, ThreadsRequireSharedMemory, - UnknownTargetEntryPoint, - NonExecutableEntryPoint, EmittingLlvmModuleRequiresLlvmBackend, LlvmLacksTargetSupport, ZigLacksTargetSupport, @@ -352,25 +343,6 @@ pub fn resolve(options: Options) ResolveError!Config { break :b false; }; - const entry: ?[]const u8 = switch (options.entry) { - .disabled => null, - .default => b: { - if (options.output_mode != .Exe) break :b null; - - // When producing C source code, the decision of entry point is made - // when compiling the C code, not when producing the C code. - if (target.ofmt == .c) break :b null; - - break :b target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse - return error.UnknownTargetEntryPoint; - }, - .enabled => target_util.defaultEntrySymbolName(target, wasi_exec_model) orelse - return error.UnknownTargetEntryPoint, - .named => |name| name, - }; - if (entry != null and options.output_mode != .Exe) - return error.NonExecutableEntryPoint; - const any_unwind_tables = options.any_unwind_tables or link_libunwind or target_util.needUnwindTables(target); @@ -519,7 +491,6 @@ pub fn resolve(options: Options) ResolveError!Config { .use_llvm = use_llvm, .use_lib_llvm = use_lib_llvm, .use_lld = use_lld, - .entry = entry, .wasi_exec_model = wasi_exec_model, .debug_format = debug_format, .root_strip = root_strip, diff --git a/src/link.zig b/src/link.zig index 8fc1e8cc917f..a051d27b12f3 100644 --- a/src/link.zig +++ b/src/link.zig @@ -83,6 +83,8 @@ pub const File = struct { symbol_count_hint: u64 = 32, program_code_size_hint: u64 = 256 * 1024, + /// This may depend on what symbols are found during the linking process. + entry: Entry, /// Virtual address of the entry point procedure relative to image base. entry_addr: ?u64, stack_size: ?u64, @@ -169,6 +171,13 @@ pub const File = struct { module_definition_file: ?[]const u8, wasi_emulated_libs: []const wasi_libc.CRTFile, + + pub const Entry = union(enum) { + default, + disabled, + enabled, + named: []const u8, + }; }; /// Attempts incremental linking, if the file already exists. If diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 861ec030b36d..53f999b9655e 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -17,6 +17,7 @@ dynamicbase: bool, major_subsystem_version: u16, minor_subsystem_version: u16, lib_dirs: []const []const u8, +entry: link.File.OpenOptions.Entry, entry_addr: ?u32, module_definition_file: ?[]const u8, pdb_out_path: ?[]const u8, @@ -303,7 +304,12 @@ pub fn createEmpty( .Obj => 0, }, + // Subsystem depends on the set of public symbol names from linked objects. + // See LinkerDriver::inferSubsystem from the LLD project for the flow chart. .subsystem = options.subsystem, + + .entry = options.entry, + .tsaware = options.tsaware, .nxcompat = options.nxcompat, .dynamicbase = options.dynamicbase, @@ -2498,7 +2504,20 @@ inline fn getSizeOfImage(self: Coff) u32 { /// Returns symbol location corresponding to the set entrypoint (if any). pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { const comp = self.base.comp; - const entry_name = comp.config.entry orelse return null; + + // TODO This is incomplete. + // The entry symbol name depends on the subsystem as well as the set of + // public symbol names from linked objects. + // See LinkerDriver::findDefaultEntry from the LLD project for the flow chart. + const entry_name = switch (self.entry) { + .disabled => return null, + .default => switch (comp.config.output_mode) { + .Exe => "wWinMainCRTStartup", + .Obj, .Lib => return null, + }, + .enabled => "wWinMainCRTStartup", + .named => |name| name, + }; const global_index = self.resolver.get(entry_name) orelse return null; return self.globals.items[global_index]; } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 5b01f6364543..6afe741f6635 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -52,6 +52,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib; const target = comp.root_mod.resolved_target.result; const optimize_mode = comp.root_mod.optimize_mode; + const entry_name: ?[]const u8 = switch (self.entry) { + // This logic isn't quite right for disabled or enabled. No point in fixing it + // when the goal is to eliminate dependency on LLD anyway. + // https://github.com/ziglang/zig/issues/17751 + .disabled, .default, .enabled => null, + .named => |name| name, + }; // See link/Elf.zig for comments on how this mechanism works. const id_symlink_basename = "lld.id"; @@ -80,7 +87,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } try man.addOptionalFile(module_obj_path); - man.hash.addOptionalBytes(comp.config.entry); + man.hash.addOptionalBytes(entry_name); man.hash.add(self.base.stack_size); man.hash.add(self.image_base); man.hash.addListOfBytes(self.lib_dirs); @@ -218,8 +225,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append("-DLL"); } - if (comp.config.entry) |entry| { - try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry})); + if (entry_name) |name| { + try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name})); } if (self.tsaware) { @@ -441,7 +448,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } else { try argv.append("-NODEFAULTLIB"); - if (!is_lib and comp.config.entry == null) { + if (!is_lib and entry_name == null) { if (comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ea8454490cc8..65fc0ff5a37b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -25,6 +25,7 @@ linker_script: ?[]const u8, version_script: ?[]const u8, print_icf_sections: bool, print_map: bool, +entry_name: ?[]const u8, ptr_width: PtrWidth, @@ -290,6 +291,13 @@ pub fn createEmpty( .page_size = page_size, .default_sym_version = default_sym_version, + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else defaultEntrySymbolName(target.cpu.arch), + .enabled => defaultEntrySymbolName(target.cpu.arch), + .named => |name| name, + }, + .image_base = b: { if (is_dyn_lib) break :b 0; if (output_mode == .Exe and comp.config.pie) break :b 0; @@ -1305,7 +1313,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Look for entry address in objects if not set by the incremental compiler. if (self.entry_index == null) { - if (comp.config.entry) |name| { + if (self.entry_name) |name| { self.entry_index = self.globalByName(name); } } @@ -1679,9 +1687,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } for (self.base.rpath_list) |rpath| { @@ -2427,7 +2434,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. - man.hash.addOptionalBytes(comp.config.entry); + man.hash.addOptionalBytes(self.entry_name); man.hash.add(self.image_base); man.hash.add(self.base.gc_sections); man.hash.addOptional(self.sort_section); @@ -2563,9 +2570,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } for (self.base.force_undefined_symbols.keys()) |sym| { @@ -6512,6 +6518,13 @@ const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; +fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { + return switch (cpu_arch) { + .mips, .mipsel, .mips64, .mips64el => "__start", + else => "_start", + }; +} + const std = @import("std"); const build_options = @import("build_options"); const builtin = @import("builtin"); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d8fc71c0f07b..8c0874e3cb4d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1,4 +1,5 @@ base: File, +entry_name: ?[]const u8, /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. llvm_object: ?*LlvmObject = null, @@ -231,6 +232,12 @@ pub fn createEmpty( .install_name = options.install_name, .entitlements = options.entitlements, .compatibility_version = options.compatibility_version, + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else default_entry_symbol_name, + .enabled => default_entry_symbol_name, + .named => |name| name, + }, }; if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, comp); @@ -1629,8 +1636,9 @@ pub fn resolveSymbols(self: *MachO) !void { // we search for it in libraries should there be no object files specified // on the linker line. if (output_mode == .Exe) { - const entry_name = comp.config.entry.?; - _ = try self.addUndefined(entry_name, .{}); + if (self.entry_name) |entry_name| { + _ = try self.addUndefined(entry_name, .{}); + } } // Force resolution of any symbols requested by the user. @@ -5085,8 +5093,7 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 { /// Returns symbol location corresponding to the set entrypoint if any. /// Asserts output mode is executable. pub fn getEntryPoint(self: MachO) ?SymbolWithLoc { - const comp = self.base.comp; - const entry_name = comp.config.entry orelse return null; + const entry_name = self.entry_name orelse return null; const global = self.getGlobal(entry_name) orelse return null; return global; } @@ -5645,6 +5652,8 @@ pub fn logAtom(self: *MachO, atom_index: Atom.Index, logger: anytype) void { } } +const default_entry_symbol_name = "_main"; + pub const base_tag: File.Tag = File.Tag.macho; pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1))); pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2))); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index fa6aa152e4b3..05fa8e671a2f 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -276,9 +276,8 @@ pub fn linkWithZld( try argv.append("-dead_strip_dylibs"); } - if (comp.config.entry) |entry| { - try argv.append("-e"); - try argv.append(entry); + if (macho_file.entry_name) |entry_name| { + try argv.appendSlice(&.{ "-e", entry_name }); } for (objects) |obj| { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index b4b0f16d4a8d..91653ce641fa 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -37,6 +37,7 @@ pub const Relocation = types.Relocation; pub const base_tag: link.File.Tag = .wasm; base: link.File, +entry_name: ?[]const u8, import_symbols: bool, export_symbol_names: []const []const u8, global_base: ?u64, @@ -397,6 +398,7 @@ pub fn createEmpty( const use_llvm = comp.config.use_llvm; const output_mode = comp.config.output_mode; const shared_memory = comp.config.shared_memory; + const wasi_exec_model = comp.config.wasi_exec_model; // If using LLD to link, this code should produce an object file so that it // can be passed to LLD. @@ -434,6 +436,13 @@ pub fn createEmpty( .initial_memory = options.initial_memory, .max_memory = options.max_memory, .wasi_emulated_libs = options.wasi_emulated_libs, + + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else defaultEntrySymbolName(wasi_exec_model), + .enabled => defaultEntrySymbolName(wasi_exec_model), + .named => |name| name, + }, }; if (use_llvm and comp.config.have_zcu) { wasm.llvm_object = try LlvmObject.create(arena, comp); @@ -3042,7 +3051,7 @@ fn setupExports(wasm: *Wasm) !void { fn setupStart(wasm: *Wasm) !void { const comp = wasm.base.comp; // do not export entry point if user set none or no default was set. - const entry_name = comp.config.entry orelse return; + const entry_name = wasm.entry_name orelse return; const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); @@ -3475,8 +3484,8 @@ fn resetState(wasm: *Wasm) void { } pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld; - const use_llvm = wasm.base.comp.config.use_llvm; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; if (use_lld) { return wasm.linkWithLLD(comp, prog_node); @@ -3492,7 +3501,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const tracy = trace(@src()); defer tracy.end(); - const gpa = wasm.base.comp.gpa; + const gpa = comp.gpa; const shared_memory = comp.config.shared_memory; const import_memory = comp.config.import_memory; @@ -3503,8 +3512,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); - const opt_zcu = wasm.base.comp.module; - const use_llvm = wasm.base.comp.config.use_llvm; + const opt_zcu = comp.module; + const use_llvm = comp.config.use_llvm; // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. @@ -3535,7 +3544,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l defer if (!wasm.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - const objects = wasm.base.comp.objects; + const objects = comp.objects; // NOTE: The following section must be maintained to be equal // as the section defined in `linkWithLLD` @@ -3556,7 +3565,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.addOptionalBytes(wasm.entry_name); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); man.hash.add(import_memory); @@ -3605,12 +3614,12 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l var positionals = std.ArrayList([]const u8).init(arena); try positionals.ensureUnusedCapacity(objects.len); - const target = wasm.base.comp.root_mod.resolved_target.result; - const output_mode = wasm.base.comp.config.output_mode; - const link_mode = wasm.base.comp.config.link_mode; - const link_libc = wasm.base.comp.config.link_libc; - const link_libcpp = wasm.base.comp.config.link_libcpp; - const wasi_exec_model = wasm.base.comp.config.wasi_exec_model; + const target = comp.root_mod.resolved_target.result; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const link_libc = comp.config.link_libc; + const link_libcpp = comp.config.link_libcpp; + const wasi_exec_model = comp.config.wasi_exec_model; // When the target os is WASI, we allow linking with WASI-LIBC if (target.os.tag == .wasi) { @@ -4648,7 +4657,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.addOptionalBytes(wasm.entry_name); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); man.hash.add(import_memory); @@ -4799,9 +4808,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--export-dynamic"); } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (wasm.entry_name) |entry_name| { + try argv.appendSlice(&.{ "--entry", entry_name }); } else { try argv.append("--no-entry"); } @@ -5347,3 +5355,10 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { try wasm.mark(target_loc.finalLoc(wasm)); } } + +fn defaultEntrySymbolName(wasi_exec_model: std.builtin.WasiExecModel) []const u8 { + return switch (wasi_exec_model) { + .reactor => "_initialize", + .command => "_start", + }; +} diff --git a/src/main.zig b/src/main.zig index 0822557158bb..54db7eb37d3d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -857,6 +857,7 @@ fn buildOutputType( var linker_optimization: ?[]const u8 = null; var linker_module_definition_file: ?[]const u8 = null; var test_no_exec = false; + var entry: Compilation.CreateOptions.Entry = .default; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; var stack_size: ?u64 = null; var image_base: ?u64 = null; @@ -1129,7 +1130,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-O")) { mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal()); } else if (mem.startsWith(u8, arg, "-fentry=")) { - create_module.opts.entry = .{ .named = arg["-fentry=".len..] }; + entry = .{ .named = arg["-fentry=".len..] }; } else if (mem.eql(u8, arg, "--force_undefined")) { try force_undefined_symbols.put(arena, args_iter.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack")) { @@ -1556,12 +1557,12 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--import-memory")) { create_module.opts.import_memory = true; } else if (mem.eql(u8, arg, "-fentry")) { - switch (create_module.opts.entry) { - .default, .disabled => create_module.opts.entry = .enabled, + switch (entry) { + .default, .disabled => entry = .enabled, .enabled, .named => {}, } } else if (mem.eql(u8, arg, "-fno-entry")) { - create_module.opts.entry = .disabled; + entry = .disabled; } else if (mem.eql(u8, arg, "--export-memory")) { create_module.opts.export_memory = true; } else if (mem.eql(u8, arg, "--import-symbols")) { @@ -2065,7 +2066,7 @@ fn buildOutputType( create_module.sysroot = it.only_arg; }, .entry => { - create_module.opts.entry = .{ .named = it.only_arg }; + entry = .{ .named = it.only_arg }; }, .force_undefined_symbol => { try force_undefined_symbols.put(arena, it.only_arg, {}); @@ -2210,7 +2211,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--export-table")) { linker_export_table = true; } else if (mem.eql(u8, arg, "--no-entry")) { - create_module.opts.entry = .disabled; + entry = .disabled; } else if (mem.eql(u8, arg, "--initial-memory")) { const next_arg = linker_args_it.nextOrFatal(); linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2284,7 +2285,7 @@ fn buildOutputType( }; have_version = true; } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { - create_module.opts.entry = .{ .named = linker_args_it.nextOrFatal() }; + entry = .{ .named = linker_args_it.nextOrFatal() }; } else if (mem.eql(u8, arg, "-u")) { try force_undefined_symbols.put(arena, linker_args_it.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { @@ -3200,6 +3201,7 @@ fn buildOutputType( .minor_subsystem_version = minor_subsystem_version, .link_eh_frame_hdr = link_eh_frame_hdr, .link_emit_relocs = link_emit_relocs, + .entry = entry, .force_undefined_symbols = force_undefined_symbols, .stack_size = stack_size, .image_base = image_base, @@ -3845,8 +3847,6 @@ fn createModule( error.ObjectFilesCannotShareMemory => fatal("object files cannot share memory", .{}), error.SharedMemoryRequiresAtomicsAndBulkMemory => fatal("shared memory requires atomics and bulk_memory CPU features", .{}), error.ThreadsRequireSharedMemory => fatal("threads require shared memory", .{}), - error.UnknownTargetEntryPoint => fatal("unknown target entry point", .{}), - error.NonExecutableEntryPoint => fatal("entry points only allowed for executables", .{}), error.EmittingLlvmModuleRequiresLlvmBackend => fatal("emitting an LLVM module requires using the LLVM backend", .{}), error.LlvmLacksTargetSupport => fatal("LLVM lacks support for the specified target", .{}), error.ZigLacksTargetSupport => fatal("compiler backend unavailable for the specified target", .{}), diff --git a/src/target.zig b/src/target.zig index d1a98601cf22..262632b373db 100644 --- a/src/target.zig +++ b/src/target.zig @@ -683,23 +683,3 @@ pub fn backendSupportsFeature( .safety_checked_instructions => use_llvm, }; } - -pub fn defaultEntrySymbolName( - target: std.Target, - /// May be `undefined` when `target` is not WASI. - wasi_exec_model: std.builtin.WasiExecModel, -) ?[]const u8 { - return switch (target.ofmt) { - .coff => "wWinMainCRTStartup", - .macho => "_main", - .elf, .plan9 => switch (target.cpu.arch) { - .mips, .mipsel, .mips64, .mips64el => "__start", - else => "_start", - }, - .wasm => switch (wasi_exec_model) { - .reactor => "_initialize", - .command => "_start", - }, - else => null, - }; -} From 524dc756b30c19db070362c8094459c7c8e4fd8a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 23:45:44 -0700 Subject: [PATCH 098/133] Compilation: several branch regression fixes * move wasi_emulated_libs into Compilation - It needs to be accessed from Compilation, which needs to potentially build those artifacts. * Compilation: improve error reporting for two cases - the setMiscFailure mechanism is handy - let's use it! * fix one instance of incorrectly checking for emit_bin via `comp.bin_file != null`. There are more instances of this that need to be fixed in a future commit. * fix renameTmpIntoCache not handling the case where it needs to make the "o" directory in the zig-cache directory. - while I'm at it, simplify the logic for handling the fact that Windows returns error.AccessDenied rather than error.PathAlreadyExists for failure to rename a directory over another one. * fix missing cache hash additions - there are still more to add in a future commit - addNonIncrementalStuffToCacheManifest is called when bin_file is always null, and then it incorrectly checks if bin_file is non-null and only then adds a bunch of stuff to the cache hash. It needs to instead add to the cache hash based on lf_open_opts. --- src/Compilation.zig | 148 +++++++++++++++++++++++++++----------------- src/link.zig | 2 - src/link/Wasm.zig | 24 ++++--- 3 files changed, 102 insertions(+), 72 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 9029d8ecbcbc..86caba765189 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -190,6 +190,7 @@ compiler_rt_lib: ?CRTFile = null, compiler_rt_obj: ?CRTFile = null, glibc_so_files: ?glibc.BuiltSharedObjects = null, +wasi_emulated_libs: []const wasi_libc.CRTFile, /// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source, /// The set of needed CRT (C runtime) files differs depending on the target and compilation settings. @@ -707,6 +708,8 @@ pub const Win32Resource = struct { pub const MiscTask = enum { write_builtin_zig, + rename_results, + check_whole_cache, glibc_crt_file, glibc_shared_objects, musl_crt_file, @@ -1500,6 +1503,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .function_sections = options.function_sections, .data_sections = options.data_sections, .native_system_include_paths = options.native_system_include_paths, + .wasi_emulated_libs = options.wasi_emulated_libs, }; // Prevent some footguns by making the "any" fields of config reflect @@ -1521,7 +1525,6 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .z_max_page_size = options.linker_z_max_page_size, .darwin_sdk_layout = libc_dirs.darwin_sdk_layout, .frameworks = options.frameworks, - .wasi_emulated_libs = options.wasi_emulated_libs, .lib_dirs = options.lib_dirs, .rpath_list = options.rpath_list, .symbol_wrap_set = options.symbol_wrap_set, @@ -1672,10 +1675,10 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { }; errdefer comp.destroy(); - const target = options.root_mod.resolved_target.result; + const target = comp.root_mod.resolved_target.result; - const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, options.config.use_llvm); - const capable_of_building_zig_libc = canBuildZigLibC(target, options.config.use_llvm); + const capable_of_building_compiler_rt = canBuildLibCompilerRt(target, comp.config.use_llvm); + const capable_of_building_zig_libc = canBuildZigLibC(target, comp.config.use_llvm); // Add a `CObject` for each `c_source_files`. try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len); @@ -1768,25 +1771,21 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { }); } - if (comp.bin_file) |lf| { - if (lf.cast(link.File.Wasm)) |wasm| { - if (comp.wantBuildWasiLibcFromSource()) { - if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; + if (comp.wantBuildWasiLibcFromSource()) { + if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; - // worst-case we need all components - try comp.work_queue.ensureUnusedCapacity(wasm.wasi_emulated_libs.len + 2); + // worst-case we need all components + try comp.work_queue.ensureUnusedCapacity(comp.wasi_emulated_libs.len + 2); - for (wasm.wasi_emulated_libs) |crt_file| { - comp.work_queue.writeItemAssumeCapacity(.{ - .wasi_libc_crt_file = crt_file, - }); - } - comp.work_queue.writeAssumeCapacity(&[_]Job{ - .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) }, - .{ .wasi_libc_crt_file = .libc_a }, - }); - } + for (comp.wasi_emulated_libs) |crt_file| { + comp.work_queue.writeItemAssumeCapacity(.{ + .wasi_libc_crt_file = crt_file, + }); } + comp.work_queue.writeAssumeCapacity(&[_]Job{ + .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) }, + .{ .wasi_libc_crt_file = .libc_a }, + }); } if (comp.wantBuildMinGWFromSource()) { @@ -1832,11 +1831,11 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { } if (comp.bin_file) |lf| { - if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) { + if (target.isMinGW() and comp.config.any_non_single_threaded) { // LLD might drop some symbols as unused during LTO and GCing, therefore, // we force mark them for resolution here. - const tls_index_sym = switch (comp.getTarget().cpu.arch) { + const tls_index_sym = switch (target.cpu.arch) { .x86 => "__tls_index", else => "_tls_index", }; @@ -2024,12 +2023,14 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void try comp.addNonIncrementalStuffToCacheManifest(&man); const is_hit = man.hit() catch |err| { - // TODO properly bubble these up instead of emitting a warning const i = man.failed_file_index orelse return err; const pp = man.files.items[i].prefixed_path orelse return err; const prefix = man.cache.prefixes()[pp.prefix].path orelse ""; - std.log.warn("{s}: {s}{s}", .{ @errorName(err), prefix, pp.sub_path }); - return err; + return comp.setMiscFailure( + .check_whole_cache, + "unable to check cache: stat file '{}{s}{s}' failed: {s}", + .{ comp.local_cache_directory, prefix, pp.sub_path, @errorName(err) }, + ); }; if (is_hit) { comp.last_update_was_cache_hit = true; @@ -2221,7 +2222,17 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); const o_sub_path = "o" ++ s ++ digest; - try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); + renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path) catch |err| { + return comp.setMiscFailure( + .rename_results, + "failed to rename compilation results ('{}{s}') into local cache ('{}{s}'): {s}", + .{ + comp.local_cache_directory, tmp_dir_sub_path, + comp.local_cache_directory, o_sub_path, + @errorName(err), + }, + ); + }; comp.wholeCacheModeSetBinFilePath(whole, &digest); // Failure here only means an unnecessary cache miss. @@ -2251,42 +2262,36 @@ fn renameTmpIntoCache( tmp_dir_sub_path: []const u8, o_sub_path: []const u8, ) !void { + var seen_eaccess = false; while (true) { - if (builtin.os.tag == .windows) { - // Work around windows `renameW` can't fail with `PathAlreadyExists` + std.fs.rename( + cache_directory.handle, + tmp_dir_sub_path, + cache_directory.handle, + o_sub_path, + ) catch |err| switch (err) { + // On Windows, rename fails with `AccessDenied` rather than `PathAlreadyExists`. // See https://github.com/ziglang/zig/issues/8362 - if (cache_directory.handle.access(o_sub_path, .{})) |_| { - try cache_directory.handle.deleteTree(o_sub_path); - continue; - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return e, - } - std.fs.rename( - cache_directory.handle, - tmp_dir_sub_path, - cache_directory.handle, - o_sub_path, - ) catch |err| { - log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) }); - return err; - }; - break; - } else { - std.fs.rename( - cache_directory.handle, - tmp_dir_sub_path, - cache_directory.handle, - o_sub_path, - ) catch |err| switch (err) { - error.PathAlreadyExists => { + error.AccessDenied => switch (builtin.os.tag) { + .windows => { + if (!seen_eaccess) return error.AccessDenied; + seen_eaccess = true; try cache_directory.handle.deleteTree(o_sub_path); continue; }, - else => |e| return e, - }; - break; - } + else => return error.AccessDenied, + }, + error.PathAlreadyExists => { + try cache_directory.handle.deleteTree(o_sub_path); + continue; + }, + error.FileNotFound => { + try cache_directory.handle.makePath("o"); + continue; + }, + else => |e| return e, + }; + break; } } @@ -2386,6 +2391,10 @@ 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.config.dll_export_fns); + man.hash.add(comp.config.is_test); man.hash.add(comp.config.test_evented_io); man.hash.addOptionalBytes(comp.test_filter); man.hash.addOptionalBytes(comp.test_name_prefix); @@ -2393,6 +2402,20 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.formatted_panics); man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); + } else { + cache_helpers.addResolvedTarget(&man.hash, comp.root_mod.resolved_target); + man.hash.add(comp.root_mod.optimize_mode); + man.hash.add(comp.root_mod.code_model); + man.hash.add(comp.root_mod.single_threaded); + man.hash.add(comp.root_mod.error_tracing); + man.hash.add(comp.root_mod.pic); + man.hash.add(comp.root_mod.omit_frame_pointer); + man.hash.add(comp.root_mod.stack_check); + man.hash.add(comp.root_mod.red_zone); + man.hash.add(comp.root_mod.sanitize_c); + man.hash.add(comp.root_mod.sanitize_thread); + man.hash.add(comp.root_mod.unwind_tables); + man.hash.add(comp.root_mod.structured_cfg); } for (comp.objects) |obj| { @@ -3829,8 +3852,19 @@ pub fn obtainCObjectCacheManifest( // Only things that need to be added on top of the base hash, and only things // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. + cache_helpers.addResolvedTarget(&man.hash, owner_mod.resolved_target); + man.hash.add(owner_mod.optimize_mode); + man.hash.add(owner_mod.code_model); + man.hash.add(owner_mod.single_threaded); + man.hash.add(owner_mod.error_tracing); + man.hash.add(owner_mod.pic); + man.hash.add(owner_mod.omit_frame_pointer); + man.hash.add(owner_mod.stack_check); + man.hash.add(owner_mod.red_zone); man.hash.add(owner_mod.sanitize_c); man.hash.add(owner_mod.sanitize_thread); + man.hash.add(owner_mod.unwind_tables); + man.hash.add(owner_mod.structured_cfg); man.hash.addListOfBytes(owner_mod.cc_argv); man.hash.add(comp.config.link_libcpp); diff --git a/src/link.zig b/src/link.zig index a051d27b12f3..fdcd5fcf41b8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -170,8 +170,6 @@ pub const File = struct { /// (Windows) .def file to specify when linking module_definition_file: ?[]const u8, - wasi_emulated_libs: []const wasi_libc.CRTFile, - pub const Entry = union(enum) { default, disabled, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 91653ce641fa..7f3ca877c600 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -43,7 +43,6 @@ export_symbol_names: []const []const u8, global_base: ?u64, initial_memory: ?u64, max_memory: ?u64, -wasi_emulated_libs: []const wasi_libc.CRTFile, /// Output name of the file name: []const u8, /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. @@ -435,7 +434,6 @@ pub fn createEmpty( .global_base = options.global_base, .initial_memory = options.initial_memory, .max_memory = options.max_memory, - .wasi_emulated_libs = options.wasi_emulated_libs, .entry_name = switch (options.entry) { .disabled => null, @@ -3626,7 +3624,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const is_exe_or_dyn_lib = output_mode == .Exe or (output_mode == .Lib and link_mode == .Dynamic); if (is_exe_or_dyn_lib) { - for (wasm.wasi_emulated_libs) |crt_file| { + for (comp.wasi_emulated_libs) |crt_file| { try positionals.append(try comp.get_libc_crt_file( arena, wasi_libc.emulatedLibCRFileLibName(crt_file), @@ -4601,7 +4599,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const import_memory = comp.config.import_memory; const target = comp.root_mod.resolved_target.result; - const gpa = wasm.base.comp.gpa; + const gpa = comp.gpa; var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -4611,7 +4609,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (wasm.base.comp.module != null) blk: { + const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { try wasm.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -4626,7 +4624,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_obj = wasm.base.comp.config.output_mode == .Obj; + const is_obj = comp.config.output_mode == .Obj; const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |lib| break :blk lib.full_object_path; if (comp.compiler_rt_obj) |obj| break :blk obj.full_object_path; @@ -4823,7 +4821,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--allow-undefined"); } - if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) { + if (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic) { try argv.append("--shared"); } if (comp.config.pie) { @@ -4842,10 +4840,10 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } if (target.os.tag == .wasi) { - const is_exe_or_dyn_lib = wasm.base.comp.config.output_mode == .Exe or - (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic); + const is_exe_or_dyn_lib = comp.config.output_mode == .Exe or + (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic); if (is_exe_or_dyn_lib) { - for (wasm.wasi_emulated_libs) |crt_file| { + for (comp.wasi_emulated_libs) |crt_file| { try argv.append(try comp.get_libc_crt_file( arena, wasi_libc.emulatedLibCRFileLibName(crt_file), @@ -4891,7 +4889,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.comp.config.output_mode != .Obj and + if (comp.config.output_mode != .Obj and !comp.skip_linker_dependencies and !comp.config.link_libc) { @@ -4902,7 +4900,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.comp.verbose_link) { + if (comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } @@ -4977,7 +4975,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // it, and then can react to that in the same way as trying to run an ELF file // from a foreign CPU architecture. if (fs.has_executable_bit and target.os.tag == .wasi and - wasm.base.comp.config.output_mode == .Exe) + comp.config.output_mode == .Exe) { // TODO: what's our strategy for reporting linker errors from this function? // report a nice error here with the file path if it fails instead of From 1ef4df9044a01f78841393f7b92da742775ffbfb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 23 Dec 2023 23:53:14 -0700 Subject: [PATCH 099/133] std.Build.Step.Compile: support modules with different args Now that the CLI supports per-module settings, the build system takes advantage of this when lowering a compilation to the command line. --- lib/std/Build/Step/Compile.zig | 142 +++++++++++++++------------------ 1 file changed, 64 insertions(+), 78 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 683648856a0e..571fefa30808 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -831,81 +831,42 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { self.exec_cmd_args = duped_args; } -fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { - const b = cs.step.owner; - // First, traverse the whole dependency graph and give every module a - // unique name, ideally one named after what it's called somewhere in the - // graph. It will help here to have both a mapping from module to name and - // a set of all the currently-used names. - var mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8) = .{}; - var names = std.StringHashMap(void).init(b.allocator); - - { - var it = cs.root_module.iterateDependencies(null, false); - _ = it.next(); // Skip over the root module. +const CliNamedModules = struct { + modules: std.AutoArrayHashMapUnmanaged(*Module, void), + names: std.StringArrayHashMapUnmanaged(void), + + /// Traverse the whole dependency graph and give every module a unique + /// name, ideally one named after what it's called somewhere in the graph. + /// It will help here to have both a mapping from module to name and a set + /// of all the currently-used names. + fn init(arena: Allocator, root_module: *Module) Allocator.Error!CliNamedModules { + var self: CliNamedModules = .{ + .modules = .{}, + .names = .{}, + }; + var it = root_module.iterateDependencies(null, false); + { + const item = it.next().?; + assert(root_module == item.module); + try self.modules.put(arena, root_module, {}); + try self.names.put(arena, "root", {}); + } while (it.next()) |item| { - // While we're traversing the root dependencies, let's make sure that no module names - // have colons in them, since the CLI forbids it. We handle this for transitive - // dependencies further down. - if (std.mem.indexOfScalar(u8, item.name, ':') != null) { - return cs.step.fail("module '{s}' contains a colon", .{item.name}); - } - var name = item.name; var n: usize = 0; - while (names.contains(name)) { - name = b.fmt("{s}{d}", .{ item.name, n }); + while (true) { + const gop = try self.names.getOrPut(arena, name); + if (!gop.found_existing) { + try self.modules.putNoClobber(arena, item.module, {}); + break; + } + name = try std.fmt.allocPrint(arena, "{s}{d}", .{ item.name, n }); n += 1; } - - try mod_names.put(b.allocator, item.module, name); - try names.put(name, {}); } + return self; } - - // Since the module names given to the CLI are based off of the exposed - // names, we already know that none of the CLI names have colons in them, - // so there's no need to check that explicitly. - - // Every module in the graph is now named; output their definitions - for (mod_names.keys(), mod_names.values()) |mod, name| { - const root_src = mod.root_source_file orelse continue; - const deps_str = try constructDepString(b.allocator, mod_names, mod.import_table); - const src = root_src.getPath2(mod.owner, &cs.step); - try zig_args.append("--mod"); - try zig_args.append(b.fmt("{s}:{s}:{s}", .{ name, deps_str, src })); - } - - // Lastly, output the root dependencies - const deps_str = try constructDepString(b.allocator, mod_names, cs.root_module.import_table); - if (deps_str.len > 0) { - try zig_args.append("--deps"); - try zig_args.append(deps_str); - } -} - -fn constructDepString( - allocator: std.mem.Allocator, - mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8), - deps: std.StringArrayHashMapUnmanaged(*Module), -) ![]const u8 { - var deps_str = std.ArrayList(u8).init(allocator); - var it = deps.iterator(); - while (it.next()) |kv| { - const expose = kv.key_ptr.*; - const name = mod_names.get(kv.value_ptr.*).?; - if (std.mem.eql(u8, expose, name)) { - try deps_str.writer().print("{s},", .{name}); - } else { - try deps_str.writer().print("{s}={s},", .{ expose, name }); - } - } - if (deps_str.items.len > 0) { - return deps_str.items[0 .. deps_str.items.len - 1]; // omit trailing comma - } else { - return ""; - } -} +}; fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) []const u8 { const maybe_path: ?*GeneratedFile = @field(self, tag_name); @@ -991,14 +952,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic; // Track the number of positional arguments so that a nice error can be // emitted if there is nothing to link. - var total_linker_objects: usize = 0; - - if (self.root_module.root_source_file) |lp| { - try zig_args.append(lp.getPath(b)); - total_linker_objects += 1; - } - - try self.root_module.appendZigProcessFlags(&zig_args, step); + var total_linker_objects: usize = @intFromBool(self.root_module.root_source_file != null); { // Fully recursive iteration including dynamic libraries to detect @@ -1010,6 +964,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } + var cli_named_modules = try CliNamedModules.init(b.allocator, &self.root_module); + // For this loop, don't chase dynamic libraries because their link // objects are already linked. var it = self.root_module.iterateDependencies(self, false); @@ -1233,6 +1189,38 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }, } } + + // We need to emit the --mod argument here so that the above link objects + // have the correct parent module, but only if the module is part of + // this compilation. + if (cli_named_modules.modules.getIndex(module)) |module_cli_index| { + const module_cli_name = cli_named_modules.names.keys()[module_cli_index]; + try module.appendZigProcessFlags(&zig_args, step); + + // --dep arguments + try zig_args.ensureUnusedCapacity(module.import_table.count() * 2); + for (module.import_table.keys(), module.import_table.values()) |name, dep| { + const dep_index = cli_named_modules.modules.getIndex(dep).?; + const dep_cli_name = cli_named_modules.names.keys()[dep_index]; + zig_args.appendAssumeCapacity("--dep"); + if (std.mem.eql(u8, dep_cli_name, name)) { + zig_args.appendAssumeCapacity(dep_cli_name); + } else { + zig_args.appendAssumeCapacity(b.fmt("{s}={s}", .{ name, dep_cli_name })); + } + } + + // The CLI assumes if it sees a --mod argument that it is a zig + // compilation unit. If there is no root source file, then this + // is not a zig compilation unit - it is perhaps a set of + // linker objects, or C source files instead. + // In such case, there will be only one module, so we can leave + // off the naming here. + if (module.root_source_file) |lp| { + const src = lp.getPath2(b, step); + try zig_args.appendSlice(&.{ "--mod", module_cli_name, src }); + } + } } if (total_linker_objects == 0) { @@ -1470,8 +1458,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } - try self.appendModuleArgs(&zig_args); - if (b.sysroot) |sysroot| { try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); } From 5e2035da145f2c758be26ee9817473b97274c34d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 24 Dec 2023 19:50:20 -0700 Subject: [PATCH 100/133] update zig1.wasm Updates the way CLI parameters for modules and dependencies are specified. Old CLI: --mod a:a,b=c:d --deps a,b=c New CLI: --dep a --dep b=c --mod a d --- stage1/zig1.wasm | Bin 2575436 -> 2630060 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 2084fd765d928eecf5f8cdf8bb243f4f1e4380dd..4d692444efab1ee22476f35ee0ff29bc02a9ac0a 100644 GIT binary patch literal 2630060 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%0D@7&8giT!0n8_G;f(@=b(>%k>elG-1 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

*KiO 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

8q#0PeB1z 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%0D=Y!#AO23`wvs}_kup%;?0~1nK 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

!JNXKTCUZe|{fA({0e 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

eH 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 z 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»RoG$`b|~w*O!J~%j2`3fOtFNRtX{Gt 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

tqEJIMjAT80SRTBXtUWzHEx+9pni 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 z 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 z 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�AM8K%x@B@MijzjO)$Vl1 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

kV_gbza)x2! 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 R;pPA&a4e8E<@QS1{|A$s$3Fl7 literal 2575436 zcmeF4dz@ZXb@$IX&vl;5%rluJgxomiAt4DQ+*E=AV-6DTNZML!TU($?D-%=*@lwlW zgb@ZAb$N^)Gek%t|HSst9Tj! zDB$o|R|9XfO|9ixtvpfjP3ns&QmjiN!8E1co0P65=*P_zP;XK<-E=EK&h%FOwWy&U z!2oU)I0EAqN~@t5cgif>DVuWBdBIDsO*YYvM)L9dbsK~jhtv)(> zrUN&VrM^#8U~$U>SW?Y!OhhcfP?=hfV|hhs2EBq@_%cK`#SN_?Aw(9$-mNzqnj2h+ zptq2c71<(OE6>fs4S45Q)#>GCv5BH?PVi(9dE8WplHRE&z~y}`H*fA6uD8Jy#Cs2-f%|q)tmn2#w%~U_D$E^c;(+*v)S=x$d@M!;IHdClvu-Spbm904|pan{2jWX|@TO}FW}9ZHZFYTaH(s;Z^xBy}L+&PWU;l

+yXNbu9O321e-H~ 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

%{`-^ysc#&gs6t=Wz)K=VNu% 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 z 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೒$i1YAO7Z&Sg?`Q)M2z6mM@{A-reae6VJd>KR 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%0AbA^(vEp)hYqpkh5r9Kz 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 K%?EG^JzB?P+t{Lh#QxuWs9H_|NRzs453) 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%0AA@^6S%h8Ms>3TFuat{bD>3j}yv- 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%0A1x2g_0AZBucsELFOa=S*3mfTY#Y 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

74xYLLQ>)!`ry5fF2giLl6(@39{61bg{

NYHg;O5K(3$K9`2&*qZXr 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

+z~>*2MuuoAX7R@BVIWj(#|_IZvCv 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᎟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

lv42q+f-}EGHIIQj+6OW_| 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%0AmP0r>m6e_4%q}F1- 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 gzLg38!M8x+bg+ig!M8)FV0O!};sQ>@~ From 190f6038bfca5e6239635cfeebd87d67d2501ea3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 19:27:15 -0700 Subject: [PATCH 101/133] zig build: reintroduce --prominent-compile-errors This reintroduced flag makes zig build behave the same as the previous commit. Without this flag, the default behavior is now changed to display compilation errors inline with the rest of error messages and the build tree context. This behavior is essential for making sense of error logs from projects that have two or more steps emitting compilation errors which is why it is now the default. --- lib/build_runner.zig | 20 +++++++++++++++++--- src/main.zig | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/build_runner.zig b/lib/build_runner.zig index 687a1eb15198..979cc93f1140 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -99,6 +99,7 @@ pub fn main() !void { var skip_oom_steps: bool = false; var color: Color = .auto; var seed: u32 = 0; + var prominent_compile_errors: bool = false; const stderr_stream = io.getStdErr().writer(); const stdout_stream = io.getStdOut().writer(); @@ -242,6 +243,8 @@ pub fn main() !void { builder.verbose_cc = true; } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { builder.verbose_llvm_cpu_features = true; + } else if (mem.eql(u8, arg, "--prominent-compile-errors")) { + prominent_compile_errors = true; } else if (mem.eql(u8, arg, "-fwine")) { builder.enable_wine = true; } else if (mem.eql(u8, arg, "-fno-wine")) { @@ -325,6 +328,7 @@ pub fn main() !void { .max_rss_mutex = .{}, .skip_oom_steps = skip_oom_steps, .memory_blocked_steps = std.ArrayList(*Step).init(arena), + .prominent_compile_errors = prominent_compile_errors, .claimed_rss = 0, .summary = summary, @@ -357,6 +361,7 @@ const Run = struct { max_rss_mutex: std.Thread.Mutex, skip_oom_steps: bool, memory_blocked_steps: std.ArrayList(*Step), + prominent_compile_errors: bool, claimed_rss: usize, summary: ?Summary, @@ -561,7 +566,7 @@ fn runStepNames( // Finally, render compile errors at the bottom of the terminal. // We use a separate compile_error_steps array list because step_stack is destructively // mutated in printTreeStep above. - if (total_compile_errors > 0) { + if (run.prominent_compile_errors and total_compile_errors > 0) { for (compile_error_steps.items) |s| { if (s.result_error_bundle.errorMessageCount() > 0) { s.result_error_bundle.renderToStdErr(renderOptions(ttyconf)); @@ -910,7 +915,11 @@ fn workerMakeOneStep( const make_result = s.make(&sub_prog_node); // No matter the result, we want to display error/warning messages. - if (s.result_error_msgs.items.len > 0) { + const show_compile_errors = !run.prominent_compile_errors and + s.result_error_bundle.errorMessageCount() > 0; + const show_error_msgs = s.result_error_msgs.items.len > 0; + + if (show_error_msgs or show_compile_errors) { sub_prog_node.context.lock_stderr(); defer sub_prog_node.context.unlock_stderr(); @@ -1003,7 +1012,11 @@ fn printErrorMessages(b: *std.Build, failing_step: *Step, run: *const Run) !void } try ttyconf.setColor(stderr, .reset); - // Finally, the actual error messages. + // Penultimately, the compilation errors. + if (!run.prominent_compile_errors and failing_step.result_error_bundle.errorMessageCount() > 0) + try failing_step.result_error_bundle.renderToWriter(renderOptions(ttyconf), stderr.writer()); + + // Finally, generic error messages. for (failing_step.result_error_msgs.items) |msg| { try ttyconf.setColor(stderr, .red); try stderr.writeAll("error: "); @@ -1078,6 +1091,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi \\ -l, --list-steps Print available steps \\ --verbose Print commands before executing them \\ --color [auto|off|on] Enable or disable colored error messages + \\ --prominent-compile-errors Buffer compile errors and display at end \\ --summary [mode] Control the printing of the build summary \\ all Print the build summary in its entirety \\ failures (Default) Only print failed steps diff --git a/src/main.zig b/src/main.zig index 54db7eb37d3d..a8ff0721ad6d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5096,6 +5096,7 @@ pub const usage_build = \\ --global-cache-dir [path] Override path to global Zig cache directory \\ --zig-lib-dir [arg] Override path to Zig lib directory \\ --build-runner [file] Override path to build runner + \\ --prominent-compile-errors Buffer compile errors and display at end \\ --seed [integer] For shuffling dependency traversal order (default: random) \\ --fetch Exit after fetching dependency tree \\ -h, --help Print this help and exit From beed47e8c3792abf87529c705726d9745546648e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 18:25:53 -0700 Subject: [PATCH 102/133] std.Build: add error_tracing field to addExecutable and friends To support easily overriding error return tracing for the main module. --- lib/std/Build.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 2074269c9b6f..02f34ebfb1df 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -607,6 +607,7 @@ pub const ExecutableOptions = struct { unwind_tables: ?bool = null, omit_frame_pointer: ?bool = null, sanitize_thread: ?bool = null, + error_tracing: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -632,6 +633,7 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { .unwind_tables = options.unwind_tables, .omit_frame_pointer = options.omit_frame_pointer, .sanitize_thread = options.sanitize_thread, + .error_tracing = options.error_tracing, }, .version = options.version, .kind = .exe, @@ -659,6 +661,7 @@ pub const ObjectOptions = struct { unwind_tables: ?bool = null, omit_frame_pointer: ?bool = null, sanitize_thread: ?bool = null, + error_tracing: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -678,6 +681,7 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { .unwind_tables = options.unwind_tables, .omit_frame_pointer = options.omit_frame_pointer, .sanitize_thread = options.sanitize_thread, + .error_tracing = options.error_tracing, }, .kind = .obj, .max_rss = options.max_rss, @@ -703,6 +707,7 @@ pub const SharedLibraryOptions = struct { unwind_tables: ?bool = null, omit_frame_pointer: ?bool = null, sanitize_thread: ?bool = null, + error_tracing: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -728,6 +733,7 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile .unwind_tables = options.unwind_tables, .omit_frame_pointer = options.omit_frame_pointer, .sanitize_thread = options.sanitize_thread, + .error_tracing = options.error_tracing, }, .kind = .lib, .linkage = .dynamic, @@ -756,6 +762,7 @@ pub const StaticLibraryOptions = struct { unwind_tables: ?bool = null, omit_frame_pointer: ?bool = null, sanitize_thread: ?bool = null, + error_tracing: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -775,6 +782,7 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile .unwind_tables = options.unwind_tables, .omit_frame_pointer = options.omit_frame_pointer, .sanitize_thread = options.sanitize_thread, + .error_tracing = options.error_tracing, }, .kind = .lib, .linkage = .static, @@ -802,6 +810,7 @@ pub const TestOptions = struct { unwind_tables: ?bool = null, omit_frame_pointer: ?bool = null, sanitize_thread: ?bool = null, + error_tracing: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, zig_lib_dir: ?LazyPath = null, @@ -822,6 +831,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { .unwind_tables = options.unwind_tables, .omit_frame_pointer = options.omit_frame_pointer, .sanitize_thread = options.sanitize_thread, + .error_tracing = options.error_tracing, }, .max_rss = options.max_rss, .filter = options.filter, From c8c32a056989cc669008f1fc295a29d55b753cc0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Dec 2023 18:26:23 -0700 Subject: [PATCH 103/133] update stack trace tests to account for new defaults ReleaseSafe optimization mode now defaults error tracing to false. --- test/src/StackTrace.zig | 78 +++++++++++++++-------------------------- test/stack_traces.zig | 47 ++++++++++++++++--------- 2 files changed, 59 insertions(+), 66 deletions(-) diff --git a/test/src/StackTrace.zig b/test/src/StackTrace.zig index f0dc9a8c0ce2..191c35009147 100644 --- a/test/src/StackTrace.zig +++ b/test/src/StackTrace.zig @@ -5,44 +5,33 @@ test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, check_exe: *std.Build.Step.Compile, -const Expect = [@typeInfo(OptimizeMode).Enum.fields.len][]const u8; +const Config = struct { + name: []const u8, + source: []const u8, + Debug: ?PerMode = null, + ReleaseSmall: ?PerMode = null, + ReleaseSafe: ?PerMode = null, + ReleaseFast: ?PerMode = null, -pub fn addCase(self: *StackTrace, config: anytype) void { - if (@hasField(@TypeOf(config), "exclude")) { - if (config.exclude.exclude()) return; - } - if (@hasField(@TypeOf(config), "exclude_arch")) { - const exclude_arch: []const std.Target.Cpu.Arch = &config.exclude_arch; - for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return; - } - if (@hasField(@TypeOf(config), "exclude_os")) { - const exclude_os: []const std.Target.Os.Tag = &config.exclude_os; - for (exclude_os) |os| if (os == builtin.os.tag) return; - } - for (self.optimize_modes) |optimize_mode| { - switch (optimize_mode) { - .Debug => { - if (@hasField(@TypeOf(config), "Debug")) { - self.addExpect(config.name, config.source, optimize_mode, config.Debug); - } - }, - .ReleaseSafe => { - if (@hasField(@TypeOf(config), "ReleaseSafe")) { - self.addExpect(config.name, config.source, optimize_mode, config.ReleaseSafe); - } - }, - .ReleaseFast => { - if (@hasField(@TypeOf(config), "ReleaseFast")) { - self.addExpect(config.name, config.source, optimize_mode, config.ReleaseFast); - } - }, - .ReleaseSmall => { - if (@hasField(@TypeOf(config), "ReleaseSmall")) { - self.addExpect(config.name, config.source, optimize_mode, config.ReleaseSmall); - } - }, - } - } + const PerMode = struct { + expect: []const u8, + exclude_os: []const std.Target.Os.Tag = &.{}, + error_tracing: ?bool = null, + }; +}; + +pub fn addCase(self: *StackTrace, config: Config) void { + if (config.Debug) |per_mode| + self.addExpect(config.name, config.source, .Debug, per_mode); + + if (config.ReleaseSmall) |per_mode| + self.addExpect(config.name, config.source, .ReleaseSmall, per_mode); + + if (config.ReleaseFast) |per_mode| + self.addExpect(config.name, config.source, .ReleaseFast, per_mode); + + if (config.ReleaseSafe) |per_mode| + self.addExpect(config.name, config.source, .ReleaseSafe, per_mode); } fn addExpect( @@ -50,19 +39,9 @@ fn addExpect( name: []const u8, source: []const u8, optimize_mode: OptimizeMode, - mode_config: anytype, + mode_config: Config.PerMode, ) void { - if (@hasField(@TypeOf(mode_config), "exclude")) { - if (mode_config.exclude.exclude()) return; - } - if (@hasField(@TypeOf(mode_config), "exclude_arch")) { - const exclude_arch: []const std.Target.Cpu.Arch = &mode_config.exclude_arch; - for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return; - } - if (@hasField(@TypeOf(mode_config), "exclude_os")) { - const exclude_os: []const std.Target.Os.Tag = &mode_config.exclude_os; - for (exclude_os) |os| if (os == builtin.os.tag) return; - } + for (mode_config.exclude_os) |tag| if (tag == builtin.os.tag) return; const b = self.b; const annotated_case_name = fmt.allocPrint(b.allocator, "check {s} ({s})", .{ @@ -78,6 +57,7 @@ fn addExpect( .root_source_file = write_src.files.items[0].getPath(), .optimize = optimize_mode, .target = b.host, + .error_tracing = mode_config.error_tracing, }); const run = b.addRunArtifact(exe); diff --git a/test/stack_traces.zig b/test/stack_traces.zig index 0ace004bc64c..467c53bcb935 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -20,7 +20,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -31,6 +31,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -70,7 +71,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO }, .expect = @@ -83,6 +84,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -125,7 +127,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -136,6 +138,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -176,7 +179,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -187,6 +190,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -230,7 +234,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -244,6 +248,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -286,7 +291,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -297,6 +302,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -336,7 +342,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -350,6 +356,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -391,7 +398,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -402,6 +409,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -461,7 +469,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO .linux, // defeated by aggressive inlining }, @@ -478,6 +486,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -531,7 +540,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO }, .expect = @@ -547,6 +556,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -595,7 +605,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO }, .expect = @@ -611,6 +621,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -659,7 +670,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO }, .expect = @@ -675,6 +686,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -728,7 +740,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { , }, .ReleaseSafe = .{ - .exclude_os = .{ + .exclude_os = &.{ .windows, // TODO }, .expect = @@ -747,6 +759,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ ^ \\ , + .error_tracing = true, }, .ReleaseFast = .{ .expect = @@ -763,10 +776,6 @@ pub fn addCases(cases: *tests.StackTracesContext) void { }); cases.addCase(.{ - .exclude_os = .{ - .openbsd, // integer overflow - .windows, // TODO intermittent failures - }, .name = "dumpCurrentStackTrace", .source = \\const std = @import("std"); @@ -783,6 +792,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\} , .Debug = .{ + .exclude_os = &.{ + .openbsd, // integer overflow + .windows, // TODO intermittent failures + }, .expect = \\source.zig:7:8: [address] in foo (test) \\ bar(); From 435b74acd6384029588755ae87568d03911da5c2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 10:23:27 -0700 Subject: [PATCH 104/133] move force_undefined_symbols into Compilation This field is needed by Compilation regardless of whether a link file is instantiated. Fixes an invalid check for bin_file=null. --- src/Compilation.zig | 26 ++++++++++++++------------ src/link.zig | 5 ----- src/link/C.zig | 1 - src/link/Coff.zig | 1 - src/link/Coff/lld.zig | 4 ++-- src/link/Elf.zig | 5 ++--- src/link/MachO.zig | 3 +-- src/link/MachO/dead_strip.zig | 6 ++++-- src/link/MachO/zld.zig | 2 +- src/link/NvPtx.zig | 1 - src/link/Plan9.zig | 1 - src/link/SpirV.zig | 1 - src/link/Wasm.zig | 1 - 13 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 86caba765189..d42d731188b1 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -86,6 +86,10 @@ no_builtin: bool, function_sections: bool, data_sections: bool, native_system_include_paths: []const []const u8, +/// List of symbols forced as undefined in the symbol table +/// thus forcing their resolution by the linker. +/// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. +force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) = @@ -1504,6 +1508,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .data_sections = options.data_sections, .native_system_include_paths = options.native_system_include_paths, .wasi_emulated_libs = options.wasi_emulated_libs, + .force_undefined_symbols = options.force_undefined_symbols, }; // Prevent some footguns by making the "any" fields of config reflect @@ -1569,7 +1574,6 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .headerpad_size = options.headerpad_size, .headerpad_max_install_names = options.headerpad_max_install_names, .dead_strip_dylibs = options.dead_strip_dylibs, - .force_undefined_symbols = options.force_undefined_symbols, .pdb_source_path = options.pdb_source_path, .pdb_out_path = options.pdb_out_path, .entry_addr = null, // CLI does not expose this option (yet?) @@ -1830,18 +1834,16 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { try comp.work_queue.writeItem(.libtsan); } - if (comp.bin_file) |lf| { - if (target.isMinGW() and comp.config.any_non_single_threaded) { - // LLD might drop some symbols as unused during LTO and GCing, therefore, - // we force mark them for resolution here. + if (target.isMinGW() and comp.config.any_non_single_threaded) { + // LLD might drop some symbols as unused during LTO and GCing, therefore, + // we force mark them for resolution here. - const tls_index_sym = switch (target.cpu.arch) { - .x86 => "__tls_index", - else => "_tls_index", - }; + const tls_index_sym = switch (target.cpu.arch) { + .x86 => "__tls_index", + else => "_tls_index", + }; - try lf.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); - } + try comp.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); } if (comp.include_compiler_rt and capable_of_building_compiler_rt) { @@ -2447,6 +2449,7 @@ 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); + man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_asm); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); @@ -2482,7 +2485,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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) { diff --git a/src/link.zig b/src/link.zig index fdcd5fcf41b8..6729f00ea903 100644 --- a/src/link.zig +++ b/src/link.zig @@ -64,10 +64,6 @@ pub const File = struct { print_gc_sections: bool, build_id: std.zig.BuildId, rpath_list: []const []const u8, - /// List of symbols forced as undefined in the symbol table - /// thus forcing their resolution by the linker. - /// Corresponds to `-u ` for ELF/MachO and `/include:` for COFF/PE. - force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), allow_shlib_undefined: bool, stack_size: u64, @@ -129,7 +125,6 @@ pub const File = struct { print_icf_sections: bool, print_map: bool, - force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), /// Use a wrapper function for symbol. Any undefined reference to symbol /// will be resolved to __wrap_symbol. Any undefined reference to /// __real_symbol will be resolved to symbol. This can be used to provide a diff --git a/src/link/C.zig b/src/link/C.zig index 669587bda9ec..958ce12a064f 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -142,7 +142,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 53f999b9655e..aefecb014e4a 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -284,7 +284,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .ptr_width = ptr_width, .page_size = page_size, diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 6afe741f6635..3a833c40aef6 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -103,7 +103,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } try link.hashAddSystemLibs(&man, comp.system_libs); - man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); + man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); man.hash.addOptional(self.subsystem); man.hash.add(comp.config.is_test); man.hash.add(self.tsaware); @@ -217,7 +217,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } - for (self.base.force_undefined_symbols.keys()) |symbol| { + for (comp.force_undefined_symbols.keys()) |symbol| { try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol})); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 65fc0ff5a37b..085522d67bd2 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -285,7 +285,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .ptr_width = ptr_width, .page_size = page_size, @@ -2473,7 +2472,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.addOptionalBytes(self.soname); man.hash.addOptional(comp.version); try link.hashAddSystemLibs(&man, self.base.comp.system_libs); - man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); + man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); man.hash.add(self.base.allow_shlib_undefined); man.hash.add(self.bind_global_refs_locally); man.hash.add(self.compress_debug_sections); @@ -2574,7 +2573,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.appendSlice(&.{ "--entry", name }); } - for (self.base.force_undefined_symbols.keys()) |sym| { + for (comp.force_undefined_symbols.keys()) |sym| { try argv.append("-u"); try argv.append(sym); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8c0874e3cb4d..6bf4d95ef4c0 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -220,7 +220,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .mode = mode, .pagezero_vmsize = options.pagezero_size orelse default_pagezero_vmsize, @@ -1642,7 +1641,7 @@ pub fn resolveSymbols(self: *MachO) !void { } // Force resolution of any symbols requested by the user. - for (self.base.force_undefined_symbols.keys()) |sym_name| { + for (comp.force_undefined_symbols.keys()) |sym_name| { _ = try self.addUndefined(sym_name, .{}); } diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index 02cf68e46ee8..fe3740e82667 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -34,7 +34,9 @@ fn addRoot(macho_file: *MachO, roots: *AtomTable, file: u32, sym_loc: SymbolWith fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void { log.debug("collecting roots", .{}); - switch (macho_file.base.comp.config.output_mode) { + const comp = macho_file.base.comp; + + switch (comp.config.output_mode) { .Exe => { // Add entrypoint as GC root if (macho_file.getEntryPoint()) |global| { @@ -61,7 +63,7 @@ fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void { } // Add all symbols force-defined by the user. - for (macho_file.base.force_undefined_symbols.keys()) |sym_name| { + for (comp.force_undefined_symbols.keys()) |sym_name| { const global_index = macho_file.resolver.get(sym_name).?; const global = macho_file.globals.items[global_index]; const sym = macho_file.getSymbol(global); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 05fa8e671a2f..81b10c59d9bf 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -85,7 +85,7 @@ pub fn linkWithZld( } try link.hashAddSystemLibs(&man, comp.system_libs); man.hash.addOptionalBytes(comp.sysroot); - man.hash.addListOfBytes(macho_file.base.force_undefined_symbols.keys()); + man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); try man.addOptionalFile(macho_file.entitlements); // We don't actually care whether it's a cache hit or miss; we just diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 2025372323a7..1f5af5b86edc 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -60,7 +60,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .llvm_object = llvm_object, }; diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index ceabfe2864f1..e93c889dcd7d 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -325,7 +325,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .sixtyfour_bit = sixtyfour_bit, .bases = undefined, diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 5124ff19f619..fc9e0c9a6009 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -71,7 +71,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .object = codegen.Object.init(gpa), }; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 7f3ca877c600..cdd40891daa7 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -424,7 +424,6 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, .rpath_list = options.rpath_list, - .force_undefined_symbols = options.force_undefined_symbols, }, .name = undefined, .import_table = options.import_table, From 372b407740224ae20fad49647bbde56330b24967 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 10:34:55 -0700 Subject: [PATCH 105/133] move eh_frame_hdr from link.File to Compilation since it's accessed by Compilation. fixes an invalid check of bin_file==null --- src/Compilation.zig | 8 ++++---- src/link.zig | 1 - src/link/Elf.zig | 16 ++++++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index d42d731188b1..85ad6a2649a8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -85,6 +85,7 @@ skip_linker_dependencies: bool, no_builtin: bool, function_sections: bool, data_sections: bool, +link_eh_frame_hdr: bool, native_system_include_paths: []const []const u8, /// List of symbols forced as undefined in the symbol table /// thus forcing their resolution by the linker. @@ -1509,6 +1510,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .native_system_include_paths = options.native_system_include_paths, .wasi_emulated_libs = options.wasi_emulated_libs, .force_undefined_symbols = options.force_undefined_symbols, + .link_eh_frame_hdr = link_eh_frame_hdr, }; // Prevent some footguns by making the "any" fields of config reflect @@ -1558,7 +1560,6 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .image_base = options.image_base, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, - .eh_frame_hdr = link_eh_frame_hdr, .emit_relocs = options.link_emit_relocs, .soname = options.soname, .compatibility_version = options.compatibility_version, @@ -2457,6 +2458,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.skip_linker_dependencies); man.hash.add(comp.include_compiler_rt); + man.hash.add(comp.link_eh_frame_hdr); if (comp.config.link_libc) { man.hash.add(comp.libc_installation != null); const target = comp.root_mod.resolved_target.result; @@ -2490,7 +2492,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes switch (lf.tag) { .elf => { const elf = lf.cast(link.File.Elf).?; - 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); @@ -6213,8 +6214,7 @@ 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 unwind_tables = comp.link_eh_frame_hdr; const strip = comp.compilerRtStrip(); const optimize_mode = comp.compilerRtOptMode(); diff --git a/src/link.zig b/src/link.zig index 6729f00ea903..065779177e64 100644 --- a/src/link.zig +++ b/src/link.zig @@ -85,7 +85,6 @@ pub const File = struct { entry_addr: ?u64, stack_size: ?u64, image_base: ?u64, - eh_frame_hdr: bool, emit_relocs: bool, z_nodelete: bool, z_notext: bool, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 085522d67bd2..f20282a80291 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,6 +1,5 @@ base: link.File, image_base: u64, -eh_frame_hdr: bool, emit_relocs: bool, z_nodelete: bool, z_notext: bool, @@ -306,7 +305,6 @@ pub fn createEmpty( }; }, - .eh_frame_hdr = options.eh_frame_hdr, .emit_relocs = options.emit_relocs, .z_nodelete = options.z_nodelete, .z_notext = options.z_notext, @@ -1726,7 +1724,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("--print-gc-sections"); } - if (self.eh_frame_hdr) { + if (comp.link_eh_frame_hdr) { try argv.append("--eh-frame-hdr"); } @@ -2437,7 +2435,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.add(self.image_base); man.hash.add(self.base.gc_sections); man.hash.addOptional(self.sort_section); - man.hash.add(self.eh_frame_hdr); + man.hash.add(comp.link_eh_frame_hdr); man.hash.add(self.emit_relocs); man.hash.add(comp.config.rdynamic); man.hash.addListOfBytes(self.lib_dirs); @@ -2633,7 +2631,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("--print-map"); } - if (self.eh_frame_hdr) { + if (comp.link_eh_frame_hdr) { try argv.append("--eh-frame-hdr"); } @@ -3317,6 +3315,9 @@ pub fn deleteDeclExport( } fn addLinkerDefinedSymbols(self: *Elf) !void { + const comp = self.base.comp; + const gpa = comp.gpa; + const linker_defined_index = self.linker_defined_index orelse return; const linker_defined = self.file(linker_defined_index).?.linker_defined; self.dynamic_index = try linker_defined.addGlobal("_DYNAMIC", self); @@ -3331,7 +3332,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self); self.end_index = try linker_defined.addGlobal("_end", self); - if (self.eh_frame_hdr) { + if (comp.link_eh_frame_hdr) { self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self); } @@ -3345,7 +3346,6 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { for (self.shdrs.items) |shdr| { if (self.getStartStopBasename(shdr)) |name| { - const gpa = self.base.comp.gpa; try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); @@ -3510,7 +3510,7 @@ fn initSyntheticSections(self: *Elf) !void { .offset = std.math.maxInt(u64), }); - if (self.eh_frame_hdr) { + if (comp.link_eh_frame_hdr) { self.eh_frame_hdr_section_index = try self.addSection(.{ .name = ".eh_frame_hdr", .type = elf.SHT_PROGBITS, From 5b05e99dd48520c0efd5f624760b3218bc1311ec Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 10:42:32 -0700 Subject: [PATCH 106/133] Compilation: consolidate module hashing code --- src/Compilation.zig | 62 +++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 85ad6a2649a8..ae49f75d9731 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -799,6 +799,24 @@ pub const EmitLoc = struct { }; pub const cache_helpers = struct { + pub fn addModule(hh: *Cache.HashHelper, mod: *const Package.Module) void { + addResolvedTarget(hh, mod.resolved_target); + hh.add(mod.optimize_mode); + hh.add(mod.code_model); + hh.add(mod.single_threaded); + hh.add(mod.error_tracing); + hh.add(mod.valgrind); + hh.add(mod.pic); + hh.add(mod.strip); + hh.add(mod.omit_frame_pointer); + hh.add(mod.stack_check); + hh.add(mod.red_zone); + hh.add(mod.sanitize_c); + hh.add(mod.sanitize_thread); + hh.add(mod.unwind_tables); + hh.add(mod.structured_cfg); + } + pub fn addResolvedTarget( hh: *Cache.HashHelper, resolved_target: Package.Module.ResolvedTarget, @@ -1131,21 +1149,7 @@ fn addModuleTableToCacheHash( continue; } - cache_helpers.addResolvedTarget(hash, mod.resolved_target); - hash.add(mod.optimize_mode); - hash.add(mod.code_model); - hash.add(mod.single_threaded); - hash.add(mod.error_tracing); - hash.add(mod.valgrind); - hash.add(mod.pic); - hash.add(mod.strip); - hash.add(mod.omit_frame_pointer); - hash.add(mod.stack_check); - hash.add(mod.red_zone); - hash.add(mod.sanitize_c); - hash.add(mod.sanitize_thread); - hash.add(mod.unwind_tables); - hash.add(mod.structured_cfg); + cache_helpers.addModule(hash, mod); switch (hash_type) { .path_bytes => { @@ -2406,19 +2410,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); } else { - cache_helpers.addResolvedTarget(&man.hash, comp.root_mod.resolved_target); - man.hash.add(comp.root_mod.optimize_mode); - man.hash.add(comp.root_mod.code_model); - man.hash.add(comp.root_mod.single_threaded); - man.hash.add(comp.root_mod.error_tracing); - man.hash.add(comp.root_mod.pic); - man.hash.add(comp.root_mod.omit_frame_pointer); - man.hash.add(comp.root_mod.stack_check); - man.hash.add(comp.root_mod.red_zone); - man.hash.add(comp.root_mod.sanitize_c); - man.hash.add(comp.root_mod.sanitize_thread); - man.hash.add(comp.root_mod.unwind_tables); - man.hash.add(comp.root_mod.structured_cfg); + cache_helpers.addModule(&man.hash, comp.root_mod); } for (comp.objects) |obj| { @@ -3855,19 +3847,7 @@ pub fn obtainCObjectCacheManifest( // Only things that need to be added on top of the base hash, and only things // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. - cache_helpers.addResolvedTarget(&man.hash, owner_mod.resolved_target); - man.hash.add(owner_mod.optimize_mode); - man.hash.add(owner_mod.code_model); - man.hash.add(owner_mod.single_threaded); - man.hash.add(owner_mod.error_tracing); - man.hash.add(owner_mod.pic); - man.hash.add(owner_mod.omit_frame_pointer); - man.hash.add(owner_mod.stack_check); - man.hash.add(owner_mod.red_zone); - man.hash.add(owner_mod.sanitize_c); - man.hash.add(owner_mod.sanitize_thread); - man.hash.add(owner_mod.unwind_tables); - man.hash.add(owner_mod.structured_cfg); + cache_helpers.addModule(&man.hash, owner_mod); man.hash.addListOfBytes(owner_mod.cc_argv); man.hash.add(comp.config.link_libcpp); From 7f13754778ff1c0709b5b3e63de40ffbf5049164 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 11:22:31 -0700 Subject: [PATCH 107/133] Compilation: fix whole mode cache hash before this commit it was trying to hash based on resolved bin_file settings, but bin_file was always null since cache mode is always whole when this function is called! hash based on the lf_open_opts instead. --- src/Compilation.zig | 155 +++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 88 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index ae49f75d9731..06b406a59c6c 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -815,6 +815,7 @@ pub const cache_helpers = struct { hh.add(mod.sanitize_thread); hh.add(mod.unwind_tables); hh.add(mod.structured_cfg); + hh.addListOfBytes(mod.cc_argv); } pub fn addResolvedTarget( @@ -2398,10 +2399,6 @@ 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.config.dll_export_fns); - man.hash.add(comp.config.is_test); man.hash.add(comp.config.test_evented_io); man.hash.addOptionalBytes(comp.test_filter); man.hash.addOptionalBytes(comp.test_name_prefix); @@ -2439,18 +2436,42 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } } + 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); + man.hash.add(comp.config.dll_export_fns); + man.hash.add(comp.config.rdynamic); + man.hash.addOptionalBytes(comp.sysroot); man.hash.addOptional(comp.version); + man.hash.add(comp.link_eh_frame_hdr); + man.hash.add(comp.skip_linker_dependencies); + man.hash.add(comp.include_compiler_rt); man.hash.addListOfBytes(comp.rc_include_dir_list); man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); + man.hash.addListOfBytes(comp.framework_dirs); + try link.hashAddSystemLibs(man, comp.system_libs); 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.skip_linker_dependencies); - man.hash.add(comp.include_compiler_rt); - man.hash.add(comp.link_eh_frame_hdr); + const opts = comp.cache_use.whole.lf_open_opts; + + try man.addOptionalFile(opts.linker_script); + try man.addOptionalFile(opts.version_script); + + man.hash.addOptional(opts.stack_size); + man.hash.addOptional(opts.image_base); + man.hash.addOptional(opts.gc_sections); + man.hash.add(opts.emit_relocs); + man.hash.addListOfBytes(opts.lib_dirs); + man.hash.addListOfBytes(opts.rpath_list); + man.hash.addListOfBytes(opts.symbol_wrap_set.keys()); + man.hash.add(opts.each_lib_rpath); if (comp.config.link_libc) { man.hash.add(comp.libc_installation != null); const target = comp.root_mod.resolved_target.result; @@ -2463,86 +2484,45 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes } man.hash.addOptionalBytes(target.dynamic_linker.get()); } - try link.hashAddSystemLibs(man, comp.system_libs); - - 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); - man.hash.add(comp.config.dll_export_fns); - man.hash.add(comp.config.rdynamic); - - 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.add(lf.allow_shlib_undefined); - - switch (lf.tag) { - .elf => { - const elf = lf.cast(link.File.Elf).?; - 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.addOptional(wasm.initial_memory); - man.hash.addOptional(wasm.max_memory); - man.hash.addOptional(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.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 - } - } + man.hash.addOptional(opts.allow_shlib_undefined); + man.hash.add(opts.bind_global_refs_locally); + + // ELF specific stuff + man.hash.add(opts.z_nodelete); + man.hash.add(opts.z_notext); + man.hash.add(opts.z_defs); + man.hash.add(opts.z_origin); + man.hash.add(opts.z_nocopyreloc); + man.hash.add(opts.z_now); + man.hash.add(opts.z_relro); + man.hash.add(opts.z_common_page_size orelse 0); + man.hash.add(opts.z_max_page_size orelse 0); + man.hash.add(opts.hash_style); + man.hash.add(opts.compress_debug_sections); + man.hash.addOptional(opts.sort_section); + man.hash.addOptionalBytes(opts.soname); + man.hash.add(opts.build_id); + + // WASM specific stuff + man.hash.addOptional(opts.initial_memory); + man.hash.addOptional(opts.max_memory); + man.hash.addOptional(opts.global_base); + + // Mach-O specific stuff + try link.File.MachO.hashAddFrameworks(man, opts.frameworks); + try man.addOptionalFile(opts.entitlements); + man.hash.addOptional(opts.pagezero_size); + man.hash.addOptional(opts.headerpad_size); + man.hash.add(opts.headerpad_max_install_names); + man.hash.add(opts.dead_strip_dylibs); + + // COFF specific stuff + man.hash.addOptional(opts.subsystem); + man.hash.add(opts.tsaware); + man.hash.add(opts.nxcompat); + man.hash.add(opts.dynamicbase); + man.hash.addOptional(opts.major_subsystem_version); + man.hash.addOptional(opts.minor_subsystem_version); } fn emitOthers(comp: *Compilation) void { @@ -3848,7 +3828,6 @@ pub fn obtainCObjectCacheManifest( // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. cache_helpers.addModule(&man.hash, owner_mod); - man.hash.addListOfBytes(owner_mod.cc_argv); man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list From 4c3342ed76f543f2043c51c11596acae61e933ea Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 12:55:38 -0700 Subject: [PATCH 108/133] glibc: fix crash from not setting owner module --- src/glibc.zig | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/glibc.zig b/src/glibc.zig index d478c6e939a7..838f55c87926 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -1067,13 +1067,7 @@ fn buildSharedLib( const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 }; const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?); const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename; - const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename }); - const c_source_files = [1]Compilation.CSourceFile{ - .{ - .src_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, asm_file_basename }), - .owner = undefined, - }, - }; + const map_file_path = try path.join(arena, &.{ bin_directory.path.?, all_map_basename }); const optimize_mode = comp.compilerRtOptMode(); const strip = comp.compilerRtStrip(); @@ -1115,13 +1109,20 @@ fn buildSharedLib( .builtin_mod = null, }); + const c_source_files = [1]Compilation.CSourceFile{ + .{ + .src_path = try path.join(arena, &.{ bin_directory.path.?, asm_file_basename }), + .owner = root_mod, + }, + }; + const sub_compilation = try Compilation.create(comp.gpa, .{ .local_cache_directory = zig_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, .thread_pool = comp.thread_pool, .self_exe_path = comp.self_exe_path, - .cache_mode = .whole, + .cache_mode = .incremental, .config = config, .root_mod = root_mod, .root_name = lib.name, From 476484f09c98a3a49e0a6be3b92d563ad362ee04 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 12:56:14 -0700 Subject: [PATCH 109/133] Compilation: inline the flush function There is only one call to this function and this made it easier to troubleshoot the logic. --- src/Compilation.zig | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 06b406a59c6c..6b0bd7345c39 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2202,10 +2202,26 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void return; } - // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and - // -femit-asm to handle, in the case of C objects. + // Flush below handles -femit-bin but there is still -femit-llvm-ir, + // -femit-llvm-bc, and -femit-asm, in the case of C objects. comp.emitOthers(); - try comp.flush(main_progress_node); + + { + if (comp.bin_file) |lf| { + // This is needed before reading the error flags. + lf.flush(comp, main_progress_node) catch |err| switch (err) { + error.FlushFailure => {}, // error reported through link_error_flags + error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr + else => |e| return e, + }; + comp.link_error_flags = lf.error_flags; + } + + if (comp.module) |module| { + try link.File.C.flushEmitH(module); + } + } + if (comp.totalErrorCount() != 0) return; try maybeGenerateAutodocs(comp, main_progress_node); @@ -2323,22 +2339,6 @@ fn maybeGenerateAutodocs(comp: *Compilation, prog_node: *std.Progress.Node) !voi } } -fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void { - if (comp.bin_file) |lf| { - // This is needed before reading the error flags. - lf.flush(comp, prog_node) catch |err| switch (err) { - error.FlushFailure => {}, // error reported through link_error_flags - error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr - else => |e| return e, - }; - comp.link_error_flags = lf.error_flags; - } - - if (comp.module) |module| { - try link.File.C.flushEmitH(module); - } -} - /// Communicate the output binary location to parent Compilations. fn wholeCacheModeSetBinFilePath( comp: *Compilation, From 791e83c22396e029e0f2bc19b75fd86f8cd7851f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 13:20:13 -0700 Subject: [PATCH 110/133] frontend: make dll_export_fns=false on non-windows Fixes a regression introduced in this branch. --- src/Compilation/Config.zig | 6 ++++++ src/main.zig | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 4abf3e88d4ac..5f8776fd1f81 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -138,6 +138,7 @@ pub const ResolveError = error{ LlvmLibraryUnavailable, LldUnavailable, ClangUnavailable, + DllExportFnsRequiresWindows, }; pub fn resolve(options: Options) ResolveError!Config { @@ -459,6 +460,11 @@ pub fn resolve(options: Options) ResolveError!Config { const rdynamic = options.rdynamic orelse false; const dll_export_fns = b: { + if (target.os.tag != .windows) { + if (options.dll_export_fns == true) + return error.DllExportFnsRequiresWindows; + break :b false; + } if (options.dll_export_fns) |x| break :b x; if (rdynamic) break :b true; break :b switch (options.output_mode) { diff --git a/src/main.zig b/src/main.zig index a8ff0721ad6d..1470653f1e13 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3842,8 +3842,8 @@ fn createModule( create_module.opts.any_dyn_libs = true; create_module.resolved_options = Compilation.Config.resolve(create_module.opts) catch |err| switch (err) { - error.WasiExecModelRequiresWasi => fatal("execution model only allowed for WASI OS targets", .{}), - error.SharedMemoryIsWasmOnly => fatal("shared memory only allowed for WebAssembly CPU targets", .{}), + error.WasiExecModelRequiresWasi => fatal("only WASI OS targets support execution model", .{}), + error.SharedMemoryIsWasmOnly => fatal("only WebAssembly CPU targets support shared memory", .{}), error.ObjectFilesCannotShareMemory => fatal("object files cannot share memory", .{}), error.SharedMemoryRequiresAtomicsAndBulkMemory => fatal("shared memory requires atomics and bulk_memory CPU features", .{}), error.ThreadsRequireSharedMemory => fatal("threads require shared memory", .{}), @@ -3869,6 +3869,7 @@ fn createModule( error.LlvmLibraryUnavailable => fatal("zig was compiled without LLVM libraries", .{}), error.LldUnavailable => fatal("zig was compiled without LLD libraries", .{}), error.ClangUnavailable => fatal("zig was compiled without Clang libraries", .{}), + error.DllExportFnsRequiresWindows => fatal("only Windows OS targets support DLLs", .{}), }; } From 6509c492ad7908c515a0c00751e1348b26dda4e7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 16:12:06 -0700 Subject: [PATCH 111/133] move misc_errors from linker to Compilation So that they can be referenced by getAllErrorsAlloc(). Fixes missing compile errors. --- src/Compilation.zig | 133 ++++++++++++++++++++++---------------------- src/link.zig | 8 --- src/link/Coff.zig | 4 +- src/link/Elf.zig | 55 +++++++++--------- src/link/MachO.zig | 55 ++++++++++-------- 5 files changed, 130 insertions(+), 125 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 6b0bd7345c39..cb47a5d88a1d 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -28,7 +28,9 @@ const libcxx = @import("libcxx.zig"); const wasi_libc = @import("wasi_libc.zig"); const fatal = @import("main.zig").fatal; const clangMain = @import("main.zig").clangMain; -const Module = @import("Module.zig"); +const Zcu = @import("Module.zig"); +/// Deprecated; use `Zcu`. +const Module = Zcu; const InternPool = @import("InternPool.zig"); const Cache = std.Build.Cache; const c_codegen = @import("codegen/c.zig"); @@ -97,6 +99,7 @@ win32_resource_table: if (build_options.only_core_functionality) void else std.A if (build_options.only_core_functionality) {} else .{}, link_error_flags: link.File.ErrorFlags = .{}, +link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, lld_errors: std.ArrayListUnmanaged(LldError) = .{}, work_queue: std.fifo.LinearFifo(Job, .Dynamic), @@ -1874,87 +1877,90 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { return comp; } -pub fn destroy(self: *Compilation) void { - if (self.bin_file) |lf| lf.destroy(); - if (self.module) |zcu| zcu.deinit(); - self.cache_use.deinit(); - self.work_queue.deinit(); - self.anon_work_queue.deinit(); - self.c_object_work_queue.deinit(); +pub fn destroy(comp: *Compilation) void { + if (comp.bin_file) |lf| lf.destroy(); + if (comp.module) |zcu| zcu.deinit(); + comp.cache_use.deinit(); + comp.work_queue.deinit(); + comp.anon_work_queue.deinit(); + comp.c_object_work_queue.deinit(); if (!build_options.only_core_functionality) { - self.win32_resource_work_queue.deinit(); + comp.win32_resource_work_queue.deinit(); } - self.astgen_work_queue.deinit(); - self.embed_file_work_queue.deinit(); + comp.astgen_work_queue.deinit(); + comp.embed_file_work_queue.deinit(); - const gpa = self.gpa; - self.system_libs.deinit(gpa); + const gpa = comp.gpa; + comp.system_libs.deinit(gpa); { - var it = self.crt_files.iterator(); + var it = comp.crt_files.iterator(); while (it.next()) |entry| { gpa.free(entry.key_ptr.*); entry.value_ptr.deinit(gpa); } - self.crt_files.deinit(gpa); + comp.crt_files.deinit(gpa); } - if (self.libunwind_static_lib) |*crt_file| { + if (comp.libunwind_static_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.libcxx_static_lib) |*crt_file| { + if (comp.libcxx_static_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.libcxxabi_static_lib) |*crt_file| { + if (comp.libcxxabi_static_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.compiler_rt_lib) |*crt_file| { + if (comp.compiler_rt_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.compiler_rt_obj) |*crt_file| { + if (comp.compiler_rt_obj) |*crt_file| { crt_file.deinit(gpa); } - if (self.libc_static_lib) |*crt_file| { + if (comp.libc_static_lib) |*crt_file| { crt_file.deinit(gpa); } - if (self.glibc_so_files) |*glibc_file| { + if (comp.glibc_so_files) |*glibc_file| { glibc_file.deinit(gpa); } - for (self.c_object_table.keys()) |key| { + for (comp.c_object_table.keys()) |key| { key.destroy(gpa); } - self.c_object_table.deinit(gpa); + comp.c_object_table.deinit(gpa); - for (self.failed_c_objects.values()) |bundle| { + for (comp.failed_c_objects.values()) |bundle| { bundle.destroy(gpa); } - self.failed_c_objects.deinit(gpa); + comp.failed_c_objects.deinit(gpa); if (!build_options.only_core_functionality) { - for (self.win32_resource_table.keys()) |key| { + for (comp.win32_resource_table.keys()) |key| { key.destroy(gpa); } - self.win32_resource_table.deinit(gpa); + comp.win32_resource_table.deinit(gpa); - for (self.failed_win32_resources.values()) |*value| { + for (comp.failed_win32_resources.values()) |*value| { value.deinit(gpa); } - self.failed_win32_resources.deinit(gpa); + comp.failed_win32_resources.deinit(gpa); } - for (self.lld_errors.items) |*lld_error| { + for (comp.link_errors.items) |*item| item.deinit(gpa); + comp.link_errors.deinit(gpa); + + for (comp.lld_errors.items) |*lld_error| { lld_error.deinit(gpa); } - self.lld_errors.deinit(gpa); + comp.lld_errors.deinit(gpa); - self.clearMiscFailures(); + comp.clearMiscFailures(); - self.cache_parent.manifest_dir.close(); + comp.cache_parent.manifest_dir.close(); - // This destroys `self`. - var arena_instance = self.arena; + // This destroys `comp`. + var arena_instance = comp.arena; arena_instance.deinit(); } @@ -2214,7 +2220,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr else => |e| return e, }; - comp.link_error_flags = lf.error_flags; } if (comp.module) |module| { @@ -2745,23 +2750,23 @@ fn addBuf(bufs_list: []std.os.iovec_const, bufs_len: *usize, buf: []const u8) vo } /// This function is temporally single-threaded. -pub fn totalErrorCount(self: *Compilation) u32 { +pub fn totalErrorCount(comp: *Compilation) u32 { var total: usize = - self.misc_failures.count() + - @intFromBool(self.alloc_failure_occurred) + - self.lld_errors.items.len; + comp.misc_failures.count() + + @intFromBool(comp.alloc_failure_occurred) + + comp.lld_errors.items.len; - for (self.failed_c_objects.values()) |bundle| { + for (comp.failed_c_objects.values()) |bundle| { total += bundle.diags.len; } if (!build_options.only_core_functionality) { - for (self.failed_win32_resources.values()) |errs| { + for (comp.failed_win32_resources.values()) |errs| { total += errs.errorMessageCount(); } } - if (self.module) |module| { + if (comp.module) |module| { total += module.failed_exports.count(); total += module.failed_embed_files.count(); @@ -2804,17 +2809,15 @@ pub fn totalErrorCount(self: *Compilation) u32 { // The "no entry point found" error only counts if there are no semantic analysis errors. if (total == 0) { - total += @intFromBool(self.link_error_flags.no_entry_point_found); + total += @intFromBool(comp.link_error_flags.no_entry_point_found); } - total += @intFromBool(self.link_error_flags.missing_libc); + total += @intFromBool(comp.link_error_flags.missing_libc); - if (self.bin_file) |lf| { - total += lf.misc_errors.items.len; - } + total += comp.link_errors.items.len; // Compile log errors only count if there are no other errors. if (total == 0) { - if (self.module) |module| { + if (comp.module) |module| { total += @intFromBool(module.compile_log_decls.count() != 0); } } @@ -2823,24 +2826,24 @@ pub fn totalErrorCount(self: *Compilation) u32 { } /// This function is temporally single-threaded. -pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { - const gpa = self.gpa; +pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { + const gpa = comp.gpa; var bundle: ErrorBundle.Wip = undefined; try bundle.init(gpa); defer bundle.deinit(); - for (self.failed_c_objects.values()) |diag_bundle| { + for (comp.failed_c_objects.values()) |diag_bundle| { try diag_bundle.addToErrorBundle(&bundle); } if (!build_options.only_core_functionality) { - for (self.failed_win32_resources.values()) |error_bundle| { + for (comp.failed_win32_resources.values()) |error_bundle| { try bundle.addBundleAsRoots(error_bundle); } } - for (self.lld_errors.items) |lld_error| { + for (comp.lld_errors.items) |lld_error| { const notes_len = @as(u32, @intCast(lld_error.context_lines.len)); try bundle.addRootErrorMessage(.{ @@ -2854,19 +2857,19 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { })); } } - for (self.misc_failures.values()) |*value| { + for (comp.misc_failures.values()) |*value| { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString(value.msg), .notes_len = if (value.children) |b| b.errorMessageCount() else 0, }); if (value.children) |b| try bundle.addBundleAsNotes(b); } - if (self.alloc_failure_occurred) { + if (comp.alloc_failure_occurred) { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString("memory allocation failure"), }); } - if (self.module) |module| { + if (comp.module) |module| { for (module.failed_files.keys(), module.failed_files.values()) |file, error_msg| { if (error_msg) |msg| { try addModuleErrorMsg(module, &bundle, msg.*); @@ -2938,14 +2941,14 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { } if (bundle.root_list.items.len == 0) { - if (self.link_error_flags.no_entry_point_found) { + if (comp.link_error_flags.no_entry_point_found) { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString("no entry point found"), }); } } - if (self.link_error_flags.missing_libc) { + if (comp.link_error_flags.missing_libc) { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString("libc not available"), .notes_len = 2, @@ -2959,7 +2962,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { })); } - if (self.bin_file) |lf| for (lf.misc_errors.items) |link_err| { + for (comp.link_errors.items) |link_err| { try bundle.addRootErrorMessage(.{ .msg = try bundle.addString(link_err.msg), .notes_len = @intCast(link_err.notes.len), @@ -2970,9 +2973,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { .msg = try bundle.addString(note.msg), })); } - }; + } - if (self.module) |module| { + if (comp.module) |module| { if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { const keys = module.compile_log_decls.keys(); const values = module.compile_log_decls.values(); @@ -2998,9 +3001,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { } } - assert(self.totalErrorCount() == bundle.root_list.items.len); + assert(comp.totalErrorCount() == bundle.root_list.items.len); - const compile_log_text = if (self.module) |m| m.compile_log_text.items else ""; + const compile_log_text = if (comp.module) |m| m.compile_log_text.items else ""; return bundle.toOwnedBundle(compile_log_text); } diff --git a/src/link.zig b/src/link.zig index 065779177e64..e60571a47318 100644 --- a/src/link.zig +++ b/src/link.zig @@ -67,9 +67,6 @@ pub const File = struct { allow_shlib_undefined: bool, stack_size: u64, - error_flags: ErrorFlags = .{}, - misc_errors: std.ArrayListUnmanaged(ErrorMsg) = .{}, - /// Prevents other processes from clobbering files in the output directory /// of this linking operation. lock: ?Cache.Lock = null, @@ -465,13 +462,8 @@ pub const File = struct { } pub fn destroy(base: *File) void { - const gpa = base.comp.gpa; base.releaseLock(); if (base.file) |f| f.close(); - { - for (base.misc_errors.items) |*item| item.deinit(gpa); - base.misc_errors.deinit(gpa); - } switch (base.tag) { .c => @fieldParentPtr(C, "base", base).deinit(), diff --git a/src/link/Coff.zig b/src/link/Coff.zig index aefecb014e4a..7c95c3803ee5 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1839,10 +1839,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.entry_addr == null and comp.config.output_mode == .Exe) { log.debug("flushing. no_entry_point_found = true\n", .{}); - self.base.error_flags.no_entry_point_found = true; + comp.link_error_flags.no_entry_point_found = true; } else { log.debug("flushing. no_entry_point_found = false\n", .{}); - self.base.error_flags.no_entry_point_found = false; + comp.link_error_flags.no_entry_point_found = false; try self.writeHeader(); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index f20282a80291..a74b4b5ae66a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1170,7 +1170,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // libc dep - self.base.error_flags.missing_libc = false; + comp.link_error_flags.missing_libc = false; if (comp.config.link_libc) { if (comp.libc_installation) |lc| { const flags = target_util.libcFullLinkFlags(target); @@ -1221,7 +1221,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }); try system_libs.append(.{ .path = path }); } else { - self.base.error_flags.missing_libc = true; + comp.link_error_flags.missing_libc = true; } } @@ -1259,7 +1259,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }; } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; // Init all objects for (self.objects.items) |index| { @@ -1269,7 +1269,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node try self.file(index).?.shared_object.init(self); } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; // Dedup shared objects { @@ -1388,14 +1388,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node if (self.entry_index == null and self.base.isExe()) { log.debug("flushing. no_entry_point_found = true", .{}); - self.base.error_flags.no_entry_point_found = true; + comp.link_error_flags.no_entry_point_found = true; } else { log.debug("flushing. no_entry_point_found = false", .{}); - self.base.error_flags.no_entry_point_found = false; + comp.link_error_flags.no_entry_point_found = false; try self.writeElfHeader(); } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; } pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { @@ -1427,7 +1427,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const }; } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; // First, we flush relocatable object file generated with our backends. if (self.zigObjectPtr()) |zig_object| { @@ -1539,7 +1539,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const try self.base.file.?.setEndPos(total_size); try self.base.file.?.pwriteAll(buffer.items, 0); - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; } pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { @@ -1570,14 +1570,14 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) }; } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; // Init all objects for (self.objects.items) |index| { try self.file(index).?.object.init(self); } - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; // Now, we are ready to resolve the symbols across all input files. // We will first resolve the files in the ZigObject, next in the parsed @@ -1611,7 +1611,7 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) try self.writeShdrTable(); try self.writeElfHeader(); - if (self.base.misc_errors.items.len > 0) return error.FlushFailure; + if (comp.link_errors.items.len > 0) return error.FlushFailure; } /// --verbose-link output @@ -2888,7 +2888,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } // libc dep - self.base.error_flags.missing_libc = false; + comp.link_error_flags.missing_libc = false; if (comp.config.link_libc) { if (self.base.comp.libc_installation != null) { const needs_grouping = link_mode == .Static; @@ -2909,7 +2909,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .Dynamic => "libc.so", })); } else { - self.base.error_flags.missing_libc = true; + comp.link_error_flags.missing_libc = true; } } } @@ -3132,7 +3132,8 @@ fn writePhdrTable(self: *Elf) !void { } fn writeElfHeader(self: *Elf) !void { - if (self.base.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable + const comp = self.base.comp; + if (comp.link_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; @@ -3146,7 +3147,6 @@ fn writeElfHeader(self: *Elf) !void { }; index += 1; - const comp = self.base.comp; const target = comp.root_mod.resolved_target.result; const endian = target.cpu.arch.endian(); hdr_buf[index] = switch (endian) { @@ -6055,7 +6055,7 @@ pub fn tlsAddress(self: *Elf) u64 { } const ErrorWithNotes = struct { - /// Allocated index in misc_errors array. + /// Allocated index in comp.link_errors array. index: usize, /// Next available note slot. @@ -6069,7 +6069,7 @@ const ErrorWithNotes = struct { ) error{OutOfMemory}!void { const comp = elf_file.base.comp; const gpa = comp.gpa; - const err_msg = &elf_file.base.misc_errors.items[err.index]; + const err_msg = &comp.link_errors.items[err.index]; err_msg.msg = try std.fmt.allocPrint(gpa, format, args); } @@ -6081,7 +6081,7 @@ const ErrorWithNotes = struct { ) error{OutOfMemory}!void { const comp = elf_file.base.comp; const gpa = comp.gpa; - const err_msg = &elf_file.base.misc_errors.items[err.index]; + const err_msg = &comp.link_errors.items[err.index]; assert(err.note_slot < err_msg.notes.len); err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; err.note_slot += 1; @@ -6089,15 +6089,17 @@ const ErrorWithNotes = struct { }; pub fn addErrorWithNotes(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); return self.addErrorWithNotesAssumeCapacity(note_count); } fn addErrorWithNotesAssumeCapacity(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { - const gpa = self.base.comp.gpa; - const index = self.base.misc_errors.items.len; - const err = self.base.misc_errors.addOneAssumeCapacity(); + const comp = self.base.comp; + const gpa = comp.gpa; + const index = comp.link_errors.items.len; + const err = comp.link_errors.addOneAssumeCapacity(); err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; return .{ .index = index }; } @@ -6129,10 +6131,11 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { } fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; const max_notes = 4; - try self.base.misc_errors.ensureUnusedCapacity(gpa, undefs.count()); + try comp.link_errors.ensureUnusedCapacity(gpa, undefs.count()); var it = undefs.iterator(); while (it.next()) |entry| { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 6bf4d95ef4c0..c0a259d982eb 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -323,8 +323,8 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li if (build_options.have_llvm) { return self.base.linkAsArchive(comp, prog_node); } else { - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); - self.base.misc_errors.appendAssumeCapacity(.{ + try comp.link_errors.ensureUnusedCapacity(gpa, 1); + comp.link_errors.appendAssumeCapacity(.{ .msg = try gpa.dupe(u8, "TODO: non-LLVM archiver for MachO object files"), }); return error.FlushFailure; @@ -426,7 +426,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No try self.resolveSymbols(); if (self.getEntryPoint() == null) { - self.base.error_flags.no_entry_point_found = true; + comp.link_error_flags.no_entry_point_found = true; } if (self.unresolved.count() > 0) { try self.reportUndefined(); @@ -5254,14 +5254,15 @@ fn reportMissingLibraryError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len); errdefer gpa.free(notes); for (checked_paths, notes) |path, *note| { note.* = .{ .msg = try std.fmt.allocPrint(gpa, "tried {s}", .{path}) }; } - self.base.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5274,15 +5275,16 @@ fn reportDependencyError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); defer notes.deinit(); if (path) |p| { notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) }); } notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "a dependency of {s}", .{parent}) }); - self.base.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = try notes.toOwnedSlice(), }); @@ -5294,12 +5296,13 @@ pub fn reportParseError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) }; - self.base.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5311,21 +5314,23 @@ pub fn reportUnresolvedBoundarySymbol( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); var notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while resolving {s}", .{sym_name}) }; - self.base.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); } pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; const count = self.unresolved.count(); - try self.base.misc_errors.ensureUnusedCapacity(gpa, count); + try comp.link_errors.ensureUnusedCapacity(gpa, count); for (self.unresolved.keys()) |global_index| { const global = self.globals.items[global_index]; @@ -5346,7 +5351,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { }; err_msg.notes = try notes.toOwnedSlice(); - self.base.misc_errors.appendAssumeCapacity(err_msg); + comp.link_errors.appendAssumeCapacity(err_msg); } } @@ -5355,8 +5360,9 @@ fn reportSymbolCollision( first: SymbolWithLoc, other: SymbolWithLoc, ) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); defer notes.deinit(); @@ -5379,12 +5385,13 @@ fn reportSymbolCollision( }) }; err_msg.notes = try notes.toOwnedSlice(); - self.base.misc_errors.appendAssumeCapacity(err_msg); + comp.link_errors.appendAssumeCapacity(err_msg); } fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - try self.base.misc_errors.ensureUnusedCapacity(gpa, 1); + const comp = self.base.comp; + const gpa = comp.gpa; + try comp.link_errors.ensureUnusedCapacity(gpa, 1); const notes = try gpa.alloc(File.ErrorMsg, 1); errdefer gpa.free(notes); @@ -5402,7 +5409,7 @@ fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{Ou else unreachable; - self.base.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "unhandled symbol type: '{s}' has type {s}", .{ self.getSymbolName(sym_with_loc), sym_type, From 8babc14cdfc6563c32e1b6eece548389b7249d10 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 17:51:59 -0700 Subject: [PATCH 112/133] std.Build.Module: default CSourceFile flags to empty list --- lib/std/Build/Module.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 9daa89deb8d5..ce17d655a028 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -88,7 +88,7 @@ pub const CSourceFiles = struct { pub const CSourceFile = struct { file: LazyPath, - flags: []const []const u8, + flags: []const []const u8 = &.{}, pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile { return .{ From 027e7c1c49fbabf6e199cbd585f0b4f9ec1eb77e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 17:52:12 -0700 Subject: [PATCH 113/133] test.link.glibc_compat: fix invalid build system API usage --- test/link/glibc_compat/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index 6bafb0715231..bb8d5d056daf 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -7,11 +7,11 @@ pub fn build(b: *std.Build) void { for ([_][]const u8{ "aarch64-linux-gnu.2.27", "aarch64-linux-gnu.2.34" }) |t| { const exe = b.addExecutable(.{ .name = t, - .root_source_file = .{ .path = "main.c" }, .target = b.resolveTargetQuery(std.Target.Query.parse( .{ .arch_os_abi = t }, ) catch unreachable), }); + exe.addCSourceFile(.{ .file = .{ .path = "main.c" } }); exe.linkLibC(); // TODO: actually test the output _ = exe.getEmittedBin(); From e47141a14e568b2aaa866de4e75496fcd63f1621 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 17:52:32 -0700 Subject: [PATCH 114/133] frontend: fix incorrect WebAssembly hasDebugInfo=false --- src/target.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target.zig b/src/target.zig index 262632b373db..5ae5c420c2e3 100644 --- a/src/target.zig +++ b/src/target.zig @@ -407,7 +407,6 @@ pub fn hasDebugInfo(target: std.Target) bool { std.Target.nvptx.featureSetHas(target.cpu.features, .ptx78) or std.Target.nvptx.featureSetHas(target.cpu.features, .ptx80) or std.Target.nvptx.featureSetHas(target.cpu.features, .ptx81), - .wasm32, .wasm64 => false, .bpfel, .bpfeb => false, else => true, }; From 3a0b76b855b243867d84d8bfa5de550143bed2ae Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 17:52:59 -0700 Subject: [PATCH 115/133] link.File.Wasm: remove dead condition --- src/link/Wasm.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index cdd40891daa7..a0907d6c5149 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3486,7 +3486,7 @@ pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) lin if (use_lld) { return wasm.linkWithLLD(comp, prog_node); - } else if (use_llvm and !use_lld) { + } else if (use_llvm) { return wasm.linkWithZld(comp, prog_node); } else { return wasm.flushModule(comp, prog_node); From 659e043a34e1b5b24cb83ce5569d7ee295eb27ad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 23:47:31 -0700 Subject: [PATCH 116/133] Compilation: don't add importlib jobs when outputting C code Fixes "building import libs not included in core functionality" when bootstrapping on Windows. --- src/Compilation.zig | 14 ++++++++++---- src/mingw.zig | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index cb47a5d88a1d..7ff5801e46d3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3580,6 +3580,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v }; }, .windows_import_lib => |index| { + if (build_options.only_c) + @panic("building import libs not included in core functionality"); + const named_frame = tracy.namedFrame("windows_import_lib"); defer named_frame.end(); @@ -6391,15 +6394,18 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { // If we haven't seen this library yet and we're targeting Windows, we need // to queue up a work item to produce the DLL import library for this. const gop = try comp.system_libs.getOrPut(comp.gpa, lib_name); - if (!gop.found_existing and comp.getTarget().os.tag == .windows) { + if (!gop.found_existing) { gop.value_ptr.* = .{ .needed = true, .weak = false, .path = null, }; - try comp.work_queue.writeItem(.{ - .windows_import_lib = comp.system_libs.count() - 1, - }); + const target = comp.root_mod.resolved_target.result; + if (target.os.tag == .windows and target.ofmt != .c) { + try comp.work_queue.writeItem(.{ + .windows_import_lib = comp.system_libs.count() - 1, + }); + } } } diff --git a/src/mingw.zig b/src/mingw.zig index fb8972df21c9..d8f344778304 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -287,7 +287,7 @@ fn add_cc_args( } pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { - if (build_options.only_c) @panic("building import libs not included in core functionality"); + if (build_options.only_c) @compileError("building import libs not included in core functionality"); var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); From 92cc2f41e6027a1e3bec7b3daa01da8dc90a9370 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Dec 2023 23:55:15 -0700 Subject: [PATCH 117/133] CLI: fix compilation on Windows --- src/main.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.zig b/src/main.zig index 1470653f1e13..e026e3d7ac64 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3659,11 +3659,13 @@ fn createModule( external_system_libs.len != 0) { if (create_module.libc_installation == null) { - create_module.libc_installation = try LibCInstallation.findNative(.{ + create_module.libc_installation = LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, .target = target, - }); + }) catch |err| { + fatal("unable to find native libc installation: {s}", .{@errorName(err)}); + }; try create_module.lib_dirs.appendSlice(arena, &.{ create_module.libc_installation.?.msvc_lib_dir.?, From b8674910d45f0b87f82376abbd7a705ad77fe79a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 16:42:54 -0700 Subject: [PATCH 118/133] restore -fno-emit-bin -femit-llvm-ir functionality Now, link.File will always be null when -fno-emit-bin is specified, and in the case that LLVM artifacts are still required, the Zcu instance has an LlvmObject. --- src/Compilation.zig | 108 ++++++++++++++++--- src/Module.zig | 251 ++++++++++++++++++++++++-------------------- src/link.zig | 41 +------- 3 files changed, 231 insertions(+), 169 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 7ff5801e46d3..e086e2383032 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -39,6 +39,7 @@ const Zir = @import("Zir.zig"); const Autodoc = @import("Autodoc.zig"); const resinator = @import("resinator.zig"); const Builtin = @import("Builtin.zig"); +const LlvmObject = @import("codegen/llvm.zig").Object; pub const Config = @import("Compilation/Config.zig"); @@ -1434,6 +1435,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { .emit_h = emit_h, .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa), .error_limit = error_limit, + .llvm_object = null, }; try zcu.init(); break :blk zcu; @@ -1683,6 +1685,17 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { }, } + // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir. + if (options.emit_bin == null and (comp.verbose_llvm_ir != null or + comp.verbose_llvm_bc != null or + (use_llvm and comp.emit_asm != null) or + comp.emit_llvm_ir != null or + comp.emit_llvm_bc != null)) + { + if (build_options.only_c) unreachable; + if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp); + } + comp.arena = arena_allocator; break :comp comp; }; @@ -2016,6 +2029,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void const tracy_trace = trace(@src()); defer tracy_trace.end(); + // This arena is scoped to this one update. + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + comp.clearMiscFailures(); comp.last_update_was_cache_hit = false; @@ -2034,7 +2053,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void man = comp.cache_parent.obtain(); whole.cache_manifest = &man; - try comp.addNonIncrementalStuffToCacheManifest(&man); + try addNonIncrementalStuffToCacheManifest(comp, arena, &man); const is_hit = man.hit() catch |err| { const i = man.failed_file_index orelse return err; @@ -2065,8 +2084,8 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void tmp_dir_rand_int = std.crypto.random.int(u64); const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); - const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path}); - errdefer comp.gpa.free(path); + const path = try comp.local_cache_directory.join(gpa, &.{tmp_dir_sub_path}); + errdefer gpa.free(path); const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); errdefer handle.close(); @@ -2100,10 +2119,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void .directory = tmp_artifact_directory, .sub_path = std.fs.path.basename(sub_path), }; - // It's a bit strange to use the Compilation arena allocator here - // but in practice it won't leak much and usually whole cache mode - // will be combined with exactly one call to update(). - const arena = comp.arena.allocator(); comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts); } }, @@ -2127,7 +2142,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } if (comp.module) |module| { - module.compile_log_text.shrinkAndFree(module.gpa, 0); + module.compile_log_text.shrinkAndFree(gpa, 0); module.generation += 1; // Make sure std.zig is inside the import_table. We unconditionally need @@ -2189,7 +2204,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void comp.root_name, @as(usize, @intFromPtr(module)), }); - module.intern_pool.dumpGenericInstances(comp.gpa); + module.intern_pool.dumpGenericInstances(gpa); } if (comp.config.is_test and comp.totalErrorCount() == 0) { @@ -2222,8 +2237,23 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void }; } - if (comp.module) |module| { - try link.File.C.flushEmitH(module); + if (comp.module) |zcu| { + try link.File.C.flushEmitH(zcu); + + if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + const default_emit = switch (comp.cache_use) { + .whole => |whole| .{ + .directory = whole.tmp_artifact_directory.?, + .sub_path = "dummy", + }, + .incremental => |incremental| .{ + .directory = incremental.artifact_directory, + .sub_path = "dummy", + }, + }; + try emitLlvmObject(comp, arena, default_emit, null, llvm_object, main_progress_node); + } } } @@ -2238,7 +2268,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // Close tmp dir and link.File to avoid open handle during rename. if (whole.tmp_artifact_directory) |*tmp_directory| { tmp_directory.handle.close(); - if (tmp_directory.path) |p| comp.gpa.free(p); + if (tmp_directory.path) |p| gpa.free(p); whole.tmp_artifact_directory = null; } else unreachable; @@ -2389,13 +2419,13 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo /// anything from the link cache manifest. pub const link_hash_implementation_version = 10; -fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { +fn addNonIncrementalStuffToCacheManifest( + comp: *Compilation, + arena: Allocator, + man: *Cache.Manifest, +) !void { const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - comptime assert(link_hash_implementation_version == 10); if (comp.module) |mod| { @@ -2568,6 +2598,50 @@ fn emitOthers(comp: *Compilation) void { } } +pub fn emitLlvmObject( + comp: *Compilation, + arena: Allocator, + default_emit: Emit, + bin_emit_loc: ?EmitLoc, + llvm_object: *LlvmObject, + prog_node: *std.Progress.Node, +) !void { + if (build_options.only_c) @compileError("unreachable"); + + var sub_prog_node = prog_node.start("LLVM Emit Object", 0); + sub_prog_node.activate(); + sub_prog_node.context.refresh(); + defer sub_prog_node.end(); + + try llvm_object.emit(.{ + .pre_ir_path = comp.verbose_llvm_ir, + .pre_bc_path = comp.verbose_llvm_bc, + .bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc), + .asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm), + .post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir), + .post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc), + + .is_debug = comp.root_mod.optimize_mode == .Debug, + .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, + .time_report = comp.time_report, + .sanitize_thread = comp.config.any_sanitize_thread, + .lto = comp.config.lto, + }); +} + +fn resolveEmitLoc( + arena: Allocator, + default_emit: Emit, + opt_loc: ?EmitLoc, +) Allocator.Error!?[*:0]const u8 { + const loc = opt_loc orelse return null; + const slice = if (loc.directory) |directory| + try directory.joinZ(arena, &.{loc.basename}) + else + try default_emit.basenamePath(arena, loc.basename); + return slice.ptr; +} + fn reportMultiModuleErrors(mod: *Module) !void { // Some cases can give you a whole bunch of multi-module errors, which it's not helpful to // print all of, so we'll cap the number of these to emit. diff --git a/src/Module.zig b/src/Module.zig index 9d5f4a69d2fa..558c03d685c7 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -37,6 +37,7 @@ const clang = @import("clang.zig"); const InternPool = @import("InternPool.zig"); const Alignment = InternPool.Alignment; const BuiltinFn = std.zig.BuiltinFn; +const LlvmObject = @import("codegen/llvm.zig").Object; comptime { @setEvalBranchQuota(4000); @@ -53,6 +54,10 @@ comptime { /// General-purpose allocator. Used for both temporary and long-term storage. gpa: Allocator, comp: *Compilation, +/// Usually, the LlvmObject is managed by linker code, however, in the case +/// that -fno-emit-bin is specified, the linker code never executes, so we +/// store the LlvmObject here. +llvm_object: ?*LlvmObject, /// Pointer to externally managed resource. root_mod: *Package.Module, @@ -2476,36 +2481,41 @@ pub fn init(mod: *Module) !void { try mod.global_error_set.put(gpa, .empty, {}); } -pub fn deinit(mod: *Module) void { - const gpa = mod.gpa; +pub fn deinit(zcu: *Zcu) void { + const gpa = zcu.gpa; + + if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + llvm_object.deinit(); + } - for (mod.import_table.keys()) |key| { + for (zcu.import_table.keys()) |key| { gpa.free(key); } - var failed_decls = mod.failed_decls; - mod.failed_decls = .{}; - for (mod.import_table.values()) |value| { - value.destroy(mod); + var failed_decls = zcu.failed_decls; + zcu.failed_decls = .{}; + for (zcu.import_table.values()) |value| { + value.destroy(zcu); } - mod.import_table.deinit(gpa); + zcu.import_table.deinit(gpa); - for (mod.embed_table.keys(), mod.embed_table.values()) |path, embed_file| { + for (zcu.embed_table.keys(), zcu.embed_table.values()) |path, embed_file| { gpa.free(path); gpa.destroy(embed_file); } - mod.embed_table.deinit(gpa); + zcu.embed_table.deinit(gpa); - mod.compile_log_text.deinit(gpa); + zcu.compile_log_text.deinit(gpa); - mod.local_zir_cache.handle.close(); - mod.global_zir_cache.handle.close(); + zcu.local_zir_cache.handle.close(); + zcu.global_zir_cache.handle.close(); for (failed_decls.values()) |value| { value.destroy(gpa); } failed_decls.deinit(gpa); - if (mod.emit_h) |emit_h| { + if (zcu.emit_h) |emit_h| { for (emit_h.failed_decls.values()) |value| { value.destroy(gpa); } @@ -2514,68 +2524,68 @@ pub fn deinit(mod: *Module) void { emit_h.allocated_emit_h.deinit(gpa); } - for (mod.failed_files.values()) |value| { + for (zcu.failed_files.values()) |value| { if (value) |msg| msg.destroy(gpa); } - mod.failed_files.deinit(gpa); + zcu.failed_files.deinit(gpa); - for (mod.failed_embed_files.values()) |msg| { + for (zcu.failed_embed_files.values()) |msg| { msg.destroy(gpa); } - mod.failed_embed_files.deinit(gpa); + zcu.failed_embed_files.deinit(gpa); - for (mod.failed_exports.values()) |value| { + for (zcu.failed_exports.values()) |value| { value.destroy(gpa); } - mod.failed_exports.deinit(gpa); + zcu.failed_exports.deinit(gpa); - for (mod.cimport_errors.values()) |*errs| { + for (zcu.cimport_errors.values()) |*errs| { errs.deinit(gpa); } - mod.cimport_errors.deinit(gpa); + zcu.cimport_errors.deinit(gpa); - mod.compile_log_decls.deinit(gpa); + zcu.compile_log_decls.deinit(gpa); - for (mod.decl_exports.values()) |*export_list| { + for (zcu.decl_exports.values()) |*export_list| { export_list.deinit(gpa); } - mod.decl_exports.deinit(gpa); + zcu.decl_exports.deinit(gpa); - for (mod.value_exports.values()) |*export_list| { + for (zcu.value_exports.values()) |*export_list| { export_list.deinit(gpa); } - mod.value_exports.deinit(gpa); + zcu.value_exports.deinit(gpa); - for (mod.export_owners.values()) |*value| { + for (zcu.export_owners.values()) |*value| { freeExportList(gpa, value); } - mod.export_owners.deinit(gpa); + zcu.export_owners.deinit(gpa); - mod.global_error_set.deinit(gpa); + zcu.global_error_set.deinit(gpa); - mod.test_functions.deinit(gpa); + zcu.test_functions.deinit(gpa); - for (mod.global_assembly.values()) |s| { + for (zcu.global_assembly.values()) |s| { gpa.free(s); } - mod.global_assembly.deinit(gpa); + zcu.global_assembly.deinit(gpa); - mod.reference_table.deinit(gpa); + zcu.reference_table.deinit(gpa); { - var it = mod.intern_pool.allocated_namespaces.iterator(0); + var it = zcu.intern_pool.allocated_namespaces.iterator(0); while (it.next()) |namespace| { namespace.decls.deinit(gpa); namespace.usingnamespace_set.deinit(gpa); } } - mod.intern_pool.deinit(gpa); - mod.tmp_hack_arena.deinit(); + zcu.intern_pool.deinit(gpa); + zcu.tmp_hack_arena.deinit(); - mod.capture_scope_parents.deinit(gpa); - mod.runtime_capture_scopes.deinit(gpa); - mod.comptime_capture_scopes.deinit(gpa); + zcu.capture_scope_parents.deinit(gpa); + zcu.runtime_capture_scopes.deinit(gpa); + zcu.comptime_capture_scopes.deinit(gpa); } pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { @@ -3222,14 +3232,14 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { } } -pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void { +pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError!void { const tracy = trace(@src()); defer tracy.end(); - const ip = &mod.intern_pool; - const func = mod.funcInfo(func_index); + const ip = &zcu.intern_pool; + const func = zcu.funcInfo(func_index); const decl_index = func.owner_decl; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); switch (decl.analysis) { .unreferenced => unreachable, @@ -3253,13 +3263,13 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr .success => return, } - const gpa = mod.gpa; + const gpa = zcu.gpa; var tmp_arena = std.heap.ArenaAllocator.init(gpa); defer tmp_arena.deinit(); const sema_arena = tmp_arena.allocator(); - var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { + var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { error.AnalysisFail => { if (func.analysis(ip).state == .in_progress) { // If this decl caused the compile error, the analysis field would @@ -3273,25 +3283,22 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr }; defer air.deinit(gpa); - const comp = mod.comp; - - const no_bin_file = (comp.bin_file == null and - comp.emit_asm == null and - comp.emit_llvm_ir == null and - comp.emit_llvm_bc == null); + const comp = zcu.comp; const dump_air = builtin.mode == .Debug and comp.verbose_air; const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); - if (no_bin_file and !dump_air and !dump_llvm_ir) return; + if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) { + return; + } var liveness = try Liveness.analyze(gpa, air, ip); defer liveness.deinit(gpa); if (dump_air) { - const fqn = try decl.getFullyQualifiedName(mod); + const fqn = try decl.getFullyQualifiedName(zcu); std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}); - @import("print_air.zig").dump(mod, air, liveness); + @import("print_air.zig").dump(zcu, air, liveness); std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}); } @@ -3307,12 +3314,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr verify.verify() catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => { - try mod.failed_decls.ensureUnusedCapacity(gpa, 1); - mod.failed_decls.putAssumeCapacityNoClobber( + try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); + zcu.failed_decls.putAssumeCapacityNoClobber( decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(mod), + decl.srcLoc(zcu), "invalid liveness: {s}", .{@errorName(err)}, ), @@ -3323,28 +3330,32 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr }; } - if (no_bin_file and !dump_llvm_ir) return; - - const lf = comp.bin_file.?; - lf.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.AnalysisFail => { - decl.analysis = .codegen_failure; - return; - }, - else => { - try mod.failed_decls.ensureUnusedCapacity(gpa, 1); - mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( - gpa, - decl.srcLoc(mod), - "unable to codegen: {s}", - .{@errorName(err)}, - )); - decl.analysis = .codegen_failure_retryable; - return; - }, - }; - return; + if (comp.bin_file) |lf| { + lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.AnalysisFail => { + decl.analysis = .codegen_failure; + }, + else => { + try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); + zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( + gpa, + decl.srcLoc(zcu), + "unable to codegen: {s}", + .{@errorName(err)}, + )); + decl.analysis = .codegen_failure_retryable; + }, + }; + } else if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.AnalysisFail => { + decl.analysis = .codegen_failure; + }, + }; + } }, } } @@ -5235,44 +5246,57 @@ pub fn processExports(mod: *Module) !void { const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export); fn processExportsInner( - mod: *Module, + zcu: *Zcu, symbol_exports: *SymbolExports, exported: Exported, exports: []const *Export, ) error{OutOfMemory}!void { - const gpa = mod.gpa; + const gpa = zcu.gpa; for (exports) |new_export| { const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name); if (gop.found_existing) { new_export.status = .failed_retryable; - try mod.failed_exports.ensureUnusedCapacity(gpa, 1); - const src_loc = new_export.getSrcLoc(mod); + try zcu.failed_exports.ensureUnusedCapacity(gpa, 1); + const src_loc = new_export.getSrcLoc(zcu); const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{ - new_export.opts.name.fmt(&mod.intern_pool), + new_export.opts.name.fmt(&zcu.intern_pool), }); errdefer msg.destroy(gpa); const other_export = gop.value_ptr.*; - const other_src_loc = other_export.getSrcLoc(mod); - try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{}); - mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg); + const other_src_loc = other_export.getSrcLoc(zcu); + try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{}); + zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg); new_export.status = .failed; } else { gop.value_ptr.* = new_export; } } - const lf = mod.comp.bin_file orelse return; - lf.updateExports(mod, exported, exports) catch |err| switch (err) { + if (zcu.comp.bin_file) |lf| { + try handleUpdateExports(zcu, exports, lf.updateExports(zcu, exported, exports)); + } else if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + try handleUpdateExports(zcu, exports, llvm_object.updateExports(zcu, exported, exports)); + } +} + +fn handleUpdateExports( + zcu: *Zcu, + exports: []const *Export, + result: link.File.UpdateExportsError!void, +) Allocator.Error!void { + const gpa = zcu.gpa; + result catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => { + error.AnalysisFail => { const new_export = exports[0]; new_export.status = .failed_retryable; - try mod.failed_exports.ensureUnusedCapacity(gpa, 1); - const src_loc = new_export.getSrcLoc(mod); + try zcu.failed_exports.ensureUnusedCapacity(gpa, 1); + const src_loc = new_export.getSrcLoc(zcu); const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{ @errorName(err), }); - mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg); + zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg); }, }; } @@ -5415,41 +5439,38 @@ pub fn populateTestFunctions( try mod.linkerUpdateDecl(decl_index); } -pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void { - const comp = mod.comp; +pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { + const comp = zcu.comp; if (comp.bin_file) |lf| { - const decl = mod.declPtr(decl_index); - lf.updateDecl(mod, decl_index) catch |err| switch (err) { + lf.updateDecl(zcu, decl_index) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { + const decl = zcu.declPtr(decl_index); decl.analysis = .codegen_failure; - return; }, else => { - const gpa = mod.gpa; - try mod.failed_decls.ensureUnusedCapacity(gpa, 1); - mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( + const decl = zcu.declPtr(decl_index); + const gpa = zcu.gpa; + try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); + zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( gpa, - decl.srcLoc(mod), + decl.srcLoc(zcu), "unable to codegen: {s}", .{@errorName(err)}, )); decl.analysis = .codegen_failure_retryable; - return; }, }; - } else { - const dump_llvm_ir = builtin.mode == .Debug and - (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); - - if (comp.emit_asm != null or - comp.emit_llvm_ir != null or - comp.emit_llvm_bc != null or - dump_llvm_ir) - { - @panic("TODO handle emit_asm, emit_llvm_ir, and emit_llvm_bc along with -fno-emit-bin"); - } + } else if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.AnalysisFail => { + const decl = zcu.declPtr(decl_index); + decl.analysis = .codegen_failure; + }, + }; } } diff --git a/src/link.zig b/src/link.zig index e60571a47318..89f412588838 100644 --- a/src/link.zig +++ b/src/link.zig @@ -984,49 +984,16 @@ pub const File = struct { return output_mode == .Lib and !self.isStatic(); } - pub fn resolveEmitLoc( - base: File, - arena: Allocator, - opt_loc: ?Compilation.EmitLoc, - ) Allocator.Error!?[*:0]const u8 { - const loc = opt_loc orelse return null; - const slice = if (loc.directory) |directory| - try directory.joinZ(arena, &.{loc.basename}) - else - try base.emit.basenamePath(arena, loc.basename); - return slice.ptr; - } - pub fn emitLlvmObject( base: File, arena: Allocator, llvm_object: *LlvmObject, prog_node: *std.Progress.Node, ) !void { - const comp = base.comp; - - var sub_prog_node = prog_node.start("LLVM Emit Object", 0); - sub_prog_node.activate(); - sub_prog_node.context.refresh(); - defer sub_prog_node.end(); - - try llvm_object.emit(.{ - .pre_ir_path = comp.verbose_llvm_ir, - .pre_bc_path = comp.verbose_llvm_bc, - .bin_path = try base.resolveEmitLoc(arena, .{ - .directory = null, - .basename = base.zcu_object_sub_path.?, - }), - .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm), - .post_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), - .post_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), - - .is_debug = comp.root_mod.optimize_mode == .Debug, - .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, - .time_report = comp.time_report, - .sanitize_thread = comp.config.any_sanitize_thread, - .lto = comp.config.lto, - }); + return base.comp.emitLlvmObject(arena, base.emit, .{ + .directory = null, + .basename = base.zcu_object_sub_path.?, + }, llvm_object, prog_node); } pub const C = @import("link/C.zig"); From 8fa44969095caa293cb76b9a0b5fc0c0c270dc3b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 17:20:16 -0700 Subject: [PATCH 119/133] std.Build.Step.Compile: fix search prefix lowering Instead of adding -I and -L flags at the end of the CLI, they need to be added for every module, after the module-specific flags. --- lib/std/Build/Step/Compile.zig | 110 ++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 571fefa30808..92b6d0de4a23 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -894,9 +894,48 @@ fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_st fn make(step: *Step, prog_node: *std.Progress.Node) !void { const b = step.owner; + const arena = b.allocator; const self = @fieldParentPtr(Compile, "step", step); - var zig_args = ArrayList([]const u8).init(b.allocator); + // Convert search prefixes to -I and -L arguments to be added at the end of + // each module's configuration. + var search_prefix_args: std.ArrayListUnmanaged([]const u8) = .{}; + for (b.search_prefixes.items) |search_prefix| { + var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { + return step.fail("unable to open prefix directory '{s}': {s}", .{ + search_prefix, @errorName(err), + }); + }; + defer prefix_dir.close(); + + // Avoid passing -L and -I flags for nonexistent directories. + // This prevents a warning, that should probably be upgraded to an error in Zig's + // CLI parsing code, when the linker sees an -L directory that does not exist. + + if (prefix_dir.accessZ("lib", .{})) |_| { + try search_prefix_args.appendSlice(arena, &.{ + "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + + if (prefix_dir.accessZ("include", .{})) |_| { + try search_prefix_args.appendSlice(arena, &.{ + "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + } + + var zig_args = ArrayList([]const u8).init(arena); defer zig_args.deinit(); try zig_args.append(b.zig_exe); @@ -910,14 +949,14 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(cmd); if (b.reference_trace) |some| { - try zig_args.append(try std.fmt.allocPrint(b.allocator, "-freference-trace={d}", .{some})); + try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); } try addFlag(&zig_args, "llvm", self.use_llvm); try addFlag(&zig_args, "lld", self.use_lld); if (self.root_module.resolved_target.?.query.ofmt) |ofmt| { - try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); + try zig_args.append(try std.fmt.allocPrint(arena, "-ofmt={s}", .{@tagName(ofmt)})); } switch (self.entry) { @@ -925,7 +964,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { .disabled => try zig_args.append("-fno-entry"), .enabled => try zig_args.append("-fentry"), .symbol_name => |entry_name| { - try zig_args.append(try std.fmt.allocPrint(b.allocator, "-fentry={s}", .{entry_name})); + try zig_args.append(try std.fmt.allocPrint(arena, "-fentry={s}", .{entry_name})); }, } @@ -939,7 +978,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.stack_size) |stack_size| { try zig_args.append("--stack"); - try zig_args.append(try std.fmt.allocPrint(b.allocator, "{}", .{stack_size})); + try zig_args.append(try std.fmt.allocPrint(arena, "{}", .{stack_size})); } { @@ -964,7 +1003,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } - var cli_named_modules = try CliNamedModules.init(b.allocator, &self.root_module); + var cli_named_modules = try CliNamedModules.init(arena, &self.root_module); // For this loop, don't chase dynamic libraries because their link // objects are already linked. @@ -983,7 +1022,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { // Inherit dependencies on darwin frameworks. if (!already_linked) { for (module.frameworks.keys(), module.frameworks.values()) |name, info| { - try frameworks.put(b.allocator, name, info); + try frameworks.put(arena, name, info); } } @@ -997,7 +1036,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } }, .system_lib => |system_lib| { - if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null) + if ((try seen_system_libs.fetchPut(arena, system_lib.name, {})) != null) continue; if (already_linked) @@ -1196,6 +1235,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (cli_named_modules.modules.getIndex(module)) |module_cli_index| { const module_cli_name = cli_named_modules.names.keys()[module_cli_index]; try module.appendZigProcessFlags(&zig_args, step); + // These go after `appendZigProcessFlags` so that + // --search-prefix directories are prioritized lower than + // per-module settings. + try zig_args.appendSlice(search_prefix_args.items); // --dep arguments try zig_args.ensureUnusedCapacity(module.import_table.count() * 2); @@ -1385,11 +1428,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.appendSlice(&[_][]const u8{ "--entitlements", entitlements }); } if (self.pagezero_size) |pagezero_size| { - const size = try std.fmt.allocPrint(b.allocator, "{x}", .{pagezero_size}); + const size = try std.fmt.allocPrint(arena, "{x}", .{pagezero_size}); try zig_args.appendSlice(&[_][]const u8{ "-pagezero_size", size }); } if (self.headerpad_size) |headerpad_size| { - const size = try std.fmt.allocPrint(b.allocator, "{x}", .{headerpad_size}); + const size = try std.fmt.allocPrint(arena, "{x}", .{headerpad_size}); try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size }); } if (self.headerpad_max_install_names) { @@ -1462,41 +1505,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); } - for (b.search_prefixes.items) |search_prefix| { - var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { - return step.fail("unable to open prefix directory '{s}': {s}", .{ - search_prefix, @errorName(err), - }); - }; - defer prefix_dir.close(); - - // Avoid passing -L and -I flags for nonexistent directories. - // This prevents a warning, that should probably be upgraded to an error in Zig's - // CLI parsing code, when the linker sees an -L directory that does not exist. - - if (prefix_dir.accessZ("lib", .{})) |_| { - try zig_args.appendSlice(&.{ - "-L", try fs.path.join(b.allocator, &.{ search_prefix, "lib" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - - if (prefix_dir.accessZ("include", .{})) |_| { - try zig_args.appendSlice(&.{ - "-I", try fs.path.join(b.allocator, &.{ search_prefix, "include" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - } - if (self.rc_includes != .any) { try zig_args.append("-rcincludes"); try zig_args.append(@tagName(self.rc_includes)); @@ -1554,12 +1562,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try b.cache_root.handle.makePath("args"); const args_to_escape = zig_args.items[2..]; - var escaped_args = try ArrayList([]const u8).initCapacity(b.allocator, args_to_escape.len); + var escaped_args = try ArrayList([]const u8).initCapacity(arena, args_to_escape.len); arg_blk: for (args_to_escape) |arg| { for (arg, 0..) |c, arg_idx| { if (c == '\\' or c == '"') { // Slow path for arguments that need to be escaped. We'll need to allocate and copy - var escaped = try ArrayList(u8).initCapacity(b.allocator, arg.len + 1); + var escaped = try ArrayList(u8).initCapacity(arena, arg.len + 1); const writer = escaped.writer(); try writer.writeAll(arg[0..arg_idx]); for (arg[arg_idx..]) |to_escape| { @@ -1575,8 +1583,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { // Write the args to zig-cache/args/ to avoid conflicts with // other zig build commands running in parallel. - const partially_quoted = try std.mem.join(b.allocator, "\" \"", escaped_args.items); - const args = try std.mem.concat(b.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); + const partially_quoted = try std.mem.join(arena, "\" \"", escaped_args.items); + const args = try std.mem.concat(arena, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); var args_hash: [Sha256.digest_length]u8 = undefined; Sha256.hash(args, &args_hash, .{}); @@ -1590,9 +1598,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { const args_file = "args" ++ fs.path.sep_str ++ args_hex_hash; try b.cache_root.handle.writeFile(args_file, args); - const resolved_args_file = try mem.concat(b.allocator, u8, &.{ + const resolved_args_file = try mem.concat(arena, u8, &.{ "@", - try b.cache_root.join(b.allocator, &.{args_file}), + try b.cache_root.join(arena, &.{args_file}), }); zig_args.shrinkRetainingCapacity(2); From 196ddf010c97f2faf69513e61099a233d4270795 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 17:42:23 -0700 Subject: [PATCH 120/133] frontend: fix populateTestFunctions accessing the wrong module The test runner reads the list of test function pointers from its own builtin module, which is the root_mod, not main_mod. --- src/Module.zig | 2 +- src/Package/Module.zig | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Module.zig b/src/Module.zig index 558c03d685c7..9d3810f671e5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5307,7 +5307,7 @@ pub fn populateTestFunctions( ) !void { const gpa = mod.gpa; const ip = &mod.intern_pool; - const builtin_mod = mod.main_mod.getBuiltinDependency(); + const builtin_mod = mod.root_mod.getBuiltinDependency(); const builtin_file = (mod.importPkg(builtin_mod) catch unreachable).file; const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); const builtin_namespace = mod.namespacePtr(root_decl.src_namespace); diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 3c3a1c81e6da..66d5a21eab7d 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -466,6 +466,9 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P return mod; } +/// Asserts that the module has a builtin module, which is not true for non-zig +/// modules such as ones only used for `@embedFile`, or the root module when +/// there is no Zig Compilation Unit. pub fn getBuiltinDependency(m: Module) *Module { const result = m.deps.values()[0]; assert(result.isBuiltin()); From 751ff043d777c31655757df3ca93b2acaa8204a4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 18:05:30 -0700 Subject: [PATCH 121/133] fix stack_iterator test build script When I updated this build script to the new API, I incorrectly translated the logic for setting unwind_tables. This commit fixes it. --- test/standalone/stack_iterator/build.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/standalone/stack_iterator/build.zig b/test/standalone/stack_iterator/build.zig index d40a377d3958..463a533ac400 100644 --- a/test/standalone/stack_iterator/build.zig +++ b/test/standalone/stack_iterator/build.zig @@ -22,7 +22,7 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "unwind.zig" }, .target = target, .optimize = optimize, - .unwind_tables = target.result.isDarwin(), + .unwind_tables = if (target.result.isDarwin()) true else null, .omit_frame_pointer = false, }); @@ -84,7 +84,7 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "shared_lib_unwind.zig" }, .target = target, .optimize = optimize, - .unwind_tables = target.result.isDarwin(), + .unwind_tables = if (target.result.isDarwin()) true else null, .omit_frame_pointer = true, }); From 668c0cdeda93491050b1f260865a963d008fd553 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 21:20:51 -0700 Subject: [PATCH 122/133] compiler: Compilation.Config: trivial refactor --- src/Compilation/Config.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 5f8776fd1f81..78273f66e42e 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -105,7 +105,7 @@ pub const Options = struct { export_memory: ?bool = null, shared_memory: ?bool = null, test_evented_io: bool = false, - debug_format: ?Config.DebugFormat = null, + debug_format: ?DebugFormat = null, dll_export_fns: ?bool = null, rdynamic: ?bool = null, }; From 96b4eeab55e21b294af3c915dda2881258601532 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 21:21:42 -0700 Subject: [PATCH 123/133] std: disable failing test on macos See tracking issue https://github.com/ziglang/zig/issues/18395 --- lib/std/os/test.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 40e0991e5fc8..490e12350624 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -752,6 +752,11 @@ test "fsync" { } test "getrlimit and setrlimit" { + if (builtin.target.os.tag == .macos) { + // https://github.com/ziglang/zig/issues/18395 + return error.SkipZigTest; + } + if (!@hasDecl(os.system, "rlimit")) { return error.SkipZigTest; } From c2cc1b37928034cdcd49d07819fbb4f87683cf87 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 21:34:11 -0700 Subject: [PATCH 124/133] frontend: add logging to help troubleshoot builtin.zig write failures --- src/Builtin.zig | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Builtin.zig b/src/Builtin.zig index dc9ccc22c4df..21681c7ac638 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -280,10 +280,25 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { fn writeFile(file: *File, mod: *Module) !void { var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; - var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); + var af = mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf) catch |err| { + std.log.warn("unable to create builtin atomic file '{}{s}'", .{ + mod.root, mod.root_src_path, + }); + return err; + }; defer af.deinit(); - try af.file.writeAll(file.source); - try af.finish(); + af.file.writeAll(file.source) catch |err| { + std.log.warn("unable to write builtin file data to '{}{s}'", .{ + mod.root, mod.root_src_path, + }); + return err; + }; + af.finish() catch |err| { + std.log.warn("unable to rename atomic builtin file into '{}{s}'", .{ + mod.root, mod.root_src_path, + }); + return err; + }; file.stat = .{ .size = file.source.len, From e22102dfc6356a16e83341d0cd0526762c696ad6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Dec 2023 23:16:31 -0700 Subject: [PATCH 125/133] Compilation: make create() take an arena allocator Instead of making its own inside create. 10 out of 10 calls to create() had already an arena in scope, so this commit means that 10 instances of Compilation now reuse an existing arena with the same lifetime rather than creating a redundant one. In other words, this very slightly optimizes initialization of the frontend in terms of memory allocation. --- src/Compilation.zig | 28 ++++++++-------------------- src/Sema.zig | 2 +- src/glibc.zig | 2 +- src/libcxx.zig | 4 ++-- src/libtsan.zig | 2 +- src/libunwind.zig | 2 +- src/main.zig | 4 ++-- src/musl.zig | 2 +- 8 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index e086e2383032..66c136d076bd 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -45,9 +45,9 @@ pub const Config = @import("Compilation/Config.zig"); /// General-purpose allocator. Used for both temporary and long-term storage. gpa: Allocator, -/// Arena-allocated memory, mostly used during initialization. However, it can be used -/// for other things requiring the same lifetime as the `Compilation`. -arena: std.heap.ArenaAllocator, +/// Arena-allocated memory, mostly used during initialization. However, it can +/// be used for other things requiring the same lifetime as the `Compilation`. +arena: Allocator, /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. /// TODO: rename to zcu: ?*Zcu module: ?*Module, @@ -1178,7 +1178,7 @@ fn addModuleTableToCacheHash( } } -pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { +pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compilation { const output_mode = options.config.output_mode; const is_dyn_lib = switch (output_mode) { .Obj, .Exe => false, @@ -1197,13 +1197,6 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { const have_zcu = options.config.have_zcu; const comp: *Compilation = comp: { - // For allocations that have the same lifetime as Compilation. This - // arena is used only during this initialization and then is freed in - // deinit(). - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - errdefer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - // We put the `Compilation` itself in the arena. Freeing the arena will free the module. // It's initialized later after we prepare the initialization options. const root_name = try arena.dupeZ(u8, options.root_name); @@ -1454,7 +1447,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { comp.* = .{ .gpa = gpa, - .arena = undefined, // populated after we are finished with `arena` + .arena = arena, .module = opt_zcu, .cache_use = undefined, // populated below .bin_file = null, // populated below @@ -1696,7 +1689,6 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation { if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp); } - comp.arena = arena_allocator; break :comp comp; }; errdefer comp.destroy(); @@ -1971,10 +1963,6 @@ pub fn destroy(comp: *Compilation) void { comp.clearMiscFailures(); comp.cache_parent.manifest_dir.close(); - - // This destroys `comp`. - var arena_instance = comp.arena; - arena_instance.deinit(); } pub fn clearMiscFailures(comp: *Compilation) void { @@ -4082,7 +4070,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module }; } - const out_zig_path = try comp.local_cache_directory.join(comp.arena.allocator(), &.{ + const out_zig_path = try comp.local_cache_directory.join(comp.arena, &.{ "o", &digest, cimport_zig_basename, }); if (comp.verbose_cimport) { @@ -6302,7 +6290,7 @@ fn buildOutputFromZig( .output_mode = output_mode, }); - const sub_compilation = try Compilation.create(gpa, .{ + const sub_compilation = try Compilation.create(gpa, arena, .{ .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, @@ -6411,7 +6399,7 @@ pub fn build_crt_file( item.owner = root_mod; } - const sub_compilation = try Compilation.create(gpa, .{ + const sub_compilation = try Compilation.create(gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, diff --git a/src/Sema.zig b/src/Sema.zig index 3a54b20ea4c2..a01dd174a85d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5761,7 +5761,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr return sema.failWithOwnedErrorMsg(&child_block, msg); } const parent_mod = parent_block.ownerModule(); - const c_import_mod = Package.Module.create(comp.arena.allocator(), .{ + const c_import_mod = Package.Module.create(comp.arena, .{ .global_cache_directory = comp.global_cache_directory, .paths = .{ .root = .{ diff --git a/src/glibc.zig b/src/glibc.zig index 838f55c87926..00d76f32fb0d 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -1116,7 +1116,7 @@ fn buildSharedLib( }, }; - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .local_cache_directory = zig_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, diff --git a/src/libcxx.zig b/src/libcxx.zig index abcbc0187ec2..8e28c2174d4a 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -272,7 +272,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, @@ -459,7 +459,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, diff --git a/src/libtsan.zig b/src/libtsan.zig index a736c3271315..14a7db088873 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -245,7 +245,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { }); } - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, diff --git a/src/libunwind.zig b/src/libunwind.zig index 0f23f8b352a7..5f0613c3619a 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -123,7 +123,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void { .owner = root_mod, }; } - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .self_exe_path = comp.self_exe_path, .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, diff --git a/src/main.zig b/src/main.zig index e026e3d7ac64..091e4b26682b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3130,7 +3130,7 @@ fn buildOutputType( gimmeMoreOfThoseSweetSweetFileDescriptors(); - const comp = Compilation.create(gpa, .{ + const comp = Compilation.create(gpa, arena, .{ .zig_lib_directory = zig_lib_directory, .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, @@ -5508,7 +5508,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi try root_mod.deps.put(arena, "@build", build_mod); - const comp = Compilation.create(gpa, .{ + const comp = Compilation.create(gpa, arena, .{ .zig_lib_directory = zig_lib_directory, .local_cache_directory = local_cache_directory, .global_cache_directory = global_cache_directory, diff --git a/src/musl.zig b/src/musl.zig index 4a62d5ededd7..c244257a7017 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -251,7 +251,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr .builtin_mod = null, }); - const sub_compilation = try Compilation.create(comp.gpa, .{ + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, From a89d6878d2780f966b7327f8d366e6ac5f5cd8fc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 29 Dec 2023 16:31:36 -0700 Subject: [PATCH 126/133] Compilation: fix cache hash of incremental builds Without this commit, unrelated test builds using incremental cache mode (self-hosted, no lld) would end up using the same cache namespace, which is undesireable since concurrent builds will clobber each other's work. This happened because of passing the root module to addModuleToCacheHash. In the case of a test build, the root module actually does not connect to the rest of the import table. Instead, the main module needs to be passed, which has "root" in its import table. The other call to addModuleTableToCacheHash which is in addNonIncrementalStuffToCacheManifest already correctly passes the main module. In the future, I think this problem can be fully addressed by obtaining an advisory lock on the output binary file. However, even in that case, it is still valuable to make different compilations use different cache namespaces lest unrelated compilations suffer from pointless thrashing rather than being independently edited. --- src/Compilation.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 66c136d076bd..250a94fe94af 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1374,6 +1374,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil cache.hash.add(options.config.wasi_exec_model); // TODO audit this and make sure everything is in it + const main_mod = options.main_mod orelse options.root_mod; const comp = try arena.create(Compilation); const opt_zcu: ?*Module = if (have_zcu) blk: { // Pre-open the directory handles for cached ZIR code so that it does not need @@ -1420,7 +1421,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil zcu.* = .{ .gpa = gpa, .comp = comp, - .main_mod = options.main_mod orelse options.root_mod, + .main_mod = main_mod, .root_mod = options.root_mod, .std_mod = std_mod, .global_zir_cache = global_zir_cache, @@ -1608,7 +1609,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil // do want to namespace different source file names because they are // likely different compilations and therefore this would be likely to // cause cache hits. - try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, .path_bytes); + try addModuleTableToCacheHash(gpa, arena, &hash, main_mod, .path_bytes); // In the case of incremental cache mode, this `artifact_directory` // is computed based on a hash of non-linker inputs, and it is where all From 6b2709616e22e7651f16293034cc0d25f0e9be0a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 29 Dec 2023 16:51:20 -0700 Subject: [PATCH 127/133] frontend: ignore AccessDenied when writing builtin.zig This issue already existed in master branch, however, the more aggressive caching of builtin.zig in this branch made it happen more often. I added doc comments to AtomicFile to explain when this problem can occur. For the compiler's use case, error.AccessDenied can be simply swallowed because it means the destination file already exists and there is nothing else to do besides proceed with the AtomicFile cleanup. I never solved the mystery of why the log statements weren't printing but those are temporary debugging instruments anyway, and I am already too many yaks deep to whip out another razor. closes #14978 --- lib/std/fs/AtomicFile.zig | 4 ++++ src/Builtin.zig | 30 +++++++++++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/std/fs/AtomicFile.zig b/lib/std/fs/AtomicFile.zig index b090bc95828e..c95ae9bcf2bb 100644 --- a/lib/std/fs/AtomicFile.zig +++ b/lib/std/fs/AtomicFile.zig @@ -65,6 +65,10 @@ pub fn deinit(self: *AtomicFile) void { pub const FinishError = posix.RenameError; +/// On Windows, this function introduces a period of time where some file +/// system operations on the destination file will result in +/// `error.AccessDenied`, including rename operations (such as the one used in +/// this function). pub fn finish(self: *AtomicFile) FinishError!void { assert(self.file_exists); if (self.file_open) { diff --git a/src/Builtin.zig b/src/Builtin.zig index 21681c7ac638..3211dd3a690b 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -280,24 +280,19 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { fn writeFile(file: *File, mod: *Module) !void { var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; - var af = mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf) catch |err| { - std.log.warn("unable to create builtin atomic file '{}{s}'", .{ - mod.root, mod.root_src_path, - }); - return err; - }; + var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); defer af.deinit(); - af.file.writeAll(file.source) catch |err| { - std.log.warn("unable to write builtin file data to '{}{s}'", .{ - mod.root, mod.root_src_path, - }); - return err; - }; - af.finish() catch |err| { - std.log.warn("unable to rename atomic builtin file into '{}{s}'", .{ - mod.root, mod.root_src_path, - }); - return err; + try af.file.writeAll(file.source); + af.finish() catch |err| switch (err) { + error.AccessDenied => switch (builtin.os.tag) { + .windows => { + // Very likely happened due to another process or thread + // simultaneously creating the same, correct builtin.zig file. + // This is not a problem; ignore it. + }, + else => return err, + }, + else => return err, }; file.stat = .{ @@ -307,6 +302,7 @@ fn writeFile(file: *File, mod: *Module) !void { }; } +const builtin = @import("builtin"); const std = @import("std"); const Allocator = std.mem.Allocator; const build_options = @import("build_options"); From 7fb9f58f85f1dc9c18c49bc1114d9d978fdbed33 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 14:40:23 -0700 Subject: [PATCH 128/133] Compilation: rename before flush during whole cache mode The linker needs to know the file system path of output in the flush function because file paths inside the build artifacts reference each other. Fixes a regression introduced in this branch. --- src/Compilation.zig | 122 ++++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 250a94fe94af..11b3328e0e10 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2216,39 +2216,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void // -femit-llvm-bc, and -femit-asm, in the case of C objects. comp.emitOthers(); - { - if (comp.bin_file) |lf| { - // This is needed before reading the error flags. - lf.flush(comp, main_progress_node) catch |err| switch (err) { - error.FlushFailure => {}, // error reported through link_error_flags - error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr - else => |e| return e, - }; - } - - if (comp.module) |zcu| { - try link.File.C.flushEmitH(zcu); - - if (zcu.llvm_object) |llvm_object| { - if (build_options.only_c) unreachable; - const default_emit = switch (comp.cache_use) { - .whole => |whole| .{ - .directory = whole.tmp_artifact_directory.?, - .sub_path = "dummy", - }, - .incremental => |incremental| .{ - .directory = incremental.artifact_directory, - .sub_path = "dummy", - }, - }; - try emitLlvmObject(comp, arena, default_emit, null, llvm_object, main_progress_node); - } - } - } - - if (comp.totalErrorCount() != 0) return; - try maybeGenerateAutodocs(comp, main_progress_node); - switch (comp.cache_use) { .whole => |whole| { const digest = man.final(); @@ -2261,15 +2228,32 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void whole.tmp_artifact_directory = null; } else unreachable; - if (comp.bin_file) |lf| { - lf.destroy(); - comp.bin_file = null; - } - const s = std.fs.path.sep_str; const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); const o_sub_path = "o" ++ s ++ digest; + // Work around windows `AccessDenied` if any files within this + // directory are open by closing and reopening the file handles. + const need_writable_dance = w: { + if (builtin.os.tag == .windows) { + if (comp.bin_file) |lf| { + // We cannot just call `makeExecutable` as it makes a false + // assumption that we have a file handle open only when linking + // an executable file. This used to be true when our linkers + // were incapable of emitting relocatables and static archive. + // Now that they are capable, we need to unconditionally close + // the file handle and re-open it in the follow up call to + // `makeWritable`. + if (lf.file) |f| { + f.close(); + lf.file = null; + break :w true; + } + } + } + break :w false; + }; + renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path) catch |err| { return comp.setMiscFailure( .rename_results, @@ -2283,15 +2267,75 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void }; comp.wholeCacheModeSetBinFilePath(whole, &digest); + // The linker flush functions need to know the final output path + // for debug info purposes because executable debug info contains + // references object file paths. + if (comp.bin_file) |lf| { + lf.emit = .{ + .directory = comp.local_cache_directory, + .sub_path = whole.bin_sub_path.?, + }; + + // Has to be after the `wholeCacheModeSetBinFilePath` above. + if (need_writable_dance) { + try lf.makeWritable(); + } + } + + try flush(comp, arena, main_progress_node); + if (comp.totalErrorCount() != 0) return; + // Failure here only means an unnecessary cache miss. man.writeManifest() catch |err| { log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); }; + if (comp.bin_file) |lf| { + lf.destroy(); + comp.bin_file = null; + } + assert(whole.lock == null); whole.lock = man.toOwnedLock(); }, - .incremental => {}, + .incremental => { + try flush(comp, arena, main_progress_node); + if (comp.totalErrorCount() != 0) return; + }, + } +} + +fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void { + if (comp.bin_file) |lf| { + // This is needed before reading the error flags. + lf.flush(comp, prog_node) catch |err| switch (err) { + error.FlushFailure => {}, // error reported through link_error_flags + error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr + else => |e| return e, + }; + } + + if (comp.module) |zcu| { + try link.File.C.flushEmitH(zcu); + + if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + const default_emit = switch (comp.cache_use) { + .whole => |whole| .{ + .directory = whole.tmp_artifact_directory.?, + .sub_path = "dummy", + }, + .incremental => |incremental| .{ + .directory = incremental.artifact_directory, + .sub_path = "dummy", + }, + }; + try emitLlvmObject(comp, arena, default_emit, null, llvm_object, prog_node); + } + } + + if (comp.totalErrorCount() == 0) { + try maybeGenerateAutodocs(comp, prog_node); } } From 7cec11a66bfd9d38bd355ba55aca4fa0e61ba4b5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 16:45:52 -0700 Subject: [PATCH 129/133] CI: update windows scripts to new CLI module syntax --- ci/x86_64-windows-debug.ps1 | 8 ++++---- ci/x86_64-windows-release.ps1 | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ci/x86_64-windows-debug.ps1 b/ci/x86_64-windows-debug.ps1 index c1ae92494e98..bb6ff3ebee74 100644 --- a/ci/x86_64-windows-debug.ps1 +++ b/ci/x86_64-windows-debug.ps1 @@ -76,15 +76,15 @@ Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..." CheckLastExitCode & "stage3-debug\bin\zig.exe" build-obj ` - ..\lib\compiler_rt.zig ` --zig-lib-dir "$ZIG_LIB_DIR" ` -ofmt=c ` -OReleaseSmall ` --name compiler_rt ` -femit-bin="compiler_rt-x86_64-windows-msvc.c" ` - --mod build_options::config.zig ` - --deps build_options ` - -target x86_64-windows-msvc + --dep build_options ` + -target x86_64-windows-msvc ` + --mod root ..\lib\compiler_rt.zig ` + --mod build_options config.zig CheckLastExitCode Import-Module "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" diff --git a/ci/x86_64-windows-release.ps1 b/ci/x86_64-windows-release.ps1 index 988402606b5c..7467e3deaa08 100644 --- a/ci/x86_64-windows-release.ps1 +++ b/ci/x86_64-windows-release.ps1 @@ -75,15 +75,15 @@ Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..." CheckLastExitCode & "stage3-release\bin\zig.exe" build-obj ` - ..\lib\compiler_rt.zig ` --zig-lib-dir "$ZIG_LIB_DIR" ` -ofmt=c ` -OReleaseSmall ` --name compiler_rt ` -femit-bin="compiler_rt-x86_64-windows-msvc.c" ` - --mod build_options::config.zig ` - --deps build_options ` - -target x86_64-windows-msvc + --dep build_options ` + -target x86_64-windows-msvc ` + --mod root ..\lib\compiler_rt.zig ` + --mod build_options config.zig CheckLastExitCode Import-Module "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" From eae6d45cded76dd027569c86a7cdd5bc9039664b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 18:47:42 -0700 Subject: [PATCH 130/133] CLI: introduce global -I args for C include paths This isn't technically needed since per-module -I args can suffice, but this can produce very long CLI invocations when several --mod args are combined with --search-prefix args since the -I args have to be repeated for each module. This is a partial revert of ecbe8bbf2df2ed4d473efbc32e0b6d7091fba76f. --- lib/std/Build/Step/Compile.zig | 78 ++++++++++++++++------------------ src/Compilation.zig | 7 +++ src/main.zig | 10 +++-- 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 92b6d0de4a23..d6a016f183b7 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -897,44 +897,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { const arena = b.allocator; const self = @fieldParentPtr(Compile, "step", step); - // Convert search prefixes to -I and -L arguments to be added at the end of - // each module's configuration. - var search_prefix_args: std.ArrayListUnmanaged([]const u8) = .{}; - for (b.search_prefixes.items) |search_prefix| { - var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { - return step.fail("unable to open prefix directory '{s}': {s}", .{ - search_prefix, @errorName(err), - }); - }; - defer prefix_dir.close(); - - // Avoid passing -L and -I flags for nonexistent directories. - // This prevents a warning, that should probably be upgraded to an error in Zig's - // CLI parsing code, when the linker sees an -L directory that does not exist. - - if (prefix_dir.accessZ("lib", .{})) |_| { - try search_prefix_args.appendSlice(arena, &.{ - "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - - if (prefix_dir.accessZ("include", .{})) |_| { - try search_prefix_args.appendSlice(arena, &.{ - "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), - }); - } else |err| switch (err) { - error.FileNotFound => {}, - else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ - search_prefix, @errorName(e), - }), - } - } - var zig_args = ArrayList([]const u8).init(arena); defer zig_args.deinit(); @@ -1235,10 +1197,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (cli_named_modules.modules.getIndex(module)) |module_cli_index| { const module_cli_name = cli_named_modules.names.keys()[module_cli_index]; try module.appendZigProcessFlags(&zig_args, step); - // These go after `appendZigProcessFlags` so that - // --search-prefix directories are prioritized lower than - // per-module settings. - try zig_args.appendSlice(search_prefix_args.items); // --dep arguments try zig_args.ensureUnusedCapacity(module.import_table.count() * 2); @@ -1505,6 +1463,42 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot }); } + // -I and -L arguments that appear after the last --mod argument apply to all modules. + for (b.search_prefixes.items) |search_prefix| { + var prefix_dir = fs.cwd().openDir(search_prefix, .{}) catch |err| { + return step.fail("unable to open prefix directory '{s}': {s}", .{ + search_prefix, @errorName(err), + }); + }; + defer prefix_dir.close(); + + // Avoid passing -L and -I flags for nonexistent directories. + // This prevents a warning, that should probably be upgraded to an error in Zig's + // CLI parsing code, when the linker sees an -L directory that does not exist. + + if (prefix_dir.accessZ("lib", .{})) |_| { + try zig_args.appendSlice(&.{ + "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + + if (prefix_dir.accessZ("include", .{})) |_| { + try zig_args.appendSlice(&.{ + "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), + }); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{ + search_prefix, @errorName(e), + }), + } + } + if (self.rc_includes != .any) { try zig_args.append("-rcincludes"); try zig_args.append(@tagName(self.rc_includes)); diff --git a/src/Compilation.zig b/src/Compilation.zig index 11b3328e0e10..98f4012a26d1 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -165,6 +165,7 @@ last_update_was_cache_hit: bool = false, c_source_files: []const CSourceFile, rc_source_files: []const RcSourceFile, +global_cc_argv: []const []const u8, cache_parent: *Cache, /// Path to own executable for invoking `zig clang`. self_exe_path: ?[]const u8, @@ -1120,6 +1121,7 @@ pub const CreateOptions = struct { /// (Windows) PDB output path pdb_out_path: ?[]const u8 = null, error_limit: ?Compilation.Module.ErrorInt = null, + global_cc_argv: []const []const u8 = &.{}, pub const Entry = link.File.OpenOptions.Entry; }; @@ -1515,6 +1517,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .wasi_emulated_libs = options.wasi_emulated_libs, .force_undefined_symbols = options.force_undefined_symbols, .link_eh_frame_hdr = link_eh_frame_hdr, + .global_cc_argv = options.global_cc_argv, }; // Prevent some footguns by making the "any" fields of config reflect @@ -2527,6 +2530,8 @@ fn addNonIncrementalStuffToCacheManifest( cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir); cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); + man.hash.addListOfBytes(comp.global_cc_argv); + const opts = comp.cache_use.whole.lf_open_opts; try man.addOptionalFile(opts.linker_script); @@ -3941,6 +3946,7 @@ pub fn obtainCObjectCacheManifest( // that apply both to @cImport and compiling C objects. No linking stuff here! // Also nothing that applies only to compiling .zig code. cache_helpers.addModule(&man.hash, owner_mod); + man.hash.addListOfBytes(comp.global_cc_argv); man.hash.add(comp.config.link_libcpp); // When libc_installation is null it means that Zig generated this dir list @@ -5411,6 +5417,7 @@ pub fn addCCArgs( } } + try argv.appendSlice(comp.global_cc_argv); try argv.appendSlice(mod.cc_argv); } diff --git a/src/main.zig b/src/main.zig index 091e4b26682b..4442234bd299 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3244,6 +3244,10 @@ fn buildOutputType( .pdb_out_path = pdb_out_path, .error_limit = error_limit, .native_system_include_paths = create_module.native_system_include_paths, + // Any leftover C compilation args (such as -I) apply globally rather + // than to any particular module. This feature can greatly reduce CLI + // noise when --search-prefix and --mod are combined. + .global_cc_argv = try cc_argv.toOwnedSlice(arena), }) catch |err| switch (err) { error.LibCUnavailable => { const triple_name = try target.zigTriple(arena); @@ -3421,9 +3425,9 @@ const CreateModule = struct { c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile), rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile), - // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. - // This array is populated by zig cc frontend and then has to be converted to zig-style - // CPU features. + /// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. + /// This array is populated by zig cc frontend and then has to be converted to zig-style + /// CPU features. llvm_m_args: std.ArrayListUnmanaged([]const u8), sysroot: ?[]const u8, lib_dirs: std.ArrayListUnmanaged([]const u8), From d5c1e7f7b1381036f7d98c1944607cb0e1c0d4da Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 19:11:57 -0700 Subject: [PATCH 131/133] link: accept the update arena in flush This branch introduced an arena allocator for temporary allocations in Compilation.update. Almost every implementation of flush() inside the linker code was already creating a local arena that had the lifetime of the function call. This commit passes the update arena so that all those local ones can be deleted, resulting in slightly more efficient memory usage with every compilation update. While at it, this commit also removes the Compilation parameter from the linker flush function API since a reference to the Compilation is now already stored in `link.File`. --- src/Compilation.zig | 2 +- src/link.zig | 29 +++++++++++++------------ src/link/C.zig | 11 ++++++---- src/link/Coff.zig | 18 +++++++--------- src/link/Coff/lld.zig | 8 +++---- src/link/Elf.zig | 48 +++++++++++++++++++----------------------- src/link/MachO.zig | 21 +++++++++--------- src/link/MachO/zld.zig | 25 ++++++++++------------ src/link/NvPtx.zig | 8 +++---- src/link/Plan9.zig | 12 +++++++---- src/link/SpirV.zig | 9 +++++--- src/link/Wasm.zig | 36 ++++++++++++------------------- 12 files changed, 108 insertions(+), 119 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 98f4012a26d1..6c7f1d0d83cb 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2311,7 +2311,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void { if (comp.bin_file) |lf| { // This is needed before reading the error flags. - lf.flush(comp, prog_node) catch |err| switch (err) { + lf.flush(arena, prog_node) catch |err| switch (err) { error.FlushFailure => {}, // error reported through link_error_flags error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr else => |e| return e, diff --git a/src/link.zig b/src/link.zig index 89f412588838..5c296b49abb5 100644 --- a/src/link.zig +++ b/src/link.zig @@ -547,19 +547,22 @@ pub const File = struct { /// Commit pending changes and write headers. Takes into account final output mode /// and `use_lld`, not only `effectiveOutputMode`. - pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + /// `arena` has the lifetime of the call to `Compilation.update`. + pub fn flush(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { if (build_options.only_c) { assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).flush(comp, prog_node); + return @fieldParentPtr(C, "base", base).flush(arena, prog_node); } + const comp = base.comp; if (comp.clang_preprocessor_mode == .yes) { + const gpa = comp.gpa; const emit = base.emit; // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) // Until then, we do `lld -r -o output.o input.o` even though the output is the same // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file // to the final location. See also the corresponding TODO in Coff linking. - const full_out_path = try emit.directory.join(comp.gpa, &[_][]const u8{emit.sub_path}); - defer comp.gpa.free(full_out_path); + const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path}); + defer gpa.free(full_out_path); assert(comp.c_object_table.count() == 1); const the_key = comp.c_object_table.keys()[0]; const cached_pp_file_path = the_key.status.success.object_path; @@ -571,25 +574,25 @@ pub const File = struct { const output_mode = comp.config.output_mode; const link_mode = comp.config.link_mode; if (use_lld and output_mode == .Lib and link_mode == .Static) { - return base.linkAsArchive(comp, prog_node); + return base.linkAsArchive(arena, prog_node); } switch (base.tag) { inline else => |tag| { - return @fieldParentPtr(tag.Type(), "base", base).flush(comp, prog_node); + return @fieldParentPtr(tag.Type(), "base", base).flush(arena, prog_node); }, } } /// Commit pending changes and write headers. Works based on `effectiveOutputMode` /// rather than final output mode. - pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { switch (base.tag) { .c => { - return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); + return @fieldParentPtr(C, "base", base).flushModule(arena, prog_node); }, inline else => |tag| { if (build_options.only_c) unreachable; - return @fieldParentPtr(tag.Type(), "base", base).flushModule(comp, prog_node); + return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, prog_node); }, } } @@ -707,14 +710,12 @@ pub const File = struct { } } - pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { + pub fn linkAsArchive(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { const tracy = trace(@src()); defer tracy.end(); + const comp = base.comp; const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); const directory = base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); @@ -724,7 +725,7 @@ pub const File = struct { // If there is no Zig code to compile, then we should skip flushing the output file // because it will not be part of the linker line anyway. const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { - try base.flushModule(comp, prog_node); + try base.flushModule(arena, prog_node); const dirname = fs.path.dirname(full_out_path_z) orelse "."; break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? }); diff --git a/src/link/C.zig b/src/link/C.zig index 958ce12a064f..68facb374b27 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -376,8 +376,8 @@ pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.De _ = decl_index; } -pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void { - return self.flushModule(comp, prog_node); +pub fn flush(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void { + return self.flushModule(arena, prog_node); } fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { @@ -393,7 +393,9 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { return defines; } -pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void { +pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !void { + _ = arena; // Has the same lifetime as the call to Compilation.update. + const tracy = trace(@src()); defer tracy.end(); @@ -401,7 +403,8 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo sub_prog_node.activate(); defer sub_prog_node.end(); - const gpa = self.base.comp.gpa; + const comp = self.base.comp; + const gpa = comp.gpa; const module = self.base.comp.module.?; { diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 7c95c3803ee5..7d825ef4d14d 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1706,28 +1706,26 @@ fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void { gop.value_ptr.* = current; } -pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; +pub fn flush(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + const comp = self.base.comp; + const use_lld = build_options.have_llvm and comp.config.use_lld; if (use_lld) { - return lld.linkWithLLD(self, comp, prog_node); + return lld.linkWithLLD(self, arena, prog_node); } - switch (self.base.comp.config.output_mode) { - .Exe, .Obj => return self.flushModule(comp, prog_node), + switch (comp.config.output_mode) { + .Exe, .Obj => return self.flushModule(arena, prog_node), .Lib => return error.TODOImplementWritingLibFiles, } } -pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; const gpa = comp.gpa; if (self.llvm_object) |llvm_object| { - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - try self.base.emitLlvmObject(arena, llvm_object, prog_node); return; } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 3a833c40aef6..914be5a4435a 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -17,14 +17,12 @@ const Allocator = mem.Allocator; const Coff = @import("../Coff.zig"); const Compilation = @import("../../Compilation.zig"); -pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !void { +pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); const directory = self.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); @@ -32,7 +30,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { - try self.flushModule(comp, prog_node); + try self.flushModule(arena, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? }); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index a74b4b5ae66a..2f1d5703f973 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1026,22 +1026,20 @@ pub fn markDirty(self: *Elf, shdr_index: u16) void { } } -pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flush(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; if (use_lld) { - return self.linkWithLLD(comp, prog_node); + return self.linkWithLLD(arena, prog_node); } - try self.flushModule(comp, prog_node); + try self.flushModule(arena, prog_node); } -pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); if (self.llvm_object) |llvm_object| { try self.base.emitLlvmObject(arena, llvm_object, prog_node); @@ -2349,22 +2347,20 @@ fn scanRelocs(self: *Elf) !void { } } -fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { +fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); + const comp = self.base.comp; + const gpa = comp.gpa; const directory = self.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: { - try self.flushModule(comp, prog_node); + const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { + try self.flushModule(arena, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? }); @@ -2378,15 +2374,15 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const output_mode = self.base.comp.config.output_mode; + const output_mode = comp.config.output_mode; const is_obj = output_mode == .Obj; const is_lib = output_mode == .Lib; - const link_mode = self.base.comp.config.link_mode; + const link_mode = comp.config.link_mode; const is_dyn_lib = link_mode == .Dynamic and is_lib; const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; const have_dynamic_linker = comp.config.link_libc and link_mode == .Dynamic and is_exe_or_dyn_lib; - const target = self.base.comp.root_mod.resolved_target.result; + const target = comp.root_mod.resolved_target.result; const compiler_rt_path: ?[]const u8 = blk: { if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; @@ -2459,8 +2455,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.add(self.hash_style); // strip does not need to go into the linker hash because it is part of the hash namespace if (comp.config.link_libc) { - man.hash.add(self.base.comp.libc_installation != null); - if (self.base.comp.libc_installation) |libc_installation| { + man.hash.add(comp.libc_installation != null); + if (comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); } if (have_dynamic_linker) { @@ -2469,7 +2465,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } man.hash.addOptionalBytes(self.soname); man.hash.addOptional(comp.version); - try link.hashAddSystemLibs(&man, self.base.comp.system_libs); + try link.hashAddSystemLibs(&man, comp.system_libs); man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); man.hash.add(self.base.allow_shlib_undefined); man.hash.add(self.bind_global_refs_locally); @@ -2743,7 +2739,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v if (self.each_lib_rpath) { var test_path = std.ArrayList(u8).init(arena); for (self.lib_dirs) |lib_dir_path| { - for (self.base.comp.system_libs.keys()) |link_lib| { + for (comp.system_libs.keys()) |link_lib| { if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic))) continue; if ((try rpath_table.fetchPut(lib_dir_path, {})) == null) { @@ -2771,7 +2767,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } if (comp.config.link_libc) { - if (self.base.comp.libc_installation) |libc_installation| { + if (comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); } @@ -2841,8 +2837,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // Shared libraries. if (is_exe_or_dyn_lib) { - const system_libs = self.base.comp.system_libs.keys(); - const system_libs_values = self.base.comp.system_libs.values(); + const system_libs = comp.system_libs.keys(); + const system_libs_values = comp.system_libs.values(); // Worst-case, we need an --as-needed argument for every lib, as well // as one before and one after. @@ -2890,7 +2886,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // libc dep comp.link_error_flags.missing_libc = false; if (comp.config.link_libc) { - if (self.base.comp.libc_installation != null) { + if (comp.libc_installation != null) { const needs_grouping = link_mode == .Static; if (needs_grouping) try argv.append("--start-group"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); @@ -2939,7 +2935,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-Bsymbolic"); } - if (self.base.comp.verbose_link) { + if (comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index c0a259d982eb..cb26aa0ca34e 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -315,13 +315,14 @@ pub fn open( return createEmpty(arena, comp, emit, options); } -pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - const gpa = self.base.comp.gpa; - const output_mode = self.base.comp.config.output_mode; +pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + const comp = self.base.comp; + const gpa = comp.gpa; + const output_mode = comp.config.output_mode; - if (output_mode == .Lib and self.base.comp.config.link_mode == .Static) { + if (output_mode == .Lib and comp.config.link_mode == .Static) { if (build_options.have_llvm) { - return self.base.linkAsArchive(comp, prog_node); + return self.base.linkAsArchive(arena, prog_node); } else { try comp.link_errors.ensureUnusedCapacity(gpa, 1); comp.link_errors.appendAssumeCapacity(.{ @@ -332,19 +333,17 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) li } switch (self.mode) { - .zld => return zld.linkWithZld(self, comp, prog_node), - .incremental => return self.flushModule(comp, prog_node), + .zld => return zld.linkWithZld(self, arena, prog_node), + .incremental => return self.flushModule(arena, prog_node), } } -pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); if (self.llvm_object) |llvm_object| { try self.base.emitLlvmObject(arena, llvm_object, prog_node); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 81b10c59d9bf..b266bfeb47b8 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -1,27 +1,24 @@ pub fn linkWithZld( macho_file: *MachO, - comp: *Compilation, + arena: Allocator, prog_node: *std.Progress.Node, ) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.comp.gpa; - const target = macho_file.base.comp.root_mod.resolved_target.result; + const comp = macho_file.base.comp; + const gpa = comp.gpa; + const target = comp.root_mod.resolved_target.result; const emit = macho_file.base.emit; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - const directory = emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path}); - const opt_zcu = macho_file.base.comp.module; + const opt_zcu = comp.module; // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { - try macho_file.flushModule(comp, prog_node); + try macho_file.flushModule(arena, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, macho_file.base.zcu_object_sub_path.? }); @@ -35,8 +32,8 @@ pub fn linkWithZld( sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const output_mode = macho_file.base.comp.config.output_mode; - const link_mode = macho_file.base.comp.config.link_mode; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; const cpu_arch = target.cpu.arch; const is_lib = output_mode == .Lib; const is_dyn_lib = link_mode == .Dynamic and is_lib; @@ -50,7 +47,7 @@ pub fn linkWithZld( var digest: [Cache.hex_digest_len]u8 = undefined; - const objects = macho_file.base.comp.objects; + const objects = comp.objects; if (!macho_file.base.disable_lld_caching) { man = comp.cache_parent.obtain(); @@ -76,7 +73,7 @@ pub fn linkWithZld( man.hash.add(macho_file.headerpad_max_install_names); man.hash.add(macho_file.base.gc_sections); man.hash.add(macho_file.dead_strip_dylibs); - man.hash.add(macho_file.base.comp.root_mod.strip); + man.hash.add(comp.root_mod.strip); try MachO.hashAddFrameworks(&man, macho_file.frameworks); man.hash.addListOfBytes(macho_file.base.rpath_list); if (is_dyn_lib) { @@ -406,7 +403,7 @@ pub fn linkWithZld( try macho_file.createDyldPrivateAtom(); try macho_file.createTentativeDefAtoms(); - if (macho_file.base.comp.config.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { const global = macho_file.getEntryPoint().?; if (macho_file.getSymbol(global).undf()) { // We do one additional check here in case the entry point was found in one of the dylibs. diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 1f5af5b86edc..111b59fc3ba5 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -106,18 +106,18 @@ pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void { return self.llvm_object.freeDecl(decl_index); } -pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - return self.flushModule(comp, prog_node); +pub fn flush(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + return self.flushModule(arena, prog_node); } -pub fn flushModule(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *NvPtx, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { if (build_options.skip_non_native) @panic("Attempted to compile for architecture that was disabled by build configuration"); // The code that was here before mutated the Compilation's file emission mechanism. // That's not supposed to happen in flushModule, so I deleted the code. + _ = arena; _ = self; - _ = comp; _ = prog_node; @panic("TODO: rewrite the NvPtx.flushModule function"); } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index e93c889dcd7d..a635b0bf5b23 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -608,8 +608,9 @@ fn allocateGotIndex(self: *Plan9) usize { } } -pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; +pub fn flush(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + const comp = self.base.comp; + const use_lld = build_options.have_llvm and comp.config.use_lld; assert(!use_lld); switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) { @@ -618,7 +619,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li .Obj => return error.TODOImplementPlan9Objs, .Lib => return error.TODOImplementWritingLibFiles, } - return self.flushModule(comp, prog_node); + return self.flushModule(arena, prog_node); } pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void { @@ -666,11 +667,14 @@ fn atomCount(self: *Plan9) usize { return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count; } -pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { if (build_options.skip_non_native and builtin.object_format != .plan9) { @panic("Attempted to compile for object format that was disabled by build configuration"); } + _ = arena; // Has the same lifetime as the call to Compilation.update. + + const comp = self.base.comp; const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index fc9e0c9a6009..7b66d914bf1b 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -173,15 +173,17 @@ pub fn freeDecl(self: *SpirV, decl_index: InternPool.DeclIndex) void { _ = decl_index; } -pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - return self.flushModule(comp, prog_node); +pub fn flush(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + return self.flushModule(arena, prog_node); } -pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { if (build_options.skip_non_native) { @panic("Attempted to compile for architecture that was disabled by build configuration"); } + _ = arena; // Has the same lifetime as the call to Compilation.update. + const tracy = trace(@src()); defer tracy.end(); @@ -191,6 +193,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No const spv = &self.object.spv; + const comp = self.base.comp; const gpa = comp.gpa; const target = comp.getTarget(); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index a0907d6c5149..185d80258882 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3480,33 +3480,29 @@ fn resetState(wasm: *Wasm) void { wasm.debug_pubtypes_index = null; } -pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flush(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + const comp = wasm.base.comp; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; if (use_lld) { - return wasm.linkWithLLD(comp, prog_node); + return wasm.linkWithLLD(arena, prog_node); } else if (use_llvm) { - return wasm.linkWithZld(comp, prog_node); + return wasm.linkWithZld(arena, prog_node); } else { - return wasm.flushModule(comp, prog_node); + return wasm.flushModule(arena, prog_node); } } /// Uses the in-house linker to link one or multiple object -and archive files into a WebAssembly binary. -fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = comp.gpa; + const comp = wasm.base.comp; const shared_memory = comp.config.shared_memory; const import_memory = comp.config.import_memory; - // Used for all temporary memory allocated during flushin - var arena_instance = std.heap.ArenaAllocator.init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); - const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); const opt_zcu = comp.module; @@ -3516,7 +3512,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l // will not be part of the linker line anyway. const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { assert(use_llvm); // `linkWithZld` should never be called when the Wasm backend is used - try wasm.flushModule(comp, prog_node); + try wasm.flushModule(arena, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? }); @@ -3708,15 +3704,11 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l } } -pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { +pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = comp.gpa; - // Used for all temporary memory allocated during flushin - var arena_instance = std.heap.ArenaAllocator.init(gpa); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); + const comp = wasm.base.comp; if (wasm.llvm_object) |llvm_object| { try wasm.base.emitLlvmObject(arena, llvm_object, prog_node); @@ -4589,19 +4581,17 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void { } } -fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void { +fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); + const comp = wasm.base.comp; const shared_memory = comp.config.shared_memory; const export_memory = comp.config.export_memory; const import_memory = comp.config.import_memory; const target = comp.root_mod.resolved_target.result; const gpa = comp.gpa; - var arena_allocator = std.heap.ArenaAllocator.init(gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); @@ -4609,7 +4599,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { - try wasm.flushModule(comp, prog_node); + try wasm.flushModule(arena, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? }); From 2b63ba31e9757347b4e8d10c435396f94367ef45 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 19:27:40 -0700 Subject: [PATCH 132/133] add standalone test for depending on the main module --- test/standalone.zig | 4 +++ test/standalone/depend_on_main_mod/build.zig | 28 +++++++++++++++++++ .../standalone/depend_on_main_mod/src/foo.zig | 6 ++++ .../depend_on_main_mod/src/main.zig | 5 ++++ 4 files changed, 43 insertions(+) create mode 100644 test/standalone/depend_on_main_mod/build.zig create mode 100644 test/standalone/depend_on_main_mod/src/foo.zig create mode 100644 test/standalone/depend_on_main_mod/src/main.zig diff --git a/test/standalone.zig b/test/standalone.zig index 0303c49c133f..b26e85c15930 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -258,6 +258,10 @@ pub const build_cases = [_]BuildCase{ .build_root = "test/standalone/ios", .import = @import("standalone/ios/build.zig"), }, + .{ + .build_root = "test/standalone/depend_on_main_mod", + .import = @import("standalone/depend_on_main_mod/build.zig"), + }, }; const std = @import("std"); diff --git a/test/standalone/depend_on_main_mod/build.zig b/test/standalone/depend_on_main_mod/build.zig new file mode 100644 index 000000000000..bbef64693e59 --- /dev/null +++ b/test/standalone/depend_on_main_mod/build.zig @@ -0,0 +1,28 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "depend_on_main_mod", + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + const foo_module = b.addModule("foo", .{ + .root_source_file = .{ .path = "src/foo.zig" }, + }); + + foo_module.addImport("root2", &exe.root_module); + exe.root_module.addImport("foo", foo_module); + + const run_cmd = b.addRunArtifact(exe); + run_cmd.expectExitCode(0); + + test_step.dependOn(&run_cmd.step); +} diff --git a/test/standalone/depend_on_main_mod/src/foo.zig b/test/standalone/depend_on_main_mod/src/foo.zig new file mode 100644 index 000000000000..0a52bce8aa6f --- /dev/null +++ b/test/standalone/depend_on_main_mod/src/foo.zig @@ -0,0 +1,6 @@ +const std = @import("std"); +const assert = std.debug.assert; + +pub fn run() void { + comptime assert(@import("root") == @import("root2")); +} diff --git a/test/standalone/depend_on_main_mod/src/main.zig b/test/standalone/depend_on_main_mod/src/main.zig new file mode 100644 index 000000000000..0735fff4c790 --- /dev/null +++ b/test/standalone/depend_on_main_mod/src/main.zig @@ -0,0 +1,5 @@ +const std = @import("std"); + +pub fn main() !void { + @import("foo").run(); +} From c546ddb3edc557fae4b932e5239b9dcb66117832 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Jan 2024 19:45:34 -0700 Subject: [PATCH 133/133] disable standalone coff_dwarf test on aarch64-windows See tracking issue #18427 --- test/standalone/coff_dwarf/build.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/standalone/coff_dwarf/build.zig b/test/standalone/coff_dwarf/build.zig index b85b44b686cb..cd7c17efb37e 100644 --- a/test/standalone/coff_dwarf/build.zig +++ b/test/standalone/coff_dwarf/build.zig @@ -11,6 +11,11 @@ pub fn build(b: *std.Build) void { if (builtin.os.tag != .windows) return; + if (builtin.cpu.arch == .aarch64) { + // https://github.com/ziglang/zig/issues/18427 + return; + } + const exe = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" },

d2@TgDME`{aP$5e1nau-WpRV2K%lZr#ztBFm4GP8%@J|sCkPDjj3ihrrCGs5^@!>I0cSod|3 zH3oDrFocLQoWiQ=>5%hmcre3_!I92Wo62bnc%LJ`()?bm(7lH$u`J8OieP0<@y>v@ zEU}VbiwnFGT&>_;Q|><{9p6ePt{lUOFuGvk(P4S9TskRt2m+hXw|y zkBbC2Fm^-a`*kE~3iDjFC5EAOyOHq#s-0pgsQT^93|nq(IdIDn#_a8;2Aa0#^~rL? zj44@;=<;^D47)132aq8UAvB~&5E3TDnN~9(S+xLcB9a&N$~5+7F$%!|ugiX7@q^`H zfX&$_dmn7c=Kq!w&#Y_yUDXXgNGJo~l^HLA+Lchnf^aMCmq3pwIlgK%h=4^zR+;m} zi)eq5y*FzaDsmQQj18hD0wI?ck4)BFC5(jE4QNy2!Ga}DBKw93T`-|da16?#L+sTR!qQq`ZMtkx3)k=n}TT>uVsm*m~h8-S8IcK}<8!c$NR zZips8E>;t;X#fZf5vSh(G^Z>*kk%f^*t4dXodhL;d9R=2lMmbwt*7^{%HRm0E@*?` z77a`%(xt{^bIr@h!K{*+SE40eSNL2wg0AWN0Ek33{S_>2KD`-uk947E%jQ%u?Ar0; z!>$vdOqs@ZBul18ZJcg}3d$XT9!zvD zI?#BmWA+e(-^6sCw+#FW69RsZkAgvD`yX>s|7a`k(HU%*gfSrGTkuZxt+CcQOt@O; zq-h}QC!dzlK~@FqQrE~dNTD4k-bw}AI&bO4M67!r~sW2bZA(-Z_ zWHYx4!5=gWBWU!M~4r(*EQ(X5Vk!l>gB1jecOctHEHsEqfW zUA*r!yiXb4w>aLHd-_U3F~d6v#jMX5p`TWt6?fdzXLNDNPyKil6wlD-XY)QQpnFhZ z#Vhenp9d|u)s9MlMNzk1yw5UB8vE<6#n?zuEP=f+5FgtQgX$CvbMP1Jls;KxBpp=f z>`J^7Y#KqzxcsvSSsm&h^jO(!`wUD^QD69cG)Lk$P9k`-=*G$C5R+iUgF7k<79vJ_ z`{K4hlpVf2RTLImOqDwY*js$e2wjaew=m7(JxmD@T|{(H3|t9`tUo@;HbS(Dr0Ccn;6=VTbQ~y*E07}| zqX5BY{=t|(^C=g~Fvd?Sz`24!&ZH0L;h(Qef_pen12|A-IFjUcQ_#e|&C5`!ShX> zo8Fl7*c!TvW(d87x63)&HPQ8y!*!rYTMK;>1X`6rMeoQfAq52}dL^K+BiaZUa?R4@ zuZpPIugdoRq>B@OxFNbiCRCj*+Lezw#EoKCxlaAj(aRyGv^~nu$+q0N90BDzlY?Dx zF*I8~cZhKy>)hHN41tx@u&uM9-$CCVHs?4Joo~&aHpy2+%;tw622!VDUi6Ujb*or+ zP~ebJhFz}2U58AFc~etSWBwG9n8}$s;Sn7J&^0zStmL=*8$<@&%vqw7KJTChtX~^M zqzv}e?X|k>Y+IJUw9_C!&O-`Dm{CZqicazer4o8mloF4(0Okg@<1**|bM=+3tcQ z(oQ2Zm->rsO(GTuHcba7h2?Z(x>hr!i7aJdsgkMGrK=U0avMX*?;Ca5QMuVKlJmF= z@1}}UJBwf2i(k`T))OmqJE#baYUsuUzr#W6?REUl(;lqncS8(EF$8Eq8hzj$VL%3w zcTO-T#&_*vhG?4hQ-m~dg`Qb)y61R;z0jF3V+I4hHsQ$!UmFQt^5A@x+1MEluP0ZWc2_D6xQrImr=rIF8s2D+is~xfD8na~ zV3Wz=VGJ>uX=J8~`NT6edFa`8o@u_VbLO`*+^%PN9Sgtnsc6&cMpSM4F|8kvwdSRT zeo0}fq+?;3rRuBOm#KxF?MZ8>y~$u`Z`NhHy+xNB+n6*-$kI-Y)wJ8X+}iHwa&!9% zU2bV(^3sfYjnAmDbPQ^xNuN<;no&fM+oJj!&7g3j8KoIi+%u!DV6s$h%SJUvFdmFN z_yAPTgE~KuqHfC?{J>OrTQ%j*eV2P`w+psCrxOTY8%+L-thII0QbgN2^ z@yQnbU=c_+tNsCgY|@WGeoX4e5I-){k7hU$8WePzn%?R`+F27ML3JlxV-r$+U_7BN zXQVkNAR5z{gLYln2#dYbcdzKOaz&R}MQel%FUiE#S_t1Dv5Ey?D?}wQix$ixPx3bf zk0^5t;?KngnjRqEvUWKLJveG*Fa(EM0eDP7 zFh$(W9g@yn+{yBX_HW`0`|uc^w{}`)&hA!VO?5_e=6KQi$cm;v^>bKQ(w?S=^9HnX z5+!N2m7-n?%1Z&%nHyDyuo}0mocDFw`dZe>s$>UTk?PNRdM7um`scm-99uDr&~Vsl zZN;~Zk)(!)6@MP2%vIuhY@XJ8J(U=agBoezcC#a9HxfM~A^)n%*&ITgdErIRkC zU?iyFy1j`8m^0bwk3e^08hrn-*#4;vpXPL|X`r+p5Yz}IOj3Hvw_*F|RHvSA|3uOA zBXzmX+JDoJ5W^4RN(nvdd)NW0sFM&$UfTW{WruzSS{%)Ol#8~17W;%ovybZ0UzZ-O z&3-vNGHcmH_S?F}S~eefC?Lba0nrc%;;H=g0R`?MCXz|KBs;7AZz=a*3xTN&0kM@X zR;7xIBvz?SA$_3pgIMg$TIsH0Q3*SOmtyy0PLtDeo7$zG4=QJ_;JXH5Mo(#~QoFS|!ZPH^L2d32vzt z>ep9NE=;5C%yHxf-Dq%v&50H~m@$;-TTmhG<`N^no9os44+UETYKxPXm4*KK^Xl^n#@ql0w;w_{y z)j=2!7#W^+22C{;rGJcw1yO|wwqc8)9~Ay%*g}GFfEsc|LTI7<@18C ziziNF5eEbVWKSYehUq9Ekv3Xq0o_xq%+YHmTa|+09zL z?Ae_ElR8vb2!@bN4ntys^jtycIB=smpftgF;8PT*gUCkzpI6N%HCV#*DT{SVKCPHNp zK%`DjG$2%!4}^Jriui-udzN(r0mdiI%@*|>1emSM2j}&-eDe7WfG-9}DGYnrp;8)v z^Ausx5ElKwv{k}XL=N5f6gTdO^&oY;W0SNaR03O)@D)y$4!bxVsWW>E%Tu9tME+$TE&~04Y=w@aI@ND$_!Ppme7m%{!fBJr`wa!a& zz9K${A!KHh!%qh)k;!>+w#BQgChtao(HVH8A4Uw&F3N^HsOkk|@krELu9Unq6a!bP z4XmNXgxYX2+Mwl?8J)qVwf2eJgkpN-c6dl|J4>&6sD-e`isvgjFM>&!7m`35WIaZO zrw%a@*BQiZ83@svkC;HW;HpAUx-9$5FSwxezJaJECy_Eo%iE_a`3n8fMvgoVjrMpv z%|?2h1EX9b&EMf}FwJnF!luY)*mj>|8nuAz3C7 zTyvoo+<2@j57NBKxhtvGZdIpK8I;WTh(E$I3*a006b_=9WOhU~k=MFAD^LgJo5T}C z@I1`NU0xb~-O6p9n~96P0V*aordJ9A>v@sS9b;bp2DgV$ZeC5Av)L2!kYn|+?#ud9 zm_}vSFHE6Koe|v+W*=tkZU;){%*|YkVTp4Ypm<#a=Ryv1;HGB^&SkCDIwN6*m=9sZ zknM9)o1^F|pcyAqQXwQMe35#Qa+z}RNP7j-M2iDx+}@G7EbkW_Rh}*kUW^N|l^&%Q zZo~j=s<-&nZeh2Llr3Ti3Th9rj498JJe3HAKfXKr&~BJN`$J&PW61|3Y!Icf6WKt8 zFo+zf#IxObF4IOTTa7zaj^3q{VodGWS%ZNC3g!^KX{TQNZ z+HyQ2^GY2p7Op$tkBkXiD)QMJ^k!g=ggKMID;-}EVJ2>jWDFEjs<|u$861lIwFWic z0FSil?0exOQrOpWzJpC6v=j-SD0r^dmtXMoj7)cSlLJ4}IPVG(3 z`TvbY)gEO_;0Y>A_D3c`nLX_uhsThP_3zIaR*8iakUL8dQK>(N?TdCOYkf_NY# zSnE=NpyBt{T%(ZFeF%OkI~*Hvh9%x>W;iX&po=2@ew|7%q>6QvD%oX3Ft8P(78*>b zAx-%vhH;ULD5XSJUJ5Nz?o9DnWGj$CeMEUG3Ba%>C9V|hT!GpLb%^9pb_jNJCqN-6 z-NA)VZZ`^sQx2IiCF07yUa1!}`L@oe0X8bYSYn36L2l*(2LW;c`c|EII+QJAhyhdl zx*Fal+UE1SJIX**Nk{DS0bdV>A>yg{E`WtI0b?zI3gFsjL;oxM^QNY}scjDNMlWd{ zlGk|%J4a|#_6tZRw7at$9KxKkb!gDq-L7^A)vg$$HO~O~4ujAxVUiH?W4p7DDAB*O zESpO7=-%!!ZX;F6#YMVwj}hZgu+Hv@Bg;^S7~;VfEC9jv?d*(sOENAa0rIC!*p>xA z3nXB^a0W=SBeOsxK&eeDOKpS%e2hW0qF#g%XE8ZOEInI^cEE_SLoh-!X=x-J6#+ki zqgdQS!~rjG6quI5vHg5#puQKgF<={*4 zM1r_HI(9#&G*>E-F;>^!cT(B(4Af|8Y79u3L6k1aY<=25B37x*d>F8$k*gncC;yUI zY%I+@rlji14xkG1MP667z`fVS`}zE4C(&ea$f6T#NH7eD>lT&>H!r|hSF=g5=EdIQ zYICyyiX>5aber?;7%2wO^HhJ^vd{ml2QBIR9K=yfI8mutbr|r@eChp(I8y}6ltou~ zp;Sy}$sAbOL~~#<-fGU7g_6}?iEV=87 zsIudA24wQ#u~~ws69EBUf~LzV369N}_UjdKV`A4>0mR$$J-ymMs%~YovwM?-4ZXQ# z)he`CEIf}^Wg-mytTz8X#^n=fKPKR*t2X#-2~;MqL4f66N8CszP$Hg~lwh6KW32ae z@J>oF0APdC48Uo9pJ{f6@5eycvfOM6Mg9-rK5P@T|+Szc}KGlWkNnjw1o#pIXg#6rzJB43;}}j?KfnrYdYk z#k$E8eyK|tIe8U5YewVlw1}O`bG3~xJo;Z>y!$7AB*|V2yHiN0h);vx+%w>d%&hMh z2*%)$DF=}g7+M`xzecCwwlk0(&aNREFP?^C^5bqSV^lX&$S_?GRLr-1**H*a`m%8_ z4!&^$&7S>9B*$PWGhd+0nbr_Gx3LgY;-c*JxXwsFVVYY><$zfNw8A5#z;zl*W-!#% zHcd~YjN(g`fDhEa3rU50e4@;#dh)AlJH<{7s@TR5SjZ;7Q!#8l2A@Hmu`t!YM@P6H zaRT|{`pUzui#^009wZvD4H4Nq*-4UrFmU&TAol03+qVy3@Bd1${K<-PLD1d3d~fO6 zE?5Dxp6GMWGFa*)AoX-o6@~6F-P9d|7oHwtPOI-M3!Vy;VJGRIyz7Pr)(1mFevmou z6eU)?qawDiZ&QVqD}>4TN#=ql7-3lLP;b4Rwe%04z9qiGxzh5GTMS z#FW-RBXR>Kzpyrpsh%PuyUY_$r)&6*b{>`3C19nZO0Z@sY2pl07xzWV8VsbS*>4Oq zW(`(l+o_XUEppxRe4iM;SX_JRXK`Jn{++ZeSFUTb07%9gM)Hob>Sja<2T`mqh`gDd zc;dDKxtxjwoaKpbuu{{3e1V>VTLO8zE#|nb-7#DIEsWnrp^ts2mQqnj1cejHFRpc@ zg(<%&TrU?28=dv2^xzB>u9qrtc^==Ir0WYlz?+SPgslfainht@KA5fnot@WTTfLLt zT;2-!IyEE&s)Kk+CY&WDLAazDsGrEcs4QIWhVS@v44(mkfAf%i<4=dtPPZ`jrdjy+ z4`OHF`}^9$n)VAt+1s;kNrxu0F;I?Cj%H`0ZXKNnF43SCWlig=&Cle>zGy`KaAz~a zm;8p+Fn4h^n9h!cQab--x@>E+KNtc-WJ@PN>_~c<;SHXkS+_o2%fHKQ$ye5*?YDMF zX|PU)d-_Dn3|f}^%sLyP?_1JQAJa8N1}`LSu^QajEQQ`HWxMlUNx#%Nw2>kLlg@a~ z4!!(JER1`303Ay=8AM;G*xX0`6H5!~0cIF8`5Xo##*nP}mDSl0u}5aq_I2$IRUAZY z!CXZcAV~>i5$dcB_030}ahtsA&C2QwI&Ha`iuXoDe)DY&03@EYM`bQyGflaT(NOKe zMGTx*yDy?5P46l8UUkOXqX-7vZV=J|Y)w!vK)4b7wee9F5FSgvIHI-W2#2`MFS6jS zm44C9rfeHMj!{Aiz>+?~U|}D#u;@##uXm z6kQ`bm&gn27z+ryp|HG?C)c+zp06SsEj1+Dob5srGd4DPc*q!}t*`7x(MfgM5Sv() zaAFk{E!#Uu?8O`Jhu-t@2_V78%WOP3)JdS6^Y&3K`2V#-NcYd%e70NIr)=oWNgyRtGBE)B|H^<%gd ztx9z&Cs8(pO4AQ**dtUT`%6}!NjQv4BS#}MTAUBPX37A)fC~z2Xz0C6@Y_?wt1ACu|!blJ)w^hY1X#8M0{qpqiVn%C+!`N=iC~z!CS6 z>`Ak2D(1wKuB>w+GGT{rSjkUbV2Df<61^}kNG9gp4YD5-P@Yz~>8*t2$ zzR`vp>U(`^usHGU88DIJC4fcaCj`$9bS_h_u|mdv3EECCyN3OqkO`a9PLo7!2ePGv zJ#4R0`8=BH_8gLe831zE{Wcx1;N)Xak1B7z+XvmEQ9%(D>WYn(Rcc!*YzPo^aK zVA9jU{mRdklidP(xcG^Y-F_dZFEb^Wa3S9mvh-WYP!!f2K+tkAk|1}HiEb#Tg_j## zNaDy)dkiHy$&TQ=Kpt(sRzuKWOBI(|`*pf(YmZZ81HCv6{-@d#CNE7RhHPYbmA?Z{ z+}?`N@H+dIQWCSydi;6gy^_oZ?_;TUS7I8Mbt!>YDz`qs3Nad2qFCmZaamn{ldFUdIRDeyOT6`(c$sTCcsfTl};po|4N+@hEj+(`O)$M@=BsugK!p4j!m-c4cMASNtl#g)-^co z8SEslAkJtyfq{Ky(51?J)utD@JZW5qH6`f`2y}%FA}PT0Sup6S_4l;>J%bc)(V!6d zQw{GaY=5x4!V?72UE!r8zCuROP{DC@S|A#2?G{u*7xih}ht2lj3}(L$3GWdp&l%BT zt;+DSaz6|Cx>aZIP;Q8Nbs)wJUnYml7k$ECK(aD2K@A0O!M;~*rxuD%eZG=CgQG=W;~XJ-uM8DYwV1F0GeJvxlH7+ZWcm zZUL;y-2z>!a<>4M@@|2yrTjc@I5CV@$&!|bCMxn=2SJae8+LWZ{T#z_#T8DlkE{s?~;p~ii`Hxr9NumRPBv+Fq$E;(i z!M~R%$}++GM(*YfDW1=nwmjn!IA0m2I$I%e-)~GuF?@A4TI50D3O8S#%YiakBL}YL zE&RWKj%dWq=aU0LYL6V~-ojiCl+8Dn1D}tJ&_KrToE%9y+W%z%0)r_dazK#c6x%OV z@}Rl7Y7GBiwjbA>uhxqf;Z60~bP#W9lT23QsT!GNL^lXgw>{8gIBksAV%#0Uz$a2@ z>X-TBMl|jt>4XM+!Uz0$BK7-))XqzaR8i&fkOH}XZaSXuoz_duZcvK{Qzh=EWLr3) zlts)`yJ1!f!mWB^Sa$ZsuuQEQW0Ha*eQ$Lr5~Li%a=uS2hJ|qL-XInWYFQB^a~)k% z&H`<4VX4W3Sl&{OJ%WpvkS(|1-(0% z&D|@Y?Mx)hH2Z6|DF`@T2!IyRaUgGlv$H`FV5wURID)+)kM246q8mc?u+hh-I3=8B zho1`@N4nTp6gHM}NDFK%@}z`~Ctoy>*|EHh?9VFMpXS(D>chtI7v0cQe9W+c0-Lw! zy~^ely;JJc$rsg@$J(3#{$_hUEu6|*GjF?1Qunn#^`e>)C&E&yQChYZn6BnQZ%uY| zLZ183pMKG8Sk72lTCNe*fwJ-9r>Nk*4_0YGBA24N>;x`WGJW`P;=;F>3_>i3aLGeR z6h?8brt{&&A$C-DG9kje5Jyt9o%v8LG$Z@o-Ps3rYhH#K`Ag&z}2PQQNI84>AJ`5TslZCRtHGc7R{0v6=0TWhJ|1Z7E_Kk<1m5#|BG z4+OFifLbEMA_3$j94^ZwDcp$cddP725|g2c2=toNGz5W?5xCMGyQ$J_BP3*a`4Gt> z0)36e$<;aB!{YXd#7~&BLj1405S(n-hDk88uj~z+cW)s5x^!feZ-S@F6WZzvV>N)Z zK)LzN7C|?^;ic5J$d>{xV__!114%lr#jG2m_!8iyXkY2H_ev{8Nt`Q%eC_Fme9d-4 zz7+gz+GHN`^^m9#gq_tEE3IlG4B`oi>v~!GLuTh&YrAdRmD~gD8#yQlF_|3TnjL6D z%4S<{wMWo`h7?x6$(Zh$t&iO4MlaUTX1eLI?gp1&4EwSZtMNQ3o9U#l0}hc8ntdEQ z&SQj`7lxdd7$_fP5HsAx%S$v@x@bW?|4csPx9%MFxRYgA@<>1p&fy?0zEosvGB9fg3j|?AW!d`64nferE$F5- z*={kT(47Z&m7M4v_#iwfKSr?!jKGJ+OEt3slnxs6s!ySLsjx)*9yFo3)WVinAcKgB zAYQ$Mu$<=PIO$J8bHa^TXijEVYrwKOmPlipcijRGzP@4fc%hq&5E}U}QWTN2^Ubd(CN}0u)x{Aw0oW~YZU{&(4 zj?}gMMj-a-R|;aC)hsiOVV+&j^yva}lGlVt%V&nW%k#^|du-hXXhSc{(}3iga$MER zH=FW(P9l2DTY|HNyF@sjL+JNSke4?`EY3~qG@A;+O%9mC!!AXyNFJF z$XroPDUy@dRu`~JhTueYWTunX#z(}>n>d}=^eGkeiRP~C!wOE^xQhSuP+j(&7!5If(DkNo$ZnlXHkg`6m>Vz61OFyK2V-a`!Zr;kDkFl8ygLcd*tDI+!yB5MdIb0nY!5&wPSJRyGYLV)x_9ldhm`)%|T4r!wwV3q^->6o| z{)`Tw(W+!@+ZK4964ug04$^ZOo5gb*d`{< zbKRzc%_rh$BqYo#a-NfkN9UuFLrF){(Ljx4cU&rpP!SB|N>#qb8voQh_H`~K3gUpA zjyI2wUsXmP=?c{4&!l{K17ldQbbL37$t>G@|z?|Dp-}Xa{{U=z2$d! z3lp)op7lK)Rq}s=cbEe@CMoj7M1juhIlWsZV+rf#ypaeH(}PV$+6u{=^0wMy zJ&;HPO*7Be{a*-^O?r)HhQNSey5dzW_C z`kC)afUE!*i4~`?eWu3D;-}W~tcZ!r<|echFRxXnHMW@QucY|3)!7N?jYXQ1rT)*4 zkWM3#EaG+)ri%h?!jZ41*4n8Q#Vg`A&R6H6^4Km?<4>qYJ4Ckh8SNjTfb`YFT$P{W zkgm|6K6Lnj3;12m0XDBs`8f!ZBxi&&ad?%siB}5QB|*Vwe*%CfFC_~8Q8n7Bw_jcq zNI(cEIMbzqXM3sOfMN1%FBP1D3KpCS78tX00(htg1tZyTP6cP6g3pTDmEuHB644ZY zSE*CPm_aq!oT#9u#_Z5L_b1s;fBc6NQcpy;PU`P%Ap*yi@eeaF5yp?!tV7$i5oE;Z5^{b+(E4$>0$Od)xGeSh_7t09W&+0!2+s7u= zUF16Jlhd{>@M=?L5OE}edeQ5cyjZ7+IcHUwvYVYOsFmbR#!RHq?x@@-aIJftjao5! zdQIMHgBs|I{(k6ZhzeFF#4z=&zhd}Lh{3PF#u&f)U+VA0b9+HPU{yXJn0`$#ZTfP; zH0XI?mkDr9*C&5tD8IQM*vNZjmeS%mn#@;;*Ra%W zdpToRjn7YX;z=DTKNatp2r?ZHEGgmKM7vqV0C&rX68V#fnD7p&RFYJ4q%W+)2H|2L z!Du8Bm2YEV-LBUAB7|ZElh;|D2`z6RjaK-_pci?h-a=Um4@R=%Crfj@r=}wghXPnynB_RcY&ZbsZ({3o+XvS{-E!W^(>jYgzJzQ;$HI_ zA>gW|y}%6ZZ%SoN@eI+70>IO6bp^RicTM~to-JQlEF<#W4Fk?kn6nub7}SJ$WsqlQ zt!d79Q&3?yE8{~Xd2fA>=oe_fk_C~E-k;SRw-}TRU^@$@9-t+erOq!!8Z9Aa7IhBn zDSf4Scvy$WP-iXq10y>nuOT;PqRBb}rA)R=X^{ z++sRrXQv+_InU*G&>DM|pvT84Q+1Ep2*?MnIEHc_3q4FwfCd6Yxyoune zB*Sz@yiS4{VmR>BvfuuVMYu{kMx>KX>I4ud<7aRzq{$MKo9 zJ}V~Noo(rGS^clC>|G~3#Wz&GM?XZLVx)7NtXpubVkjU~!V#DqQ}NLWxrT4`%AroC zPp$RcqToe_9JVBrfHO)4T3@xk%X}1~>rR~f7tVgUf8;+5iiOU(wzKQ74l%P;eYv9w$kiU|A=^XUjd4)7)oX`Y zW|?92y3(Nn8R=R&n|J`=-Lgh>C-7rtVQDl&jm&lANvwcLdjvFgQhafb9R;5)%LFYP zV5A0=EHbD$57QW$z3eEC_O4MCw9DAaM_5RXVnFH6Ei5*+6V({Z#x7U6EZt~a#VOXv zqQv>Mf*J?-4z;zo&X(_-1N5&X#saJ$<4N1L5L>EB*c)92UQ_ZcO{H(WANdX|g#j865#`VTNaAt+>(^DGPb+TujZ zLQF3Eurg?c0V7~~VM5Z(B|#tu=_(mORTNYpFctzWhk(RMKOIat;Gt3MY%33KDmD zDMv~Zeo28Y5Z_kr&9`;e_$+!e4U)?~d5i_4^?*)4(D~O?p7W$)HOw=+Ni2Cl^@XK1 zOuu5SD0anZ?orUYd5w&sCcl_z$|SYyFBk!u5}Wc}w*r0S9X#^kGtm-8k`wCUL}wL7 zJJfoIcw@nNAV~+G2`}~=R2*Zb_XohWrN96$Yc|F$ti-|uGX~aNH(ji02+=au71Nkj z0U;)Iy~CCr)G^h6%F=NbD^K7^CJSq0zV{5} z+b?z~-+r+}Nx=&YEdbPf3Yi zw(pI%qQNhk-ud*(Z?n@@t{dpbnsjCLw5jjXeS4t9#kixgRa&7*0T`asK=+fDo+k2vc` z`MDmn**E&?ED-Ne&kfj z1-qB>{BxqEe#yC%?dPjTHZ_B{_j9t1ZI^8f>+pg6sFeLmOv|aYmcl<%mxkKI{_R1& zMW0Ikt68TO*+XwIS(L~g$HBq4EwVXeC5Mu8R`PHU^j1r3&oDghw>jkwhqUhDk^)rRCHmTTs$Ovuz(Gnr#6~R>iome?C&bKj#Rn+1_!ds zj-0dQFg@W?SbYZQmo0C}Pob8!FrQKI0d1D$_<+F2FZ2O!WC}juG+w)i4+!W$etJOU z+{hXi@d1G%6nwx}&g3FKU>hgX?SW>ep|K>)Pb01*$9ldM?tLqWY{19G|8n8DmMlsG z?-79WuwG=zrf_eXCz&ezqvVH@++DyEX=El97ouxPHonRl<}*phhm3_nKdfsg`<*B=6f}~LQu&qD)in^Pq=MDwOZ+$XNZRaLk}un1 zc4V^;9trxx$*`tZg1g`-2Xb{62^AIgj-W$4Nt0c*W{JD(m|6bbz^^69;&I6Ds_6KN z3bGT{mUaDDFoc8AE2}5gYMsF#3I5Il&ib3ouM8aQ9cuLA`*hgMXO z9qxjIEMnT6fpgfvF_Y%mHLhLtW9QtOGIq=c40g`0VfF0+XI9|M88|!nHCuqQw+9?+ zYrYH4Tp65s1Lr@myzHp#wL^4s5l55NLwih0=@W5IOPGG$bBQ?p_HU1SG>7iRhS~rc zjx}K_+W{JXnm%6@J=23BD{{t=X~TbdO$py;)@bj{2lrwkktB4sDmZz1345URs zdZG)`VS#kSK>7-P9WFpRy5j3>sSDDPGDu4X5*9Dy1jo|3aVO4xEX}Sd`$G8w(mXeA zGQl42g$wV0hqLvnXs!nYl~(yZbYP!4fTd}^+mXHM$bxm`_59jPM-JO??_W_%cA(pl zg>pv@SVz8thO*=5>A{KdvL{hRr{d$|rh}XepB(2<(XtM5YP>un^@%<@$$s>w*@`21 zcv;tCO?!&F?6fM&Hu3AJ@w_L`tf(kEV{P^c$7jYxwPw{j5Mb)(5(j&_p`!Rhy&H@E zNqHa+^)#%~D!)h%o(MfSESQfN%$y{|@54atCaR+=KF*dLYE^P%yfodG3~)EMxukd& zk#02`(z&EO417UVXOlM9Y&LW`r@h>~wx_4d{>kjP3A%HApEQD{YVRta%#B-mjrqP$ zIM3N+^?g0P^;YJ`b&#D&(ZMn+byxS2hFFL_d^?!NiOxmE@0$L*{s@0V6ttPs%^~C8 zAjq0WRxWp%j7z5VdNyFb36u2MI~d$Q4fFkk`@*`O-{;o#{GK$97E_zwGbk2wJDB}5 z7Gkp*Ox+L}r-zymcwJ!#jts?#nB5&4<;7avnaY7iN|tw90vC)%9t_MzF31y3Bc^5J zDi`NC*+U)_hCEI%%ZZW4>Ap{L@_2@=C0*IY z0Xv<%gycb!F9&&SyVT@y#t_`&m@)D=lZf}pzMU=l7?kPaP|t{|6l^T9_2+Qkh~;$g z#44X0c2YXh_eo9{M_2jeh?CM%-zTjg(>~cl7Y^8xkR6yEOCr^YM(q?2iMF&`M`KqFCuJ4W~F}I9*8!$BY!P_#<-zlU&Hir~bhnSiO}4V_HQn^*k2q#dy~LET6a76TTet zcF_kBc%{yDmE1)eNBnWvLPmYw9tk3KZUT6Av^;NB6tncG4d&VKNj@?;4W3)&le42P zF`j2I_w)=VtsvIiuCbhoXUDY6U+OVE4{xUB@|dzkY$b0VW^0?m6>@eAd+uS^uxE=v z$=~N9-C%Z&OK@Ku9L!2v;;BC#j{P&O=^jKHHxh?a0+ll4?ob zRwwZ{$3mUQL!D3Q%JWlJ=aSRha#81TuQQhrpB^o9JJrd`GWrs75SlDg+l%2KfBI$S zAg2w9D_8#0qgn~RMYOd<_HY!)GHpFMQf3}1H5D(7*aCLUORoscI6hJ)9;=uEJs}nV z@tou;LVQ|Ro-cDHQ|^fIqtgKZg2(wKCrZ#1pIHTr(<8=^&IB-?41v-)Z9F?trVWSu z%*abf8#H;TXyZ?wlQ!a@KfW_Y|a1phIUYkd4v05R@WM>VBeImly5fR3{B8;KNmhZ7}lrG=Co=6hhumUA zTpMWXkcK9Yhd51JXkY@jaLG*O-ZH~TotZl1levGS$w{rIDwrbfb&Cq-B3e_cU|$3^ z7XdD))NMs;K(`G=w5C)Ctlwbx#I z?X}ik+o3UQjFHTFG*VuQJ^P*M;wAUV+`u<+R-?*1FKs%jbxmPUeZ_Gx^Q3{U84Wk~<66JO#F+YV$@in%p?yvKTicoL z}`%+ zTq01GHcoC$`%il1*6}Vb(I@(78mrz3nJO7KGyEpA`aJo(TanH5rz^5k8@^8FtRnNE z%<8m?bZg6;q5l&?pNtmW`$6XIL3Wlv!v(I+33ySl^2r>3sXUqg6CA2#?=d}J&x>g* zdP#6eLv2{(E%o~pb@->V1-pSt5%bMmLL6dq_`dzbX>HWUA*iv ztoZm8m8UA#DCdfRrQWj8H^4q(Q@>Eyv6*O;cpE-D)E{=#gT`(WZcJ-1#aorFC!Y4=lCmB<^ePB~v)YT{Y=qS`Zu4||}t>2FM=ooiOjZ4>G$JH?i z?OZ-5HWZZ1TAjw9Go&`?@aJq@L;c^Wq{qnWBws_XuVlHF=Qn}ky{TDCF7$koE;d(O zjxx_D`a~aHAY}cL1TigH)o-UI7r9H6RVqwIxw=?OTcV6o#=y1<*3eYGIlonDO@YYi zNL#O|CI40}nd?C-?UOTIr3qAM&4Je0E_CLF&Vr#sj{0OCbe!k>+=c>@#SEQ=JUWYp z&i^8GW*s^{%S90XwwIx^26C@JX1YMa4#V>+t z12tt(_XujT2TEhSn0zjb&-fB24fe+c+ujuRvl(pLVE>I^*L5lxs|}kiq>@^>Bk@Q5 zM!)qw_0f+BbZt}6Z5_}x1N~8fl3H|=QU~MT@yMK33m{omyXt~Nh6Ml=eFM`W@^@?(d0F1`P>$0o#{eLpeEEn z>ueV~^Fn7qg(NTHY94gFP}@*IvS@V~Itz-1O=aw2Rpa;7LT73VbdGhECQzX>1vc3FvbA>$ysv zu>_hKRu_$Y3l(+}p#sUnu~^w6-5DQBOLDdXptO^(Hzk@Cj>_{G#b%tk#9gv1?D(F` zB|iRL3m&d6WyRQ2Kqk;bh;PxzjlL88|XoSPW6Ivs%E}fQwEv{bg~!p&$~e<4fHmF zDsOtqt*Q1IB!8B1YujLN6|Bx}*$Dfm8SHvloc#*H>YSO4u;(+_HG} z33i<$3^wx42Qt|8lKA(>NI zyBd%&qcc0K80>clb~y)|jm_W9V3!T{+Xc&EWt+6^cQV)|gWV%o9p#YHp|iA0&SbEQ z2D@9Z3pv;f-}h&*3kLgbf}PL7X88Vg20L%CFB0rr2J3|Me+lDxFQDfP>|Y6NwioQT zGO$?#yFp+xyMhPz$OKjd^hTW3y(co%Fo6IGG!&1IyC9e zleW2K%1SYFbF!|O_DN4#Yr7Y%4S+Y{TMWxJJDY8hpQqFdjVjwyo(w8!yFJ-|>*`-outrU^om2#@96a(R0 z%CwZ(d?|BQ%BZ$wxWtpn`DlqJ(>!5xjuLRGrJv~Jd?d#tJBDt-I?c~bfS?)$-$W}i z2uHav#!aorB=a1XvnNdo00poWW%nqx=0M1WDOP+O8V2R(#uYH*$=(~pFk@uDUY*xA z5E%t>mc)s!9u%B7x=qacQNm|4)pU}(WJ)E-ys5KT{i@~Ih63!|RT!x|qG#F=xlV|z z6vQG?GWAxMe<`(UUM%D}TcE;ag|thT7-tzStK21PDkLG`DOn|Pi(5fm-cUfYZgutG zvR=>_-6>oaJT43A4C38V=emj#sBl>Tm-Ah?EDDz;!{r5BEp~8uY(oLb@@BX!8!p!h zml=;s>PkuJa-yp!feM!ya5>e5%dBvjGhDuftJw}NXEqd&%x{Lvyy0?)|rBn>*+IZR;u|thm@{LeJR<`c##(wVOa=V%$SmJWo1k5+fd?PWW zF{11n`e7?>8~^9N@WLkFEl16|DqHb1=-r2Uv1>Qxh}E?cHD&13GVeKz#NNUYMwL%0 z!c0D0MSfwLWu{I3k{y$les)Vo*t2t%uNn<|M(e8WvE2@lb9=RNS-<>Vt!+;RFr;2m zeu_v(MY)J|R0F#Htj`@{!Io+6kkIBDt@M>3D(XG9ZL4og0CU_UyAXZRmUas2Sy~eI z-WJu6>ginKvI&W!0mDDnu1+>HV=p0I?mgoQB&_rlah0y!a4?n-SH7gO5O?{KI*r}* z8zu;M|3Hr z0!YGyP>#JMcP}N|?i?l4RVnFv?Wo&nTY#i2WY~Q+m^*U3F=%5~+3$R28@5c6G*Wcx zWQXM1Cyh)w!g5KHG%_ONB1d){B8vc-nn-_nXrKt`$u^?R#o-vcSOaaDrW9t0u2y0&la_(E<{yhOZc7KNt8OND1=cZlvU_P^~WWvxcgXmdO4M?#)H z_TIyOBecKV*sjhQrcsWM#E>Lh(kA`D7;*;;NoQecEn5~Jayd12IL3^H7YCz;N_7-B z>Nf`gKee0TP*0<%6!8X@C7%{YSciv|7`DbiT@2yw4+b=CM`8lw1*IBbceKm(BL;qs zni@TWriwFSamIj-W3`rQ{-vc#X_s$ltpQxIRk9R9omS?6ze%kOpFt}%Vq=Y1JL%T9 z^W~wn^W_ZPd^>@QT#w?4>h99q7f+$F{SBi1-}oGI{Pxi%`546Hb;sluC^t9K9LZ#D z7i*Uo1mur`rCS^v01bw{)M95ojuT^TpC$wD9D7;xlhBrkkbtl3gGNdGZmBcKm^BCw zLrHRmFrv4mx813SXLsmjUs8RbMOqCL<#1I`C0(Vv8uO#FAGB?J)P+5W5#G{&m_!_E zLQPGuf_(!RzYb%2uYtN5#!UA%u{7$4DUvup(5m0*&QH+Cj7NP|LVECClS+vUA&gg) za}89>nyl$2d3Ts)o8Jds>}>MNDE!}Ab`|8cH7-O(<3y&C7*1O5bVyZ2AXR%bQKLb z7~pxdhYHeR`i!wqDey~?faEZaTL}`aFk0Zw=`jv>)AiMdLRN`Rtdcy+b%(N%9mcV= zm~^*hQ2Lz%MiJ}duO2``_PeHY?5P^9x=n1?=r!MC=_sa;)Z5YhjbT4W#cp?%=e^?Gs&7^H`mIUt$~J;kP$jJ(j-qb7WhQR7b*IRu0+erMw;(R8+hGa zxwc(h*_XtAq)}I{JJVXaif5=%WxhMN9BOJsO|5Y5#Iz0ci$i+IkY*FWW=I!ouz`@e z6;=hsbhPPfMw`BS^3fJqPpa)40_O6WZ}&Zk{;TG1`i@0Zo!J|XhWfWd`I?=C4zzBn z%5QHo?xN2Der;|^|4P8f6ID~Gh4aWlvEfT#d8}iQa_6`+1aA&@A=I$y?WFxX$LzSh zx~0C=x$Wu!&hODycaDaN0kOoiDN3P+=T#~-!pYrTmaE%+g%}rp$Zmd$=vF#&3ch8_ zI8su3KQlPlSB($>4_yXU*?(Jhwi6%JUqQF|8`Majaa9HH8dF!3?M~hLFSHWeC6T0L z)7XAjYcX-YZ|v5FCEv*Pt){wqi!D@X1g%2?MzgU`sq}@?F*abBMzQ|l4wn^mpK=+8 zG%3#yPdtaI7C0<6K22Vl{MkRgD~>PisK2=qmi^f!iu{4#wr`+Sksu1xNzh-y#@6s! zher?wG*Z^f|2CLV$D|IIlD`ke2kTKtma4GS7lu_BvXrzAkq4@je4EynrR0LrL(z%( zO2C+K0XvtBrX)w-c2qj2Xc;6E+-N9ducz~`r#8Gkk$-)B!|S>H>)8#j&*opB+3kEfQ5oN3NE);pWR0+XHOPA;lYgQ6H1N~zLjx=-J(QH>0z88HuQ8f}KOSJN zL2y+h$4r1wo-8<7qaRm^w1UPPK1uDhh@L!)5R6=uG=obtKXlq7L>-evit1{&uW;&2 z`~YpEL3xT%UrA&%4Xuk{_U3?lA%m#|cWRawR>h??6F`>xdTH#VZ#jjpRx+tLbPvKfoB0dm@rBi$b@JCr92x zI!rr2E3{c)K=bp?vG^CaW8Ra#Vh{FjTEuQZcXJGxim(&2a$hi*Zvq>ZjNteZt}wjs z2cG9Qa>wZ34VK#VYA5-rAO%^6{nh8EohN$RDbjScQxC4%&Oh#Lr@nZ`?PQ#qKM^}t zr~kxwuH%rO>PeBxb+f1ShlRrn6xi-*EkWyX=%z4B0lqO7QwOB9zD@EYr8Tl>Q=Wnc zIyi~bz@)!}np)jZx5cCo&ofo^KmlfisL4fPX@}%`EHw{^4}0M~6Fx5ZTCP=sXQs@U zP!FtgI%jDZA5*0#%uk=_VM2ZJG&%?9lqv|GXV5c0D+F%JwL!-jKI5K2YCJDJ^ATZL z&tWMu>Q#E?6N1n8jNrR^Mh~vqGoMotc1odV27U3&dWJdTd7;YZd#NI`+*PRZ*B zTeD^M-=DRKqLqTrQ*IYm)=E-C#`P#S?g+% zi~1(~SS*oE7|>l=GGPNXDAIkBt2f@$44LWz(>o!4c=+Z3Zh-Z1|E)N5LhUU zx9aM8(GssrwYg0_D+i7C#{HaM4IWkhic(W{g7KV*FP89Q(rWYxPTqZuF}^=|F6HG6GnJ zTn_3LQanRXn0$*{>J@MYCGGSk=B<#`VbC}8#t_G*4Gr!kO&F#e%1St9tTjlbc2H4W z(z-Q-t8z8CQVY<(lZR04zrpfpH8_OFHMrw&Yj~8ehxn9~K<|hlYMtYsq)R6{&`oQU zdNRXWX>+Wm%{t;BrXR`SJ(b=}i*VE>tY;&k$STD!DetjTNU&WN1-8N^SIUCgMxJd($G7u6r)Po1`KS85&8t+i7_|l!Q_$H`@uXEV zCOCc;Gc8dCPyMTUvKEagzdxLmoGP#smTbWbb93;40>7~4AMh)PRT`$>6Woi<-sgt@ zANku~cej7&Z%?_~v)s~YEn)`0Nfo7o7d@fI^+y*t9DKWkhE%s zUtx1x_tzbWj`4f&;RDe+XvmU(QNL_QUePbEqYL^);w6#@4{-f{e|?tgGyeJyxc(ikEdZ@upf<7{*aE{Np`gi5{>12zM?-w(8hc}%pLd&!8zh@ucGanUoVTcZwkDln&L zSL>IJ9SMPZMvYKU;zKT4UlG8UGR~P|o^d{01a}zcL;U6#<)i-AGs;K&t!I>Tx~1C* zC^Rlx^S`I`oNisQ?tyRUd0nzZUgcLDa>7ay4-vD;wV0PUS?Y${4n)iLrC9AibezXx zqPD%>8+;TC#_##-k8u6_{`$jQ|AD_g$Mso%{UNSDP((NmYfk1c(f9<~`(fSCY3LMn z#S$h{2Q`JoV{f1CRS>}`j2s!D14rvnVcl@0rbxrgH(s*puwAiFRNy{^@3qQb{mX$#J^jY zuLzHMLW5BX$cLc2OK8g&1W-?`uR$0p4KanIFw+|oC5sz=ZcucSbh{+a3pG+#{I!0# zdLT&0BQ7kCB@<%~62B_O6hd{|zyMMxL+_386szl=lObtI9*qgL|G^D?33I%yUeF$c z0MAKPetCgLhk+^n8hPiQGY(9PmhPjtTu0iIEEt}&3Obe`+Dxc17dxTGi_Pc5w6a0T zh-Q=w9mZEVbl8+TzaNFojDE)3Y7jsDYU_InZbOS>qRqw7(=Jx)AQ`wBqk#s&LP@Kj z2RjR~%;l-|NdXZBr8g&VR`(plR;jpSE|;4Sx{G%q^B^i(Fb&C5rBk-??2**Ik0%Q;6@9l#dLNMxlN=3X2{U=f%~kjmZZ? zJY+C+RsLY+Ch~VWpCgi+3jIVUa1lm8nfr1B2%qAKEGCxix_37(P1M@d9pM<@!f?5+ zisKmgG8p1g<Vy`MqKYIb0wuR&cTe<<4xG6tCPRG0e* z2C#6_{#Kt&Q9jk;HMij9H#buYEVUS<;4;xwX8_OmE3%XHdyh929QG=>*n==&XFEvIISqe)| z0}diQQ5sRuM^=#nSF9u~nn1x)=FYm$`Qj`nfrtbfExQPFl%}Bw1O#H(G?7rU`<4b7 zD&u`k3bnzdzKF~hIg3x(hgLAsT~9Xs&?b)9;y;=N|BJ)Ib-sp=AM<+VI=yV8U*!i_ zf~Z1J>cJvsJE^@rZ7-OV=o=rL35&%-^mP6eJ#ZoSSuuUsDX7@_7w|8#JN|awy9?bH zD*Wqu&Ig4;nSaG%5QK_}A*QyBjw+XF8DZu*T4CobQy_ivP@GEzA*DzPy2A*TE5#TYf~QZe9<Hq6?6` z$v+0hi%5QK7DWV*YP2YZAo&XAr!Po2MmQgDEQ;Zb7xe_BIL4O1?3S-8!^u~tHLG76 zg&z58Y)^Q|79fN%xF8KVCJ=Galgp@0<&($y_-hOO50@VbAH_L=AUWfQqQRE6<1hx9q6Xj%?=gf*rARjoa?($FgqEX%(T*Q3A0b{tAC0h3smc!QY!SHoB?>`bWhEMABs-4#-ACkb-cpp%D zDYuwHmg(#@mPqWR;*thQiJ!!g4W^T<4uAUBSyS!GOzH~qDQiu2{vJLcW@eFJt*OrG z9znOD`}RDIlt^9p>tHOtKp+hpJ?4d0WAdc;cltcfW+~R5&)w0DlC61sx=}ePRBn8( zP#M`86^BD>`+>rwZNqSQaXOH-5u_IGG5V-+$yeV$-R)aJRnjDHsS1tR~A&29)6Ar~WLt(3M`@l5-+n8jJC!Dv8pjU}#;+6OvgMvFA zSbwauw3J z#(m;}NG!02!+v2_Kk}@P<6nRj`;FBWR7;ILgm|&|FqA03HlsuvoE%I-H=wOQIo0=oiYs$9& zk|0*Rh_B9xUMHNl_^W}iVj_6RMfmhr1_p=XZIxk(W5lyI+QS82MmjdDSk#tD5Yv8$ zFMZc`VrI6hHGm#7UIBKBi&R{T8+*jHgf(bORDbB*WJ>(jOg;{Xo5A44Cc{Qz)6Xz&AUVmY>BWyR`}B)F2w#0}aTsqY#PT8x zI&K3WG8u)q4L8LLqA|cX$Ls5wXmXJ`hL`3z30Vo-XCh>K@WV6qjPaZP4e)zm*3r)g zeuTa~WBlfY-*wL~euK{fzfTCi7d^lD4b+ng`c}6_B@6pCpTeFZ3J5OiwB&i)dL}m1@eS$&zCmi#4_MszVmr zv1FRpi*PPdk4m%fMGQ>2pbbO{KB-z)cS?phifi)BDDLQwbkY2plH5pU^bz6n6z5}! zOe47D_%Ep`-Skdp_8xkB(rj8_Mw-(qZ?KEvPfi+4N;%S~udhlQ!VjOZxHv2PwrBV~ zAL2~Q>1R3}ED68oS={25{ig8Nn%Z)0Mr+3Mv*N9vK23Su;Zn~zZ%MML@9=7Amzk^` zZlP$x?l~QLKda_k^W2f=z25}#NNs(lto=UW_dL(kEHE?HZedSS?@3*@8L=ZmozRqa ztA*RMp0qxsmi10E&v?>0uhP1Q%@$MOQ=6^6pz@xsNPb$gm96Tvlvko3D4py*#Qu~Q z-rpSPA0qHiW~4?1^B+IPKTK7x)yguz5d0hq&JVigzsu%LYHfb@=P zV_>YcO-O%EwetZhvfJ5#q^+_oz_c4_o8ut1o|w+mr@ia?P@nl{+KE#?7-;!vdyZ`{ zDdb3A^cvgP0$VElLcFG5TkOY1C{8fZj4p*{Paz-~0Zp4MkcWWXFj#2W*gzrUB*O6M zvw*VIbQ5n;W`DNk(jL(t;=dRhoeS9OqhaJ~z|Kp{29n@atqS%8&>UdX=e}_~_AH(o zwbzbPh2cI9$*7psstmynu~wg!)O4ACq+V&Q2c>zdp5X^&B0f(4D8LSV_m{a;GxT>Z zyt~my(^_;C84T6R*7mz`*pK|+sI69AuZiA%`EOlCkB+kgx~GOZTgwMeKj?c}KY}~W znp&u)l&v^QvnN)p*iB*D4lU@by3x3%J2uQVX<~Dj|H%U(^1!g6ajv8GCbkQ)?2_B& zG%UlkvkY97aoP0bW|(ev_1wIpG5lb?IkE}wnoxt%o_E>#v^nqg8OGxLlz(f7xc2-T z|0i}qD-P82uDfTK9egY1rEacJU%ENC;W$_ecjI6@F5+fPS6gzi$bnty*>mml%(1^B zj$MFb8(kc`kaDbYek?kU9l0CMd-@#vD;QZwd9XRh_E7R_TwBix2JLPY3p=Lejpty7 za{YEhZ2ukiNw2LTCM%7RgP#oEbnx+q7;p!JAHt-|`cMDDAIV++;OKq#k>X_J;Qk*b znG5~|gzomnaQwBA#>h$YS1t#cbh@j_*gY8hsPX_Q!X3zDZHhIO_QSO*;|%a*-R^Z6 zzio&3dw-K3;)8i2uM@F;(L+SU^e2DwiFd^8ubpwcnN*VkSr1se^e2V!o*eMAMHK6vY+*cy?|BL}}4FamM9dui!0tl&-jSa)KV+&W#Z>lu=OPmKgZc6HT%@c;h>T6!5O-{w~0y zyNL@qSa=f^JoLlX%M@`0*jrU-I61+$0EC(qsc8}=xA~R zO!<2I!NQS=gM}X&Na?!}G_C>h@WIybU8f%;Xjqs!(znC6Ox)F~j5e>q=t|<8Q7ALg zxKpkna6LlZDdr92EevK{ldS!Rqp{5muvYvz%@u7RNMe;f-vKZ@?B31r zjvHF$9;m1v0_Wg|4vX8SL$2=A)ug{tD79uD3f@zgG6kX?K1d52BX{4|V(4iJDy?Ks zVJ2)*?ABvN-Xw+`nuRk!IiqK5*Y3f?Mww76TGv&YobQ%_RF)$!BvuvaH7v6Q{KWoVhE6Nlddz@qaL;TGnI@0d2gLZBXZ{Mnwjyd+~Ua4|F32= zHfm(>cvyB??ab|K3_6AA4lwB>TwOXupK5Dj&2SU7v=~EBX_7#qf*%$ee*dd!_j^7a zy!t*Ws8G%x=rVlpBS+u$+ZPvq{yiTF9;AEcRu&#P^61g&{cmawPaJGN^5%)jshNfL z!$;^U5e}TOvZ~3h(JI;++~`YH8HJZXP$Q#^+flGObR8SV zI(F_Jr-_;hXuY0Nf;?tuSd!qW4oAa{Axw7**+Q?Z93r8nQvAUcxK2t2l*Bh!wbIq& zxJG7auomh`H;rq zs)KKTs^v}MbL641suB?X;*Y*^AiN$=U&scKYI5#Hud?+)pVV&dgVzj%$t{e6YBFpK zf@J2GkzfpI<9DmD62BXPt{gK?rB$(yv>*Bb649t;n&<=rg%wRg(269|gu6HRc>zag zdZ>)52O8i~qq0{sMOSl`NgD_akCNZ|&qu~QsPcyDBkhM@W%LnJ$t}s7+k_FoQ4sr< z*N)=QG%TwwlbF;$CdyZtA^MKF~9%)JqIw(G|orzlkMv|u6)0r+{l9KFf&?erx z??M%9u}=C7(pt$sFi^anD_C0+bf?N;(&F2=PKSKs3F1qb*3$`RA-H=KZl?>vP&sf?#tWkOZFiFQQv@GAKB^X--GlZlk7DfdC>$= z$n?Xs*ELAGkgZ>K01qUJ1OIN-WXzif`4b-5K!FJ;U{z>7LSU*ZP+{~#idiy#@xGg4 z3hJQl_#a568Gli06~RC!#*Hf={`!a;i#xx^sa1c=U^IP7Lr_abGkX(H##fUC+MzfN z7i6QAy?6Q}_6SN!BX?x7rY`Pfxfd5(bfk+}M&b$3#R~FHL6Kc=(kw1^O0;{UIh?92 zQkkl>H(lcaTY0OGK%^N)ym!fUD7%O!as3{nl#qjGZ5 zQ$R5+E_TJ@nuxJO>981|o>(GJqcrG|P3a1H)T&%5U$_x75x`*~j#MySy_QKlpc$;>Q>2DFoH^>Q4^R(*kHu(%gCVY z?&X=(J$-8;PX1b&U6ldBA{jIVtPzwh8H9B3rU|qiiHf8RHxRKD{~N_fvBN0^{vHc2G@}F`k%-wlr;OcDGCGC?&HS<} ztVCn+pTfIpw92)xBwws77sAGuO4x%65CeO=-uo4i;bd6eSmMe;fIaa<<#1!*J`j}6 z)Z$9es^S+kq(f0jJHj&Q7`$a}b{R{yU~f&1WKCdCl`zP0w_fbleny9yqQ6@8`0t3l z00VMxh|3@TM3Nol!QScByb&S6vLyT z!dUY#l{E^ZBw4ek^zEP^84$IEXwuO}pC(&Rg!o-L(wo>IC&CH0(UZVrSWJMCm&5+C z8=e?rAlPbHhp!}lZ0KTW@(iu)`)mV)s+gLLpKS)x-p4R`Bt%iLEsro6TOJFb=LL*G zE%-vHVBSa9TR{sdNI1`6up(6P-G#8~W45)0myYU$4WsS)$g4CYj}TR*u~YbClh9qL zL1X~EyC-6$xf85hKwORCO59+D$iYt)BZQm!Qo%>sl#8H4YJnYBBZSc)l^!DF8WWpo zY6FKxiR!HaVw*N-m12Zx0V#z_j5p$iHOdNzWK}>HvhSLZKv%pKr6_G8i}|V2cT|Dq zl29&To&*?&D=}Mh5AZS z>q~WXO+x8^X^=C?K+TCB77E2;35=CLO`XqnPV5Vo*-5(?8Tb5XcXCp?gB#@?m#Uzh z1GcqD7{L#0h;Cqm7T>td1SBb&WYwyT4^c{*V!zaE7oLqA(X?2M-!=k$7zNt+(9fjS zg-H2nAObmRvLOp0i`$f zNF!W)G|@T9YZF^c9Sfl-Zx*X!_tP>F z@XO-fhkj0nts&DWd@*jGx9v5M3`SH;1oQljHcPn(C&Q^5oiDu)bQ}ns0=b z&=FdO4(rUV(TTT42ae=uR+Z!sIgUhkW5Vo?Gz>cj^26p}x)xY$RT(T%Rh!Ydv;2K~Zh;e@NG7Wo(n9Qq0OYGG7%tB1HR&e2^1&nhFFU{Ty=LYwZ2o2rr zg7uguy249&((}48WJ>DLkp>h>!%LxP7lnxpFbYE_;ppfD2|&k1m}0&4{ZD|Y$qUY3 z)aa5VvE7i;BxR=DdSJbzRkDF)TS*1JJK7HqYt-7_W0&Wg+y-ItafQ356Ur_50cq8s z^@s9ubMi}WK;EVSiJ(gNH?Y`nyBZ`=%gK3G8d0))9R1*PjGVo}T_jc1;@_8= zFjSj^Zqih{F_OgpV!NSUmmh{MG~(_ilp=wiz^d^T1G_hms=$Qfk1H3f@!;!`97;+j zU3Dye-*!pB67~Xyr(|M|5-NHUnup29uni#%+@`FfxXgt$l-IXXDU(ZvK`Jlq&m*e$ z;^#LUi2i-2YL;2?uUpkZ(9C~f@+X~IOt!Vztn9S}84x|OCzVAa6@OC(0%dK^U|y6e z`7P9fQ5$TAN6C$dYAhpumbMKfRJ~-A{@WtAL4hqpRVIBcki z$V2uw{6OyyHQiR7K-P}fvUYk_l`|wlvqkLev|~pE``b)MQF7g@laL(D$s>=nz7$rZ|IDRRshg>y#Lhfp9w(2%RWu@&QRK;V zo8^Ai&$gUkVS~<=U{b~;n$fZwD$P`-X$d;+wB$pU<(GUK5P}mL_A=9o^D8?QtK`!r zI#_(oKxMu{KXzL;-lp$r*t zucL-eGaXKw=2$_v47~MG#FOZ&&D(wP ze}a^1L6oBo(XWz752Hp(9;D;Flr3`Ylg$W<7UaZ$W2~*Iu7a5rVey|UyM1G8WLea{ zOk)%#v(DZdv_tK_u~{%x^_#VvC~)b-zh``~7=&R!&GrF9zXJ_xA$@Ep*iy`N`M0uX zCKM4^FJupdn8_P|oUs240y9QQ1Vh)eHOR>bV;=^!Q>oEE{{XyeMqo@zmcq!*lZb-1&+{?Q2 zyX8QzF{3%KrDdigugT{yd5fGYC2a$=c`v7~K?2O=+C6M?n_b4c+=Cn4&u)H9`IFIH zLe5XjFX`!)6wRoErj~G>k;_aWr4VZt?ZyPxgEjkE)IokZ&Zx1qsjVVe#A!q_@Ri%N zO7>J5Cta(GH(Wb&Y0>xfAXBw;M^bL6mHIl9GHF|2%c@2ZJ@ml>>6w|8SLh+OIsyq_ z=m2zw2WYs>l2pjHRqKUPr+G4Y(jRFH$(ClmX7gjr4EYjG{W4W_+J313EU#UHFH2{KMOk5Dxz^ z#UGV8>r@SW29-olQDg0uR3}-+s$O;%b(lJn3h(wv6EZ=g9#?Zg{I2+8_V&k>7ou8W|(S_EwXV8Bn*y(V9s16c%n>)0%?gbO{pFrb_*P8WH(vSGBZD<+k zZDof#z59j#`#7zW4hZs* zruv2!$4p@ejIb6ciCH;*5zCxP!g2q;DH0M@;x9?-E$s{U_ej=K@)EU& z1%RonD*DFwm&ow5FT5px%prVQ+8f-&oTE(5oi7;QeDMdXn z(oXrn-WGoi%=U$^F-XnaTI0|T&7p-la%ZM7-U^_9aIoDV5m|$mfoaWC?sBSu27SB% zorC0fV=VdQb@s1b6F=NhBjM`lMl+OjnljH}kW2#i@lUnmJwYI6evq6?ZysqRKWD&H z!2}V%2uWz3kypMfx(oa@8Y^+Tf-BUih>ouGY7wHUC9m7iW-XFCZI+9*qD~T}?v6i2 z@%zHp=a;Rb)861-ks(by0VvDpK&DD#!#D5)8~!9Xpl&roEtbllNq8ix}T!wGjM z8346{INsZdv&slyDkJ)rA{znBddp9KFkA6ga(nNV$U`?&0MB?av=Tf0Wkqw?O zo#%dSac;tg$>7bwz0_AfKsFVvab1Qq0qzn}$_H|vM-KZMkxC4asaGvjI) z7URo?&vC3ts*`1Us~{HzVg;)|Oy&xZE}bht%AtDXzf*WRF7<8aJJE!-EnWGgViZ1H zP|j4X^VF4eCU(B!Ltca>DM8u@!Lo=!yKI)rZB6mpuxqmG)j`wS|*)F5Puk^ zZIoShab`v-Tk$&zunB_XC9MME7jdz_NgFXC7Z6&2Ahud?zxs=x*YgAu92)>0WV$R# zPiPh5M^r9vy;Nbx7H_2}D+NaS63Jt0uX_Ao!e064Hr2bQKv<%)v;K&x7j|UW*CLR= zm^7;=W8|HryrH)z`aYYSsO)tHEzt_(=2(8_4;bs$rosgs0!T29Kj+-}ENlI@8S0ny z$x!x*D7?idX@lN!mQU*0C(!V9>KT-(rgPMsgjHUWM4DtJ8_;C7nTyGBq9$lt4bx}p zO=$+{y^b}I<1ukNMQHZ^MtD#rirN7gXwu6D?1mgs7Gef7PQ24iY?y`9SgsqDiIO=m z*REl}L1Ql!9|>K;EAo&yB_-r+3FFgGvg8!ai>I=A$WIKEJ0uOc&_$!fXr z@c*07ks`R2>#}e-u|tVMxL)6#a^K0e#dzOXkld1@GqSvcNm60u-2+SrCPk*szeZU9 z@XMo`8`oCU{BiPFlvmW3J`#9uQD8!3FW_%AvOJ1f?d0-OKJC=b`t6t>Hj!!jw2 zN@yRp=zcvv$n$&YDJFdDGi^zi6saLXu#!Mh$9I5;)&B}_wUkq{9ePF#OsTU-BiU^N zAmCIBNlGDPFaJqiaqccJoDH5Xe+L#{GXrX(V7hpDxXU0=M44q9wbLq%$T+ZBM_?nS z%gHe_oy#fh%xW69>tFbpIEUIP!evuTkZZG5tGufL*@_KTsI8!`YnQS91LC~P=7uAd?kr&HQCB8yI*g8sKX0y)HnJb!n8+l} zA`i=B%T=)@CgM8KJj0185(+!H!^Pmeuk5f@_aUD(e`90PyNRe@yU2|z#0&AeT(7|% zZltT%+&=S3u?%uZokrnP5&^N>YoVOPs0Z{Jx(2!m{eC%W<@%ixpzuqHx-kt(dXSBJ zH{cz{o1iKd6{@~9hVgnNF6uNB>rkg*uEonrU|oP$`3~kyR?_=G{g(SsgO26mV;8&&!MI| z);nIxvz|-hFkSL9GSa6^nlwI`0`DBlA1misUZRY(AI}s?rWvh>yplHF#kve)=$~Tk znKfl(-#+7R7dBSz;lR$fHgyNdRah5}=@1UdLC1?!lEqKXx(dm#ewCa(4i_XdWf!(} zTzwax;E|a4oPKHcOu1EO1;}-BUPNNHSI3{@y5F<&DqWn3bybke^BV6iB`agGlZOl3 zsgo}9tLQ6}9?6_RKE|^lAanBYJWAkf8NMX=8Ifo_eb&y0Qglj3DDs>`%Dgf_j)_Br zdR=qK?Jcsy;PKkGw&ARnR9_|h-nF3E=tu2in3lVyy8f}waJTtny`DXAQ(g8zLVH!p zl+9$&6lyI%EvA�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