diff --git a/CMakeLists.txt b/CMakeLists.txt index b5f9c023778e037e00615d53fff3c703c928c0b0..0108f448dfb4c090ba347ebeee3ca6bfe81de839 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,22 +480,23 @@ 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/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" + "${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" @@ -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" @@ -516,12 +516,12 @@ 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" "${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" @@ -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 08fff00b2d0672f83b57804f99a3913d2c7549f5..c6236b3d27722a232afdc57988427b1939b40ce3 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); diff --git a/build.zig b/build.zig index 11b3006039b748f3a304e3869bcc87abdfcecb89..d24b51741acadd351a6aa8966d8e1b2c6529ad49 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.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; @@ -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.result.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.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" }; @@ -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.result.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/ci/x86_64-windows-debug.ps1 b/ci/x86_64-windows-debug.ps1 index c1ae92494e9868813dff21760188d1fcb8569756..bb6ff3ebee746147b03407a895a3f6044d5f678f 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 988402606b5c869b9b6e94336566039770d78d00..7467e3deaa0882d58d5779a69658e97091029129 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" diff --git a/deps/aro/aro/Driver.zig b/deps/aro/aro/Driver.zig index 18a24b86a7ed0343aab92cf3c9b3e868987b2cfc..1738b14093cb12d9e89eb2c85f84149264239c46 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/deps/aro/build/GenerateDef.zig b/deps/aro/build/GenerateDef.zig index 129d65ebdf2a63557dc08c4432e4a81e667c8640..5c0f8d4b18bd8aac59810da0e33ac6ede110eca1 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 a5e537c43c4c55f3248f64e295e021dafb8fe0a5..979cc93f1140486409b19ebb355f854fdea02c15 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -46,7 +46,10 @@ pub fn main() !void { return error.InvalidArgs; }; - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const host: std.Build.ResolvedTarget = .{ + .query = .{}, + .result = try std.zig.system.resolveTargetQuery(.{}), + }; const build_root_directory: std.Build.Cache.Directory = .{ .path = build_root, @@ -96,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(); @@ -239,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")) { @@ -322,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, @@ -354,11 +361,12 @@ 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, ttyconf: std.io.tty.Config, - stderr: std.fs.File, + stderr: File, }; fn runStepNames( @@ -558,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)); @@ -579,7 +587,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); @@ -593,11 +601,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), @@ -610,10 +752,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 => "+- ", @@ -626,119 +765,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; @@ -888,26 +915,15 @@ 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(); - 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: { @@ -962,6 +978,54 @@ 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); + + // 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: "); + 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) { @@ -1027,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 @@ -1111,7 +1176,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, diff --git a/lib/std/Build.zig b/lib/std/Build.zig index ad6eff9d586ca069bdc9fd80919dbe9c4de381d0..5795bb149fc4df1d2b5f2a16f738c3bdcc9ec272 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -10,55 +10,17 @@ 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 CrossTarget = std.zig.CrossTarget; -const NativeTargetInfo = std.zig.system.NativeTargetInfo; 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"); -/// 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, @@ -96,7 +58,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 = &.{}, @@ -124,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 = "", @@ -250,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 { @@ -414,7 +375,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption const v = @field(args, field.name); const T = @TypeOf(v); switch (T) { - CrossTarget => { + Target.Query => { user_input_options.put(field.name, .{ .name = field.name, .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, @@ -422,12 +383,19 @@ 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"); + }, + ResolvedTarget => { + user_input_options.put(field.name, .{ + .name = field.name, + .value = .{ .scalar = v.query.zigTriple(allocator) catch @panic("OOM") }, + .used = false, + }) catch @panic("OOM"); + user_input_options.put("cpu", .{ + .name = "cpu", + .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") }, .used = false, }) catch @panic("OOM"); }, @@ -633,45 +601,57 @@ 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, + error_tracing: ?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 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, + .pic = options.pic, + .strip = options.strip, + .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, - .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, }); } @@ -679,77 +659,99 @@ 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, + error_tracing: ?bool = null, 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, + .pic = options.pic, + .strip = options.strip, + .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, - .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, }); } 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, + error_tracing: ?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 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, + .pic = options.pic, + .strip = options.strip, + .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, .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, }); } @@ -757,44 +759,55 @@ 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, + error_tracing: ?bool = null, 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, + .pic = options.pic, + .strip = options.strip, + .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, .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, }); } 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, @@ -802,38 +815,49 @@ 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, + error_tracing: ?bool = null, 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 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, + .error_tracing = options.error_tracing, + }, .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, }); } 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, @@ -843,9 +867,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, }); @@ -856,41 +881,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 @@ -918,10 +919,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; } @@ -1143,7 +1140,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) }); @@ -1208,19 +1205,25 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio } pub const StandardTargetOptionsArgs = struct { - whitelist: ?[]const CrossTarget = null, - - default_target: CrossTarget = CrossTarget{}, + whitelist: ?[]const Target.Query = null, + default_target: Target.Query = .{}, }; +/// 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 { - 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; @@ -1228,8 +1231,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: Target.Query.ParseOptions.Diagnostics = .{}; + const selected_target = Target.Query.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, @@ -1242,7 +1245,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros for (diags.arch.?.allCpuModels()) |cpu| { log.err(" {s}", .{cpu.name}); } - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, error.UnknownCpuFeature => { @@ -1257,7 +1260,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros for (diags.arch.?.allFeaturesList()) |feature| { log.err(" {s}: {s}", .{ feature.name, feature.description }); } - self.markInvalidUserInput(); + b.markInvalidUserInput(); return args.default_target; }, error.UnknownOperatingSystem => { @@ -1266,83 +1269,38 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros \\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(); + 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"); + const whitelist = args.whitelist orelse return selected_target; - 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 = CrossTarget{}; - 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(std.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(std.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; + // 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 { @@ -1422,7 +1380,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, @@ -1490,7 +1448,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); } @@ -1536,7 +1494,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); } @@ -1593,7 +1551,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(Target.Query, .{}).exeFileExt(); for (self.search_prefixes.items) |search_prefix| { for (names) |name| { if (fs.path.isAbsolute(name)) { @@ -1895,15 +1853,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 { @@ -2048,34 +1997,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 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, @@ -2107,34 +2028,6 @@ pub const InstalledFile = struct { } }; -pub fn serializeCpu(allocator: Allocator, cpu: std.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(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); - 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 @@ -2165,6 +2058,33 @@ 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: Target.Query, + result: Target, +}; + +/// 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: 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; + + return .{ + .query = query, + .result = std.zig.system.resolveTargetQuery(query) catch + @panic("unable to resolve target query"), + }; +} + +pub fn wantSharedLibSymLinks(target: 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 283a3d1f5f7235be7015051773e17d745b40dac1..18c1ffa07a2aa3434bbb011ae98c3db456a12113 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()), }, @@ -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 new file mode 100644 index 0000000000000000000000000000000000000000..ce17d655a028fd7e2844aef3612ea78f23f17b2a --- /dev/null +++ b/lib/std/Build/Module.zig @@ -0,0 +1,753 @@ +/// 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(*Step.Compile, void), +root_source_file: ?LazyPath, +/// The modules that are mapped into this module's import table. +/// Use `addImport` rather than modifying this field directly in order to +/// maintain step dependency edges. +import_table: std.StringArrayHashMapUnmanaged(*Module), + +resolved_target: ?std.Build.ResolvedTarget = null, +optimize: ?std.builtin.OptimizeMode = null, +dwarf_format: ?std.dwarf.Format, + +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.ArrayListUnmanaged(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, +valgrind: ?bool, +pic: ?bool, +red_zone: ?bool, +omit_frame_pointer: ?bool, +error_tracing: ?bool, +link_libc: ?bool, +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: *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: *Step.Compile, + config_header_step: *Step.ConfigHeader, +}; + +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 { + /// 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, + + /// 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, + + /// `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, + 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, + /// 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 difficult to obtain stack traces. Has target-dependent effects. + omit_frame_pointer: ?bool = null, + error_tracing: ?bool = null, +}; + +pub const Import = struct { + name: []const u8, + module: *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 = .{}, + .resolved_target = options.target, + .optimize = options.optimize, + .link_libc = options.link_libc, + .link_libcpp = options.link_libcpp, + .dwarf_format = options.dwarf_format, + .c_macros = .{}, + .include_dirs = .{}, + .lib_paths = .{}, + .rpaths = .{}, + .frameworks = .{}, + .c_std = options.c_std, + .link_objects = .{}, + .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, + .error_tracing = options.error_tracing, + .export_symbol_names = &.{}, + }; + + m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM"); + for (options.imports) |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, false); + 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); + 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.allocator, b.dupe(name), module) catch @panic("OOM"); + + var it = module.iterateDependencies(null, false); + 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| 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), + + .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: *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: *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: CreateOptions) void { + const module = create(m.owner, options); + return addImport(m, name, module); +} + +pub fn addOptions(m: *Module, module_name: []const u8, options: *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), + chase_dyn_libs: bool, + + pub const Key = struct { + /// The compilation that contains the `Module`. Note that a `Module` might be + /// used by more than one compilation. + 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: ?*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| { + if (!it.chase_dyn_libs and compile.isDynamicLibrary()) continue; + + 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: ?*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(.{ + .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; + + const target = m.requireKnownTarget(); + if (target.is_libc_lib_name(name)) { + m.link_libc = true; + return; + } + if (target.is_libcpp_lib_name(name)) { + m.link_libcpp = true; + return; + } + + m.link_objects.append(b.allocator, .{ + .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 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. + 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 b = m.owner; + const allocator = b.allocator; + const c_source_files = allocator.create(CSourceFiles) catch @panic("OOM"); + c_source_files.* = .{ + .dependency = options.dependency, + .files = b.dupeStrings(options.files), + .flags = b.dupeStrings(options.flags), + }; + m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM"); +} + +pub fn addCSourceFile(m: *Module, source: CSourceFile) void { + 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); +} + +/// 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 { + 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 (target.ofmt != .coff) return; + + 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 { + 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, 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: ?*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.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"); + 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); + 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.resolved_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 target.query.serializeCpuAlloc(b.allocator), + }); + + if (target.query.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 }); + }, + } + } + + 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| { + 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| 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( + 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); +} + +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.resolved_target orelse + @panic("this API requires the Module to be created with a known 'target' field"); + return resolved_target.result; +} + +const Module = @This(); +const std = @import("std"); +const assert = std.debug.assert; +const LazyPath = std.Build.LazyPath; +const Step = std.Build.Step; diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index 3be9cdc83cdb03c9c1913ce29769c4c137fdad17..c5eb1f776bbd5d8bfc68f51a7ad735a2a2939935 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 c90f0cb1033e9c0d126f03c5f368f3b5d11f48e3..d6a016f183b71c0bee6034dd6bcbd406561c9c9c 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -9,14 +9,11 @@ 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; 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(); @@ -24,36 +21,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,32 +50,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 /// Behavior of automatic detection of include directories when compiling .rc files. @@ -111,14 +80,13 @@ 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. /// 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. @@ -177,15 +145,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,91 +188,17 @@ 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) { +pub const Entry = union(enum) { /// Let the compiler decide whether to make an entry point and what to name /// it. default, @@ -322,118 +210,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) { - 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 { @@ -447,7 +241,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}); } @@ -458,6 +251,9 @@ pub fn create(owner: *std.Build, options: Options) *Compile { else owner.fmt("{s} ", .{name}); + const resolved_target = options.root_module.target.?; + const target = resolved_target.result; + const step_name = owner.fmt("{s} {s}{s} {s}", .{ switch (options.kind) { .exe => "zig build-exe", @@ -466,15 +262,13 @@ 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 orelse .Debug), + resolved_target.query.zigTriple(owner.allocator) catch @panic("OOM"), }); - const target_info = NativeTargetInfo.detect(options.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, @@ -489,17 +283,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 = undefined, .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 +301,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,28 +321,20 @@ 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, }; + 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); } - 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.ofmt == .coff) { if (options.win32_manifest) |lp| { self.win32_manifest = lp.dupe(self.step.owner); lp.addStepDependencies(&self.step); @@ -575,14 +345,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 }); @@ -590,9 +360,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; @@ -600,8 +370,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile { } } - if (root_src) |rs| rs.addStepDependencies(&self.step); - return self; } @@ -701,7 +469,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` @@ -718,113 +486,75 @@ 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: Compile, name: []const u8) bool { - if (isLibCLibrary(name)) { - return self.is_linking_libc; - } - if (isLibCppLibrary(name)) { - return self.is_linking_libcpp; - } - for (self.link_objects.items) |link_object| { - switch (link_object) { - .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true, - else => continue, +/// 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, true); + 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 (self.rootModuleTarget().is_libc_lib_name(name)) { + return is_linking_libc; + } + + 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: *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; } 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.target.isWindows(); + return self.isDynamicLibrary() and self.rootModuleTarget().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. -/// `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 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 }); +/// 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 @@ -924,98 +654,45 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 { } pub fn linkSystemLibrary(self: *Compile, name: []const u8) void { - self.linkSystemLibrary2(name, .{}); + return self.root_module.linkSystemLibrary(name, .{}); } -/// deprecated: use linkSystemLibrary2 -pub fn linkSystemLibraryNeeded(self: *Compile, name: []const u8) void { - return linkSystemLibrary2(self, name, .{ .needed = true }); -} - -/// 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; - } + return self.root_module.linkSystemLibrary(name, options); +} + +pub fn linkFramework(c: *Compile, name: []const u8) void { + c.root_module.linkFramework(name, .{}); +} - 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"); +/// Deprecated. Use `c.root_module.linkFramework`. +pub fn linkFrameworkNeeded(c: *Compile, name: []const u8) void { + c.root_module.linkFramework(name, .{ .needed = true }); } -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 = &.{}, -}; +/// 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: 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 { @@ -1042,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 { @@ -1070,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 { @@ -1080,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. @@ -1112,138 +774,51 @@ 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 { - 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(IncludeDir{ .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(IncludeDir{ .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(IncludeDir{ .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(IncludeDir{ .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(IncludeDir{ .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 { - 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(IncludeDir{ .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 addFrameworkPath(self: *Compile, directory_path: LazyPath) void { + self.root_module.addFrameworkPath(directory_path); } pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { @@ -1256,129 +831,42 @@ 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), -) error{OutOfMemory}!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); - 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| { - // 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"); - } - 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; +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", {}); } - - 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"); + while (it.next()) |item| { + var name = item.name; + var n: usize = 0; + 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 to_name.append(.{ - .name = kv.key_ptr.*, - .mod = kv.value_ptr.*, - }); - } - } - - // 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 })); } + return self; } - - // Lastly, output the root dependencies - const deps_str = try constructDepString(b.allocator, mod_names, cs.modules); - 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.AutoHashMap(*Module, []const u8), - deps: std.StringArrayHashMap(*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); @@ -1406,13 +894,10 @@ 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); - 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); + var zig_args = ArrayList([]const u8).init(arena); defer zig_args.deinit(); try zig_args.append(b.zig_exe); @@ -1426,14 +911,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.target.ofmt) |ofmt| { - try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); + if (self.root_module.resolved_target.?.query.ofmt) |ofmt| { + try zig_args.append(try std.fmt.allocPrint(arena, "-ofmt={s}", .{@tagName(ofmt)})); } switch (self.entry) { @@ -1441,7 +926,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})); }, } @@ -1455,194 +940,311 @@ 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})); } - if (self.root_src) |root_src| try zig_args.append(root_src.getPath(b)); - - // 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 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 seen_system_libs: std.StringHashMapUnmanaged(void) = .{}; + var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .{}; - // 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); - } - } - }, - }, - - .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; + 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 = @intFromBool(self.root_module.root_source_file != null); + + { + // 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; + } + } + + 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. + var it = self.root_module.iterateDependencies(self, false); + + while (it.next()) |key| { + const module = key.module; + const compile = key.compile.?; + + // 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 (!already_linked) { + for (module.frameworks.keys(), module.frameworks.values()) |name, info| { + try frameworks.put(arena, 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. + for (module.link_objects.items) |link_object| { + switch (link_object) { + .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(arena, system_lib.name, {})) != null) + continue; + + if (already_linked) + 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| { + switch (other.kind) { + .exe => return step.fail("cannot link with an executable build artifact", .{}), + .@"test" => return step.fail("cannot link with a test", .{}), + .obj => { + 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: { + 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; + } - else => |e| return e, + // 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) + { + if (fs.path.dirname(full_path_lib)) |dirname| { + try zig_args.append("-rpath"); + try zig_args.append(dirname); + } + } + }, } }, - } - }, + .assembly_file => |asm_file| l: { + if (!my_responsibility) break :l; - .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_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)); - }, - - .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 (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| l: { + if (!my_responsibility) break :l; + + 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)); + total_linker_objects += 1; + }, + + .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"); + 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)); + } + } + total_linker_objects += c_source_files.files.len; + }, + + .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"); + 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)); + total_linker_objects += 1; + }, } - 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)); + } + + // 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 })); } } - }, - - .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; + + // 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 }); } - try zig_args.append(rc_source_file.file.getPath(b)); - }, + } + } + + if (total_linker_objects == 0) { + return step.fail("the linker needs one or more objects to link", .{}); + } + + 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.is_linking_libcpp) { + try zig_args.append("-lc++"); + } + + if (self.is_linking_libc) { + try zig_args.append("-lc"); } } @@ -1650,14 +1252,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(manifest_file.getPath(b)); } - if (transitive_deps.is_linking_libcpp) { - try zig_args.append("-lc++"); - } - - if (transitive_deps.is_linking_libc) { - try zig_args.append("-lc"); - } - if (self.image_base) |image_base| { try zig_args.append("--image-base"); try zig_args.append(b.fmt("0x{x}", .{image_base})); @@ -1702,17 +1296,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 +1352,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 +1371,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(b.fmt("{}", .{version})); } - if (self.target.isDarwin()) { + if (self.rootModuleTarget().isDarwin()) { const install_name = self.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{ - self.target.libPrefix(), + self.rootModuleTarget().libPrefix(), self.name, - self.target.dynamicLibSuffix(), + self.rootModuleTarget().dynamicLibSuffix(), }); try zig_args.append("-install_name"); try zig_args.append(install_name); @@ -1808,11 +1386,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) { @@ -1823,27 +1401,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 +1433,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)); @@ -1921,103 +1459,11 @@ 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 }); } + // -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}", .{ @@ -2032,7 +1478,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (prefix_dir.accessZ("lib", .{})) |_| { try zig_args.appendSlice(&.{ - "-L", try fs.path.join(b.allocator, &.{ search_prefix, "lib" }), + "-L", try fs.path.join(arena, &.{ search_prefix, "lib" }), }); } else |err| switch (err) { error.FileNotFound => {}, @@ -2043,7 +1489,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (prefix_dir.accessZ("include", .{})) |_| { try zig_args.appendSlice(&.{ - "-I", try fs.path.join(b.allocator, &.{ search_prefix, "include" }), + "-I", try fs.path.join(arena, &.{ search_prefix, "include" }), }); } else |err| switch (err) { error.FileNotFound => {}, @@ -2058,7 +1504,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 +1520,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); @@ -2117,12 +1556,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| { @@ -2138,8 +1577,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, .{}); @@ -2153,9 +1592,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); @@ -2223,7 +1662,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 std.Build.wantSharedLibSymLinks(self.rootModuleTarget())) { try doAtomicSymLinks( step, @@ -2234,43 +1673,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"); - 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, @@ -2345,67 +1747,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; @@ -2490,3 +1831,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.resolved_target.?.result; +} diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 9f040349c67782b2716979ef960ae82e21868b26..c352b2460c0177e9712e815bb72a4402ab0c6841 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 f3c9ca3bef0e271a8eeed015692f3d27c151eb3d..b9c3acfbc912d6d9af338556d295431588f78764 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 8255be5cf4101cad0f70b1f66297c5457d32cd1c..7f334a2e69c55f69ebec22533d26d6a5d8e6be89 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(), }); } @@ -298,7 +294,10 @@ test Options { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); - const host = try std.zig.system.NativeTargetInfo.detect(.{}); + const host: std.Build.ResolvedTarget = .{ + .query = .{}, + .result = try std.zig.system.resolveTargetQuery(.{}), + }; var cache: std.Build.Cache = .{ .gpa = arena.allocator(), diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 5555b03e94efe8f33188f78c4cfbc9e08394715b..d48fe2a2f178127eb28c2508662961f3dac7eaf4 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.target.isWindows()) { + 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,8 +676,10 @@ 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.rootModuleTarget().isGnuLibC() and + exe.is_linking_libc; + 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, })) { @@ -714,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.target.getCpuArch(); - const os_tag = exe.target.getOsTag(); - const abi = exe.target.getAbi(); + 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 @@ -756,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.result.dynamic_linker.get() orelse "(none)"; return step.fail( \\the host system is unable to execute binaries from the target @@ -768,8 +764,8 @@ fn runCommand( .bad_os_or_cpu => { 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 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})", .{ host_name, foreign_name, @@ -777,7 +773,7 @@ fn runCommand( }, } - if (exe.target.isWindows()) { + 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); } @@ -1295,15 +1291,15 @@ 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, true); + while (it.next()) |item| { + const other = item.compile.?; + if (item.module == &other.root_module) { + if (item.module.resolved_target.?.result.os.tag == .windows and + other.isDynamicLibrary()) + { + addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?); + } } } } @@ -1320,8 +1316,8 @@ fn failForeign( return error.MakeSkipped; 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 host_name = try b.host.result.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 26e59dad90743057e2a1a234cce85ab162764488..31919ba11a5a8ddd334d7e2e0783cd8a1efd6641 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 01019274fd919172d9e17540ff029b111539af1f..7fcf06249f38c39f3cf8ba0e0ea4e3378d76cb51 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/Target.zig b/lib/std/Target.zig new file mode 100644 index 0000000000000000000000000000000000000000..f8ce63b37fb8aa190fba9adeea8e386ad2d7c4cd --- /dev/null +++ b/lib/std/Target.zig @@ -0,0 +1,2727 @@ +//! 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"); + +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) Allocator.Error![]u8 { + return Query.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, + + /// Used to construct the dynamic linker path. This field should not be used + /// directly. See `get` and `set`. + 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 { + 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 = @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 { + 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)); + 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 (abi == .android) { + const suffix = if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""; + return print(&result, "/system/bin/linker{s}", .{suffix}); + } + + if (abi.isMusl()) { + const is_arm = switch (cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => true, + else => false, + }; + const arch_part = switch (cpu.arch) { + .arm, .thumb => "arm", + .armeb, .thumbeb => "armeb", + else => |arch| @tagName(arch), + }; + 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 (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 (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 (abi.floatAbi()) { + .hard => "/lib/ld-linux-armhf.so.3", + else => "/lib/ld-linux.so.3", + }), + + .mips, + .mipsel, + .mips64, + .mips64el, + => { + const lib_suffix = switch (abi) { + .gnuabin32, .gnux32 => "32", + .gnuabi64 => "64", + else => "", + }; + 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 }); + }, + + .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 (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_cpu_abi(cpu: Cpu, abi: Abi) u16 { + switch (abi) { + .gnux32, .muslx32, .gnuabin32, .gnuilp32 => return 32, + .gnuabi64 => return 64, + else => {}, + } + return switch (cpu.arch) { + .avr, + .msp430, + .spu_2, + => 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, + => 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, + => 64, + + .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 { + 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/Query.zig b/lib/std/Target/Query.zig new file mode 100644 index 0000000000000000000000000000000000000000..10130e03bba6a9d32bb05e8c8f6b921ab5e81e1a --- /dev/null +++ b/lib/std/Target/Query.zig @@ -0,0 +1,777 @@ +//! 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, + +cpu_model: CpuModel = CpuModel.determined_by_cpu_arch, + +/// Sparse set of CPU features to add to the set from `cpu_model`. +cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, + +/// Sparse set of CPU features to remove from the set from `cpu_model`. +cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, + +/// `null` means native. +os_tag: ?Target.Os.Tag = null, + +/// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native) +/// then `null` for this field means native. +os_version_min: ?OsVersion = null, + +/// When cross compiling, `null` means default (latest known OS version). +/// When `os_tag` is native, `null` means equal to the native OS version. +os_version_max: ?OsVersion = null, + +/// `null` means default when cross compiling, or native when os_tag is native. +/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. +glibc_version: ?SemanticVersion = null, + +/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. +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: Target.DynamicLinker = Target.DynamicLinker.none, + +/// `null` means default for the cpu/arch/os combo. +ofmt: ?Target.ObjectFormat = null, + +pub const CpuModel = union(enum) { + /// Always native + native, + + /// Always baseline + baseline, + + /// If CPU Architecture is native, then the CPU model will be native. Otherwise, + /// it will be baseline. + 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; + +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, + .os_version_min = undefined, + .os_version_max = undefined, + .abi = target.abi, + .glibc_version = if (target.isGnuLibC()) + target.os.version_range.linux.glibc + else + null, + }; + result.updateOsVersionRange(target.os); + + const all_features = target.cpu.arch.allFeaturesList(); + var cpu_model_set = target.cpu.model.features; + cpu_model_set.populateDependencies(all_features); + { + // The "add" set is the full set with the CPU Model set removed. + const add_set = &result.cpu_features_add; + add_set.* = target.cpu.features; + add_set.removeFeatureSet(cpu_model_set); + } + { + // The "sub" set is the features that are on in CPU Model set and off in the full set. + const sub_set = &result.cpu_features_sub; + sub_set.* = cpu_model_set; + sub_set.removeFeatureSet(target.cpu.features); + } + return result; +} + +fn updateOsVersionRange(self: *Query, os: Target.Os) void { + switch (os.tag) { + .freestanding, + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .solaris, + .illumos, + .zos, + .haiku, + .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, + => { + self.os_version_min = .{ .none = {} }; + self.os_version_max = .{ .none = {} }; + }, + + .freebsd, + .macos, + .ios, + .tvos, + .watchos, + .netbsd, + .openbsd, + .dragonfly, + => { + self.os_version_min = .{ .semver = os.version_range.semver.min }; + self.os_version_max = .{ .semver = os.version_range.semver.max }; + }, + + .linux => { + self.os_version_min = .{ .semver = os.version_range.linux.range.min }; + self.os_version_max = .{ .semver = os.version_range.linux.range.max }; + }, + + .windows => { + self.os_version_min = .{ .windows = os.version_range.windows.min }; + self.os_version_max = .{ .windows = os.version_range.windows.max }; + }, + } +} + +pub const ParseOptions = struct { + /// This is sometimes called a "triple". It looks roughly like this: + /// riscv64-linux-musl + /// The fields are, respectively: + /// * CPU Architecture + /// * Operating System (and optional version range) + /// * C ABI (optional, with optional glibc version) + /// The string "native" can be used for CPU architecture as well as Operating System. + /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted. + arch_os_abi: []const u8 = "native", + + /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" + /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features + /// to remove from the set. + /// The following special strings are recognized for CPU Model name: + /// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set + /// of features that is expected to be supported on most available hardware. + /// * "native" - The native CPU model is to be detected when compiling. + /// If this field is not provided (`null`), then the value will depend on the + /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". + cpu_features: ?[]const u8 = null, + + /// Absolute path to dynamic linker, to override the default, which is either a natively + /// detected path, or a standard path. + dynamic_linker: ?[]const u8 = null, + + object_format: ?[]const u8 = null, + + /// If this is provided, the function will populate some information about parsing failures, + /// so that user-friendly error messages can be delivered. + diagnostics: ?*Diagnostics = null, + + pub const Diagnostics = struct { + /// If the architecture was determined, this will be populated. + arch: ?Target.Cpu.Arch = null, + + /// If the OS name was determined, this will be populated. + os_name: ?[]const u8 = null, + + /// If the OS tag was determined, this will be populated. + os_tag: ?Target.Os.Tag = null, + + /// If the ABI was determined, this will be populated. + abi: ?Target.Abi = null, + + /// If the CPU name was determined, this will be populated. + cpu_name: ?[]const u8 = null, + + /// If error.UnknownCpuFeature is returned, this will be populated. + unknown_feature_name: ?[]const u8 = null, + }; +}; + +pub fn parse(args: ParseOptions) !Query { + var dummy_diags: ParseOptions.Diagnostics = undefined; + const diags = args.diagnostics orelse &dummy_diags; + + var result: Query = .{ + .dynamic_linker = Target.DynamicLinker.init(args.dynamic_linker), + }; + + var it = mem.splitScalar(u8, args.arch_os_abi, '-'); + const arch_name = it.first(); + const arch_is_native = mem.eql(u8, arch_name, "native"); + if (!arch_is_native) { + result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse + return error.UnknownArchitecture; + } + const arch = result.cpu_arch orelse builtin.cpu.arch; + diags.arch = arch; + + if (it.next()) |os_text| { + try parseOs(&result, diags, os_text); + } else if (!arch_is_native) { + return error.MissingOperatingSystem; + } + + const opt_abi_text = it.next(); + if (opt_abi_text) |abi_text| { + var abi_it = mem.splitScalar(u8, abi_text, '.'); + const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse + return error.UnknownApplicationBinaryInterface; + result.abi = abi; + diags.abi = abi; + + const abi_ver_text = abi_it.rest(); + if (abi_it.next() != null) { + 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, + }; + } else { + return error.InvalidAbiVersion; + } + } + } + + if (it.next() != null) return error.UnexpectedExtraField; + + if (args.cpu_features) |cpu_features| { + const all_features = arch.allFeaturesList(); + var index: usize = 0; + while (index < cpu_features.len and + cpu_features[index] != '+' and + cpu_features[index] != '-') + { + index += 1; + } + const cpu_name = cpu_features[0..index]; + diags.cpu_name = cpu_name; + + const add_set = &result.cpu_features_add; + const sub_set = &result.cpu_features_sub; + if (mem.eql(u8, cpu_name, "native")) { + result.cpu_model = .native; + } else if (mem.eql(u8, cpu_name, "baseline")) { + result.cpu_model = .baseline; + } else { + result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) }; + } + + while (index < cpu_features.len) { + const op = cpu_features[index]; + const set = switch (op) { + '+' => add_set, + '-' => sub_set, + else => unreachable, + }; + index += 1; + const start = index; + while (index < cpu_features.len and + cpu_features[index] != '+' and + cpu_features[index] != '-') + { + index += 1; + } + const feature_name = cpu_features[start..index]; + for (all_features, 0..) |feature, feat_index_usize| { + const feat_index = @as(Target.Cpu.Feature.Set.Index, @intCast(feat_index_usize)); + if (mem.eql(u8, feature_name, feature.name)) { + set.addFeature(feat_index); + break; + } + } else { + diags.unknown_feature_name = feature_name; + return error.UnknownCpuFeature; + } + } + } + + if (args.object_format) |ofmt_name| { + result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse + return error.UnknownObjectFormat; + } + + return result; +} + +/// 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 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, '-'); + const arch_name = it.first(); + const arch_is_native = mem.eql(u8, arch_name, "native"); + if (arch_is_native) { + return builtin.cpu.arch; + } else { + return std.meta.stringToEnum(Target.Cpu.Arch, arch_name); + } +} + +/// Similar to `SemanticVersion.parse`, but with following changes: +/// * Leading zeroes are allowed. +/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. +pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion { + const parseVersionComponentFn = (struct { + fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize { + return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) { + error.InvalidCharacter => return error.InvalidVersion, + error.Overflow => return error.Overflow, + }; + } + }).parseVersionComponentInner; + var version_components = mem.splitScalar(u8, ver, '.'); + const major = version_components.first(); + const minor = version_components.next() orelse return error.InvalidVersion; + const patch = version_components.next() orelse "0"; + if (version_components.next() != null) return error.InvalidVersion; + return .{ + .major = try parseVersionComponentFn(major), + .minor = try parseVersionComponentFn(minor), + .patch = try parseVersionComponentFn(patch), + }; +} + +test parseVersion { + try std.testing.expectError(error.InvalidVersion, parseVersion("1")); + try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2")); + try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3")); + try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); +} + +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: 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: Query) bool { + return self.os_tag == null and self.abi == null; +} + +pub fn isNative(self: Query) bool { + return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); +} + +/// Formats a version with the patch component omitted if it is zero, +/// unlike SemanticVersion.format which formats all its version components regardless. +fn formatVersion(version: SemanticVersion, writer: anytype) !void { + if (version.patch == 0) { + try writer.print("{d}.{d}", .{ version.major, version.minor }); + } else { + try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch }); + } +} + +pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { + if (self.isNative()) { + return allocator.dupe(u8, "native"); + } + + const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native"; + const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; + + var result = std.ArrayList(u8).init(allocator); + defer result.deinit(); + + try result.writer().print("{s}-{s}", .{ arch_name, os_name }); + + // 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) |min| { + switch (min) { + .none => {}, + .semver => |v| { + try result.writer().writeAll("."); + try formatVersion(v, result.writer()); + }, + .windows => |v| { + try result.writer().print("{s}", .{v}); + }, + } + } + if (self.os_version_max) |max| { + switch (max) { + .none => {}, + .semver => |v| { + try result.writer().writeAll("..."); + try formatVersion(v, result.writer()); + }, + .windows => |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}); + }, + } + } + + if (self.glibc_version) |v| { + 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| { + const name = @tagName(abi); + try result.ensureUnusedCapacity(name.len + 1); + result.appendAssumeCapacity('-'); + result.appendSliceAssumeCapacity(name); + } + + return result.toOwnedSlice(); +} + +/// 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); + }, + } + + if (q.cpu_features_add.isEmpty() and q.cpu_features_sub.isEmpty()) { + // The CPU name alone is sufficient. + return; + } + + 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 serializeCpuAlloc(q: Query, ally: Allocator) Allocator.Error![]u8 { + var buffer = std.ArrayList(u8).init(ally); + try serializeCpu(q, &buffer); + return buffer.toOwnedSlice(); +} + +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 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 { + var it = mem.splitScalar(u8, text, '.'); + const os_name = it.first(); + diags.os_name = os_name; + const os_is_native = mem.eql(u8, os_name, "native"); + if (!os_is_native) { + result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse + return error.UnknownOperatingSystem; + } + const tag = result.os_tag orelse builtin.os.tag; + diags.os_tag = tag; + + const version_text = it.rest(); + if (it.next() == null) return; + + switch (tag) { + .freestanding, + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .solaris, + .illumos, + .zos, + .haiku, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .wasi, + .emscripten, + .uefi, + .opencl, + .glsl450, + .vulkan, + .plan9, + .driverkit, + .shadermodel, + .liteos, + .other, + => return error.InvalidOperatingSystemVersion, + + .freebsd, + .macos, + .ios, + .tvos, + .watchos, + .netbsd, + .openbsd, + .linux, + .dragonfly, + => { + var range_it = mem.splitSequence(u8, version_text, "..."); + + const min_text = range_it.next().?; + const min_ver = parseVersion(min_text) catch |err| switch (err) { + error.Overflow => return error.InvalidOperatingSystemVersion, + error.InvalidVersion => return error.InvalidOperatingSystemVersion, + }; + result.os_version_min = .{ .semver = min_ver }; + + const max_text = range_it.next() orelse return; + const max_ver = parseVersion(max_text) catch |err| switch (err) { + error.Overflow => return error.InvalidOperatingSystemVersion, + error.InvalidVersion => return error.InvalidOperatingSystemVersion, + }; + result.os_version_max = .{ .semver = max_ver }; + }, + + .windows => { + var range_it = mem.splitSequence(u8, version_text, "..."); + + const min_text = range_it.first(); + const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse + return error.InvalidOperatingSystemVersion; + result.os_version_min = .{ .windows = min_ver }; + + const max_text = range_it.next() orelse return; + const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse + return error.InvalidOperatingSystemVersion; + result.os_version_max = .{ .windows = max_ver }; + }, + } +} + +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()) { + var query = try Query.parse(.{}); + query.setGnuLibCVersion(2, 1, 1); + + const text = try query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + + var buf: [256]u8 = undefined; + const triple = std.fmt.bufPrint( + buf[0..], + "native-native-{s}.2.1.1", + .{@tagName(builtin.target.abi)}, + ) catch unreachable; + + try std.testing.expectEqualSlices(u8, triple, text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "aarch64-linux", + .cpu_features = "native", + }); + + try std.testing.expect(query.cpu_arch.? == .aarch64); + try std.testing.expect(query.cpu_model == .native); + } + { + const query = try Query.parse(.{ .arch_os_abi = "native" }); + + try std.testing.expect(query.cpu_arch == null); + try std.testing.expect(query.isNative()); + + const text = try query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "native", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "x86_64-linux-gnu", + .cpu_features = "x86_64-sse-sse2-avx-cx8", + }); + const target = try std.zig.system.resolveTargetQuery(query); + + try std.testing.expect(target.os.tag == .linux); + try std.testing.expect(target.abi == .gnu); + try std.testing.expect(target.cpu.arch == .x86_64); + try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); + try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); + try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); + try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); + try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); + + try std.testing.expect(Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov })); + try std.testing.expect(!Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx })); + 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 query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "arm-linux-musleabihf", + .cpu_features = "generic+v8a", + }); + const target = try std.zig.system.resolveTargetQuery(query); + + try std.testing.expect(target.os.tag == .linux); + try std.testing.expect(target.abi == .musleabihf); + try std.testing.expect(target.cpu.arch == .arm); + 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 query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", + .cpu_features = "generic+v8a", + }); + const target = try std.zig.system.resolveTargetQuery(query); + + try std.testing.expect(target.cpu.arch == .aarch64); + try std.testing.expect(target.os.tag == .linux); + try std.testing.expect(target.os.version_range.linux.range.min.major == 3); + try std.testing.expect(target.os.version_range.linux.range.min.minor == 10); + try std.testing.expect(target.os.version_range.linux.range.min.patch == 0); + try std.testing.expect(target.os.version_range.linux.range.max.major == 4); + try std.testing.expect(target.os.version_range.linux.range.max.minor == 4); + try std.testing.expect(target.os.version_range.linux.range.max.patch == 1); + try std.testing.expect(target.os.version_range.linux.glibc.major == 2); + try std.testing.expect(target.os.version_range.linux.glibc.minor == 27); + try std.testing.expect(target.os.version_range.linux.glibc.patch == 0); + try std.testing.expect(target.abi == .gnu); + + 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/Target/aarch64.zig b/lib/std/Target/aarch64.zig new file mode 100644 index 0000000000000000000000000000000000000000..011cb20aefbced7e2f787921de5d01e6d85f0b85 --- /dev/null +++ b/lib/std/Target/aarch64.zig @@ -0,0 +1,2656 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + a510, + a65, + a710, + a76, + a78, + a78c, + aes, + aggressive_fma, + alternate_sextload_cvt_f32_pattern, + altnzcv, + am, + amvs, + arith_bcc_fusion, + arith_cbz_fusion, + ascend_store_address, + b16b16, + balance_fp_ops, + bf16, + brbe, + bti, + call_saved_x10, + call_saved_x11, + call_saved_x12, + call_saved_x13, + call_saved_x14, + call_saved_x15, + call_saved_x18, + call_saved_x8, + call_saved_x9, + ccdp, + ccidx, + ccpp, + chk, + clrbhb, + cmp_bcc_fusion, + complxnum, + contextidr_el2, + cortex_r82, + crc, + crypto, + cssc, + custom_cheap_as_move, + d128, + disable_latency_sched_heuristic, + dit, + dotprod, + ecv, + el2vmsa, + el3, + enable_select_opt, + ete, + exynos_cheap_as_move, + f32mm, + f64mm, + fgt, + fix_cortex_a53_835769, + flagm, + fmv, + force_32bit_jump_tables, + fp16fml, + fp_armv8, + fptoint, + fullfp16, + fuse_address, + fuse_addsub_2reg_const1, + fuse_adrp_add, + fuse_aes, + fuse_arith_logic, + fuse_crypto_eor, + fuse_csel, + fuse_literals, + gcs, + harden_sls_blr, + harden_sls_nocomdat, + harden_sls_retbr, + hbc, + hcx, + i8mm, + ite, + jsconv, + lor, + ls64, + lse, + lse128, + lse2, + lsl_fast, + mec, + mops, + mpam, + mte, + neon, + nmi, + no_bti_at_return_twice, + no_neg_immediates, + no_sve_fp_ld1r, + no_zcz_fp, + nv, + outline_atomics, + pan, + pan_rwv, + pauth, + perfmon, + predictable_select_expensive, + predres, + prfm_slc_target, + rand, + ras, + rasv2, + rcpc, + rcpc3, + rcpc_immo, + rdm, + reserve_x1, + reserve_x10, + reserve_x11, + reserve_x12, + reserve_x13, + reserve_x14, + reserve_x15, + reserve_x18, + reserve_x2, + reserve_x20, + reserve_x21, + reserve_x22, + reserve_x23, + reserve_x24, + reserve_x25, + reserve_x26, + reserve_x27, + reserve_x28, + reserve_x3, + reserve_x30, + reserve_x4, + reserve_x5, + reserve_x6, + reserve_x7, + reserve_x9, + rme, + sb, + sel2, + sha2, + sha3, + slow_misaligned_128store, + slow_paired_128, + slow_strqro_store, + sm4, + sme, + sme2, + sme2p1, + sme_f16f16, + sme_f64f64, + sme_i16i64, + spe, + spe_eef, + specres2, + specrestrict, + ssbs, + strict_align, + sve, + sve2, + sve2_aes, + sve2_bitperm, + sve2_sha3, + sve2_sm4, + sve2p1, + tagged_globals, + the, + tlb_rmi, + tme, + tpidr_el1, + tpidr_el2, + tpidr_el3, + tpidrro_el0, + tracev8_4, + trbe, + uaops, + use_experimental_zeroing_pseudos, + use_postra_scheduler, + use_reciprocal_square_root, + use_scalar_inc_vl, + v8_1a, + v8_2a, + v8_3a, + v8_4a, + v8_5a, + v8_6a, + v8_7a, + v8_8a, + v8_9a, + v8a, + v8r, + v9_1a, + v9_2a, + v9_3a, + v9_4a, + v9a, + vh, + wfxt, + xs, + zcm, + zcz, + zcz_fp_workaround, + zcz_gp, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + @setEvalBranchQuota(2000); + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.a510)] = .{ + .llvm_name = "a510", + .description = "Cortex-A510 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .fuse_adrp_add, + .fuse_aes, + .use_postra_scheduler, + }), + }; + result[@intFromEnum(Feature.a65)] = .{ + .llvm_name = "a65", + .description = "Cortex-A65 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .enable_select_opt, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_literals, + .predictable_select_expensive, + }), + }; + result[@intFromEnum(Feature.a710)] = .{ + .llvm_name = "a710", + .description = "Cortex-A710 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@intFromEnum(Feature.a76)] = .{ + .llvm_name = "a76", + .description = "Cortex-A76 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .predictable_select_expensive, + }), + }; + result[@intFromEnum(Feature.a78)] = .{ + .llvm_name = "a78", + .description = "Cortex-A78 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@intFromEnum(Feature.a78c)] = .{ + .llvm_name = "a78c", + .description = "Cortex-A78C ARM processors", + .dependencies = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@intFromEnum(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES support (FEAT_AES, FEAT_PMULL)", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.aggressive_fma)] = .{ + .llvm_name = "aggressive-fma", + .description = "Enable Aggressive FMA for floating-point.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.alternate_sextload_cvt_f32_pattern)] = .{ + .llvm_name = "alternate-sextload-cvt-f32-pattern", + .description = "Use alternative pattern for sextload convert to f32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.altnzcv)] = .{ + .llvm_name = "altnzcv", + .description = "Enable alternative NZCV format for floating point comparisons (FEAT_FlagM2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.am)] = .{ + .llvm_name = "am", + .description = "Enable v8.4-A Activity Monitors extension (FEAT_AMUv1)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.amvs)] = .{ + .llvm_name = "amvs", + .description = "Enable v8.6-A Activity Monitors Virtualization support (FEAT_AMUv1p1)", + .dependencies = featureSet(&[_]Feature{ + .am, + }), + }; + result[@intFromEnum(Feature.arith_bcc_fusion)] = .{ + .llvm_name = "arith-bcc-fusion", + .description = "CPU fuses arithmetic+bcc operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.arith_cbz_fusion)] = .{ + .llvm_name = "arith-cbz-fusion", + .description = "CPU fuses arithmetic + cbz/cbnz operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ascend_store_address)] = .{ + .llvm_name = "ascend-store-address", + .description = "Schedule vector stores by ascending address", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.b16b16)] = .{ + .llvm_name = "b16b16", + .description = "Enable SVE2.1 or SME2.1 non-widening BFloat16 to BFloat16 instructions (FEAT_B16B16)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.balance_fp_ops)] = .{ + .llvm_name = "balance-fp-ops", + .description = "balance mix of odd and even D-registers for fp multiply(-accumulate) ops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.bf16)] = .{ + .llvm_name = "bf16", + .description = "Enable BFloat16 Extension (FEAT_BF16)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.brbe)] = .{ + .llvm_name = "brbe", + .description = "Enable Branch Record Buffer Extension (FEAT_BRBE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.bti)] = .{ + .llvm_name = "bti", + .description = "Enable Branch Target Identification (FEAT_BTI)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x10)] = .{ + .llvm_name = "call-saved-x10", + .description = "Make X10 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x11)] = .{ + .llvm_name = "call-saved-x11", + .description = "Make X11 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x12)] = .{ + .llvm_name = "call-saved-x12", + .description = "Make X12 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x13)] = .{ + .llvm_name = "call-saved-x13", + .description = "Make X13 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x14)] = .{ + .llvm_name = "call-saved-x14", + .description = "Make X14 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x15)] = .{ + .llvm_name = "call-saved-x15", + .description = "Make X15 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x18)] = .{ + .llvm_name = "call-saved-x18", + .description = "Make X18 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x8)] = .{ + .llvm_name = "call-saved-x8", + .description = "Make X8 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.call_saved_x9)] = .{ + .llvm_name = "call-saved-x9", + .description = "Make X9 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ccdp)] = .{ + .llvm_name = "ccdp", + .description = "Enable v8.5 Cache Clean to Point of Deep Persistence (FEAT_DPB2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ccidx)] = .{ + .llvm_name = "ccidx", + .description = "Enable v8.3-A Extend of the CCSIDR number of sets (FEAT_CCIDX)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ccpp)] = .{ + .llvm_name = "ccpp", + .description = "Enable v8.2 data Cache Clean to Point of Persistence (FEAT_DPB)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.chk)] = .{ + .llvm_name = "chk", + .description = "Enable Armv8.0-A Check Feature Status Extension (FEAT_CHK)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.clrbhb)] = .{ + .llvm_name = "clrbhb", + .description = "Enable Clear BHB instruction (FEAT_CLRBHB)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cmp_bcc_fusion)] = .{ + .llvm_name = "cmp-bcc-fusion", + .description = "CPU fuses cmp+bcc operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.complxnum)] = .{ + .llvm_name = "complxnum", + .description = "Enable v8.3-A Floating-point complex number support (FEAT_FCMA)", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.contextidr_el2)] = .{ + .llvm_name = "CONTEXTIDREL2", + .description = "Enable RW operand Context ID Register (EL2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cortex_r82)] = .{ + .llvm_name = "cortex-r82", + .description = "Cortex-R82 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .use_postra_scheduler, + }), + }; + result[@intFromEnum(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Enable ARMv8 CRC-32 checksum instructions (FEAT_CRC32)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable cryptographic instructions", + .dependencies = featureSet(&[_]Feature{ + .aes, + .sha2, + }), + }; + result[@intFromEnum(Feature.cssc)] = .{ + .llvm_name = "cssc", + .description = "Enable Common Short Sequence Compression (CSSC) instructions (FEAT_CSSC)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.custom_cheap_as_move)] = .{ + .llvm_name = "custom-cheap-as-move", + .description = "Use custom handling of cheap instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.d128)] = .{ + .llvm_name = "d128", + .description = "Enable Armv9.4-A 128-bit Page Table Descriptors, System Registers and Instructions (FEAT_D128, FEAT_LVA3, FEAT_SYSREG128, FEAT_SYSINSTR128)", + .dependencies = featureSet(&[_]Feature{ + .lse128, + }), + }; + result[@intFromEnum(Feature.disable_latency_sched_heuristic)] = .{ + .llvm_name = "disable-latency-sched-heuristic", + .description = "Disable latency scheduling heuristic", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dit)] = .{ + .llvm_name = "dit", + .description = "Enable v8.4-A Data Independent Timing instructions (FEAT_DIT)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dotprod)] = .{ + .llvm_name = "dotprod", + .description = "Enable dot product support (FEAT_DotProd)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ecv)] = .{ + .llvm_name = "ecv", + .description = "Enable enhanced counter virtualization extension (FEAT_ECV)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.el2vmsa)] = .{ + .llvm_name = "el2vmsa", + .description = "Enable Exception Level 2 Virtual Memory System Architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.el3)] = .{ + .llvm_name = "el3", + .description = "Enable Exception Level 3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.enable_select_opt)] = .{ + .llvm_name = "enable-select-opt", + .description = "Enable the select optimize pass for select loop heuristics", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ete)] = .{ + .llvm_name = "ete", + .description = "Enable Embedded Trace Extension (FEAT_ETE)", + .dependencies = featureSet(&[_]Feature{ + .trbe, + }), + }; + result[@intFromEnum(Feature.exynos_cheap_as_move)] = .{ + .llvm_name = "exynos-cheap-as-move", + .description = "Use Exynos specific handling of cheap instructions", + .dependencies = featureSet(&[_]Feature{ + .custom_cheap_as_move, + }), + }; + result[@intFromEnum(Feature.f32mm)] = .{ + .llvm_name = "f32mm", + .description = "Enable Matrix Multiply FP32 Extension (FEAT_F32MM)", + .dependencies = featureSet(&[_]Feature{ + .sve, + }), + }; + result[@intFromEnum(Feature.f64mm)] = .{ + .llvm_name = "f64mm", + .description = "Enable Matrix Multiply FP64 Extension (FEAT_F64MM)", + .dependencies = featureSet(&[_]Feature{ + .sve, + }), + }; + result[@intFromEnum(Feature.fgt)] = .{ + .llvm_name = "fgt", + .description = "Enable fine grained virtualization traps extension (FEAT_FGT)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fix_cortex_a53_835769)] = .{ + .llvm_name = "fix-cortex-a53-835769", + .description = "Mitigate Cortex-A53 Erratum 835769", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flagm)] = .{ + .llvm_name = "flagm", + .description = "Enable v8.4-A Flag Manipulation Instructions (FEAT_FlagM)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fmv)] = .{ + .llvm_name = "fmv", + .description = "Enable Function Multi Versioning support.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.force_32bit_jump_tables)] = .{ + .llvm_name = "force-32bit-jump-tables", + .description = "Force jump table entries to be 32-bits wide except at MinSize", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable FP16 FML instructions (FEAT_FHM)", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@intFromEnum(Feature.fp_armv8)] = .{ + .llvm_name = "fp-armv8", + .description = "Enable ARMv8 FP (FEAT_FP)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fptoint)] = .{ + .llvm_name = "fptoint", + .description = "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int (FEAT_FRINTTS)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fullfp16)] = .{ + .llvm_name = "fullfp16", + .description = "Full FP16 (FEAT_FP16)", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@intFromEnum(Feature.fuse_address)] = .{ + .llvm_name = "fuse-address", + .description = "CPU fuses address generation and memory operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_addsub_2reg_const1)] = .{ + .llvm_name = "fuse-addsub-2reg-const1", + .description = "CPU fuses (a + b + 1) and (a - b - 1)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_adrp_add)] = .{ + .llvm_name = "fuse-adrp-add", + .description = "CPU fuses adrp+add operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_aes)] = .{ + .llvm_name = "fuse-aes", + .description = "CPU fuses AES crypto operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_arith_logic)] = .{ + .llvm_name = "fuse-arith-logic", + .description = "CPU fuses arithmetic and logic operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_crypto_eor)] = .{ + .llvm_name = "fuse-crypto-eor", + .description = "CPU fuses AES/PMULL and EOR operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_csel)] = .{ + .llvm_name = "fuse-csel", + .description = "CPU fuses conditional select operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_literals)] = .{ + .llvm_name = "fuse-literals", + .description = "CPU fuses literal generation operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gcs)] = .{ + .llvm_name = "gcs", + .description = "Enable Armv9.4-A Guarded Call Stack Extension", + .dependencies = featureSet(&[_]Feature{ + .chk, + }), + }; + result[@intFromEnum(Feature.harden_sls_blr)] = .{ + .llvm_name = "harden-sls-blr", + .description = "Harden against straight line speculation across BLR instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_nocomdat)] = .{ + .llvm_name = "harden-sls-nocomdat", + .description = "Generate thunk code for SLS mitigation in the normal text section", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_retbr)] = .{ + .llvm_name = "harden-sls-retbr", + .description = "Harden against straight line speculation across RET and BR instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hbc)] = .{ + .llvm_name = "hbc", + .description = "Enable Armv8.8-A Hinted Conditional Branches Extension (FEAT_HBC)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hcx)] = .{ + .llvm_name = "hcx", + .description = "Enable Armv8.7-A HCRX_EL2 system register (FEAT_HCX)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.i8mm)] = .{ + .llvm_name = "i8mm", + .description = "Enable Matrix Multiply Int8 Extension (FEAT_I8MM)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ite)] = .{ + .llvm_name = "ite", + .description = "Enable Armv9.4-A Instrumentation Extension FEAT_ITE", + .dependencies = featureSet(&[_]Feature{ + .ete, + }), + }; + result[@intFromEnum(Feature.jsconv)] = .{ + .llvm_name = "jsconv", + .description = "Enable v8.3-A JavaScript FP conversion instructions (FEAT_JSCVT)", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@intFromEnum(Feature.lor)] = .{ + .llvm_name = "lor", + .description = "Enables ARM v8.1 Limited Ordering Regions extension (FEAT_LOR)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ls64)] = .{ + .llvm_name = "ls64", + .description = "Enable Armv8.7-A LD64B/ST64B Accelerator Extension (FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lse)] = .{ + .llvm_name = "lse", + .description = "Enable ARMv8.1 Large System Extension (LSE) atomic instructions (FEAT_LSE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lse128)] = .{ + .llvm_name = "lse128", + .description = "Enable Armv9.4-A 128-bit Atomic Instructions (FEAT_LSE128)", + .dependencies = featureSet(&[_]Feature{ + .lse, + }), + }; + result[@intFromEnum(Feature.lse2)] = .{ + .llvm_name = "lse2", + .description = "Enable ARMv8.4 Large System Extension 2 (LSE2) atomicity rules (FEAT_LSE2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lsl_fast)] = .{ + .llvm_name = "lsl-fast", + .description = "CPU has a fastpath logical shift of up to 3 places", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mec)] = .{ + .llvm_name = "mec", + .description = "Enable Memory Encryption Contexts Extension", + .dependencies = featureSet(&[_]Feature{ + .rme, + }), + }; + result[@intFromEnum(Feature.mops)] = .{ + .llvm_name = "mops", + .description = "Enable Armv8.8-A memcpy and memset acceleration instructions (FEAT_MOPS)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mpam)] = .{ + .llvm_name = "mpam", + .description = "Enable v8.4-A Memory system Partitioning and Monitoring extension (FEAT_MPAM)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mte)] = .{ + .llvm_name = "mte", + .description = "Enable Memory Tagging Extension (FEAT_MTE, FEAT_MTE2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.neon)] = .{ + .llvm_name = "neon", + .description = "Enable Advanced SIMD instructions (FEAT_AdvSIMD)", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@intFromEnum(Feature.nmi)] = .{ + .llvm_name = "nmi", + .description = "Enable Armv8.8-A Non-maskable Interrupts (FEAT_NMI, FEAT_GICv3_NMI)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bti_at_return_twice)] = .{ + .llvm_name = "no-bti-at-return-twice", + .description = "Don't place a BTI instruction after a return-twice", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_neg_immediates)] = .{ + .llvm_name = "no-neg-immediates", + .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_sve_fp_ld1r)] = .{ + .llvm_name = "no-sve-fp-ld1r", + .description = "Avoid using LD1RX instructions for FP", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_zcz_fp)] = .{ + .llvm_name = "no-zcz-fp", + .description = "Has no zero-cycle zeroing instructions for FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nv)] = .{ + .llvm_name = "nv", + .description = "Enable v8.4-A Nested Virtualization Enchancement (FEAT_NV, FEAT_NV2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.outline_atomics)] = .{ + .llvm_name = "outline-atomics", + .description = "Enable out of line atomics to support LSE instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pan)] = .{ + .llvm_name = "pan", + .description = "Enables ARM v8.1 Privileged Access-Never extension (FEAT_PAN)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pan_rwv)] = .{ + .llvm_name = "pan-rwv", + .description = "Enable v8.2 PAN s1e1R and s1e1W Variants (FEAT_PAN2)", + .dependencies = featureSet(&[_]Feature{ + .pan, + }), + }; + result[@intFromEnum(Feature.pauth)] = .{ + .llvm_name = "pauth", + .description = "Enable v8.3-A Pointer Authentication extension (FEAT_PAuth)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.perfmon)] = .{ + .llvm_name = "perfmon", + .description = "Enable Code Generation for ARMv8 PMUv3 Performance Monitors extension (FEAT_PMUv3)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.predictable_select_expensive)] = .{ + .llvm_name = "predictable-select-expensive", + .description = "Prefer likely predicted branches over selects", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.predres)] = .{ + .llvm_name = "predres", + .description = "Enable v8.5a execution and data prediction invalidation instructions (FEAT_SPECRES)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prfm_slc_target)] = .{ + .llvm_name = "prfm-slc-target", + .description = "Enable SLC target for PRFM instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rand)] = .{ + .llvm_name = "rand", + .description = "Enable Random Number generation instructions (FEAT_RNG)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ras)] = .{ + .llvm_name = "ras", + .description = "Enable ARMv8 Reliability, Availability and Serviceability Extensions (FEAT_RAS, FEAT_RASv1p1)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rasv2)] = .{ + .llvm_name = "rasv2", + .description = "Enable ARMv8.9-A Reliability, Availability and Serviceability Extensions (FEAT_RASv2)", + .dependencies = featureSet(&[_]Feature{ + .ras, + }), + }; + result[@intFromEnum(Feature.rcpc)] = .{ + .llvm_name = "rcpc", + .description = "Enable support for RCPC extension (FEAT_LRCPC)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rcpc3)] = .{ + .llvm_name = "rcpc3", + .description = "Enable Armv8.9-A RCPC instructions for A64 and Advanced SIMD and floating-point instruction set (FEAT_LRCPC3)", + .dependencies = featureSet(&[_]Feature{ + .rcpc_immo, + }), + }; + result[@intFromEnum(Feature.rcpc_immo)] = .{ + .llvm_name = "rcpc-immo", + .description = "Enable v8.4-A RCPC instructions with Immediate Offsets (FEAT_LRCPC2)", + .dependencies = featureSet(&[_]Feature{ + .rcpc, + }), + }; + result[@intFromEnum(Feature.rdm)] = .{ + .llvm_name = "rdm", + .description = "Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions (FEAT_RDM)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x1)] = .{ + .llvm_name = "reserve-x1", + .description = "Reserve X1, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x10)] = .{ + .llvm_name = "reserve-x10", + .description = "Reserve X10, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x11)] = .{ + .llvm_name = "reserve-x11", + .description = "Reserve X11, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x12)] = .{ + .llvm_name = "reserve-x12", + .description = "Reserve X12, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x13)] = .{ + .llvm_name = "reserve-x13", + .description = "Reserve X13, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x14)] = .{ + .llvm_name = "reserve-x14", + .description = "Reserve X14, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x15)] = .{ + .llvm_name = "reserve-x15", + .description = "Reserve X15, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x18)] = .{ + .llvm_name = "reserve-x18", + .description = "Reserve X18, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x2)] = .{ + .llvm_name = "reserve-x2", + .description = "Reserve X2, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x20)] = .{ + .llvm_name = "reserve-x20", + .description = "Reserve X20, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x21)] = .{ + .llvm_name = "reserve-x21", + .description = "Reserve X21, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x22)] = .{ + .llvm_name = "reserve-x22", + .description = "Reserve X22, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x23)] = .{ + .llvm_name = "reserve-x23", + .description = "Reserve X23, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x24)] = .{ + .llvm_name = "reserve-x24", + .description = "Reserve X24, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x25)] = .{ + .llvm_name = "reserve-x25", + .description = "Reserve X25, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x26)] = .{ + .llvm_name = "reserve-x26", + .description = "Reserve X26, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x27)] = .{ + .llvm_name = "reserve-x27", + .description = "Reserve X27, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x28)] = .{ + .llvm_name = "reserve-x28", + .description = "Reserve X28, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x3)] = .{ + .llvm_name = "reserve-x3", + .description = "Reserve X3, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x30)] = .{ + .llvm_name = "reserve-x30", + .description = "Reserve X30, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x4)] = .{ + .llvm_name = "reserve-x4", + .description = "Reserve X4, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x5)] = .{ + .llvm_name = "reserve-x5", + .description = "Reserve X5, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x6)] = .{ + .llvm_name = "reserve-x6", + .description = "Reserve X6, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x7)] = .{ + .llvm_name = "reserve-x7", + .description = "Reserve X7, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x9)] = .{ + .llvm_name = "reserve-x9", + .description = "Reserve X9, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rme)] = .{ + .llvm_name = "rme", + .description = "Enable Realm Management Extension (FEAT_RME)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sb)] = .{ + .llvm_name = "sb", + .description = "Enable v8.5 Speculation Barrier (FEAT_SB)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sel2)] = .{ + .llvm_name = "sel2", + .description = "Enable v8.4-A Secure Exception Level 2 extension (FEAT_SEL2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sha2)] = .{ + .llvm_name = "sha2", + .description = "Enable SHA1 and SHA256 support (FEAT_SHA1, FEAT_SHA256)", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.sha3)] = .{ + .llvm_name = "sha3", + .description = "Enable SHA512 and SHA3 support (FEAT_SHA3, FEAT_SHA512)", + .dependencies = featureSet(&[_]Feature{ + .sha2, + }), + }; + result[@intFromEnum(Feature.slow_misaligned_128store)] = .{ + .llvm_name = "slow-misaligned-128store", + .description = "Misaligned 128 bit stores are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_paired_128)] = .{ + .llvm_name = "slow-paired-128", + .description = "Paired 128 bit loads and stores are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_strqro_store)] = .{ + .llvm_name = "slow-strqro-store", + .description = "STR of Q register with register offset is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm4)] = .{ + .llvm_name = "sm4", + .description = "Enable SM3 and SM4 support (FEAT_SM4, FEAT_SM3)", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.sme)] = .{ + .llvm_name = "sme", + .description = "Enable Scalable Matrix Extension (SME) (FEAT_SME)", + .dependencies = featureSet(&[_]Feature{ + .bf16, + .use_scalar_inc_vl, + }), + }; + result[@intFromEnum(Feature.sme2)] = .{ + .llvm_name = "sme2", + .description = "Enable Scalable Matrix Extension 2 (SME2) instructions", + .dependencies = featureSet(&[_]Feature{ + .sme, + }), + }; + result[@intFromEnum(Feature.sme2p1)] = .{ + .llvm_name = "sme2p1", + .description = "Enable Scalable Matrix Extension 2.1 (FEAT_SME2p1) instructions", + .dependencies = featureSet(&[_]Feature{ + .sme2, + }), + }; + result[@intFromEnum(Feature.sme_f16f16)] = .{ + .llvm_name = "sme-f16f16", + .description = "Enable SME2.1 non-widening Float16 instructions (FEAT_SME_F16F16)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sme_f64f64)] = .{ + .llvm_name = "sme-f64f64", + .description = "Enable Scalable Matrix Extension (SME) F64F64 instructions (FEAT_SME_F64F64)", + .dependencies = featureSet(&[_]Feature{ + .sme, + }), + }; + result[@intFromEnum(Feature.sme_i16i64)] = .{ + .llvm_name = "sme-i16i64", + .description = "Enable Scalable Matrix Extension (SME) I16I64 instructions (FEAT_SME_I16I64)", + .dependencies = featureSet(&[_]Feature{ + .sme, + }), + }; + result[@intFromEnum(Feature.spe)] = .{ + .llvm_name = "spe", + .description = "Enable Statistical Profiling extension (FEAT_SPE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.spe_eef)] = .{ + .llvm_name = "spe-eef", + .description = "Enable extra register in the Statistical Profiling Extension (FEAT_SPEv1p2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.specres2)] = .{ + .llvm_name = "specres2", + .description = "Enable Speculation Restriction Instruction (FEAT_SPECRES2)", + .dependencies = featureSet(&[_]Feature{ + .predres, + }), + }; + result[@intFromEnum(Feature.specrestrict)] = .{ + .llvm_name = "specrestrict", + .description = "Enable architectural speculation restriction (FEAT_CSV2_2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ssbs)] = .{ + .llvm_name = "ssbs", + .description = "Enable Speculative Store Bypass Safe bit (FEAT_SSBS, FEAT_SSBS2)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.strict_align)] = .{ + .llvm_name = "strict-align", + .description = "Disallow all unaligned memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sve)] = .{ + .llvm_name = "sve", + .description = "Enable Scalable Vector Extension (SVE) instructions (FEAT_SVE)", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@intFromEnum(Feature.sve2)] = .{ + .llvm_name = "sve2", + .description = "Enable Scalable Vector Extension 2 (SVE2) instructions (FEAT_SVE2)", + .dependencies = featureSet(&[_]Feature{ + .sve, + .use_scalar_inc_vl, + }), + }; + result[@intFromEnum(Feature.sve2_aes)] = .{ + .llvm_name = "sve2-aes", + .description = "Enable AES SVE2 instructions (FEAT_SVE_AES, FEAT_SVE_PMULL128)", + .dependencies = featureSet(&[_]Feature{ + .aes, + .sve2, + }), + }; + result[@intFromEnum(Feature.sve2_bitperm)] = .{ + .llvm_name = "sve2-bitperm", + .description = "Enable bit permutation SVE2 instructions (FEAT_SVE_BitPerm)", + .dependencies = featureSet(&[_]Feature{ + .sve2, + }), + }; + result[@intFromEnum(Feature.sve2_sha3)] = .{ + .llvm_name = "sve2-sha3", + .description = "Enable SHA3 SVE2 instructions (FEAT_SVE_SHA3)", + .dependencies = featureSet(&[_]Feature{ + .sha3, + .sve2, + }), + }; + result[@intFromEnum(Feature.sve2_sm4)] = .{ + .llvm_name = "sve2-sm4", + .description = "Enable SM4 SVE2 instructions (FEAT_SVE_SM4)", + .dependencies = featureSet(&[_]Feature{ + .sm4, + .sve2, + }), + }; + result[@intFromEnum(Feature.sve2p1)] = .{ + .llvm_name = "sve2p1", + .description = "Enable Scalable Vector Extension 2.1 instructions", + .dependencies = featureSet(&[_]Feature{ + .sve2, + }), + }; + result[@intFromEnum(Feature.tagged_globals)] = .{ + .llvm_name = "tagged-globals", + .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.the)] = .{ + .llvm_name = "the", + .description = "Enable Armv8.9-A Translation Hardening Extension (FEAT_THE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tlb_rmi)] = .{ + .llvm_name = "tlb-rmi", + .description = "Enable v8.4-A TLB Range and Maintenance Instructions (FEAT_TLBIOS, FEAT_TLBIRANGE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tme)] = .{ + .llvm_name = "tme", + .description = "Enable Transactional Memory Extension (FEAT_TME)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tpidr_el1)] = .{ + .llvm_name = "tpidr-el1", + .description = "Permit use of TPIDR_EL1 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tpidr_el2)] = .{ + .llvm_name = "tpidr-el2", + .description = "Permit use of TPIDR_EL2 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tpidr_el3)] = .{ + .llvm_name = "tpidr-el3", + .description = "Permit use of TPIDR_EL3 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tpidrro_el0)] = .{ + .llvm_name = "tpidrro-el0", + .description = "Permit use of TPIDRRO_EL0 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tracev8_4)] = .{ + .llvm_name = "tracev8.4", + .description = "Enable v8.4-A Trace extension (FEAT_TRF)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.trbe)] = .{ + .llvm_name = "trbe", + .description = "Enable Trace Buffer Extension (FEAT_TRBE)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.uaops)] = .{ + .llvm_name = "uaops", + .description = "Enable v8.2 UAO PState (FEAT_UAO)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_experimental_zeroing_pseudos)] = .{ + .llvm_name = "use-experimental-zeroing-pseudos", + .description = "Hint to the compiler that the MOVPRFX instruction is merged with destructive operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_postra_scheduler)] = .{ + .llvm_name = "use-postra-scheduler", + .description = "Schedule again after register allocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_reciprocal_square_root)] = .{ + .llvm_name = "use-reciprocal-square-root", + .description = "Use the reciprocal square root approximation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_scalar_inc_vl)] = .{ + .llvm_name = "use-scalar-inc-vl", + .description = "Prefer inc/dec over add+cnt", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v8_1a)] = .{ + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .crc, + .lor, + .lse, + .pan, + .rdm, + .v8a, + .vh, + }), + }; + result[@intFromEnum(Feature.v8_2a)] = .{ + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .ccpp, + .pan_rwv, + .ras, + .uaops, + .v8_1a, + }), + }; + result[@intFromEnum(Feature.v8_3a)] = .{ + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .ccidx, + .complxnum, + .jsconv, + .pauth, + .rcpc, + .v8_2a, + }), + }; + result[@intFromEnum(Feature.v8_4a)] = .{ + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .am, + .dit, + .dotprod, + .flagm, + .lse2, + .mpam, + .nv, + .rcpc_immo, + .sel2, + .tlb_rmi, + .tracev8_4, + .v8_3a, + }), + }; + result[@intFromEnum(Feature.v8_5a)] = .{ + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", + .dependencies = featureSet(&[_]Feature{ + .altnzcv, + .bti, + .ccdp, + .fptoint, + .predres, + .sb, + .specrestrict, + .ssbs, + .v8_4a, + }), + }; + result[@intFromEnum(Feature.v8_6a)] = .{ + .llvm_name = "v8.6a", + .description = "Support ARM v8.6a instructions", + .dependencies = featureSet(&[_]Feature{ + .amvs, + .bf16, + .ecv, + .fgt, + .i8mm, + .v8_5a, + }), + }; + result[@intFromEnum(Feature.v8_7a)] = .{ + .llvm_name = "v8.7a", + .description = "Support ARM v8.7a instructions", + .dependencies = featureSet(&[_]Feature{ + .hcx, + .v8_6a, + .wfxt, + .xs, + }), + }; + result[@intFromEnum(Feature.v8_8a)] = .{ + .llvm_name = "v8.8a", + .description = "Support ARM v8.8a instructions", + .dependencies = featureSet(&[_]Feature{ + .hbc, + .mops, + .nmi, + .v8_7a, + }), + }; + result[@intFromEnum(Feature.v8_9a)] = .{ + .llvm_name = "v8.9a", + .description = "Support ARM v8.9a instructions", + .dependencies = featureSet(&[_]Feature{ + .chk, + .clrbhb, + .cssc, + .prfm_slc_target, + .rasv2, + .specres2, + .v8_8a, + }), + }; + result[@intFromEnum(Feature.v8a)] = .{ + .llvm_name = "v8a", + .description = "Support ARM v8.0a instructions", + .dependencies = featureSet(&[_]Feature{ + .el2vmsa, + .el3, + .neon, + }), + }; + result[@intFromEnum(Feature.v8r)] = .{ + .llvm_name = "v8r", + .description = "Support ARM v8r instructions", + .dependencies = featureSet(&[_]Feature{ + .ccidx, + .ccpp, + .complxnum, + .contextidr_el2, + .crc, + .dit, + .dotprod, + .flagm, + .jsconv, + .lse, + .pan_rwv, + .pauth, + .ras, + .rcpc_immo, + .rdm, + .sel2, + .specrestrict, + .tlb_rmi, + .tracev8_4, + .uaops, + }), + }; + result[@intFromEnum(Feature.v9_1a)] = .{ + .llvm_name = "v9.1a", + .description = "Support ARM v9.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_6a, + .v9a, + }), + }; + result[@intFromEnum(Feature.v9_2a)] = .{ + .llvm_name = "v9.2a", + .description = "Support ARM v9.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_7a, + .v9_1a, + }), + }; + result[@intFromEnum(Feature.v9_3a)] = .{ + .llvm_name = "v9.3a", + .description = "Support ARM v9.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_8a, + .v9_2a, + }), + }; + result[@intFromEnum(Feature.v9_4a)] = .{ + .llvm_name = "v9.4a", + .description = "Support ARM v9.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_9a, + .v9_3a, + }), + }; + result[@intFromEnum(Feature.v9a)] = .{ + .llvm_name = "v9a", + .description = "Support ARM v9a instructions", + .dependencies = featureSet(&[_]Feature{ + .mec, + .sve2, + .v8_5a, + }), + }; + result[@intFromEnum(Feature.vh)] = .{ + .llvm_name = "vh", + .description = "Enables ARM v8.1 Virtual Host extension (FEAT_VHE)", + .dependencies = featureSet(&[_]Feature{ + .contextidr_el2, + }), + }; + result[@intFromEnum(Feature.wfxt)] = .{ + .llvm_name = "wfxt", + .description = "Enable Armv8.7-A WFET and WFIT instruction (FEAT_WFxT)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xs)] = .{ + .llvm_name = "xs", + .description = "Enable Armv8.7-A limited-TLB-maintenance instruction (FEAT_XS)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zcm)] = .{ + .llvm_name = "zcm", + .description = "Has zero-cycle register moves", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zcz)] = .{ + .llvm_name = "zcz", + .description = "Has zero-cycle zeroing instructions", + .dependencies = featureSet(&[_]Feature{ + .zcz_gp, + }), + }; + result[@intFromEnum(Feature.zcz_fp_workaround)] = .{ + .llvm_name = "zcz-fp-workaround", + .description = "The zero-cycle floating-point zeroing instruction has a bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zcz_gp)] = .{ + .llvm_name = "zcz-gp", + .description = "Has zero-cycle zeroing instructions for generic registers", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const a64fx = CpuModel{ + .name = "a64fx", + .llvm_name = "a64fx", + .features = featureSet(&[_]Feature{ + .aggressive_fma, + .arith_bcc_fusion, + .complxnum, + .perfmon, + .predictable_select_expensive, + .sha2, + .sve, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const ampere1 = CpuModel{ + .name = "ampere1", + .llvm_name = "ampere1", + .features = featureSet(&[_]Feature{ + .aes, + .aggressive_fma, + .arith_bcc_fusion, + .cmp_bcc_fusion, + .fuse_address, + .fuse_aes, + .fuse_literals, + .lsl_fast, + .perfmon, + .rand, + .sha3, + .use_postra_scheduler, + .v8_6a, + }), + }; + pub const ampere1a = CpuModel{ + .name = "ampere1a", + .llvm_name = "ampere1a", + .features = featureSet(&[_]Feature{ + .aes, + .aggressive_fma, + .arith_bcc_fusion, + .cmp_bcc_fusion, + .fuse_address, + .fuse_aes, + .fuse_literals, + .lsl_fast, + .mte, + .perfmon, + .rand, + .sha3, + .sm4, + .use_postra_scheduler, + .v8_6a, + }), + }; + pub const apple_a10 = CpuModel{ + .name = "apple_a10", + .llvm_name = "apple-a10", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crc, + .crypto, + .disable_latency_sched_heuristic, + .fuse_aes, + .fuse_crypto_eor, + .lor, + .pan, + .perfmon, + .rdm, + .v8a, + .vh, + .zcm, + .zcz, + }), + }; + pub const apple_a11 = CpuModel{ + .name = "apple_a11", + .llvm_name = "apple-a11", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fullfp16, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8_2a, + .zcm, + .zcz, + }), + }; + pub const apple_a12 = CpuModel{ + .name = "apple_a12", + .llvm_name = "apple-a12", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fullfp16, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8_3a, + .zcm, + .zcz, + }), + }; + pub const apple_a13 = CpuModel{ + .name = "apple_a13", + .llvm_name = "apple-a13", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .sha3, + .v8_4a, + .zcm, + .zcz, + }), + }; + pub const apple_a14 = CpuModel{ + .name = "apple_a14", + .llvm_name = "apple-a14", + .features = featureSet(&[_]Feature{ + .aggressive_fma, + .alternate_sextload_cvt_f32_pattern, + .altnzcv, + .arith_bcc_fusion, + .arith_cbz_fusion, + .ccdp, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fptoint, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .perfmon, + .predres, + .sb, + .sha3, + .specrestrict, + .ssbs, + .v8_4a, + .zcm, + .zcz, + }), + }; + pub const apple_a15 = CpuModel{ + .name = "apple_a15", + .llvm_name = "apple-a15", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fuse_address, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .perfmon, + .sha3, + .v8_6a, + .zcm, + .zcz, + }), + }; + pub const apple_a16 = CpuModel{ + .name = "apple_a16", + .llvm_name = "apple-a16", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fuse_address, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .hcx, + .perfmon, + .sha3, + .v8_6a, + .zcm, + .zcz, + }), + }; + pub const apple_a7 = CpuModel{ + .name = "apple_a7", + .llvm_name = "apple-a7", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8a, + .zcm, + .zcz, + .zcz_fp_workaround, + }), + }; + pub const apple_a8 = CpuModel{ + .name = "apple_a8", + .llvm_name = "apple-a8", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8a, + .zcm, + .zcz, + .zcz_fp_workaround, + }), + }; + pub const apple_a9 = CpuModel{ + .name = "apple_a9", + .llvm_name = "apple-a9", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8a, + .zcm, + .zcz, + .zcz_fp_workaround, + }), + }; + pub const apple_latest = CpuModel{ + .name = "apple_latest", + .llvm_name = "apple-latest", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fuse_address, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .hcx, + .perfmon, + .sha3, + .v8_6a, + .zcm, + .zcz, + }), + }; + pub const apple_m1 = CpuModel{ + .name = "apple_m1", + .llvm_name = "apple-m1", + .features = featureSet(&[_]Feature{ + .aggressive_fma, + .alternate_sextload_cvt_f32_pattern, + .altnzcv, + .arith_bcc_fusion, + .arith_cbz_fusion, + .ccdp, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fptoint, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .perfmon, + .predres, + .sb, + .sha3, + .specrestrict, + .ssbs, + .v8_4a, + .zcm, + .zcz, + }), + }; + pub const apple_m2 = CpuModel{ + .name = "apple_m2", + .llvm_name = "apple-m2", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp16fml, + .fuse_address, + .fuse_aes, + .fuse_arith_logic, + .fuse_crypto_eor, + .fuse_csel, + .fuse_literals, + .perfmon, + .sha3, + .v8_6a, + .zcm, + .zcz, + }), + }; + pub const apple_s4 = CpuModel{ + .name = "apple_s4", + .llvm_name = "apple-s4", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fullfp16, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8_3a, + .zcm, + .zcz, + }), + }; + pub const apple_s5 = CpuModel{ + .name = "apple_s5", + .llvm_name = "apple-s5", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fullfp16, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8_3a, + .zcm, + .zcz, + }), + }; + pub const carmel = CpuModel{ + .name = "carmel", + .llvm_name = "carmel", + .features = featureSet(&[_]Feature{ + .crypto, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a34 = CpuModel{ + .name = "cortex_a34", + .llvm_name = "cortex-a34", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .v8a, + }), + }; + pub const cortex_a35 = CpuModel{ + .name = "cortex_a35", + .llvm_name = "cortex-a35", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .v8a, + }), + }; + pub const cortex_a510 = CpuModel{ + .name = "cortex_a510", + .llvm_name = "cortex-a510", + .features = featureSet(&[_]Feature{ + .a510, + .bf16, + .ete, + .fp16fml, + .i8mm, + .mte, + .perfmon, + .sve2_bitperm, + .v9a, + }), + }; + pub const cortex_a53 = CpuModel{ + .name = "cortex_a53", + .llvm_name = "cortex-a53", + .features = featureSet(&[_]Feature{ + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .fuse_adrp_add, + .fuse_aes, + .perfmon, + .use_postra_scheduler, + .v8a, + }), + }; + pub const cortex_a55 = CpuModel{ + .name = "cortex_a55", + .llvm_name = "cortex-a55", + .features = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .fullfp16, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .perfmon, + .rcpc, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const cortex_a57 = CpuModel{ + .name = "cortex_a57", + .llvm_name = "cortex-a57", + .features = featureSet(&[_]Feature{ + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .fuse_literals, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const cortex_a65 = CpuModel{ + .name = "cortex_a65", + .llvm_name = "cortex-a65", + .features = featureSet(&[_]Feature{ + .a65, + .crypto, + .dotprod, + .fullfp16, + .perfmon, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a65ae = CpuModel{ + .name = "cortex_a65ae", + .llvm_name = "cortex-a65ae", + .features = featureSet(&[_]Feature{ + .a65, + .crypto, + .dotprod, + .fullfp16, + .perfmon, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a710 = CpuModel{ + .name = "cortex_a710", + .llvm_name = "cortex-a710", + .features = featureSet(&[_]Feature{ + .a710, + .bf16, + .ete, + .fp16fml, + .i8mm, + .mte, + .perfmon, + .sve2_bitperm, + .v9a, + }), + }; + pub const cortex_a715 = CpuModel{ + .name = "cortex_a715", + .llvm_name = "cortex-a715", + .features = featureSet(&[_]Feature{ + .bf16, + .cmp_bcc_fusion, + .enable_select_opt, + .ete, + .fp16fml, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .mte, + .perfmon, + .predictable_select_expensive, + .spe, + .sve2_bitperm, + .use_postra_scheduler, + .v9a, + }), + }; + pub const cortex_a72 = CpuModel{ + .name = "cortex_a72", + .llvm_name = "cortex-a72", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .fuse_literals, + .perfmon, + .predictable_select_expensive, + .v8a, + }), + }; + pub const cortex_a73 = CpuModel{ + .name = "cortex_a73", + .llvm_name = "cortex-a73", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .enable_select_opt, + .fuse_adrp_add, + .fuse_aes, + .perfmon, + .predictable_select_expensive, + .v8a, + }), + }; + pub const cortex_a75 = CpuModel{ + .name = "cortex_a75", + .llvm_name = "cortex-a75", + .features = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .enable_select_opt, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .perfmon, + .predictable_select_expensive, + .rcpc, + .v8_2a, + }), + }; + pub const cortex_a76 = CpuModel{ + .name = "cortex_a76", + .llvm_name = "cortex-a76", + .features = featureSet(&[_]Feature{ + .a76, + .crypto, + .dotprod, + .fullfp16, + .perfmon, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a76ae = CpuModel{ + .name = "cortex_a76ae", + .llvm_name = "cortex-a76ae", + .features = featureSet(&[_]Feature{ + .a76, + .crypto, + .dotprod, + .fullfp16, + .perfmon, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a77 = CpuModel{ + .name = "cortex_a77", + .llvm_name = "cortex-a77", + .features = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .crypto, + .dotprod, + .enable_select_opt, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a78 = CpuModel{ + .name = "cortex_a78", + .llvm_name = "cortex-a78", + .features = featureSet(&[_]Feature{ + .a78, + .crypto, + .dotprod, + .fullfp16, + .perfmon, + .rcpc, + .spe, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_a78c = CpuModel{ + .name = "cortex_a78c", + .llvm_name = "cortex-a78c", + .features = featureSet(&[_]Feature{ + .a78c, + .crypto, + .dotprod, + .flagm, + .fp16fml, + .pauth, + .perfmon, + .rcpc, + .spe, + .ssbs, + .v8_2a, + }), + }; + pub const cortex_r82 = CpuModel{ + .name = "cortex_r82", + .llvm_name = "cortex-r82", + .features = featureSet(&[_]Feature{ + .cortex_r82, + .fp16fml, + .perfmon, + .predres, + .sb, + .ssbs, + .v8r, + }), + }; + pub const cortex_x1 = CpuModel{ + .name = "cortex_x1", + .llvm_name = "cortex-x1", + .features = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .crypto, + .dotprod, + .enable_select_opt, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rcpc, + .spe, + .ssbs, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const cortex_x1c = CpuModel{ + .name = "cortex_x1c", + .llvm_name = "cortex-x1c", + .features = featureSet(&[_]Feature{ + .cmp_bcc_fusion, + .crypto, + .dotprod, + .enable_select_opt, + .flagm, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .lse2, + .lsl_fast, + .pauth, + .perfmon, + .predictable_select_expensive, + .rcpc_immo, + .spe, + .ssbs, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const cortex_x2 = CpuModel{ + .name = "cortex_x2", + .llvm_name = "cortex-x2", + .features = featureSet(&[_]Feature{ + .bf16, + .cmp_bcc_fusion, + .enable_select_opt, + .ete, + .fp16fml, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .mte, + .perfmon, + .predictable_select_expensive, + .sve2_bitperm, + .use_postra_scheduler, + .v9a, + }), + }; + pub const cortex_x3 = CpuModel{ + .name = "cortex_x3", + .llvm_name = "cortex-x3", + .features = featureSet(&[_]Feature{ + .bf16, + .enable_select_opt, + .ete, + .fp16fml, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .mte, + .perfmon, + .predictable_select_expensive, + .spe, + .sve2_bitperm, + .use_postra_scheduler, + .v9a, + }), + }; + pub const cyclone = CpuModel{ + .name = "cyclone", + .llvm_name = "cyclone", + .features = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fuse_aes, + .fuse_crypto_eor, + .perfmon, + .v8a, + .zcm, + .zcz, + .zcz_fp_workaround, + }), + }; + pub const emag = CpuModel{ + .name = "emag", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .v8a, + }), + }; + pub const exynos_m1 = CpuModel{ + .name = "exynos_m1", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .use_reciprocal_square_root, + .v8a, + }), + }; + pub const exynos_m2 = CpuModel{ + .name = "exynos_m2", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .v8a, + }), + }; + pub const exynos_m3 = CpuModel{ + .name = "exynos_m3", + .llvm_name = "exynos-m3", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const exynos_m4 = CpuModel{ + .name = "exynos_m4", + .llvm_name = "exynos-m4", + .features = featureSet(&[_]Feature{ + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .dotprod, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fullfp16, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_arith_logic, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .use_postra_scheduler, + .v8_2a, + .zcz, + }), + }; + pub const exynos_m5 = CpuModel{ + .name = "exynos_m5", + .llvm_name = "exynos-m5", + .features = featureSet(&[_]Feature{ + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .dotprod, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fullfp16, + .fuse_address, + .fuse_adrp_add, + .fuse_aes, + .fuse_arith_logic, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .use_postra_scheduler, + .v8_2a, + .zcz, + }), + }; + pub const falkor = CpuModel{ + .name = "falkor", + .llvm_name = "falkor", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rdm, + .slow_strqro_store, + .use_postra_scheduler, + .v8a, + .zcz, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .enable_select_opt, + .ete, + .fuse_adrp_add, + .fuse_aes, + .neon, + .use_postra_scheduler, + }), + }; + pub const kryo = CpuModel{ + .name = "kryo", + .llvm_name = "kryo", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + .zcz, + }), + }; + pub const neoverse_512tvb = CpuModel{ + .name = "neoverse_512tvb", + .llvm_name = "neoverse-512tvb", + .features = featureSet(&[_]Feature{ + .bf16, + .ccdp, + .crypto, + .enable_select_opt, + .fp16fml, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rand, + .spe, + .ssbs, + .sve, + .use_postra_scheduler, + .v8_4a, + }), + }; + pub const neoverse_e1 = CpuModel{ + .name = "neoverse_e1", + .llvm_name = "neoverse-e1", + .features = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .perfmon, + .rcpc, + .ssbs, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const neoverse_n1 = CpuModel{ + .name = "neoverse_n1", + .llvm_name = "neoverse-n1", + .features = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .enable_select_opt, + .fullfp16, + .fuse_adrp_add, + .fuse_aes, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .rcpc, + .spe, + .ssbs, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const neoverse_n2 = CpuModel{ + .name = "neoverse_n2", + .llvm_name = "neoverse-n2", + .features = featureSet(&[_]Feature{ + .bf16, + .crypto, + .enable_select_opt, + .ete, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .mte, + .perfmon, + .predictable_select_expensive, + .sve2_bitperm, + .use_postra_scheduler, + .v8_5a, + }), + }; + pub const neoverse_v1 = CpuModel{ + .name = "neoverse_v1", + .llvm_name = "neoverse-v1", + .features = featureSet(&[_]Feature{ + .bf16, + .ccdp, + .crypto, + .enable_select_opt, + .fp16fml, + .fuse_adrp_add, + .fuse_aes, + .i8mm, + .lsl_fast, + .no_sve_fp_ld1r, + .perfmon, + .predictable_select_expensive, + .rand, + .spe, + .ssbs, + .sve, + .use_postra_scheduler, + .v8_4a, + }), + }; + pub const neoverse_v2 = CpuModel{ + .name = "neoverse_v2", + .llvm_name = "neoverse-v2", + .features = featureSet(&[_]Feature{ + .bf16, + .enable_select_opt, + .ete, + .fp16fml, + .fuse_aes, + .i8mm, + .lsl_fast, + .mte, + .perfmon, + .predictable_select_expensive, + .rand, + .spe, + .sve2_bitperm, + .use_postra_scheduler, + .v9a, + }), + }; + pub const saphira = CpuModel{ + .name = "saphira", + .llvm_name = "saphira", + .features = featureSet(&[_]Feature{ + .crypto, + .custom_cheap_as_move, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .spe, + .use_postra_scheduler, + .v8_4a, + .zcz, + }), + }; + pub const thunderx = CpuModel{ + .name = "thunderx", + .llvm_name = "thunderx", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const thunderx2t99 = CpuModel{ + .name = "thunderx2t99", + .llvm_name = "thunderx2t99", + .features = featureSet(&[_]Feature{ + .aggressive_fma, + .arith_bcc_fusion, + .crypto, + .predictable_select_expensive, + .use_postra_scheduler, + .v8_1a, + }), + }; + pub const thunderx3t110 = CpuModel{ + .name = "thunderx3t110", + .llvm_name = "thunderx3t110", + .features = featureSet(&[_]Feature{ + .aggressive_fma, + .arith_bcc_fusion, + .balance_fp_ops, + .crypto, + .perfmon, + .predictable_select_expensive, + .strict_align, + .use_postra_scheduler, + .v8_3a, + }), + }; + pub const thunderxt81 = CpuModel{ + .name = "thunderxt81", + .llvm_name = "thunderxt81", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const thunderxt83 = CpuModel{ + .name = "thunderxt83", + .llvm_name = "thunderxt83", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const thunderxt88 = CpuModel{ + .name = "thunderxt88", + .llvm_name = "thunderxt88", + .features = featureSet(&[_]Feature{ + .crc, + .crypto, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8a, + }), + }; + pub const tsv110 = CpuModel{ + .name = "tsv110", + .llvm_name = "tsv110", + .features = featureSet(&[_]Feature{ + .crypto, + .custom_cheap_as_move, + .dotprod, + .fp16fml, + .fuse_aes, + .perfmon, + .spe, + .use_postra_scheduler, + .v8_2a, + }), + }; + pub const xgene1 = CpuModel{ + .name = "xgene1", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .perfmon, + .v8a, + }), + }; +}; diff --git a/lib/std/Target/amdgpu.zig b/lib/std/Target/amdgpu.zig new file mode 100644 index 0000000000000000000000000000000000000000..012f652088a0d74236e640d15e3490cdd4abaa89 --- /dev/null +++ b/lib/std/Target/amdgpu.zig @@ -0,0 +1,2153 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"16_bit_insts", + a16, + add_no_carry_insts, + aperture_regs, + architected_flat_scratch, + architected_sgprs, + atomic_buffer_global_pk_add_f16_insts, + atomic_buffer_global_pk_add_f16_no_rtn_insts, + atomic_ds_pk_add_16_insts, + atomic_fadd_no_rtn_insts, + atomic_fadd_rtn_insts, + atomic_flat_pk_add_16_insts, + atomic_global_pk_add_bf16_inst, + auto_waitcnt_before_barrier, + back_off_barrier, + ci_insts, + cumode, + dl_insts, + dot10_insts, + dot1_insts, + dot2_insts, + dot3_insts, + dot4_insts, + dot5_insts, + dot6_insts, + dot7_insts, + dot8_insts, + dot9_insts, + dpp, + dpp8, + dpp_64bit, + ds128, + ds_src2_insts, + extended_image_insts, + fast_denormal_f32, + fast_fmaf, + flat_address_space, + flat_atomic_fadd_f32_inst, + flat_for_global, + flat_global_insts, + flat_inst_offsets, + flat_scratch, + flat_scratch_insts, + flat_segment_offset_bug, + fma_mix_insts, + fmacf64_inst, + fmaf, + force_store_sc0_sc1, + fp64, + fp8_insts, + full_rate_64_ops, + g16, + gcn3_encoding, + get_wave_id_inst, + gfx10, + gfx10_3_insts, + gfx10_a_encoding, + gfx10_b_encoding, + gfx10_insts, + gfx11, + gfx11_full_vgprs, + gfx11_insts, + gfx7_gfx8_gfx9_insts, + gfx8_insts, + gfx9, + gfx90a_insts, + gfx940_insts, + gfx9_insts, + half_rate_64_ops, + image_gather4_d16_bug, + image_insts, + image_store_d16_bug, + inst_fwd_prefetch_bug, + int_clamp_insts, + inv_2pi_inline_imm, + lds_branch_vmem_war_hazard, + lds_misaligned_bug, + ldsbankcount16, + ldsbankcount32, + load_store_opt, + localmemorysize32768, + localmemorysize65536, + mad_intra_fwd_bug, + mad_mac_f32_insts, + mad_mix_insts, + mai_insts, + max_private_element_size_16, + max_private_element_size_4, + max_private_element_size_8, + mfma_inline_literal_bug, + mimg_r128, + movrel, + negative_scratch_offset_bug, + negative_unaligned_scratch_offset_bug, + no_data_dep_hazard, + no_sdst_cmpx, + nsa_clause_bug, + nsa_encoding, + nsa_to_vmem_bug, + offset_3f_bug, + packed_fp32_ops, + packed_tid, + partial_nsa_encoding, + pk_fmac_f16_inst, + promote_alloca, + prt_strict_null, + r128_a16, + s_memrealtime, + s_memtime_inst, + scalar_atomics, + scalar_flat_scratch_insts, + scalar_stores, + sdwa, + sdwa_mav, + sdwa_omod, + sdwa_out_mods_vopc, + sdwa_scalar, + sdwa_sdst, + sea_islands, + sgpr_init_bug, + shader_cycles_register, + si_scheduler, + smem_to_vector_write_hazard, + southern_islands, + sramecc, + sramecc_support, + tgsplit, + trap_handler, + trig_reduced_range, + true16, + unaligned_access_mode, + unaligned_buffer_access, + unaligned_ds_access, + unaligned_scratch_access, + unpacked_d16_vmem, + unsafe_ds_offset_folding, + user_sgpr_init16_bug, + valu_trans_use_hazard, + vcmpx_exec_war_hazard, + vcmpx_permlane_hazard, + vgpr_index_mode, + vmem_to_scalar_write_hazard, + volcanic_islands, + vop3_literal, + vop3p, + vopd, + vscnt, + wavefrontsize16, + wavefrontsize32, + wavefrontsize64, + xnack, + xnack_support, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"16_bit_insts")] = .{ + .llvm_name = "16-bit-insts", + .description = "Has i16/f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.a16)] = .{ + .llvm_name = "a16", + .description = "Support A16 for 16-bit coordinates/gradients/lod/clamp/mip image operands", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.add_no_carry_insts)] = .{ + .llvm_name = "add-no-carry-insts", + .description = "Have VALU add/sub instructions without carry out", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aperture_regs)] = .{ + .llvm_name = "aperture-regs", + .description = "Has Memory Aperture Base and Size Registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.architected_flat_scratch)] = .{ + .llvm_name = "architected-flat-scratch", + .description = "Flat Scratch register is a readonly SPI initialized architected register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.architected_sgprs)] = .{ + .llvm_name = "architected-sgprs", + .description = "Enable the architected SGPRs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.atomic_buffer_global_pk_add_f16_insts)] = .{ + .llvm_name = "atomic-buffer-global-pk-add-f16-insts", + .description = "Has buffer_atomic_pk_add_f16 and global_atomic_pk_add_f16 instructions that can return original value", + .dependencies = featureSet(&[_]Feature{ + .flat_global_insts, + }), + }; + result[@intFromEnum(Feature.atomic_buffer_global_pk_add_f16_no_rtn_insts)] = .{ + .llvm_name = "atomic-buffer-global-pk-add-f16-no-rtn-insts", + .description = "Has buffer_atomic_pk_add_f16 and global_atomic_pk_add_f16 instructions that don't return original value", + .dependencies = featureSet(&[_]Feature{ + .flat_global_insts, + }), + }; + result[@intFromEnum(Feature.atomic_ds_pk_add_16_insts)] = .{ + .llvm_name = "atomic-ds-pk-add-16-insts", + .description = "Has ds_pk_add_bf16, ds_pk_add_f16, ds_pk_add_rtn_bf16, ds_pk_add_rtn_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.atomic_fadd_no_rtn_insts)] = .{ + .llvm_name = "atomic-fadd-no-rtn-insts", + .description = "Has buffer_atomic_add_f32 and global_atomic_add_f32 instructions that don't return original value", + .dependencies = featureSet(&[_]Feature{ + .flat_global_insts, + }), + }; + result[@intFromEnum(Feature.atomic_fadd_rtn_insts)] = .{ + .llvm_name = "atomic-fadd-rtn-insts", + .description = "Has buffer_atomic_add_f32 and global_atomic_add_f32 instructions that return original value", + .dependencies = featureSet(&[_]Feature{ + .flat_global_insts, + }), + }; + result[@intFromEnum(Feature.atomic_flat_pk_add_16_insts)] = .{ + .llvm_name = "atomic-flat-pk-add-16-insts", + .description = "Has flat_atomic_pk_add_f16 and flat_atomic_pk_add_bf16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.atomic_global_pk_add_bf16_inst)] = .{ + .llvm_name = "atomic-global-pk-add-bf16-inst", + .description = "Has global_atomic_pk_add_bf16 instruction", + .dependencies = featureSet(&[_]Feature{ + .flat_global_insts, + }), + }; + result[@intFromEnum(Feature.auto_waitcnt_before_barrier)] = .{ + .llvm_name = "auto-waitcnt-before-barrier", + .description = "Hardware automatically inserts waitcnt before barrier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.back_off_barrier)] = .{ + .llvm_name = "back-off-barrier", + .description = "Hardware supports backing off s_barrier if an exception occurs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ci_insts)] = .{ + .llvm_name = "ci-insts", + .description = "Additional instructions for CI+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cumode)] = .{ + .llvm_name = "cumode", + .description = "Enable CU wavefront execution mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dl_insts)] = .{ + .llvm_name = "dl-insts", + .description = "Has v_fmac_f32 and v_xnor_b32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot10_insts)] = .{ + .llvm_name = "dot10-insts", + .description = "Has v_dot2_f32_f16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot1_insts)] = .{ + .llvm_name = "dot1-insts", + .description = "Has v_dot4_i32_i8 and v_dot8_i32_i4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot2_insts)] = .{ + .llvm_name = "dot2-insts", + .description = "Has v_dot2_i32_i16, v_dot2_u32_u16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot3_insts)] = .{ + .llvm_name = "dot3-insts", + .description = "Has v_dot8c_i32_i4 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot4_insts)] = .{ + .llvm_name = "dot4-insts", + .description = "Has v_dot2c_i32_i16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot5_insts)] = .{ + .llvm_name = "dot5-insts", + .description = "Has v_dot2c_f32_f16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot6_insts)] = .{ + .llvm_name = "dot6-insts", + .description = "Has v_dot4c_i32_i8 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot7_insts)] = .{ + .llvm_name = "dot7-insts", + .description = "Has v_dot4_u32_u8, v_dot8_u32_u4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot8_insts)] = .{ + .llvm_name = "dot8-insts", + .description = "Has v_dot4_i32_iu8, v_dot8_i32_iu4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dot9_insts)] = .{ + .llvm_name = "dot9-insts", + .description = "Has v_dot2_f16_f16, v_dot2_bf16_bf16, v_dot2_f32_bf16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dpp)] = .{ + .llvm_name = "dpp", + .description = "Support DPP (Data Parallel Primitives) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dpp8)] = .{ + .llvm_name = "dpp8", + .description = "Support DPP8 (Data Parallel Primitives) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dpp_64bit)] = .{ + .llvm_name = "dpp-64bit", + .description = "Support DPP (Data Parallel Primitives) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ds128)] = .{ + .llvm_name = "enable-ds128", + .description = "Use ds_{read|write}_b128", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ds_src2_insts)] = .{ + .llvm_name = "ds-src2-insts", + .description = "Has ds_*_src2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.extended_image_insts)] = .{ + .llvm_name = "extended-image-insts", + .description = "Support mips != 0, lod != 0, gather4, and get_lod", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_denormal_f32)] = .{ + .llvm_name = "fast-denormal-f32", + .description = "Enabling denormals does not cause f32 instructions to run at f64 rates", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_fmaf)] = .{ + .llvm_name = "fast-fmaf", + .description = "Assuming f32 fma is at least as fast as mul + add", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_address_space)] = .{ + .llvm_name = "flat-address-space", + .description = "Support flat address space", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_atomic_fadd_f32_inst)] = .{ + .llvm_name = "flat-atomic-fadd-f32-inst", + .description = "Has flat_atomic_add_f32 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_for_global)] = .{ + .llvm_name = "flat-for-global", + .description = "Force to generate flat instruction for global", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_global_insts)] = .{ + .llvm_name = "flat-global-insts", + .description = "Have global_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_inst_offsets)] = .{ + .llvm_name = "flat-inst-offsets", + .description = "Flat instructions have immediate offset addressing mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_scratch)] = .{ + .llvm_name = "enable-flat-scratch", + .description = "Use scratch_* flat memory instructions to access scratch", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_scratch_insts)] = .{ + .llvm_name = "flat-scratch-insts", + .description = "Have scratch_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.flat_segment_offset_bug)] = .{ + .llvm_name = "flat-segment-offset-bug", + .description = "GFX10 bug where inst_offset is ignored when flat instructions access global memory", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fma_mix_insts)] = .{ + .llvm_name = "fma-mix-insts", + .description = "Has v_fma_mix_f32, v_fma_mixlo_f16, v_fma_mixhi_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fmacf64_inst)] = .{ + .llvm_name = "fmacf64-inst", + .description = "Has v_fmac_f64 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fmaf)] = .{ + .llvm_name = "fmaf", + .description = "Enable single precision FMA (not as fast as mul+add, but fused)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.force_store_sc0_sc1)] = .{ + .llvm_name = "force-store-sc0-sc1", + .description = "Has SC0 and SC1 on stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Enable double precision operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp8_insts)] = .{ + .llvm_name = "fp8-insts", + .description = "Has fp8 and bf8 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.full_rate_64_ops)] = .{ + .llvm_name = "full-rate-64-ops", + .description = "Most fp64 instructions are full rate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.g16)] = .{ + .llvm_name = "g16", + .description = "Support G16 for 16-bit gradient image operands", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gcn3_encoding)] = .{ + .llvm_name = "gcn3-encoding", + .description = "Encoding format for VI", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.get_wave_id_inst)] = .{ + .llvm_name = "get-wave-id-inst", + .description = "Has s_get_waveid_in_workgroup instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx10)] = .{ + .llvm_name = "gfx10", + .description = "GFX10 GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .a16, + .add_no_carry_insts, + .aperture_regs, + .ci_insts, + .dpp, + .dpp8, + .extended_image_insts, + .fast_denormal_f32, + .fast_fmaf, + .flat_address_space, + .flat_global_insts, + .flat_inst_offsets, + .flat_scratch_insts, + .fma_mix_insts, + .fp64, + .g16, + .gfx10_insts, + .gfx8_insts, + .gfx9_insts, + .image_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .mimg_r128, + .movrel, + .no_data_dep_hazard, + .no_sdst_cmpx, + .pk_fmac_f16_inst, + .s_memrealtime, + .s_memtime_inst, + .sdwa, + .sdwa_omod, + .sdwa_scalar, + .sdwa_sdst, + .unaligned_buffer_access, + .unaligned_ds_access, + .vop3_literal, + .vop3p, + .vscnt, + }), + }; + result[@intFromEnum(Feature.gfx10_3_insts)] = .{ + .llvm_name = "gfx10-3-insts", + .description = "Additional instructions for GFX10.3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx10_a_encoding)] = .{ + .llvm_name = "gfx10_a-encoding", + .description = "Has BVH ray tracing instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx10_b_encoding)] = .{ + .llvm_name = "gfx10_b-encoding", + .description = "Encoding format GFX10_B", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx10_insts)] = .{ + .llvm_name = "gfx10-insts", + .description = "Additional instructions for GFX10+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx11)] = .{ + .llvm_name = "gfx11", + .description = "GFX11 GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .a16, + .add_no_carry_insts, + .aperture_regs, + .ci_insts, + .dpp, + .dpp8, + .extended_image_insts, + .fast_denormal_f32, + .fast_fmaf, + .flat_address_space, + .flat_global_insts, + .flat_inst_offsets, + .flat_scratch_insts, + .fma_mix_insts, + .fp64, + .g16, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .gfx10_insts, + .gfx11_insts, + .gfx8_insts, + .gfx9_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .mimg_r128, + .movrel, + .no_data_dep_hazard, + .no_sdst_cmpx, + .pk_fmac_f16_inst, + .true16, + .unaligned_buffer_access, + .unaligned_ds_access, + .vop3_literal, + .vop3p, + .vopd, + .vscnt, + }), + }; + result[@intFromEnum(Feature.gfx11_full_vgprs)] = .{ + .llvm_name = "gfx11-full-vgprs", + .description = "GFX11 with 50% more physical VGPRs and 50% larger allocation granule than GFX10", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx11_insts)] = .{ + .llvm_name = "gfx11-insts", + .description = "Additional instructions for GFX11+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx7_gfx8_gfx9_insts)] = .{ + .llvm_name = "gfx7-gfx8-gfx9-insts", + .description = "Instructions shared in GFX7, GFX8, GFX9", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx8_insts)] = .{ + .llvm_name = "gfx8-insts", + .description = "Additional instructions for GFX8+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx9)] = .{ + .llvm_name = "gfx9", + .description = "GFX9 GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .a16, + .add_no_carry_insts, + .aperture_regs, + .ci_insts, + .dpp, + .fast_denormal_f32, + .fast_fmaf, + .flat_address_space, + .flat_global_insts, + .flat_inst_offsets, + .flat_scratch_insts, + .fp64, + .gcn3_encoding, + .gfx7_gfx8_gfx9_insts, + .gfx8_insts, + .gfx9_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .negative_scratch_offset_bug, + .r128_a16, + .s_memrealtime, + .s_memtime_inst, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .sdwa, + .sdwa_omod, + .sdwa_scalar, + .sdwa_sdst, + .unaligned_buffer_access, + .unaligned_ds_access, + .vgpr_index_mode, + .vop3p, + .wavefrontsize64, + .xnack_support, + }), + }; + result[@intFromEnum(Feature.gfx90a_insts)] = .{ + .llvm_name = "gfx90a-insts", + .description = "Additional instructions for GFX90A+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx940_insts)] = .{ + .llvm_name = "gfx940-insts", + .description = "Additional instructions for GFX940+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfx9_insts)] = .{ + .llvm_name = "gfx9-insts", + .description = "Additional instructions for GFX9+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.half_rate_64_ops)] = .{ + .llvm_name = "half-rate-64-ops", + .description = "Most fp64 instructions are half rate instead of quarter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.image_gather4_d16_bug)] = .{ + .llvm_name = "image-gather4-d16-bug", + .description = "Image Gather4 D16 hardware bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.image_insts)] = .{ + .llvm_name = "image-insts", + .description = "Support image instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.image_store_d16_bug)] = .{ + .llvm_name = "image-store-d16-bug", + .description = "Image Store D16 hardware bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.inst_fwd_prefetch_bug)] = .{ + .llvm_name = "inst-fwd-prefetch-bug", + .description = "S_INST_PREFETCH instruction causes shader to hang", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.int_clamp_insts)] = .{ + .llvm_name = "int-clamp-insts", + .description = "Support clamp for integer destination", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.inv_2pi_inline_imm)] = .{ + .llvm_name = "inv-2pi-inline-imm", + .description = "Has 1 / (2 * pi) as inline immediate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lds_branch_vmem_war_hazard)] = .{ + .llvm_name = "lds-branch-vmem-war-hazard", + .description = "Switching between LDS and VMEM-tex not waiting VM_VSRC=0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lds_misaligned_bug)] = .{ + .llvm_name = "lds-misaligned-bug", + .description = "Some GFX10 bug with multi-dword LDS and flat access that is not naturally aligned in WGP mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ldsbankcount16)] = .{ + .llvm_name = "ldsbankcount16", + .description = "The number of LDS banks per compute unit.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ldsbankcount32)] = .{ + .llvm_name = "ldsbankcount32", + .description = "The number of LDS banks per compute unit.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.load_store_opt)] = .{ + .llvm_name = "load-store-opt", + .description = "Enable SI load/store optimizer pass", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.localmemorysize32768)] = .{ + .llvm_name = "localmemorysize32768", + .description = "The size of local memory in bytes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.localmemorysize65536)] = .{ + .llvm_name = "localmemorysize65536", + .description = "The size of local memory in bytes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mad_intra_fwd_bug)] = .{ + .llvm_name = "mad-intra-fwd-bug", + .description = "MAD_U64/I64 intra instruction forwarding bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mad_mac_f32_insts)] = .{ + .llvm_name = "mad-mac-f32-insts", + .description = "Has v_mad_f32/v_mac_f32/v_madak_f32/v_madmk_f32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mad_mix_insts)] = .{ + .llvm_name = "mad-mix-insts", + .description = "Has v_mad_mix_f32, v_mad_mixlo_f16, v_mad_mixhi_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mai_insts)] = .{ + .llvm_name = "mai-insts", + .description = "Has mAI instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.max_private_element_size_16)] = .{ + .llvm_name = "max-private-element-size-16", + .description = "Maximum private access size may be 16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.max_private_element_size_4)] = .{ + .llvm_name = "max-private-element-size-4", + .description = "Maximum private access size may be 4", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.max_private_element_size_8)] = .{ + .llvm_name = "max-private-element-size-8", + .description = "Maximum private access size may be 8", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mfma_inline_literal_bug)] = .{ + .llvm_name = "mfma-inline-literal-bug", + .description = "MFMA cannot use inline literal as SrcC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mimg_r128)] = .{ + .llvm_name = "mimg-r128", + .description = "Support 128-bit texture resources", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.movrel)] = .{ + .llvm_name = "movrel", + .description = "Has v_movrel*_b32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.negative_scratch_offset_bug)] = .{ + .llvm_name = "negative-scratch-offset-bug", + .description = "Negative immediate offsets in scratch instructions with an SGPR offset page fault on GFX9", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.negative_unaligned_scratch_offset_bug)] = .{ + .llvm_name = "negative-unaligned-scratch-offset-bug", + .description = "Scratch instructions with a VGPR offset and a negative immediate offset that is not a multiple of 4 read wrong memory on GFX10", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_data_dep_hazard)] = .{ + .llvm_name = "no-data-dep-hazard", + .description = "Does not need SW waitstates", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_sdst_cmpx)] = .{ + .llvm_name = "no-sdst-cmpx", + .description = "V_CMPX does not write VCC/SGPR in addition to EXEC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nsa_clause_bug)] = .{ + .llvm_name = "nsa-clause-bug", + .description = "MIMG-NSA in a hard clause has unpredictable results on GFX10.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nsa_encoding)] = .{ + .llvm_name = "nsa-encoding", + .description = "Support NSA encoding for image instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nsa_to_vmem_bug)] = .{ + .llvm_name = "nsa-to-vmem-bug", + .description = "MIMG-NSA followed by VMEM fail if EXEC_LO or EXEC_HI equals zero", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.offset_3f_bug)] = .{ + .llvm_name = "offset-3f-bug", + .description = "Branch offset of 3f hardware bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.packed_fp32_ops)] = .{ + .llvm_name = "packed-fp32-ops", + .description = "Support packed fp32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.packed_tid)] = .{ + .llvm_name = "packed-tid", + .description = "Workitem IDs are packed into v0 at kernel launch", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.partial_nsa_encoding)] = .{ + .llvm_name = "partial-nsa-encoding", + .description = "Support partial NSA encoding for image instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pk_fmac_f16_inst)] = .{ + .llvm_name = "pk-fmac-f16-inst", + .description = "Has v_pk_fmac_f16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.promote_alloca)] = .{ + .llvm_name = "promote-alloca", + .description = "Enable promote alloca pass", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prt_strict_null)] = .{ + .llvm_name = "enable-prt-strict-null", + .description = "Enable zeroing of result registers for sparse texture fetches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.r128_a16)] = .{ + .llvm_name = "r128-a16", + .description = "Support gfx9-style A16 for 16-bit coordinates/gradients/lod/clamp/mip image operands, where a16 is aliased with r128", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.s_memrealtime)] = .{ + .llvm_name = "s-memrealtime", + .description = "Has s_memrealtime instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.s_memtime_inst)] = .{ + .llvm_name = "s-memtime-inst", + .description = "Has s_memtime instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.scalar_atomics)] = .{ + .llvm_name = "scalar-atomics", + .description = "Has atomic scalar memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.scalar_flat_scratch_insts)] = .{ + .llvm_name = "scalar-flat-scratch-insts", + .description = "Have s_scratch_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.scalar_stores)] = .{ + .llvm_name = "scalar-stores", + .description = "Has store scalar memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa)] = .{ + .llvm_name = "sdwa", + .description = "Support SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa_mav)] = .{ + .llvm_name = "sdwa-mav", + .description = "Support v_mac_f32/f16 with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa_omod)] = .{ + .llvm_name = "sdwa-omod", + .description = "Support OMod with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa_out_mods_vopc)] = .{ + .llvm_name = "sdwa-out-mods-vopc", + .description = "Support clamp for VOPC with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa_scalar)] = .{ + .llvm_name = "sdwa-scalar", + .description = "Support scalar register with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sdwa_sdst)] = .{ + .llvm_name = "sdwa-sdst", + .description = "Support scalar dst for VOPC with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sea_islands)] = .{ + .llvm_name = "sea-islands", + .description = "SEA_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .ci_insts, + .ds_src2_insts, + .extended_image_insts, + .flat_address_space, + .fp64, + .gfx7_gfx8_gfx9_insts, + .image_insts, + .localmemorysize65536, + .mad_mac_f32_insts, + .mimg_r128, + .movrel, + .s_memtime_inst, + .trig_reduced_range, + .unaligned_buffer_access, + .wavefrontsize64, + }), + }; + result[@intFromEnum(Feature.sgpr_init_bug)] = .{ + .llvm_name = "sgpr-init-bug", + .description = "VI SGPR initialization bug requiring a fixed SGPR allocation size", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.shader_cycles_register)] = .{ + .llvm_name = "shader-cycles-register", + .description = "Has SHADER_CYCLES hardware register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.si_scheduler)] = .{ + .llvm_name = "si-scheduler", + .description = "Enable SI Machine Scheduler", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.smem_to_vector_write_hazard)] = .{ + .llvm_name = "smem-to-vector-write-hazard", + .description = "s_load_dword followed by v_cmp page faults", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.southern_islands)] = .{ + .llvm_name = "southern-islands", + .description = "SOUTHERN_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .fp64, + .image_insts, + .ldsbankcount32, + .localmemorysize32768, + .mad_mac_f32_insts, + .mimg_r128, + .movrel, + .s_memtime_inst, + .trig_reduced_range, + .wavefrontsize64, + }), + }; + result[@intFromEnum(Feature.sramecc)] = .{ + .llvm_name = "sramecc", + .description = "Enable SRAMECC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sramecc_support)] = .{ + .llvm_name = "sramecc-support", + .description = "Hardware supports SRAMECC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tgsplit)] = .{ + .llvm_name = "tgsplit", + .description = "Enable threadgroup split execution", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.trap_handler)] = .{ + .llvm_name = "trap-handler", + .description = "Trap handler support", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.trig_reduced_range)] = .{ + .llvm_name = "trig-reduced-range", + .description = "Requires use of fract on arguments to trig instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.true16)] = .{ + .llvm_name = "true16", + .description = "True 16-bit operand instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_access_mode)] = .{ + .llvm_name = "unaligned-access-mode", + .description = "Enable unaligned global, local and region loads and stores if the hardware supports it", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_buffer_access)] = .{ + .llvm_name = "unaligned-buffer-access", + .description = "Hardware supports unaligned global loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_ds_access)] = .{ + .llvm_name = "unaligned-ds-access", + .description = "Hardware supports unaligned local and region loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_scratch_access)] = .{ + .llvm_name = "unaligned-scratch-access", + .description = "Support unaligned scratch loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unpacked_d16_vmem)] = .{ + .llvm_name = "unpacked-d16-vmem", + .description = "Has unpacked d16 vmem instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unsafe_ds_offset_folding)] = .{ + .llvm_name = "unsafe-ds-offset-folding", + .description = "Force using DS instruction immediate offsets on SI", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.user_sgpr_init16_bug)] = .{ + .llvm_name = "user-sgpr-init16-bug", + .description = "Bug requiring at least 16 user+system SGPRs to be enabled", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.valu_trans_use_hazard)] = .{ + .llvm_name = "valu-trans-use-hazard", + .description = "Hazard when TRANS instructions are closely followed by a use of the result", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vcmpx_exec_war_hazard)] = .{ + .llvm_name = "vcmpx-exec-war-hazard", + .description = "V_CMPX WAR hazard on EXEC (V_CMPX issue ONLY)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vcmpx_permlane_hazard)] = .{ + .llvm_name = "vcmpx-permlane-hazard", + .description = "TODO: describe me", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vgpr_index_mode)] = .{ + .llvm_name = "vgpr-index-mode", + .description = "Has VGPR mode register indexing", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vmem_to_scalar_write_hazard)] = .{ + .llvm_name = "vmem-to-scalar-write-hazard", + .description = "VMEM instruction followed by scalar writing to EXEC mask, M0 or SGPR leads to incorrect execution.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.volcanic_islands)] = .{ + .llvm_name = "volcanic-islands", + .description = "VOLCANIC_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .ci_insts, + .dpp, + .ds_src2_insts, + .extended_image_insts, + .fast_denormal_f32, + .flat_address_space, + .fp64, + .gcn3_encoding, + .gfx7_gfx8_gfx9_insts, + .gfx8_insts, + .image_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .mad_mac_f32_insts, + .mimg_r128, + .movrel, + .s_memrealtime, + .s_memtime_inst, + .scalar_stores, + .sdwa, + .sdwa_mav, + .sdwa_out_mods_vopc, + .trig_reduced_range, + .unaligned_buffer_access, + .vgpr_index_mode, + .wavefrontsize64, + }), + }; + result[@intFromEnum(Feature.vop3_literal)] = .{ + .llvm_name = "vop3-literal", + .description = "Can use one literal in VOP3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vop3p)] = .{ + .llvm_name = "vop3p", + .description = "Has VOP3P packed instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vopd)] = .{ + .llvm_name = "vopd", + .description = "Has VOPD dual issue wave32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vscnt)] = .{ + .llvm_name = "vscnt", + .description = "Has separate store vscnt counter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.wavefrontsize16)] = .{ + .llvm_name = "wavefrontsize16", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.wavefrontsize32)] = .{ + .llvm_name = "wavefrontsize32", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.wavefrontsize64)] = .{ + .llvm_name = "wavefrontsize64", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xnack)] = .{ + .llvm_name = "xnack", + .description = "Enable XNACK support", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xnack_support)] = .{ + .llvm_name = "xnack-support", + .description = "Hardware supports XNACK", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const bonaire = CpuModel{ + .name = "bonaire", + .llvm_name = "bonaire", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sea_islands, + }), + }; + pub const carrizo = CpuModel{ + .name = "carrizo", + .llvm_name = "carrizo", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + .xnack_support, + }), + }; + pub const fiji = CpuModel{ + .name = "fiji", + .llvm_name = "fiji", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .wavefrontsize64, + }), + }; + pub const generic_hsa = CpuModel{ + .name = "generic_hsa", + .llvm_name = "generic-hsa", + .features = featureSet(&[_]Feature{ + .flat_address_space, + .wavefrontsize64, + }), + }; + pub const gfx1010 = CpuModel{ + .name = "gfx1010", + .llvm_name = "gfx1010", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .ds_src2_insts, + .flat_segment_offset_bug, + .get_wave_id_inst, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .mad_mac_f32_insts, + .negative_unaligned_scratch_offset_bug, + .nsa_clause_bug, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + .xnack_support, + }), + }; + pub const gfx1011 = CpuModel{ + .name = "gfx1011", + .llvm_name = "gfx1011", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .ds_src2_insts, + .flat_segment_offset_bug, + .get_wave_id_inst, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .mad_mac_f32_insts, + .negative_unaligned_scratch_offset_bug, + .nsa_clause_bug, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + .xnack_support, + }), + }; + pub const gfx1012 = CpuModel{ + .name = "gfx1012", + .llvm_name = "gfx1012", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .ds_src2_insts, + .flat_segment_offset_bug, + .get_wave_id_inst, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .mad_mac_f32_insts, + .negative_unaligned_scratch_offset_bug, + .nsa_clause_bug, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + .xnack_support, + }), + }; + pub const gfx1013 = CpuModel{ + .name = "gfx1013", + .llvm_name = "gfx1013", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .ds_src2_insts, + .flat_segment_offset_bug, + .get_wave_id_inst, + .gfx10, + .gfx10_a_encoding, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .mad_mac_f32_insts, + .negative_unaligned_scratch_offset_bug, + .nsa_clause_bug, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + .xnack_support, + }), + }; + pub const gfx1030 = CpuModel{ + .name = "gfx1030", + .llvm_name = "gfx1030", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1031 = CpuModel{ + .name = "gfx1031", + .llvm_name = "gfx1031", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1032 = CpuModel{ + .name = "gfx1032", + .llvm_name = "gfx1032", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1033 = CpuModel{ + .name = "gfx1033", + .llvm_name = "gfx1033", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1034 = CpuModel{ + .name = "gfx1034", + .llvm_name = "gfx1034", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1035 = CpuModel{ + .name = "gfx1035", + .llvm_name = "gfx1035", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1036 = CpuModel{ + .name = "gfx1036", + .llvm_name = "gfx1036", + .features = featureSet(&[_]Feature{ + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .gfx10, + .gfx10_3_insts, + .gfx10_a_encoding, + .gfx10_b_encoding, + .ldsbankcount32, + .nsa_encoding, + .shader_cycles_register, + .wavefrontsize32, + }), + }; + pub const gfx1100 = CpuModel{ + .name = "gfx1100", + .llvm_name = "gfx1100", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .gfx11_full_vgprs, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .user_sgpr_init16_bug, + .valu_trans_use_hazard, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1101 = CpuModel{ + .name = "gfx1101", + .llvm_name = "gfx1101", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .gfx11_full_vgprs, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .valu_trans_use_hazard, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1102 = CpuModel{ + .name = "gfx1102", + .llvm_name = "gfx1102", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .user_sgpr_init16_bug, + .valu_trans_use_hazard, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1103 = CpuModel{ + .name = "gfx1103", + .llvm_name = "gfx1103", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .valu_trans_use_hazard, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1150 = CpuModel{ + .name = "gfx1150", + .llvm_name = "gfx1150", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1151 = CpuModel{ + .name = "gfx1151", + .llvm_name = "gfx1151", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .dl_insts, + .dot10_insts, + .dot5_insts, + .dot7_insts, + .dot8_insts, + .dot9_insts, + .flat_atomic_fadd_f32_inst, + .gfx11, + .gfx11_full_vgprs, + .image_insts, + .ldsbankcount32, + .mad_intra_fwd_bug, + .nsa_encoding, + .packed_tid, + .partial_nsa_encoding, + .shader_cycles_register, + .vcmpx_permlane_hazard, + .wavefrontsize32, + }), + }; + pub const gfx600 = CpuModel{ + .name = "gfx600", + .llvm_name = "gfx600", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .southern_islands, + }), + }; + pub const gfx601 = CpuModel{ + .name = "gfx601", + .llvm_name = "gfx601", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; + pub const gfx602 = CpuModel{ + .name = "gfx602", + .llvm_name = "gfx602", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; + pub const gfx700 = CpuModel{ + .name = "gfx700", + .llvm_name = "gfx700", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sea_islands, + }), + }; + pub const gfx701 = CpuModel{ + .name = "gfx701", + .llvm_name = "gfx701", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .sea_islands, + }), + }; + pub const gfx702 = CpuModel{ + .name = "gfx702", + .llvm_name = "gfx702", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .ldsbankcount16, + .sea_islands, + }), + }; + pub const gfx703 = CpuModel{ + .name = "gfx703", + .llvm_name = "gfx703", + .features = featureSet(&[_]Feature{ + .ldsbankcount16, + .sea_islands, + }), + }; + pub const gfx704 = CpuModel{ + .name = "gfx704", + .llvm_name = "gfx704", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sea_islands, + }), + }; + pub const gfx705 = CpuModel{ + .name = "gfx705", + .llvm_name = "gfx705", + .features = featureSet(&[_]Feature{ + .ldsbankcount16, + .sea_islands, + }), + }; + pub const gfx801 = CpuModel{ + .name = "gfx801", + .llvm_name = "gfx801", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + .xnack_support, + }), + }; + pub const gfx802 = CpuModel{ + .name = "gfx802", + .llvm_name = "gfx802", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const gfx803 = CpuModel{ + .name = "gfx803", + .llvm_name = "gfx803", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const gfx805 = CpuModel{ + .name = "gfx805", + .llvm_name = "gfx805", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const gfx810 = CpuModel{ + .name = "gfx810", + .llvm_name = "gfx810", + .features = featureSet(&[_]Feature{ + .image_gather4_d16_bug, + .image_store_d16_bug, + .ldsbankcount16, + .volcanic_islands, + .xnack_support, + }), + }; + pub const gfx900 = CpuModel{ + .name = "gfx900", + .llvm_name = "gfx900", + .features = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .gfx9, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mad_mix_insts, + }), + }; + pub const gfx902 = CpuModel{ + .name = "gfx902", + .llvm_name = "gfx902", + .features = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .gfx9, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mad_mix_insts, + }), + }; + pub const gfx904 = CpuModel{ + .name = "gfx904", + .llvm_name = "gfx904", + .features = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .fma_mix_insts, + .gfx9, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + }), + }; + pub const gfx906 = CpuModel{ + .name = "gfx906", + .llvm_name = "gfx906", + .features = featureSet(&[_]Feature{ + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot7_insts, + .ds_src2_insts, + .extended_image_insts, + .fma_mix_insts, + .gfx9, + .half_rate_64_ops, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .sramecc_support, + }), + }; + pub const gfx908 = CpuModel{ + .name = "gfx908", + .llvm_name = "gfx908", + .features = featureSet(&[_]Feature{ + .atomic_buffer_global_pk_add_f16_no_rtn_insts, + .atomic_fadd_no_rtn_insts, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .ds_src2_insts, + .extended_image_insts, + .fma_mix_insts, + .gfx9, + .half_rate_64_ops, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mai_insts, + .mfma_inline_literal_bug, + .pk_fmac_f16_inst, + .sramecc_support, + }), + }; + pub const gfx909 = CpuModel{ + .name = "gfx909", + .llvm_name = "gfx909", + .features = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .gfx9, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mad_mix_insts, + }), + }; + pub const gfx90a = CpuModel{ + .name = "gfx90a", + .llvm_name = "gfx90a", + .features = featureSet(&[_]Feature{ + .atomic_buffer_global_pk_add_f16_insts, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .dpp_64bit, + .fma_mix_insts, + .fmacf64_inst, + .full_rate_64_ops, + .gfx9, + .gfx90a_insts, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mai_insts, + .packed_fp32_ops, + .packed_tid, + .pk_fmac_f16_inst, + .sramecc_support, + }), + }; + pub const gfx90c = CpuModel{ + .name = "gfx90c", + .llvm_name = "gfx90c", + .features = featureSet(&[_]Feature{ + .ds_src2_insts, + .extended_image_insts, + .gfx9, + .image_gather4_d16_bug, + .image_insts, + .ldsbankcount32, + .mad_mac_f32_insts, + .mad_mix_insts, + }), + }; + pub const gfx940 = CpuModel{ + .name = "gfx940", + .llvm_name = "gfx940", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_buffer_global_pk_add_f16_insts, + .atomic_ds_pk_add_16_insts, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .atomic_flat_pk_add_16_insts, + .atomic_global_pk_add_bf16_inst, + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .dpp_64bit, + .flat_atomic_fadd_f32_inst, + .fma_mix_insts, + .fmacf64_inst, + .force_store_sc0_sc1, + .fp8_insts, + .full_rate_64_ops, + .gfx9, + .gfx90a_insts, + .gfx940_insts, + .ldsbankcount32, + .mai_insts, + .packed_fp32_ops, + .packed_tid, + .pk_fmac_f16_inst, + .sramecc_support, + }), + }; + pub const gfx941 = CpuModel{ + .name = "gfx941", + .llvm_name = "gfx941", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_buffer_global_pk_add_f16_insts, + .atomic_ds_pk_add_16_insts, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .atomic_flat_pk_add_16_insts, + .atomic_global_pk_add_bf16_inst, + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .dpp_64bit, + .flat_atomic_fadd_f32_inst, + .fma_mix_insts, + .fmacf64_inst, + .force_store_sc0_sc1, + .fp8_insts, + .full_rate_64_ops, + .gfx9, + .gfx90a_insts, + .gfx940_insts, + .ldsbankcount32, + .mai_insts, + .packed_fp32_ops, + .packed_tid, + .pk_fmac_f16_inst, + .sramecc_support, + }), + }; + pub const gfx942 = CpuModel{ + .name = "gfx942", + .llvm_name = "gfx942", + .features = featureSet(&[_]Feature{ + .architected_flat_scratch, + .atomic_buffer_global_pk_add_f16_insts, + .atomic_ds_pk_add_16_insts, + .atomic_fadd_no_rtn_insts, + .atomic_fadd_rtn_insts, + .atomic_flat_pk_add_16_insts, + .atomic_global_pk_add_bf16_inst, + .back_off_barrier, + .dl_insts, + .dot10_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .dot7_insts, + .dpp_64bit, + .flat_atomic_fadd_f32_inst, + .fma_mix_insts, + .fmacf64_inst, + .fp8_insts, + .full_rate_64_ops, + .gfx9, + .gfx90a_insts, + .gfx940_insts, + .ldsbankcount32, + .mai_insts, + .packed_fp32_ops, + .packed_tid, + .pk_fmac_f16_inst, + .sramecc_support, + }), + }; + pub const hainan = CpuModel{ + .name = "hainan", + .llvm_name = "hainan", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; + pub const hawaii = CpuModel{ + .name = "hawaii", + .llvm_name = "hawaii", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .sea_islands, + }), + }; + pub const iceland = CpuModel{ + .name = "iceland", + .llvm_name = "iceland", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const kabini = CpuModel{ + .name = "kabini", + .llvm_name = "kabini", + .features = featureSet(&[_]Feature{ + .ldsbankcount16, + .sea_islands, + }), + }; + pub const kaveri = CpuModel{ + .name = "kaveri", + .llvm_name = "kaveri", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sea_islands, + }), + }; + pub const mullins = CpuModel{ + .name = "mullins", + .llvm_name = "mullins", + .features = featureSet(&[_]Feature{ + .ldsbankcount16, + .sea_islands, + }), + }; + pub const oland = CpuModel{ + .name = "oland", + .llvm_name = "oland", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; + pub const pitcairn = CpuModel{ + .name = "pitcairn", + .llvm_name = "pitcairn", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; + pub const polaris10 = CpuModel{ + .name = "polaris10", + .llvm_name = "polaris10", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const polaris11 = CpuModel{ + .name = "polaris11", + .llvm_name = "polaris11", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const stoney = CpuModel{ + .name = "stoney", + .llvm_name = "stoney", + .features = featureSet(&[_]Feature{ + .image_gather4_d16_bug, + .image_store_d16_bug, + .ldsbankcount16, + .volcanic_islands, + .xnack_support, + }), + }; + pub const tahiti = CpuModel{ + .name = "tahiti", + .llvm_name = "tahiti", + .features = featureSet(&[_]Feature{ + .fast_fmaf, + .half_rate_64_ops, + .southern_islands, + }), + }; + pub const tonga = CpuModel{ + .name = "tonga", + .llvm_name = "tonga", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const tongapro = CpuModel{ + .name = "tongapro", + .llvm_name = "tongapro", + .features = featureSet(&[_]Feature{ + .ldsbankcount32, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const verde = CpuModel{ + .name = "verde", + .llvm_name = "verde", + .features = featureSet(&[_]Feature{ + .southern_islands, + }), + }; +}; diff --git a/lib/std/Target/arc.zig b/lib/std/Target/arc.zig new file mode 100644 index 0000000000000000000000000000000000000000..eff13c66375f656181370362f3e763fbbae794ea --- /dev/null +++ b/lib/std/Target/arc.zig @@ -0,0 +1,39 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + norm, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.norm)] = .{ + .llvm_name = "norm", + .description = "Enable support for norm instruction.", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/lib/std/Target/arm.zig b/lib/std/Target/arm.zig new file mode 100644 index 0000000000000000000000000000000000000000..5245b3357e470275c178249fb7a834beed0e244a --- /dev/null +++ b/lib/std/Target/arm.zig @@ -0,0 +1,2604 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"32bit", + @"8msecext", + a76, + aapcs_frame_chain, + aapcs_frame_chain_leaf, + aclass, + acquire_release, + aes, + atomics_32, + avoid_movs_shop, + avoid_partial_cpsr, + bf16, + big_endian_instructions, + cde, + cdecp0, + cdecp1, + cdecp2, + cdecp3, + cdecp4, + cdecp5, + cdecp6, + cdecp7, + cheap_predicable_cpsr, + clrbhb, + crc, + crypto, + d32, + db, + dfb, + disable_postra_scheduler, + dont_widen_vmovs, + dotprod, + dsp, + execute_only, + expand_fp_mlx, + exynos, + fix_cmse_cve_2021_35465, + fix_cortex_a57_aes_1742098, + fp16, + fp16fml, + fp64, + fp_armv8, + fp_armv8d16, + fp_armv8d16sp, + fp_armv8sp, + fpao, + fpregs, + fpregs16, + fpregs64, + fullfp16, + fuse_aes, + fuse_literals, + harden_sls_blr, + harden_sls_nocomdat, + harden_sls_retbr, + has_v4t, + has_v5t, + has_v5te, + has_v6, + has_v6k, + has_v6m, + has_v6t2, + has_v7, + has_v7clrex, + has_v8, + has_v8_1a, + has_v8_1m_main, + has_v8_2a, + has_v8_3a, + has_v8_4a, + has_v8_5a, + has_v8_6a, + has_v8_7a, + has_v8_8a, + has_v8_9a, + has_v8m, + has_v8m_main, + has_v9_1a, + has_v9_2a, + has_v9_3a, + has_v9_4a, + has_v9a, + hwdiv, + hwdiv_arm, + i8mm, + iwmmxt, + iwmmxt2, + lob, + long_calls, + loop_align, + m3, + mclass, + mp, + muxed_units, + mve, + mve1beat, + mve2beat, + mve4beat, + mve_fp, + nacl_trap, + neon, + neon_fpmovs, + neonfp, + no_branch_predictor, + no_bti_at_return_twice, + no_movt, + no_neg_immediates, + noarm, + nonpipelined_vfp, + pacbti, + perfmon, + prefer_ishst, + prefer_vmovsr, + prof_unpr, + r4, + ras, + rclass, + read_tp_tpidrprw, + read_tp_tpidruro, + read_tp_tpidrurw, + reserve_r9, + ret_addr_stack, + sb, + sha2, + slow_fp_brcc, + slow_load_D_subreg, + slow_odd_reg, + slow_vdup32, + slow_vgetlni32, + slowfpvfmx, + slowfpvmlx, + soft_float, + splat_vfp_neon, + strict_align, + swift, + thumb2, + thumb_mode, + trustzone, + use_mipipeliner, + use_misched, + v2, + v2a, + v3, + v3m, + v4, + v4t, + v5t, + v5te, + v5tej, + v6, + v6j, + v6k, + v6kz, + v6m, + v6sm, + v6t2, + v7a, + v7em, + v7k, + v7m, + v7r, + v7s, + v7ve, + v8_1a, + v8_1m_main, + v8_2a, + v8_3a, + v8_4a, + v8_5a, + v8_6a, + v8_7a, + v8_8a, + v8_9a, + v8a, + v8m, + v8m_main, + v8r, + v9_1a, + v9_2a, + v9_3a, + v9_4a, + v9a, + vfp2, + vfp2sp, + vfp3, + vfp3d16, + vfp3d16sp, + vfp3sp, + vfp4, + vfp4d16, + vfp4d16sp, + vfp4sp, + virtualization, + vldn_align, + vmlx_forwarding, + vmlx_hazards, + wide_stride_vfp, + xscale, + zcz, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + @setEvalBranchQuota(10000); + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"32bit")] = .{ + .llvm_name = "32bit", + .description = "Prefer 32-bit Thumb instrs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"8msecext")] = .{ + .llvm_name = "8msecext", + .description = "Enable support for ARMv8-M Security Extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.a76)] = .{ + .llvm_name = "a76", + .description = "Cortex-A76 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aapcs_frame_chain)] = .{ + .llvm_name = "aapcs-frame-chain", + .description = "Create an AAPCS compliant frame chain", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aapcs_frame_chain_leaf)] = .{ + .llvm_name = "aapcs-frame-chain-leaf", + .description = "Create an AAPCS compliant frame chain for leaf functions", + .dependencies = featureSet(&[_]Feature{ + .aapcs_frame_chain, + }), + }; + result[@intFromEnum(Feature.aclass)] = .{ + .llvm_name = "aclass", + .description = "Is application profile ('A' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.acquire_release)] = .{ + .llvm_name = "acquire-release", + .description = "Has v8 acquire/release (lda/ldaex etc) instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.atomics_32)] = .{ + .llvm_name = "atomics-32", + .description = "Assume that lock-free 32-bit atomics are available", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.avoid_movs_shop)] = .{ + .llvm_name = "avoid-movs-shop", + .description = "Avoid movs instructions with shifter operand", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.avoid_partial_cpsr)] = .{ + .llvm_name = "avoid-partial-cpsr", + .description = "Avoid CPSR partial update for OOO execution", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.bf16)] = .{ + .llvm_name = "bf16", + .description = "Enable support for BFloat16 instructions", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.big_endian_instructions)] = .{ + .llvm_name = "big-endian-instructions", + .description = "Expect instructions to be stored big-endian.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cde)] = .{ + .llvm_name = "cde", + .description = "Support CDE instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8m_main, + }), + }; + result[@intFromEnum(Feature.cdecp0)] = .{ + .llvm_name = "cdecp0", + .description = "Coprocessor 0 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp1)] = .{ + .llvm_name = "cdecp1", + .description = "Coprocessor 1 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp2)] = .{ + .llvm_name = "cdecp2", + .description = "Coprocessor 2 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp3)] = .{ + .llvm_name = "cdecp3", + .description = "Coprocessor 3 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp4)] = .{ + .llvm_name = "cdecp4", + .description = "Coprocessor 4 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp5)] = .{ + .llvm_name = "cdecp5", + .description = "Coprocessor 5 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp6)] = .{ + .llvm_name = "cdecp6", + .description = "Coprocessor 6 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cdecp7)] = .{ + .llvm_name = "cdecp7", + .description = "Coprocessor 7 ISA is CDEv1", + .dependencies = featureSet(&[_]Feature{ + .cde, + }), + }; + result[@intFromEnum(Feature.cheap_predicable_cpsr)] = .{ + .llvm_name = "cheap-predicable-cpsr", + .description = "Disable +1 predication cost for instructions updating CPSR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.clrbhb)] = .{ + .llvm_name = "clrbhb", + .description = "Enable Clear BHB instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Enable support for CRC instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable support for Cryptography extensions", + .dependencies = featureSet(&[_]Feature{ + .aes, + .sha2, + }), + }; + result[@intFromEnum(Feature.d32)] = .{ + .llvm_name = "d32", + .description = "Extend FP to 32 double registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.db)] = .{ + .llvm_name = "db", + .description = "Has data barrier (dmb/dsb) instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dfb)] = .{ + .llvm_name = "dfb", + .description = "Has full data barrier (dfb) instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.disable_postra_scheduler)] = .{ + .llvm_name = "disable-postra-scheduler", + .description = "Don't schedule again after register allocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dont_widen_vmovs)] = .{ + .llvm_name = "dont-widen-vmovs", + .description = "Don't widen VMOVS to VMOVD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dotprod)] = .{ + .llvm_name = "dotprod", + .description = "Enable support for dot product instructions", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.dsp)] = .{ + .llvm_name = "dsp", + .description = "Supports DSP instructions in ARM and/or Thumb2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.execute_only)] = .{ + .llvm_name = "execute-only", + .description = "Enable the generation of execute only code.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.expand_fp_mlx)] = .{ + .llvm_name = "expand-fp-mlx", + .description = "Expand VFP/NEON MLA/MLS instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.exynos)] = .{ + .llvm_name = "exynos", + .description = "Samsung Exynos processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .expand_fp_mlx, + .fuse_aes, + .fuse_literals, + .hwdiv, + .hwdiv_arm, + .prof_unpr, + .ret_addr_stack, + .slow_fp_brcc, + .slow_vdup32, + .slow_vgetlni32, + .slowfpvfmx, + .slowfpvmlx, + .splat_vfp_neon, + .wide_stride_vfp, + .zcz, + }), + }; + result[@intFromEnum(Feature.fix_cmse_cve_2021_35465)] = .{ + .llvm_name = "fix-cmse-cve-2021-35465", + .description = "Mitigate against the cve-2021-35465 security vulnurability", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fix_cortex_a57_aes_1742098)] = .{ + .llvm_name = "fix-cortex-a57-aes-1742098", + .description = "Work around Cortex-A57 Erratum 1742098 / Cortex-A72 Erratum 1655431 (AES)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp16)] = .{ + .llvm_name = "fp16", + .description = "Enable half-precision floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable full half-precision floating point fml instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@intFromEnum(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Floating point unit supports double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs64, + }), + }; + result[@intFromEnum(Feature.fp_armv8)] = .{ + .llvm_name = "fp-armv8", + .description = "Enable ARMv8 FP", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16, + .fp_armv8sp, + .vfp4, + }), + }; + result[@intFromEnum(Feature.fp_armv8d16)] = .{ + .llvm_name = "fp-armv8d16", + .description = "Enable ARMv8 FP with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .vfp4d16, + }), + }; + result[@intFromEnum(Feature.fp_armv8d16sp)] = .{ + .llvm_name = "fp-armv8d16sp", + .description = "Enable ARMv8 FP with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp4d16sp, + }), + }; + result[@intFromEnum(Feature.fp_armv8sp)] = .{ + .llvm_name = "fp-armv8sp", + .description = "Enable ARMv8 FP with no double precision", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .vfp4sp, + }), + }; + result[@intFromEnum(Feature.fpao)] = .{ + .llvm_name = "fpao", + .description = "Enable fast computation of positive address offsets", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpregs)] = .{ + .llvm_name = "fpregs", + .description = "Enable FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpregs16)] = .{ + .llvm_name = "fpregs16", + .description = "Enable 16-bit FP registers", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@intFromEnum(Feature.fpregs64)] = .{ + .llvm_name = "fpregs64", + .description = "Enable 64-bit FP registers", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@intFromEnum(Feature.fullfp16)] = .{ + .llvm_name = "fullfp16", + .description = "Enable full half-precision floating point", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .fpregs16, + }), + }; + result[@intFromEnum(Feature.fuse_aes)] = .{ + .llvm_name = "fuse-aes", + .description = "CPU fuses AES crypto operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fuse_literals)] = .{ + .llvm_name = "fuse-literals", + .description = "CPU fuses literal generation operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_blr)] = .{ + .llvm_name = "harden-sls-blr", + .description = "Harden against straight line speculation across indirect calls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_nocomdat)] = .{ + .llvm_name = "harden-sls-nocomdat", + .description = "Generate thunk code for SLS mitigation in the normal text section", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_retbr)] = .{ + .llvm_name = "harden-sls-retbr", + .description = "Harden against straight line speculation across RETurn and BranchRegister instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.has_v4t)] = .{ + .llvm_name = "v4t", + .description = "Support ARM v4T instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.has_v5t)] = .{ + .llvm_name = "v5t", + .description = "Support ARM v5T instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v4t, + }), + }; + result[@intFromEnum(Feature.has_v5te)] = .{ + .llvm_name = "v5te", + .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v5t, + }), + }; + result[@intFromEnum(Feature.has_v6)] = .{ + .llvm_name = "v6", + .description = "Support ARM v6 instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v5te, + }), + }; + result[@intFromEnum(Feature.has_v6k)] = .{ + .llvm_name = "v6k", + .description = "Support ARM v6k instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6, + }), + }; + result[@intFromEnum(Feature.has_v6m)] = .{ + .llvm_name = "v6m", + .description = "Support ARM v6M instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6, + }), + }; + result[@intFromEnum(Feature.has_v6t2)] = .{ + .llvm_name = "v6t2", + .description = "Support ARM v6t2 instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6k, + .has_v8m, + .thumb2, + }), + }; + result[@intFromEnum(Feature.has_v7)] = .{ + .llvm_name = "v7", + .description = "Support ARM v7 instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6t2, + .has_v7clrex, + }), + }; + result[@intFromEnum(Feature.has_v7clrex)] = .{ + .llvm_name = "v7clrex", + .description = "Has v7 clrex instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.has_v8)] = .{ + .llvm_name = "v8", + .description = "Support ARM v8 instructions", + .dependencies = featureSet(&[_]Feature{ + .acquire_release, + .has_v7, + .perfmon, + }), + }; + result[@intFromEnum(Feature.has_v8_1a)] = .{ + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8, + }), + }; + result[@intFromEnum(Feature.has_v8_1m_main)] = .{ + .llvm_name = "v8.1m.main", + .description = "Support ARM v8-1M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8m_main, + }), + }; + result[@intFromEnum(Feature.has_v8_2a)] = .{ + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_1a, + }), + }; + result[@intFromEnum(Feature.has_v8_3a)] = .{ + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_2a, + }), + }; + result[@intFromEnum(Feature.has_v8_4a)] = .{ + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .dotprod, + .has_v8_3a, + }), + }; + result[@intFromEnum(Feature.has_v8_5a)] = .{ + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_4a, + .sb, + }), + }; + result[@intFromEnum(Feature.has_v8_6a)] = .{ + .llvm_name = "v8.6a", + .description = "Support ARM v8.6a instructions", + .dependencies = featureSet(&[_]Feature{ + .bf16, + .has_v8_5a, + .i8mm, + }), + }; + result[@intFromEnum(Feature.has_v8_7a)] = .{ + .llvm_name = "v8.7a", + .description = "Support ARM v8.7a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_6a, + }), + }; + result[@intFromEnum(Feature.has_v8_8a)] = .{ + .llvm_name = "v8.8a", + .description = "Support ARM v8.8a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_7a, + }), + }; + result[@intFromEnum(Feature.has_v8_9a)] = .{ + .llvm_name = "v8.9a", + .description = "Support ARM v8.9a instructions", + .dependencies = featureSet(&[_]Feature{ + .clrbhb, + .has_v8_8a, + }), + }; + result[@intFromEnum(Feature.has_v8m)] = .{ + .llvm_name = "v8m", + .description = "Support ARM v8M Baseline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v6m, + }), + }; + result[@intFromEnum(Feature.has_v8m_main)] = .{ + .llvm_name = "v8m.main", + .description = "Support ARM v8M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v7, + }), + }; + result[@intFromEnum(Feature.has_v9_1a)] = .{ + .llvm_name = "v9.1a", + .description = "Support ARM v9.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_6a, + .has_v9a, + }), + }; + result[@intFromEnum(Feature.has_v9_2a)] = .{ + .llvm_name = "v9.2a", + .description = "Support ARM v9.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_7a, + .has_v9_1a, + }), + }; + result[@intFromEnum(Feature.has_v9_3a)] = .{ + .llvm_name = "v9.3a", + .description = "Support ARM v9.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_8a, + .has_v9_2a, + }), + }; + result[@intFromEnum(Feature.has_v9_4a)] = .{ + .llvm_name = "v9.4a", + .description = "Support ARM v9.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_9a, + .has_v9_3a, + }), + }; + result[@intFromEnum(Feature.has_v9a)] = .{ + .llvm_name = "v9a", + .description = "Support ARM v9a instructions", + .dependencies = featureSet(&[_]Feature{ + .has_v8_5a, + }), + }; + result[@intFromEnum(Feature.hwdiv)] = .{ + .llvm_name = "hwdiv", + .description = "Enable divide instructions in Thumb", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hwdiv_arm)] = .{ + .llvm_name = "hwdiv-arm", + .description = "Enable divide instructions in ARM mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.i8mm)] = .{ + .llvm_name = "i8mm", + .description = "Enable Matrix Multiply Int8 Extension", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.iwmmxt)] = .{ + .llvm_name = "iwmmxt", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@intFromEnum(Feature.iwmmxt2)] = .{ + .llvm_name = "iwmmxt2", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@intFromEnum(Feature.lob)] = .{ + .llvm_name = "lob", + .description = "Enable Low Overhead Branch extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Generate calls via indirect call instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.loop_align)] = .{ + .llvm_name = "loop-align", + .description = "Prefer 32-bit alignment for loops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.m3)] = .{ + .llvm_name = "m3", + .description = "Cortex-M3 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mclass)] = .{ + .llvm_name = "mclass", + .description = "Is microcontroller profile ('M' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mp)] = .{ + .llvm_name = "mp", + .description = "Supports Multiprocessing extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.muxed_units)] = .{ + .llvm_name = "muxed-units", + .description = "Has muxed AGU and NEON/FPU", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mve)] = .{ + .llvm_name = "mve", + .description = "Support M-Class Vector Extension with integer ops", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .fpregs16, + .fpregs64, + .has_v8_1m_main, + }), + }; + result[@intFromEnum(Feature.mve1beat)] = .{ + .llvm_name = "mve1beat", + .description = "Model MVE instructions as a 1 beat per tick architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mve2beat)] = .{ + .llvm_name = "mve2beat", + .description = "Model MVE instructions as a 2 beats per tick architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mve4beat)] = .{ + .llvm_name = "mve4beat", + .description = "Model MVE instructions as a 4 beats per tick architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mve_fp)] = .{ + .llvm_name = "mve.fp", + .description = "Support M-Class Vector Extension with integer and floating ops", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + .mve, + }), + }; + result[@intFromEnum(Feature.nacl_trap)] = .{ + .llvm_name = "nacl-trap", + .description = "NaCl trap", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.neon)] = .{ + .llvm_name = "neon", + .description = "Enable NEON instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp3, + }), + }; + result[@intFromEnum(Feature.neon_fpmovs)] = .{ + .llvm_name = "neon-fpmovs", + .description = "Convert VMOVSR, VMOVRS, VMOVS to NEON", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.neonfp)] = .{ + .llvm_name = "neonfp", + .description = "Use NEON for single precision FP", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_branch_predictor)] = .{ + .llvm_name = "no-branch-predictor", + .description = "Has no branch predictor", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bti_at_return_twice)] = .{ + .llvm_name = "no-bti-at-return-twice", + .description = "Don't place a BTI instruction after a return-twice", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_movt)] = .{ + .llvm_name = "no-movt", + .description = "Don't use movt/movw pairs for 32-bit imms", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_neg_immediates)] = .{ + .llvm_name = "no-neg-immediates", + .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.noarm)] = .{ + .llvm_name = "noarm", + .description = "Does not support ARM mode execution", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nonpipelined_vfp)] = .{ + .llvm_name = "nonpipelined-vfp", + .description = "VFP instructions are not pipelined", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pacbti)] = .{ + .llvm_name = "pacbti", + .description = "Enable Pointer Authentication and Branch Target Identification", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.perfmon)] = .{ + .llvm_name = "perfmon", + .description = "Enable support for Performance Monitor extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_ishst)] = .{ + .llvm_name = "prefer-ishst", + .description = "Prefer ISHST barriers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_vmovsr)] = .{ + .llvm_name = "prefer-vmovsr", + .description = "Prefer VMOVSR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prof_unpr)] = .{ + .llvm_name = "prof-unpr", + .description = "Is profitable to unpredicate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.r4)] = .{ + .llvm_name = "r4", + .description = "Cortex-R4 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ras)] = .{ + .llvm_name = "ras", + .description = "Enable Reliability, Availability and Serviceability extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rclass)] = .{ + .llvm_name = "rclass", + .description = "Is realtime profile ('R' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.read_tp_tpidrprw)] = .{ + .llvm_name = "read-tp-tpidrprw", + .description = "Reading thread pointer from TPIDRPRW register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.read_tp_tpidruro)] = .{ + .llvm_name = "read-tp-tpidruro", + .description = "Reading thread pointer from TPIDRURO register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.read_tp_tpidrurw)] = .{ + .llvm_name = "read-tp-tpidrurw", + .description = "Reading thread pointer from TPIDRURW register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_r9)] = .{ + .llvm_name = "reserve-r9", + .description = "Reserve R9, making it unavailable as GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ret_addr_stack)] = .{ + .llvm_name = "ret-addr-stack", + .description = "Has return address stack", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sb)] = .{ + .llvm_name = "sb", + .description = "Enable v8.5a Speculation Barrier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sha2)] = .{ + .llvm_name = "sha2", + .description = "Enable SHA1 and SHA256 support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@intFromEnum(Feature.slow_fp_brcc)] = .{ + .llvm_name = "slow-fp-brcc", + .description = "FP compare + branch is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_load_D_subreg)] = .{ + .llvm_name = "slow-load-D-subreg", + .description = "Loading into D subregs is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_odd_reg)] = .{ + .llvm_name = "slow-odd-reg", + .description = "VLDM/VSTM starting with an odd register is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_vdup32)] = .{ + .llvm_name = "slow-vdup32", + .description = "Has slow VDUP32 - prefer VMOV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_vgetlni32)] = .{ + .llvm_name = "slow-vgetlni32", + .description = "Has slow VGETLNi32 - prefer VMOV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slowfpvfmx)] = .{ + .llvm_name = "slowfpvfmx", + .description = "Disable VFP / NEON FMA instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slowfpvmlx)] = .{ + .llvm_name = "slowfpvmlx", + .description = "Disable VFP / NEON MAC instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software floating point features.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.splat_vfp_neon)] = .{ + .llvm_name = "splat-vfp-neon", + .description = "Splat register from VFP to NEON", + .dependencies = featureSet(&[_]Feature{ + .dont_widen_vmovs, + }), + }; + result[@intFromEnum(Feature.strict_align)] = .{ + .llvm_name = "strict-align", + .description = "Disallow all unaligned memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.swift)] = .{ + .llvm_name = "swift", + .description = "Swift ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.thumb2)] = .{ + .llvm_name = "thumb2", + .description = "Enable Thumb2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.thumb_mode)] = .{ + .llvm_name = "thumb-mode", + .description = "Thumb mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.trustzone)] = .{ + .llvm_name = "trustzone", + .description = "Enable support for TrustZone security extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_mipipeliner)] = .{ + .llvm_name = "use-mipipeliner", + .description = "Use the MachinePipeliner", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_misched)] = .{ + .llvm_name = "use-misched", + .description = "Use the MachineScheduler", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v2)] = .{ + .llvm_name = null, + .description = "ARMv2 architecture", + .dependencies = featureSet(&[_]Feature{ + .strict_align, + }), + }; + result[@intFromEnum(Feature.v2a)] = .{ + .llvm_name = null, + .description = "ARMv2a architecture", + .dependencies = featureSet(&[_]Feature{ + .strict_align, + }), + }; + result[@intFromEnum(Feature.v3)] = .{ + .llvm_name = null, + .description = "ARMv3 architecture", + .dependencies = featureSet(&[_]Feature{ + .strict_align, + }), + }; + result[@intFromEnum(Feature.v3m)] = .{ + .llvm_name = null, + .description = "ARMv3m architecture", + .dependencies = featureSet(&[_]Feature{ + .strict_align, + }), + }; + result[@intFromEnum(Feature.v4)] = .{ + .llvm_name = "armv4", + .description = "ARMv4 architecture", + .dependencies = featureSet(&[_]Feature{ + .strict_align, + }), + }; + result[@intFromEnum(Feature.v4t)] = .{ + .llvm_name = "armv4t", + .description = "ARMv4t architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v4t, + .strict_align, + }), + }; + result[@intFromEnum(Feature.v5t)] = .{ + .llvm_name = "armv5t", + .description = "ARMv5t architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v5t, + .strict_align, + }), + }; + result[@intFromEnum(Feature.v5te)] = .{ + .llvm_name = "armv5te", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v5te, + .strict_align, + }), + }; + result[@intFromEnum(Feature.v5tej)] = .{ + .llvm_name = "armv5tej", + .description = "ARMv5tej architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v5te, + .strict_align, + }), + }; + result[@intFromEnum(Feature.v6)] = .{ + .llvm_name = "armv6", + .description = "ARMv6 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .has_v6, + }), + }; + result[@intFromEnum(Feature.v6j)] = .{ + .llvm_name = "armv6j", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v6, + }), + }; + result[@intFromEnum(Feature.v6k)] = .{ + .llvm_name = "armv6k", + .description = "ARMv6k architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v6k, + }), + }; + result[@intFromEnum(Feature.v6kz)] = .{ + .llvm_name = "armv6kz", + .description = "ARMv6kz architecture", + .dependencies = featureSet(&[_]Feature{ + .has_v6k, + .trustzone, + }), + }; + result[@intFromEnum(Feature.v6m)] = .{ + .llvm_name = "armv6-m", + .description = "ARMv6m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .has_v6m, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v6sm)] = .{ + .llvm_name = "armv6s-m", + .description = "ARMv6sm architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .has_v6m, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v6t2)] = .{ + .llvm_name = "armv6t2", + .description = "ARMv6t2 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .has_v6t2, + }), + }; + result[@intFromEnum(Feature.v7a)] = .{ + .llvm_name = "armv7-a", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .has_v7, + .neon, + .perfmon, + }), + }; + result[@intFromEnum(Feature.v7em)] = .{ + .llvm_name = "armv7e-m", + .description = "ARMv7em architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .has_v7, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v7k)] = .{ + .llvm_name = "armv7k", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@intFromEnum(Feature.v7m)] = .{ + .llvm_name = "armv7-m", + .description = "ARMv7m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .has_v7, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v7r)] = .{ + .llvm_name = "armv7-r", + .description = "ARMv7r architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .has_v7, + .hwdiv, + .perfmon, + .rclass, + }), + }; + result[@intFromEnum(Feature.v7s)] = .{ + .llvm_name = "armv7s", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .v7a, + }), + }; + result[@intFromEnum(Feature.v7ve)] = .{ + .llvm_name = "armv7ve", + .description = "ARMv7ve architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .has_v7, + .mp, + .neon, + .perfmon, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_1a)] = .{ + .llvm_name = "armv8.1-a", + .description = "ARMv81a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_1a, + .mp, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_1m_main)] = .{ + .llvm_name = "armv8.1-m.main", + .description = "ARMv81mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .has_v8_1m_main, + .hwdiv, + .lob, + .mclass, + .noarm, + .ras, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v8_2a)] = .{ + .llvm_name = "armv8.2-a", + .description = "ARMv82a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_2a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_3a)] = .{ + .llvm_name = "armv8.3-a", + .description = "ARMv83a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_3a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_4a)] = .{ + .llvm_name = "armv8.4-a", + .description = "ARMv84a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_4a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_5a)] = .{ + .llvm_name = "armv8.5-a", + .description = "ARMv85a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_5a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_6a)] = .{ + .llvm_name = "armv8.6-a", + .description = "ARMv86a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_6a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_7a)] = .{ + .llvm_name = "armv8.7-a", + .description = "ARMv87a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_7a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_8a)] = .{ + .llvm_name = "armv8.8-a", + .description = "ARMv88a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_8a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8_9a)] = .{ + .llvm_name = "armv8.9-a", + .description = "ARMv89a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8_9a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8a)] = .{ + .llvm_name = "armv8-a", + .description = "ARMv8a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v8, + .mp, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v8m)] = .{ + .llvm_name = "armv8-m.base", + .description = "ARMv8mBaseline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .has_v7clrex, + .has_v8m, + .hwdiv, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v8m_main)] = .{ + .llvm_name = "armv8-m.main", + .description = "ARMv8mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .has_v8m_main, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + }), + }; + result[@intFromEnum(Feature.v8r)] = .{ + .llvm_name = "armv8-r", + .description = "ARMv8r architecture", + .dependencies = featureSet(&[_]Feature{ + .crc, + .db, + .dfb, + .dsp, + .fp_armv8, + .has_v8, + .mp, + .neon, + .rclass, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v9_1a)] = .{ + .llvm_name = "armv9.1-a", + .description = "ARMv91a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .db, + .dsp, + .fp_armv8, + .has_v9_1a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v9_2a)] = .{ + .llvm_name = "armv9.2-a", + .description = "ARMv92a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .db, + .dsp, + .fp_armv8, + .has_v9_2a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v9_3a)] = .{ + .llvm_name = "armv9.3-a", + .description = "ARMv93a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .has_v9_3a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v9_4a)] = .{ + .llvm_name = "armv9.4-a", + .description = "ARMv94a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .db, + .dsp, + .fp_armv8, + .has_v9_4a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.v9a)] = .{ + .llvm_name = "armv9-a", + .description = "ARMv9a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .db, + .dsp, + .fp_armv8, + .has_v9a, + .mp, + .ras, + .trustzone, + .virtualization, + }), + }; + result[@intFromEnum(Feature.vfp2)] = .{ + .llvm_name = "vfp2", + .description = "Enable VFP2 instructions", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .vfp2sp, + }), + }; + result[@intFromEnum(Feature.vfp2sp)] = .{ + .llvm_name = "vfp2sp", + .description = "Enable VFP2 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@intFromEnum(Feature.vfp3)] = .{ + .llvm_name = "vfp3", + .description = "Enable VFP3 instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp3d16, + .vfp3sp, + }), + }; + result[@intFromEnum(Feature.vfp3d16)] = .{ + .llvm_name = "vfp3d16", + .description = "Enable VFP3 instructions with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .vfp2, + .vfp3d16sp, + }), + }; + result[@intFromEnum(Feature.vfp3d16sp)] = .{ + .llvm_name = "vfp3d16sp", + .description = "Enable VFP3 instructions with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp2sp, + }), + }; + result[@intFromEnum(Feature.vfp3sp)] = .{ + .llvm_name = "vfp3sp", + .description = "Enable VFP3 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .d32, + .vfp3d16sp, + }), + }; + result[@intFromEnum(Feature.vfp4)] = .{ + .llvm_name = "vfp4", + .description = "Enable VFP4 instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp3, + .vfp4d16, + .vfp4sp, + }), + }; + result[@intFromEnum(Feature.vfp4d16)] = .{ + .llvm_name = "vfp4d16", + .description = "Enable VFP4 instructions with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .vfp3d16, + .vfp4d16sp, + }), + }; + result[@intFromEnum(Feature.vfp4d16sp)] = .{ + .llvm_name = "vfp4d16sp", + .description = "Enable VFP4 instructions with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .fp16, + .vfp3d16sp, + }), + }; + result[@intFromEnum(Feature.vfp4sp)] = .{ + .llvm_name = "vfp4sp", + .description = "Enable VFP4 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp3sp, + .vfp4d16sp, + }), + }; + result[@intFromEnum(Feature.virtualization)] = .{ + .llvm_name = "virtualization", + .description = "Supports Virtualization extension", + .dependencies = featureSet(&[_]Feature{ + .hwdiv, + .hwdiv_arm, + }), + }; + result[@intFromEnum(Feature.vldn_align)] = .{ + .llvm_name = "vldn-align", + .description = "Check for VLDn unaligned access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vmlx_forwarding)] = .{ + .llvm_name = "vmlx-forwarding", + .description = "Has multiplier accumulator forwarding", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vmlx_hazards)] = .{ + .llvm_name = "vmlx-hazards", + .description = "Has VMLx hazards", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.wide_stride_vfp)] = .{ + .llvm_name = "wide-stride-vfp", + .description = "Use a wide stride when allocating VFP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xscale)] = .{ + .llvm_name = "xscale", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@intFromEnum(Feature.zcz)] = .{ + .llvm_name = "zcz", + .description = "Has zero-cycle zeroing instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const arm1020e = CpuModel{ + .name = "arm1020e", + .llvm_name = "arm1020e", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm1020t = CpuModel{ + .name = "arm1020t", + .llvm_name = "arm1020t", + .features = featureSet(&[_]Feature{ + .v5t, + }), + }; + pub const arm1022e = CpuModel{ + .name = "arm1022e", + .llvm_name = "arm1022e", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm10e = CpuModel{ + .name = "arm10e", + .llvm_name = "arm10e", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm10tdmi = CpuModel{ + .name = "arm10tdmi", + .llvm_name = "arm10tdmi", + .features = featureSet(&[_]Feature{ + .v5t, + }), + }; + pub const arm1136j_s = CpuModel{ + .name = "arm1136j_s", + .llvm_name = "arm1136j-s", + .features = featureSet(&[_]Feature{ + .v6, + }), + }; + pub const arm1136jf_s = CpuModel{ + .name = "arm1136jf_s", + .llvm_name = "arm1136jf-s", + .features = featureSet(&[_]Feature{ + .slowfpvmlx, + .v6, + .vfp2, + }), + }; + pub const arm1156t2_s = CpuModel{ + .name = "arm1156t2_s", + .llvm_name = "arm1156t2-s", + .features = featureSet(&[_]Feature{ + .v6t2, + }), + }; + pub const arm1156t2f_s = CpuModel{ + .name = "arm1156t2f_s", + .llvm_name = "arm1156t2f-s", + .features = featureSet(&[_]Feature{ + .slowfpvmlx, + .v6t2, + .vfp2, + }), + }; + pub const arm1176jz_s = CpuModel{ + .name = "arm1176jz_s", + .llvm_name = "arm1176jz-s", + .features = featureSet(&[_]Feature{ + .v6kz, + }), + }; + pub const arm1176jzf_s = CpuModel{ + .name = "arm1176jzf_s", + .llvm_name = "arm1176jzf-s", + .features = featureSet(&[_]Feature{ + .slowfpvmlx, + .v6kz, + .vfp2, + }), + }; + pub const arm710t = CpuModel{ + .name = "arm710t", + .llvm_name = "arm710t", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm720t = CpuModel{ + .name = "arm720t", + .llvm_name = "arm720t", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm7tdmi = CpuModel{ + .name = "arm7tdmi", + .llvm_name = "arm7tdmi", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm7tdmi_s = CpuModel{ + .name = "arm7tdmi_s", + .llvm_name = "arm7tdmi-s", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm8 = CpuModel{ + .name = "arm8", + .llvm_name = "arm8", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const arm810 = CpuModel{ + .name = "arm810", + .llvm_name = "arm810", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const arm9 = CpuModel{ + .name = "arm9", + .llvm_name = "arm9", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm920 = CpuModel{ + .name = "arm920", + .llvm_name = "arm920", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm920t = CpuModel{ + .name = "arm920t", + .llvm_name = "arm920t", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm922t = CpuModel{ + .name = "arm922t", + .llvm_name = "arm922t", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm926ej_s = CpuModel{ + .name = "arm926ej_s", + .llvm_name = "arm926ej-s", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm940t = CpuModel{ + .name = "arm940t", + .llvm_name = "arm940t", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const arm946e_s = CpuModel{ + .name = "arm946e_s", + .llvm_name = "arm946e-s", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm966e_s = CpuModel{ + .name = "arm966e_s", + .llvm_name = "arm966e-s", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm968e_s = CpuModel{ + .name = "arm968e_s", + .llvm_name = "arm968e-s", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm9e = CpuModel{ + .name = "arm9e", + .llvm_name = "arm9e", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const arm9tdmi = CpuModel{ + .name = "arm9tdmi", + .llvm_name = "arm9tdmi", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const baseline = CpuModel{ + .name = "baseline", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .v7a, + }), + }; + pub const cortex_a12 = CpuModel{ + .name = "cortex_a12", + .llvm_name = "cortex-a12", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .mp, + .ret_addr_stack, + .trustzone, + .v7a, + .vfp4, + .virtualization, + .vmlx_forwarding, + }), + }; + pub const cortex_a15 = CpuModel{ + .name = "cortex_a15", + .llvm_name = "cortex-a15", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .mp, + .muxed_units, + .ret_addr_stack, + .splat_vfp_neon, + .trustzone, + .v7a, + .vfp4, + .virtualization, + .vldn_align, + }), + }; + pub const cortex_a17 = CpuModel{ + .name = "cortex_a17", + .llvm_name = "cortex-a17", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .mp, + .ret_addr_stack, + .trustzone, + .v7a, + .vfp4, + .virtualization, + .vmlx_forwarding, + }), + }; + pub const cortex_a32 = CpuModel{ + .name = "cortex_a32", + .llvm_name = "cortex-a32", + .features = featureSet(&[_]Feature{ + .v8a, + }), + }; + pub const cortex_a35 = CpuModel{ + .name = "cortex_a35", + .llvm_name = "cortex-a35", + .features = featureSet(&[_]Feature{ + .v8a, + }), + }; + pub const cortex_a5 = CpuModel{ + .name = "cortex_a5", + .llvm_name = "cortex-a5", + .features = featureSet(&[_]Feature{ + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .trustzone, + .v7a, + .vfp4, + .vmlx_forwarding, + }), + }; + pub const cortex_a53 = CpuModel{ + .name = "cortex_a53", + .llvm_name = "cortex-a53", + .features = featureSet(&[_]Feature{ + .fpao, + .v8a, + }), + }; + pub const cortex_a55 = CpuModel{ + .name = "cortex_a55", + .llvm_name = "cortex-a55", + .features = featureSet(&[_]Feature{ + .dotprod, + .v8_2a, + }), + }; + pub const cortex_a57 = CpuModel{ + .name = "cortex_a57", + .llvm_name = "cortex-a57", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .cheap_predicable_cpsr, + .fix_cortex_a57_aes_1742098, + .fpao, + .v8a, + }), + }; + pub const cortex_a7 = CpuModel{ + .name = "cortex_a7", + .llvm_name = "cortex-a7", + .features = featureSet(&[_]Feature{ + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .trustzone, + .v7a, + .vfp4, + .virtualization, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_a710 = CpuModel{ + .name = "cortex_a710", + .llvm_name = "cortex-a710", + .features = featureSet(&[_]Feature{ + .bf16, + .fp16fml, + .i8mm, + .v9a, + }), + }; + pub const cortex_a72 = CpuModel{ + .name = "cortex_a72", + .llvm_name = "cortex-a72", + .features = featureSet(&[_]Feature{ + .fix_cortex_a57_aes_1742098, + .v8a, + }), + }; + pub const cortex_a73 = CpuModel{ + .name = "cortex_a73", + .llvm_name = "cortex-a73", + .features = featureSet(&[_]Feature{ + .v8a, + }), + }; + pub const cortex_a75 = CpuModel{ + .name = "cortex_a75", + .llvm_name = "cortex-a75", + .features = featureSet(&[_]Feature{ + .dotprod, + .v8_2a, + }), + }; + pub const cortex_a76 = CpuModel{ + .name = "cortex_a76", + .llvm_name = "cortex-a76", + .features = featureSet(&[_]Feature{ + .a76, + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a76ae = CpuModel{ + .name = "cortex_a76ae", + .llvm_name = "cortex-a76ae", + .features = featureSet(&[_]Feature{ + .a76, + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a77 = CpuModel{ + .name = "cortex_a77", + .llvm_name = "cortex-a77", + .features = featureSet(&[_]Feature{ + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a78 = CpuModel{ + .name = "cortex_a78", + .llvm_name = "cortex-a78", + .features = featureSet(&[_]Feature{ + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a78c = CpuModel{ + .name = "cortex_a78c", + .llvm_name = "cortex-a78c", + .features = featureSet(&[_]Feature{ + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_a8 = CpuModel{ + .name = "cortex_a8", + .llvm_name = "cortex-a8", + .features = featureSet(&[_]Feature{ + .nonpipelined_vfp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .trustzone, + .v7a, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_a9 = CpuModel{ + .name = "cortex_a9", + .llvm_name = "cortex-a9", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .expand_fp_mlx, + .fp16, + .mp, + .muxed_units, + .neon_fpmovs, + .prefer_vmovsr, + .ret_addr_stack, + .trustzone, + .v7a, + .vldn_align, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_m0 = CpuModel{ + .name = "cortex_m0", + .llvm_name = "cortex-m0", + .features = featureSet(&[_]Feature{ + .no_branch_predictor, + .v6m, + }), + }; + pub const cortex_m0plus = CpuModel{ + .name = "cortex_m0plus", + .llvm_name = "cortex-m0plus", + .features = featureSet(&[_]Feature{ + .no_branch_predictor, + .v6m, + }), + }; + pub const cortex_m1 = CpuModel{ + .name = "cortex_m1", + .llvm_name = "cortex-m1", + .features = featureSet(&[_]Feature{ + .no_branch_predictor, + .v6m, + }), + }; + pub const cortex_m23 = CpuModel{ + .name = "cortex_m23", + .llvm_name = "cortex-m23", + .features = featureSet(&[_]Feature{ + .no_branch_predictor, + .no_movt, + .v8m, + }), + }; + pub const cortex_m3 = CpuModel{ + .name = "cortex_m3", + .llvm_name = "cortex-m3", + .features = featureSet(&[_]Feature{ + .loop_align, + .m3, + .no_branch_predictor, + .use_misched, + .v7m, + }), + }; + pub const cortex_m33 = CpuModel{ + .name = "cortex_m33", + .llvm_name = "cortex-m33", + .features = featureSet(&[_]Feature{ + .dsp, + .fix_cmse_cve_2021_35465, + .fp_armv8d16sp, + .loop_align, + .no_branch_predictor, + .slowfpvfmx, + .slowfpvmlx, + .use_misched, + .v8m_main, + }), + }; + pub const cortex_m35p = CpuModel{ + .name = "cortex_m35p", + .llvm_name = "cortex-m35p", + .features = featureSet(&[_]Feature{ + .dsp, + .fix_cmse_cve_2021_35465, + .fp_armv8d16sp, + .loop_align, + .no_branch_predictor, + .slowfpvfmx, + .slowfpvmlx, + .use_misched, + .v8m_main, + }), + }; + pub const cortex_m4 = CpuModel{ + .name = "cortex_m4", + .llvm_name = "cortex-m4", + .features = featureSet(&[_]Feature{ + .loop_align, + .no_branch_predictor, + .slowfpvfmx, + .slowfpvmlx, + .use_misched, + .v7em, + .vfp4d16sp, + }), + }; + pub const cortex_m55 = CpuModel{ + .name = "cortex_m55", + .llvm_name = "cortex-m55", + .features = featureSet(&[_]Feature{ + .fix_cmse_cve_2021_35465, + .fp_armv8d16, + .loop_align, + .mve_fp, + .no_branch_predictor, + .slowfpvmlx, + .use_misched, + .v8_1m_main, + }), + }; + pub const cortex_m7 = CpuModel{ + .name = "cortex_m7", + .llvm_name = "cortex-m7", + .features = featureSet(&[_]Feature{ + .fp_armv8d16, + .use_mipipeliner, + .use_misched, + .v7em, + }), + }; + pub const cortex_m85 = CpuModel{ + .name = "cortex_m85", + .llvm_name = "cortex-m85", + .features = featureSet(&[_]Feature{ + .fp_armv8d16, + .mve_fp, + .pacbti, + .use_misched, + .v8_1m_main, + }), + }; + pub const cortex_r4 = CpuModel{ + .name = "cortex_r4", + .llvm_name = "cortex-r4", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .r4, + .ret_addr_stack, + .v7r, + }), + }; + pub const cortex_r4f = CpuModel{ + .name = "cortex_r4f", + .llvm_name = "cortex-r4f", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .r4, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .v7r, + .vfp3d16, + }), + }; + pub const cortex_r5 = CpuModel{ + .name = "cortex_r5", + .llvm_name = "cortex-r5", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .hwdiv_arm, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .v7r, + .vfp3d16, + }), + }; + pub const cortex_r52 = CpuModel{ + .name = "cortex_r52", + .llvm_name = "cortex-r52", + .features = featureSet(&[_]Feature{ + .fpao, + .use_misched, + .v8r, + }), + }; + pub const cortex_r7 = CpuModel{ + .name = "cortex_r7", + .llvm_name = "cortex-r7", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .fp16, + .hwdiv_arm, + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .v7r, + .vfp3d16, + }), + }; + pub const cortex_r8 = CpuModel{ + .name = "cortex_r8", + .llvm_name = "cortex-r8", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .fp16, + .hwdiv_arm, + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvfmx, + .slowfpvmlx, + .v7r, + .vfp3d16, + }), + }; + pub const cortex_x1 = CpuModel{ + .name = "cortex_x1", + .llvm_name = "cortex-x1", + .features = featureSet(&[_]Feature{ + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cortex_x1c = CpuModel{ + .name = "cortex_x1c", + .llvm_name = "cortex-x1c", + .features = featureSet(&[_]Feature{ + .dotprod, + .fullfp16, + .v8_2a, + }), + }; + pub const cyclone = CpuModel{ + .name = "cyclone", + .llvm_name = "cyclone", + .features = featureSet(&[_]Feature{ + .avoid_movs_shop, + .avoid_partial_cpsr, + .disable_postra_scheduler, + .neonfp, + .ret_addr_stack, + .slowfpvfmx, + .slowfpvmlx, + .swift, + .use_misched, + .v8a, + .zcz, + }), + }; + pub const ep9312 = CpuModel{ + .name = "ep9312", + .llvm_name = "ep9312", + .features = featureSet(&[_]Feature{ + .v4t, + }), + }; + pub const exynos_m1 = CpuModel{ + .name = "exynos_m1", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .exynos, + .v8a, + }), + }; + pub const exynos_m2 = CpuModel{ + .name = "exynos_m2", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .exynos, + .v8a, + }), + }; + pub const exynos_m3 = CpuModel{ + .name = "exynos_m3", + .llvm_name = "exynos-m3", + .features = featureSet(&[_]Feature{ + .exynos, + .v8a, + }), + }; + pub const exynos_m4 = CpuModel{ + .name = "exynos_m4", + .llvm_name = "exynos-m4", + .features = featureSet(&[_]Feature{ + .dotprod, + .exynos, + .fullfp16, + .v8_2a, + }), + }; + pub const exynos_m5 = CpuModel{ + .name = "exynos_m5", + .llvm_name = "exynos-m5", + .features = featureSet(&[_]Feature{ + .dotprod, + .exynos, + .fullfp16, + .v8_2a, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const iwmmxt = CpuModel{ + .name = "iwmmxt", + .llvm_name = "iwmmxt", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; + pub const krait = CpuModel{ + .name = "krait", + .llvm_name = "krait", + .features = featureSet(&[_]Feature{ + .avoid_partial_cpsr, + .hwdiv, + .hwdiv_arm, + .muxed_units, + .ret_addr_stack, + .v7a, + .vfp4, + .vldn_align, + .vmlx_forwarding, + }), + }; + pub const kryo = CpuModel{ + .name = "kryo", + .llvm_name = "kryo", + .features = featureSet(&[_]Feature{ + .v8a, + }), + }; + pub const mpcore = CpuModel{ + .name = "mpcore", + .llvm_name = "mpcore", + .features = featureSet(&[_]Feature{ + .slowfpvmlx, + .v6k, + .vfp2, + }), + }; + pub const mpcorenovfp = CpuModel{ + .name = "mpcorenovfp", + .llvm_name = "mpcorenovfp", + .features = featureSet(&[_]Feature{ + .v6k, + }), + }; + pub const neoverse_n1 = CpuModel{ + .name = "neoverse_n1", + .llvm_name = "neoverse-n1", + .features = featureSet(&[_]Feature{ + .dotprod, + .v8_2a, + }), + }; + pub const neoverse_n2 = CpuModel{ + .name = "neoverse_n2", + .llvm_name = "neoverse-n2", + .features = featureSet(&[_]Feature{ + .bf16, + .i8mm, + .v8_5a, + }), + }; + pub const neoverse_v1 = CpuModel{ + .name = "neoverse_v1", + .llvm_name = "neoverse-v1", + .features = featureSet(&[_]Feature{ + .bf16, + .fullfp16, + .i8mm, + .v8_4a, + }), + }; + pub const sc000 = CpuModel{ + .name = "sc000", + .llvm_name = "sc000", + .features = featureSet(&[_]Feature{ + .no_branch_predictor, + .v6m, + }), + }; + pub const sc300 = CpuModel{ + .name = "sc300", + .llvm_name = "sc300", + .features = featureSet(&[_]Feature{ + .m3, + .no_branch_predictor, + .use_misched, + .v7m, + }), + }; + pub const strongarm = CpuModel{ + .name = "strongarm", + .llvm_name = "strongarm", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const strongarm110 = CpuModel{ + .name = "strongarm110", + .llvm_name = "strongarm110", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const strongarm1100 = CpuModel{ + .name = "strongarm1100", + .llvm_name = "strongarm1100", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const strongarm1110 = CpuModel{ + .name = "strongarm1110", + .llvm_name = "strongarm1110", + .features = featureSet(&[_]Feature{ + .v4, + }), + }; + pub const swift = CpuModel{ + .name = "swift", + .llvm_name = "swift", + .features = featureSet(&[_]Feature{ + .avoid_movs_shop, + .avoid_partial_cpsr, + .disable_postra_scheduler, + .hwdiv, + .hwdiv_arm, + .mp, + .neonfp, + .prefer_ishst, + .prof_unpr, + .ret_addr_stack, + .slow_load_D_subreg, + .slow_odd_reg, + .slow_vdup32, + .slow_vgetlni32, + .slowfpvfmx, + .slowfpvmlx, + .swift, + .use_misched, + .v7a, + .vfp4, + .vmlx_hazards, + .wide_stride_vfp, + }), + }; + pub const xscale = CpuModel{ + .name = "xscale", + .llvm_name = "xscale", + .features = featureSet(&[_]Feature{ + .v5te, + }), + }; +}; diff --git a/lib/std/Target/avr.zig b/lib/std/Target/avr.zig new file mode 100644 index 0000000000000000000000000000000000000000..bda274d2e6434a040396e37ef031fac4be865d86 --- /dev/null +++ b/lib/std/Target/avr.zig @@ -0,0 +1,2607 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + addsubiw, + avr0, + avr1, + avr2, + avr25, + avr3, + avr31, + avr35, + avr4, + avr5, + avr51, + avr6, + avrtiny, + @"break", + des, + eijmpcall, + elpm, + elpmx, + ijmpcall, + jmpcall, + lowbytefirst, + lpm, + lpmx, + memmappedregs, + movw, + mul, + rmw, + smallstack, + special, + spm, + spmx, + sram, + tinyencoding, + xmega, + xmega3, + xmegau, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.addsubiw)] = .{ + .llvm_name = "addsubiw", + .description = "Enable 16-bit register-immediate addition and subtraction instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.avr0)] = .{ + .llvm_name = "avr0", + .description = "The device is a part of the avr0 family", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.avr1)] = .{ + .llvm_name = "avr1", + .description = "The device is a part of the avr1 family", + .dependencies = featureSet(&[_]Feature{ + .avr0, + .lpm, + .memmappedregs, + }), + }; + result[@intFromEnum(Feature.avr2)] = .{ + .llvm_name = "avr2", + .description = "The device is a part of the avr2 family", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .avr1, + .ijmpcall, + .sram, + }), + }; + result[@intFromEnum(Feature.avr25)] = .{ + .llvm_name = "avr25", + .description = "The device is a part of the avr25 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .@"break", + .lpmx, + .movw, + .spm, + }), + }; + result[@intFromEnum(Feature.avr3)] = .{ + .llvm_name = "avr3", + .description = "The device is a part of the avr3 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .jmpcall, + }), + }; + result[@intFromEnum(Feature.avr31)] = .{ + .llvm_name = "avr31", + .description = "The device is a part of the avr31 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .elpm, + }), + }; + result[@intFromEnum(Feature.avr35)] = .{ + .llvm_name = "avr35", + .description = "The device is a part of the avr35 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .@"break", + .lpmx, + .movw, + .spm, + }), + }; + result[@intFromEnum(Feature.avr4)] = .{ + .llvm_name = "avr4", + .description = "The device is a part of the avr4 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .@"break", + .lpmx, + .movw, + .mul, + .spm, + }), + }; + result[@intFromEnum(Feature.avr5)] = .{ + .llvm_name = "avr5", + .description = "The device is a part of the avr5 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .@"break", + .lpmx, + .movw, + .mul, + .spm, + }), + }; + result[@intFromEnum(Feature.avr51)] = .{ + .llvm_name = "avr51", + .description = "The device is a part of the avr51 family", + .dependencies = featureSet(&[_]Feature{ + .avr5, + .elpm, + .elpmx, + }), + }; + result[@intFromEnum(Feature.avr6)] = .{ + .llvm_name = "avr6", + .description = "The device is a part of the avr6 family", + .dependencies = featureSet(&[_]Feature{ + .avr51, + .eijmpcall, + }), + }; + result[@intFromEnum(Feature.avrtiny)] = .{ + .llvm_name = "avrtiny", + .description = "The device is a part of the avrtiny family", + .dependencies = featureSet(&[_]Feature{ + .avr0, + .@"break", + .smallstack, + .sram, + .tinyencoding, + }), + }; + result[@intFromEnum(Feature.@"break")] = .{ + .llvm_name = "break", + .description = "The device supports the `BREAK` debugging instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.des)] = .{ + .llvm_name = "des", + .description = "The device supports the `DES k` encryption instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.eijmpcall)] = .{ + .llvm_name = "eijmpcall", + .description = "The device supports the `EIJMP`/`EICALL` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.elpm)] = .{ + .llvm_name = "elpm", + .description = "The device supports the ELPM instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.elpmx)] = .{ + .llvm_name = "elpmx", + .description = "The device supports the `ELPM Rd, Z[+]` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ijmpcall)] = .{ + .llvm_name = "ijmpcall", + .description = "The device supports `IJMP`/`ICALL`instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.jmpcall)] = .{ + .llvm_name = "jmpcall", + .description = "The device supports the `JMP` and `CALL` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lowbytefirst)] = .{ + .llvm_name = "lowbytefirst", + .description = "Do the low byte first when writing a 16-bit port or storing a 16-bit word", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lpm)] = .{ + .llvm_name = "lpm", + .description = "The device supports the `LPM` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lpmx)] = .{ + .llvm_name = "lpmx", + .description = "The device supports the `LPM Rd, Z[+]` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.memmappedregs)] = .{ + .llvm_name = "memmappedregs", + .description = "The device has CPU registers mapped in data address space", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.movw)] = .{ + .llvm_name = "movw", + .description = "The device supports the 16-bit MOVW instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mul)] = .{ + .llvm_name = "mul", + .description = "The device supports the multiplication instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rmw)] = .{ + .llvm_name = "rmw", + .description = "The device supports the read-write-modify instructions: XCH, LAS, LAC, LAT", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.smallstack)] = .{ + .llvm_name = "smallstack", + .description = "The device has an 8-bit stack pointer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.special)] = .{ + .llvm_name = "special", + .description = "Enable use of the entire instruction set - used for debugging", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .@"break", + .des, + .eijmpcall, + .elpm, + .elpmx, + .ijmpcall, + .jmpcall, + .lpm, + .lpmx, + .memmappedregs, + .movw, + .mul, + .rmw, + .spm, + .spmx, + .sram, + }), + }; + result[@intFromEnum(Feature.spm)] = .{ + .llvm_name = "spm", + .description = "The device supports the `SPM` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.spmx)] = .{ + .llvm_name = "spmx", + .description = "The device supports the `SPM Z+` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sram)] = .{ + .llvm_name = "sram", + .description = "The device has random access memory", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tinyencoding)] = .{ + .llvm_name = "tinyencoding", + .description = "The device has Tiny core specific instruction encodings", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xmega)] = .{ + .llvm_name = "xmega", + .description = "The device is a part of the xmega family", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .avr0, + .@"break", + .des, + .eijmpcall, + .elpm, + .elpmx, + .ijmpcall, + .jmpcall, + .lowbytefirst, + .lpm, + .lpmx, + .movw, + .mul, + .spm, + .spmx, + .sram, + }), + }; + result[@intFromEnum(Feature.xmega3)] = .{ + .llvm_name = "xmega3", + .description = "The device is a part of the xmega3 family", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .avr0, + .@"break", + .ijmpcall, + .jmpcall, + .lowbytefirst, + .lpm, + .lpmx, + .movw, + .mul, + .sram, + }), + }; + result[@intFromEnum(Feature.xmegau)] = .{ + .llvm_name = "xmegau", + .description = "The device is a part of the xmegau family", + .dependencies = featureSet(&[_]Feature{ + .rmw, + .xmega, + }), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const at43usb320 = CpuModel{ + .name = "at43usb320", + .llvm_name = "at43usb320", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const at43usb355 = CpuModel{ + .name = "at43usb355", + .llvm_name = "at43usb355", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const at76c711 = CpuModel{ + .name = "at76c711", + .llvm_name = "at76c711", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const at86rf401 = CpuModel{ + .name = "at86rf401", + .llvm_name = "at86rf401", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + }), + }; + pub const at90c8534 = CpuModel{ + .name = "at90c8534", + .llvm_name = "at90c8534", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90can128 = CpuModel{ + .name = "at90can128", + .llvm_name = "at90can128", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90can32 = CpuModel{ + .name = "at90can32", + .llvm_name = "at90can32", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90can64 = CpuModel{ + .name = "at90can64", + .llvm_name = "at90can64", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm1 = CpuModel{ + .name = "at90pwm1", + .llvm_name = "at90pwm1", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm161 = CpuModel{ + .name = "at90pwm161", + .llvm_name = "at90pwm161", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm2 = CpuModel{ + .name = "at90pwm2", + .llvm_name = "at90pwm2", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm216 = CpuModel{ + .name = "at90pwm216", + .llvm_name = "at90pwm216", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm2b = CpuModel{ + .name = "at90pwm2b", + .llvm_name = "at90pwm2b", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm3 = CpuModel{ + .name = "at90pwm3", + .llvm_name = "at90pwm3", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm316 = CpuModel{ + .name = "at90pwm316", + .llvm_name = "at90pwm316", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm3b = CpuModel{ + .name = "at90pwm3b", + .llvm_name = "at90pwm3b", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm81 = CpuModel{ + .name = "at90pwm81", + .llvm_name = "at90pwm81", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90s1200 = CpuModel{ + .name = "at90s1200", + .llvm_name = "at90s1200", + .features = featureSet(&[_]Feature{ + .avr0, + .smallstack, + }), + }; + pub const at90s2313 = CpuModel{ + .name = "at90s2313", + .llvm_name = "at90s2313", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s2323 = CpuModel{ + .name = "at90s2323", + .llvm_name = "at90s2323", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s2333 = CpuModel{ + .name = "at90s2333", + .llvm_name = "at90s2333", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s2343 = CpuModel{ + .name = "at90s2343", + .llvm_name = "at90s2343", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s4414 = CpuModel{ + .name = "at90s4414", + .llvm_name = "at90s4414", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s4433 = CpuModel{ + .name = "at90s4433", + .llvm_name = "at90s4433", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s4434 = CpuModel{ + .name = "at90s4434", + .llvm_name = "at90s4434", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const at90s8515 = CpuModel{ + .name = "at90s8515", + .llvm_name = "at90s8515", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s8535 = CpuModel{ + .name = "at90s8535", + .llvm_name = "at90s8535", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90scr100 = CpuModel{ + .name = "at90scr100", + .llvm_name = "at90scr100", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb1286 = CpuModel{ + .name = "at90usb1286", + .llvm_name = "at90usb1286", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90usb1287 = CpuModel{ + .name = "at90usb1287", + .llvm_name = "at90usb1287", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90usb162 = CpuModel{ + .name = "at90usb162", + .llvm_name = "at90usb162", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const at90usb646 = CpuModel{ + .name = "at90usb646", + .llvm_name = "at90usb646", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb647 = CpuModel{ + .name = "at90usb647", + .llvm_name = "at90usb647", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb82 = CpuModel{ + .name = "at90usb82", + .llvm_name = "at90usb82", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const at94k = CpuModel{ + .name = "at94k", + .llvm_name = "at94k", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + }), + }; + pub const ata5272 = CpuModel{ + .name = "ata5272", + .llvm_name = "ata5272", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const ata5505 = CpuModel{ + .name = "ata5505", + .llvm_name = "ata5505", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const ata5702m322 = CpuModel{ + .name = "ata5702m322", + .llvm_name = "ata5702m322", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5782 = CpuModel{ + .name = "ata5782", + .llvm_name = "ata5782", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5790 = CpuModel{ + .name = "ata5790", + .llvm_name = "ata5790", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5790n = CpuModel{ + .name = "ata5790n", + .llvm_name = "ata5790n", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5791 = CpuModel{ + .name = "ata5791", + .llvm_name = "ata5791", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5795 = CpuModel{ + .name = "ata5795", + .llvm_name = "ata5795", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5831 = CpuModel{ + .name = "ata5831", + .llvm_name = "ata5831", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata6285 = CpuModel{ + .name = "ata6285", + .llvm_name = "ata6285", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6286 = CpuModel{ + .name = "ata6286", + .llvm_name = "ata6286", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6289 = CpuModel{ + .name = "ata6289", + .llvm_name = "ata6289", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6612c = CpuModel{ + .name = "ata6612c", + .llvm_name = "ata6612c", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6613c = CpuModel{ + .name = "ata6613c", + .llvm_name = "ata6613c", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata6614q = CpuModel{ + .name = "ata6614q", + .llvm_name = "ata6614q", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata6616c = CpuModel{ + .name = "ata6616c", + .llvm_name = "ata6616c", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const ata6617c = CpuModel{ + .name = "ata6617c", + .llvm_name = "ata6617c", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const ata664251 = CpuModel{ + .name = "ata664251", + .llvm_name = "ata664251", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const ata8210 = CpuModel{ + .name = "ata8210", + .llvm_name = "ata8210", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata8510 = CpuModel{ + .name = "ata8510", + .llvm_name = "ata8510", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega103 = CpuModel{ + .name = "atmega103", + .llvm_name = "atmega103", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const atmega128 = CpuModel{ + .name = "atmega128", + .llvm_name = "atmega128", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1280 = CpuModel{ + .name = "atmega1280", + .llvm_name = "atmega1280", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1281 = CpuModel{ + .name = "atmega1281", + .llvm_name = "atmega1281", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284 = CpuModel{ + .name = "atmega1284", + .llvm_name = "atmega1284", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284p = CpuModel{ + .name = "atmega1284p", + .llvm_name = "atmega1284p", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284rfr2 = CpuModel{ + .name = "atmega1284rfr2", + .llvm_name = "atmega1284rfr2", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128a = CpuModel{ + .name = "atmega128a", + .llvm_name = "atmega128a", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128rfa1 = CpuModel{ + .name = "atmega128rfa1", + .llvm_name = "atmega128rfa1", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128rfr2 = CpuModel{ + .name = "atmega128rfr2", + .llvm_name = "atmega128rfr2", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega16 = CpuModel{ + .name = "atmega16", + .llvm_name = "atmega16", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega1608 = CpuModel{ + .name = "atmega1608", + .llvm_name = "atmega1608", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega1609 = CpuModel{ + .name = "atmega1609", + .llvm_name = "atmega1609", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega161 = CpuModel{ + .name = "atmega161", + .llvm_name = "atmega161", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega162 = CpuModel{ + .name = "atmega162", + .llvm_name = "atmega162", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega163 = CpuModel{ + .name = "atmega163", + .llvm_name = "atmega163", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega164a = CpuModel{ + .name = "atmega164a", + .llvm_name = "atmega164a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega164p = CpuModel{ + .name = "atmega164p", + .llvm_name = "atmega164p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega164pa = CpuModel{ + .name = "atmega164pa", + .llvm_name = "atmega164pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165 = CpuModel{ + .name = "atmega165", + .llvm_name = "atmega165", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165a = CpuModel{ + .name = "atmega165a", + .llvm_name = "atmega165a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165p = CpuModel{ + .name = "atmega165p", + .llvm_name = "atmega165p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165pa = CpuModel{ + .name = "atmega165pa", + .llvm_name = "atmega165pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168 = CpuModel{ + .name = "atmega168", + .llvm_name = "atmega168", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168a = CpuModel{ + .name = "atmega168a", + .llvm_name = "atmega168a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168p = CpuModel{ + .name = "atmega168p", + .llvm_name = "atmega168p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168pa = CpuModel{ + .name = "atmega168pa", + .llvm_name = "atmega168pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168pb = CpuModel{ + .name = "atmega168pb", + .llvm_name = "atmega168pb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169 = CpuModel{ + .name = "atmega169", + .llvm_name = "atmega169", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169a = CpuModel{ + .name = "atmega169a", + .llvm_name = "atmega169a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169p = CpuModel{ + .name = "atmega169p", + .llvm_name = "atmega169p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169pa = CpuModel{ + .name = "atmega169pa", + .llvm_name = "atmega169pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16a = CpuModel{ + .name = "atmega16a", + .llvm_name = "atmega16a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hva = CpuModel{ + .name = "atmega16hva", + .llvm_name = "atmega16hva", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hva2 = CpuModel{ + .name = "atmega16hva2", + .llvm_name = "atmega16hva2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hvb = CpuModel{ + .name = "atmega16hvb", + .llvm_name = "atmega16hvb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hvbrevb = CpuModel{ + .name = "atmega16hvbrevb", + .llvm_name = "atmega16hvbrevb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16m1 = CpuModel{ + .name = "atmega16m1", + .llvm_name = "atmega16m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16u2 = CpuModel{ + .name = "atmega16u2", + .llvm_name = "atmega16u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const atmega16u4 = CpuModel{ + .name = "atmega16u4", + .llvm_name = "atmega16u4", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega2560 = CpuModel{ + .name = "atmega2560", + .llvm_name = "atmega2560", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega2561 = CpuModel{ + .name = "atmega2561", + .llvm_name = "atmega2561", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega2564rfr2 = CpuModel{ + .name = "atmega2564rfr2", + .llvm_name = "atmega2564rfr2", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega256rfr2 = CpuModel{ + .name = "atmega256rfr2", + .llvm_name = "atmega256rfr2", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega32 = CpuModel{ + .name = "atmega32", + .llvm_name = "atmega32", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3208 = CpuModel{ + .name = "atmega3208", + .llvm_name = "atmega3208", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega3209 = CpuModel{ + .name = "atmega3209", + .llvm_name = "atmega3209", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega323 = CpuModel{ + .name = "atmega323", + .llvm_name = "atmega323", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324a = CpuModel{ + .name = "atmega324a", + .llvm_name = "atmega324a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324p = CpuModel{ + .name = "atmega324p", + .llvm_name = "atmega324p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324pa = CpuModel{ + .name = "atmega324pa", + .llvm_name = "atmega324pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324pb = CpuModel{ + .name = "atmega324pb", + .llvm_name = "atmega324pb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325 = CpuModel{ + .name = "atmega325", + .llvm_name = "atmega325", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250 = CpuModel{ + .name = "atmega3250", + .llvm_name = "atmega3250", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250a = CpuModel{ + .name = "atmega3250a", + .llvm_name = "atmega3250a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250p = CpuModel{ + .name = "atmega3250p", + .llvm_name = "atmega3250p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250pa = CpuModel{ + .name = "atmega3250pa", + .llvm_name = "atmega3250pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325a = CpuModel{ + .name = "atmega325a", + .llvm_name = "atmega325a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325p = CpuModel{ + .name = "atmega325p", + .llvm_name = "atmega325p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325pa = CpuModel{ + .name = "atmega325pa", + .llvm_name = "atmega325pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega328 = CpuModel{ + .name = "atmega328", + .llvm_name = "atmega328", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega328p = CpuModel{ + .name = "atmega328p", + .llvm_name = "atmega328p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega328pb = CpuModel{ + .name = "atmega328pb", + .llvm_name = "atmega328pb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329 = CpuModel{ + .name = "atmega329", + .llvm_name = "atmega329", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290 = CpuModel{ + .name = "atmega3290", + .llvm_name = "atmega3290", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290a = CpuModel{ + .name = "atmega3290a", + .llvm_name = "atmega3290a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290p = CpuModel{ + .name = "atmega3290p", + .llvm_name = "atmega3290p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290pa = CpuModel{ + .name = "atmega3290pa", + .llvm_name = "atmega3290pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329a = CpuModel{ + .name = "atmega329a", + .llvm_name = "atmega329a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329p = CpuModel{ + .name = "atmega329p", + .llvm_name = "atmega329p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329pa = CpuModel{ + .name = "atmega329pa", + .llvm_name = "atmega329pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32a = CpuModel{ + .name = "atmega32a", + .llvm_name = "atmega32a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32c1 = CpuModel{ + .name = "atmega32c1", + .llvm_name = "atmega32c1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32hvb = CpuModel{ + .name = "atmega32hvb", + .llvm_name = "atmega32hvb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32hvbrevb = CpuModel{ + .name = "atmega32hvbrevb", + .llvm_name = "atmega32hvbrevb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32m1 = CpuModel{ + .name = "atmega32m1", + .llvm_name = "atmega32m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32u2 = CpuModel{ + .name = "atmega32u2", + .llvm_name = "atmega32u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const atmega32u4 = CpuModel{ + .name = "atmega32u4", + .llvm_name = "atmega32u4", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32u6 = CpuModel{ + .name = "atmega32u6", + .llvm_name = "atmega32u6", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega406 = CpuModel{ + .name = "atmega406", + .llvm_name = "atmega406", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega48 = CpuModel{ + .name = "atmega48", + .llvm_name = "atmega48", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega4808 = CpuModel{ + .name = "atmega4808", + .llvm_name = "atmega4808", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega4809 = CpuModel{ + .name = "atmega4809", + .llvm_name = "atmega4809", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega48a = CpuModel{ + .name = "atmega48a", + .llvm_name = "atmega48a", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48p = CpuModel{ + .name = "atmega48p", + .llvm_name = "atmega48p", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48pa = CpuModel{ + .name = "atmega48pa", + .llvm_name = "atmega48pa", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48pb = CpuModel{ + .name = "atmega48pb", + .llvm_name = "atmega48pb", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega64 = CpuModel{ + .name = "atmega64", + .llvm_name = "atmega64", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega640 = CpuModel{ + .name = "atmega640", + .llvm_name = "atmega640", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644 = CpuModel{ + .name = "atmega644", + .llvm_name = "atmega644", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644a = CpuModel{ + .name = "atmega644a", + .llvm_name = "atmega644a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644p = CpuModel{ + .name = "atmega644p", + .llvm_name = "atmega644p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644pa = CpuModel{ + .name = "atmega644pa", + .llvm_name = "atmega644pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644rfr2 = CpuModel{ + .name = "atmega644rfr2", + .llvm_name = "atmega644rfr2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645 = CpuModel{ + .name = "atmega645", + .llvm_name = "atmega645", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450 = CpuModel{ + .name = "atmega6450", + .llvm_name = "atmega6450", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450a = CpuModel{ + .name = "atmega6450a", + .llvm_name = "atmega6450a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450p = CpuModel{ + .name = "atmega6450p", + .llvm_name = "atmega6450p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645a = CpuModel{ + .name = "atmega645a", + .llvm_name = "atmega645a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645p = CpuModel{ + .name = "atmega645p", + .llvm_name = "atmega645p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649 = CpuModel{ + .name = "atmega649", + .llvm_name = "atmega649", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490 = CpuModel{ + .name = "atmega6490", + .llvm_name = "atmega6490", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490a = CpuModel{ + .name = "atmega6490a", + .llvm_name = "atmega6490a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490p = CpuModel{ + .name = "atmega6490p", + .llvm_name = "atmega6490p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649a = CpuModel{ + .name = "atmega649a", + .llvm_name = "atmega649a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649p = CpuModel{ + .name = "atmega649p", + .llvm_name = "atmega649p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64a = CpuModel{ + .name = "atmega64a", + .llvm_name = "atmega64a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64c1 = CpuModel{ + .name = "atmega64c1", + .llvm_name = "atmega64c1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64hve = CpuModel{ + .name = "atmega64hve", + .llvm_name = "atmega64hve", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64hve2 = CpuModel{ + .name = "atmega64hve2", + .llvm_name = "atmega64hve2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64m1 = CpuModel{ + .name = "atmega64m1", + .llvm_name = "atmega64m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64rfr2 = CpuModel{ + .name = "atmega64rfr2", + .llvm_name = "atmega64rfr2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega8 = CpuModel{ + .name = "atmega8", + .llvm_name = "atmega8", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega808 = CpuModel{ + .name = "atmega808", + .llvm_name = "atmega808", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega809 = CpuModel{ + .name = "atmega809", + .llvm_name = "atmega809", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const atmega8515 = CpuModel{ + .name = "atmega8515", + .llvm_name = "atmega8515", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega8535 = CpuModel{ + .name = "atmega8535", + .llvm_name = "atmega8535", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega88 = CpuModel{ + .name = "atmega88", + .llvm_name = "atmega88", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88a = CpuModel{ + .name = "atmega88a", + .llvm_name = "atmega88a", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88p = CpuModel{ + .name = "atmega88p", + .llvm_name = "atmega88p", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88pa = CpuModel{ + .name = "atmega88pa", + .llvm_name = "atmega88pa", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88pb = CpuModel{ + .name = "atmega88pb", + .llvm_name = "atmega88pb", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8a = CpuModel{ + .name = "atmega8a", + .llvm_name = "atmega8a", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega8hva = CpuModel{ + .name = "atmega8hva", + .llvm_name = "atmega8hva", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8u2 = CpuModel{ + .name = "atmega8u2", + .llvm_name = "atmega8u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny10 = CpuModel{ + .name = "attiny10", + .llvm_name = "attiny10", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny102 = CpuModel{ + .name = "attiny102", + .llvm_name = "attiny102", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny104 = CpuModel{ + .name = "attiny104", + .llvm_name = "attiny104", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny11 = CpuModel{ + .name = "attiny11", + .llvm_name = "attiny11", + .features = featureSet(&[_]Feature{ + .avr1, + .smallstack, + }), + }; + pub const attiny12 = CpuModel{ + .name = "attiny12", + .llvm_name = "attiny12", + .features = featureSet(&[_]Feature{ + .avr1, + .smallstack, + }), + }; + pub const attiny13 = CpuModel{ + .name = "attiny13", + .llvm_name = "attiny13", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny13a = CpuModel{ + .name = "attiny13a", + .llvm_name = "attiny13a", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny15 = CpuModel{ + .name = "attiny15", + .llvm_name = "attiny15", + .features = featureSet(&[_]Feature{ + .avr1, + .smallstack, + }), + }; + pub const attiny1604 = CpuModel{ + .name = "attiny1604", + .llvm_name = "attiny1604", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1606 = CpuModel{ + .name = "attiny1606", + .llvm_name = "attiny1606", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1607 = CpuModel{ + .name = "attiny1607", + .llvm_name = "attiny1607", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1614 = CpuModel{ + .name = "attiny1614", + .llvm_name = "attiny1614", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1616 = CpuModel{ + .name = "attiny1616", + .llvm_name = "attiny1616", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1617 = CpuModel{ + .name = "attiny1617", + .llvm_name = "attiny1617", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1624 = CpuModel{ + .name = "attiny1624", + .llvm_name = "attiny1624", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1626 = CpuModel{ + .name = "attiny1626", + .llvm_name = "attiny1626", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1627 = CpuModel{ + .name = "attiny1627", + .llvm_name = "attiny1627", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny1634 = CpuModel{ + .name = "attiny1634", + .llvm_name = "attiny1634", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny167 = CpuModel{ + .name = "attiny167", + .llvm_name = "attiny167", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny20 = CpuModel{ + .name = "attiny20", + .llvm_name = "attiny20", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny202 = CpuModel{ + .name = "attiny202", + .llvm_name = "attiny202", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny204 = CpuModel{ + .name = "attiny204", + .llvm_name = "attiny204", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny212 = CpuModel{ + .name = "attiny212", + .llvm_name = "attiny212", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny214 = CpuModel{ + .name = "attiny214", + .llvm_name = "attiny214", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny22 = CpuModel{ + .name = "attiny22", + .llvm_name = "attiny22", + .features = featureSet(&[_]Feature{ + .avr2, + .smallstack, + }), + }; + pub const attiny2313 = CpuModel{ + .name = "attiny2313", + .llvm_name = "attiny2313", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny2313a = CpuModel{ + .name = "attiny2313a", + .llvm_name = "attiny2313a", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny24 = CpuModel{ + .name = "attiny24", + .llvm_name = "attiny24", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny24a = CpuModel{ + .name = "attiny24a", + .llvm_name = "attiny24a", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny25 = CpuModel{ + .name = "attiny25", + .llvm_name = "attiny25", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny26 = CpuModel{ + .name = "attiny26", + .llvm_name = "attiny26", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .smallstack, + }), + }; + pub const attiny261 = CpuModel{ + .name = "attiny261", + .llvm_name = "attiny261", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny261a = CpuModel{ + .name = "attiny261a", + .llvm_name = "attiny261a", + .features = featureSet(&[_]Feature{ + .avr25, + .smallstack, + }), + }; + pub const attiny28 = CpuModel{ + .name = "attiny28", + .llvm_name = "attiny28", + .features = featureSet(&[_]Feature{ + .avr1, + .smallstack, + }), + }; + pub const attiny3216 = CpuModel{ + .name = "attiny3216", + .llvm_name = "attiny3216", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny3217 = CpuModel{ + .name = "attiny3217", + .llvm_name = "attiny3217", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny4 = CpuModel{ + .name = "attiny4", + .llvm_name = "attiny4", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny40 = CpuModel{ + .name = "attiny40", + .llvm_name = "attiny40", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny402 = CpuModel{ + .name = "attiny402", + .llvm_name = "attiny402", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny404 = CpuModel{ + .name = "attiny404", + .llvm_name = "attiny404", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny406 = CpuModel{ + .name = "attiny406", + .llvm_name = "attiny406", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny412 = CpuModel{ + .name = "attiny412", + .llvm_name = "attiny412", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny414 = CpuModel{ + .name = "attiny414", + .llvm_name = "attiny414", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny416 = CpuModel{ + .name = "attiny416", + .llvm_name = "attiny416", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny417 = CpuModel{ + .name = "attiny417", + .llvm_name = "attiny417", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny4313 = CpuModel{ + .name = "attiny4313", + .llvm_name = "attiny4313", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny43u = CpuModel{ + .name = "attiny43u", + .llvm_name = "attiny43u", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny44 = CpuModel{ + .name = "attiny44", + .llvm_name = "attiny44", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny441 = CpuModel{ + .name = "attiny441", + .llvm_name = "attiny441", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny44a = CpuModel{ + .name = "attiny44a", + .llvm_name = "attiny44a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny45 = CpuModel{ + .name = "attiny45", + .llvm_name = "attiny45", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny461 = CpuModel{ + .name = "attiny461", + .llvm_name = "attiny461", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny461a = CpuModel{ + .name = "attiny461a", + .llvm_name = "attiny461a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny48 = CpuModel{ + .name = "attiny48", + .llvm_name = "attiny48", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny5 = CpuModel{ + .name = "attiny5", + .llvm_name = "attiny5", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny804 = CpuModel{ + .name = "attiny804", + .llvm_name = "attiny804", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny806 = CpuModel{ + .name = "attiny806", + .llvm_name = "attiny806", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny807 = CpuModel{ + .name = "attiny807", + .llvm_name = "attiny807", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny814 = CpuModel{ + .name = "attiny814", + .llvm_name = "attiny814", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny816 = CpuModel{ + .name = "attiny816", + .llvm_name = "attiny816", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny817 = CpuModel{ + .name = "attiny817", + .llvm_name = "attiny817", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const attiny828 = CpuModel{ + .name = "attiny828", + .llvm_name = "attiny828", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny84 = CpuModel{ + .name = "attiny84", + .llvm_name = "attiny84", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny841 = CpuModel{ + .name = "attiny841", + .llvm_name = "attiny841", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny84a = CpuModel{ + .name = "attiny84a", + .llvm_name = "attiny84a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny85 = CpuModel{ + .name = "attiny85", + .llvm_name = "attiny85", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny861 = CpuModel{ + .name = "attiny861", + .llvm_name = "attiny861", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny861a = CpuModel{ + .name = "attiny861a", + .llvm_name = "attiny861a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny87 = CpuModel{ + .name = "attiny87", + .llvm_name = "attiny87", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny88 = CpuModel{ + .name = "attiny88", + .llvm_name = "attiny88", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny9 = CpuModel{ + .name = "attiny9", + .llvm_name = "attiny9", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const atxmega128a1 = CpuModel{ + .name = "atxmega128a1", + .llvm_name = "atxmega128a1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128a1u = CpuModel{ + .name = "atxmega128a1u", + .llvm_name = "atxmega128a1u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128a3 = CpuModel{ + .name = "atxmega128a3", + .llvm_name = "atxmega128a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128a3u = CpuModel{ + .name = "atxmega128a3u", + .llvm_name = "atxmega128a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128a4u = CpuModel{ + .name = "atxmega128a4u", + .llvm_name = "atxmega128a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128b1 = CpuModel{ + .name = "atxmega128b1", + .llvm_name = "atxmega128b1", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128b3 = CpuModel{ + .name = "atxmega128b3", + .llvm_name = "atxmega128b3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128c3 = CpuModel{ + .name = "atxmega128c3", + .llvm_name = "atxmega128c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128d3 = CpuModel{ + .name = "atxmega128d3", + .llvm_name = "atxmega128d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128d4 = CpuModel{ + .name = "atxmega128d4", + .llvm_name = "atxmega128d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16a4 = CpuModel{ + .name = "atxmega16a4", + .llvm_name = "atxmega16a4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16a4u = CpuModel{ + .name = "atxmega16a4u", + .llvm_name = "atxmega16a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega16c4 = CpuModel{ + .name = "atxmega16c4", + .llvm_name = "atxmega16c4", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega16d4 = CpuModel{ + .name = "atxmega16d4", + .llvm_name = "atxmega16d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16e5 = CpuModel{ + .name = "atxmega16e5", + .llvm_name = "atxmega16e5", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega192a3 = CpuModel{ + .name = "atxmega192a3", + .llvm_name = "atxmega192a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega192a3u = CpuModel{ + .name = "atxmega192a3u", + .llvm_name = "atxmega192a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega192c3 = CpuModel{ + .name = "atxmega192c3", + .llvm_name = "atxmega192c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega192d3 = CpuModel{ + .name = "atxmega192d3", + .llvm_name = "atxmega192d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3 = CpuModel{ + .name = "atxmega256a3", + .llvm_name = "atxmega256a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3b = CpuModel{ + .name = "atxmega256a3b", + .llvm_name = "atxmega256a3b", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3bu = CpuModel{ + .name = "atxmega256a3bu", + .llvm_name = "atxmega256a3bu", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256a3u = CpuModel{ + .name = "atxmega256a3u", + .llvm_name = "atxmega256a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256c3 = CpuModel{ + .name = "atxmega256c3", + .llvm_name = "atxmega256c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256d3 = CpuModel{ + .name = "atxmega256d3", + .llvm_name = "atxmega256d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32a4 = CpuModel{ + .name = "atxmega32a4", + .llvm_name = "atxmega32a4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32a4u = CpuModel{ + .name = "atxmega32a4u", + .llvm_name = "atxmega32a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega32c3 = CpuModel{ + .name = "atxmega32c3", + .llvm_name = "atxmega32c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega32c4 = CpuModel{ + .name = "atxmega32c4", + .llvm_name = "atxmega32c4", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega32d3 = CpuModel{ + .name = "atxmega32d3", + .llvm_name = "atxmega32d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32d4 = CpuModel{ + .name = "atxmega32d4", + .llvm_name = "atxmega32d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32e5 = CpuModel{ + .name = "atxmega32e5", + .llvm_name = "atxmega32e5", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega384c3 = CpuModel{ + .name = "atxmega384c3", + .llvm_name = "atxmega384c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega384d3 = CpuModel{ + .name = "atxmega384d3", + .llvm_name = "atxmega384d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a1 = CpuModel{ + .name = "atxmega64a1", + .llvm_name = "atxmega64a1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a1u = CpuModel{ + .name = "atxmega64a1u", + .llvm_name = "atxmega64a1u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64a3 = CpuModel{ + .name = "atxmega64a3", + .llvm_name = "atxmega64a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a3u = CpuModel{ + .name = "atxmega64a3u", + .llvm_name = "atxmega64a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64a4u = CpuModel{ + .name = "atxmega64a4u", + .llvm_name = "atxmega64a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64b1 = CpuModel{ + .name = "atxmega64b1", + .llvm_name = "atxmega64b1", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64b3 = CpuModel{ + .name = "atxmega64b3", + .llvm_name = "atxmega64b3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64c3 = CpuModel{ + .name = "atxmega64c3", + .llvm_name = "atxmega64c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64d3 = CpuModel{ + .name = "atxmega64d3", + .llvm_name = "atxmega64d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64d4 = CpuModel{ + .name = "atxmega64d4", + .llvm_name = "atxmega64d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega8e5 = CpuModel{ + .name = "atxmega8e5", + .llvm_name = "atxmega8e5", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const avr1 = CpuModel{ + .name = "avr1", + .llvm_name = "avr1", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const avr2 = CpuModel{ + .name = "avr2", + .llvm_name = "avr2", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const avr25 = CpuModel{ + .name = "avr25", + .llvm_name = "avr25", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const avr3 = CpuModel{ + .name = "avr3", + .llvm_name = "avr3", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const avr31 = CpuModel{ + .name = "avr31", + .llvm_name = "avr31", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const avr35 = CpuModel{ + .name = "avr35", + .llvm_name = "avr35", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const avr4 = CpuModel{ + .name = "avr4", + .llvm_name = "avr4", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const avr5 = CpuModel{ + .name = "avr5", + .llvm_name = "avr5", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const avr51 = CpuModel{ + .name = "avr51", + .llvm_name = "avr51", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const avr6 = CpuModel{ + .name = "avr6", + .llvm_name = "avr6", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const avrtiny = CpuModel{ + .name = "avrtiny", + .llvm_name = "avrtiny", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const avrxmega1 = CpuModel{ + .name = "avrxmega1", + .llvm_name = "avrxmega1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega2 = CpuModel{ + .name = "avrxmega2", + .llvm_name = "avrxmega2", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega3 = CpuModel{ + .name = "avrxmega3", + .llvm_name = "avrxmega3", + .features = featureSet(&[_]Feature{ + .xmega3, + }), + }; + pub const avrxmega4 = CpuModel{ + .name = "avrxmega4", + .llvm_name = "avrxmega4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega5 = CpuModel{ + .name = "avrxmega5", + .llvm_name = "avrxmega5", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega6 = CpuModel{ + .name = "avrxmega6", + .llvm_name = "avrxmega6", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega7 = CpuModel{ + .name = "avrxmega7", + .llvm_name = "avrxmega7", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const m3000 = CpuModel{ + .name = "m3000", + .llvm_name = "m3000", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; +}; diff --git a/lib/std/Target/bpf.zig b/lib/std/Target/bpf.zig new file mode 100644 index 0000000000000000000000000000000000000000..40dc2d1c7e90229adde8e4769b3d41dea0767523 --- /dev/null +++ b/lib/std/Target/bpf.zig @@ -0,0 +1,73 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + alu32, + dummy, + dwarfris, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.alu32)] = .{ + .llvm_name = "alu32", + .description = "Enable ALU32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dummy)] = .{ + .llvm_name = "dummy", + .description = "unused feature", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dwarfris)] = .{ + .llvm_name = "dwarfris", + .description = "Disable MCAsmInfo DwarfUsesRelocationsAcrossSections", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const probe = CpuModel{ + .name = "probe", + .llvm_name = "probe", + .features = featureSet(&[_]Feature{}), + }; + pub const v1 = CpuModel{ + .name = "v1", + .llvm_name = "v1", + .features = featureSet(&[_]Feature{}), + }; + pub const v2 = CpuModel{ + .name = "v2", + .llvm_name = "v2", + .features = featureSet(&[_]Feature{}), + }; + pub const v3 = CpuModel{ + .name = "v3", + .llvm_name = "v3", + .features = featureSet(&[_]Feature{ + .alu32, + }), + }; +}; diff --git a/lib/std/Target/csky.zig b/lib/std/Target/csky.zig new file mode 100644 index 0000000000000000000000000000000000000000..331e8057bfbdccf1b8da5efd91c97159781eb261 --- /dev/null +++ b/lib/std/Target/csky.zig @@ -0,0 +1,3214 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"10e60", + @"2e3", + @"3e3r1", + @"3e3r2", + @"3e3r3", + @"3e7", + @"7e10", + btst16, + cache, + ccrt, + ck801, + ck802, + ck803, + ck803s, + ck804, + ck805, + ck807, + ck810, + ck810v, + ck860, + ck860v, + constpool, + doloop, + dsp1e2, + dsp_silan, + dspe60, + dspv2, + e1, + e2, + edsp, + elrw, + fdivdu, + float1e2, + float1e3, + float3e4, + float7e60, + floate1, + fpuv2_df, + fpuv2_sf, + fpuv3_df, + fpuv3_hf, + fpuv3_hi, + fpuv3_sf, + hard_float, + hard_float_abi, + hard_tp, + high_registers, + hwdiv, + istack, + java, + mp, + mp1e2, + multiple_stld, + nvic, + pushpop, + smart, + soft_tp, + stack_size, + trust, + vdsp2e3, + vdsp2e60f, + vdspv1, + vdspv2, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"10e60")] = .{ + .llvm_name = "10e60", + .description = "Support CSKY 10e60 instructions", + .dependencies = featureSet(&[_]Feature{ + .@"7e10", + }), + }; + result[@intFromEnum(Feature.@"2e3")] = .{ + .llvm_name = "2e3", + .description = "Support CSKY 2e3 instructions", + .dependencies = featureSet(&[_]Feature{ + .e2, + }), + }; + result[@intFromEnum(Feature.@"3e3r1")] = .{ + .llvm_name = "3e3r1", + .description = "Support CSKY 3e3r1 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"3e3r2")] = .{ + .llvm_name = "3e3r2", + .description = "Support CSKY 3e3r2 instructions", + .dependencies = featureSet(&[_]Feature{ + .@"3e3r1", + .doloop, + }), + }; + result[@intFromEnum(Feature.@"3e3r3")] = .{ + .llvm_name = "3e3r3", + .description = "Support CSKY 3e3r3 instructions", + .dependencies = featureSet(&[_]Feature{ + .doloop, + }), + }; + result[@intFromEnum(Feature.@"3e7")] = .{ + .llvm_name = "3e7", + .description = "Support CSKY 3e7 instructions", + .dependencies = featureSet(&[_]Feature{ + .@"2e3", + }), + }; + result[@intFromEnum(Feature.@"7e10")] = .{ + .llvm_name = "7e10", + .description = "Support CSKY 7e10 instructions", + .dependencies = featureSet(&[_]Feature{ + .@"3e7", + }), + }; + result[@intFromEnum(Feature.btst16)] = .{ + .llvm_name = "btst16", + .description = "Use the 16-bit btsti instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cache)] = .{ + .llvm_name = "cache", + .description = "Enable cache", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ccrt)] = .{ + .llvm_name = "ccrt", + .description = "Use CSKY compiler runtime", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck801)] = .{ + .llvm_name = "ck801", + .description = "CSKY ck801 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck802)] = .{ + .llvm_name = "ck802", + .description = "CSKY ck802 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck803)] = .{ + .llvm_name = "ck803", + .description = "CSKY ck803 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck803s)] = .{ + .llvm_name = "ck803s", + .description = "CSKY ck803s processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck804)] = .{ + .llvm_name = "ck804", + .description = "CSKY ck804 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck805)] = .{ + .llvm_name = "ck805", + .description = "CSKY ck805 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck807)] = .{ + .llvm_name = "ck807", + .description = "CSKY ck807 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck810)] = .{ + .llvm_name = "ck810", + .description = "CSKY ck810 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck810v)] = .{ + .llvm_name = "ck810v", + .description = "CSKY ck810v processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck860)] = .{ + .llvm_name = "ck860", + .description = "CSKY ck860 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ck860v)] = .{ + .llvm_name = "ck860v", + .description = "CSKY ck860v processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.constpool)] = .{ + .llvm_name = "constpool", + .description = "Dump the constant pool by compiler", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.doloop)] = .{ + .llvm_name = "doloop", + .description = "Enable doloop instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dsp1e2)] = .{ + .llvm_name = "dsp1e2", + .description = "Support CSKY dsp1e2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dsp_silan)] = .{ + .llvm_name = "dsp_silan", + .description = "Enable DSP Silan instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dspe60)] = .{ + .llvm_name = "dspe60", + .description = "Support CSKY dspe60 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dspv2)] = .{ + .llvm_name = "dspv2", + .description = "Enable DSP V2.0 instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.e1)] = .{ + .llvm_name = "e1", + .description = "Support CSKY e1 instructions", + .dependencies = featureSet(&[_]Feature{ + .elrw, + }), + }; + result[@intFromEnum(Feature.e2)] = .{ + .llvm_name = "e2", + .description = "Support CSKY e2 instructions", + .dependencies = featureSet(&[_]Feature{ + .e1, + }), + }; + result[@intFromEnum(Feature.edsp)] = .{ + .llvm_name = "edsp", + .description = "Enable DSP instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.elrw)] = .{ + .llvm_name = "elrw", + .description = "Use the extend LRW instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fdivdu)] = .{ + .llvm_name = "fdivdu", + .description = "Enable float divide instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.float1e2)] = .{ + .llvm_name = "float1e2", + .description = "Support CSKY float1e2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.float1e3)] = .{ + .llvm_name = "float1e3", + .description = "Support CSKY float1e3 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.float3e4)] = .{ + .llvm_name = "float3e4", + .description = "Support CSKY float3e4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.float7e60)] = .{ + .llvm_name = "float7e60", + .description = "Support CSKY float7e60 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.floate1)] = .{ + .llvm_name = "floate1", + .description = "Support CSKY floate1 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv2_df)] = .{ + .llvm_name = "fpuv2_df", + .description = "Enable FPUv2 double float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv2_sf)] = .{ + .llvm_name = "fpuv2_sf", + .description = "Enable FPUv2 single float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv3_df)] = .{ + .llvm_name = "fpuv3_df", + .description = "Enable FPUv3 double float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv3_hf)] = .{ + .llvm_name = "fpuv3_hf", + .description = "Enable FPUv3 half precision operate instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv3_hi)] = .{ + .llvm_name = "fpuv3_hi", + .description = "Enable FPUv3 half word converting instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpuv3_sf)] = .{ + .llvm_name = "fpuv3_sf", + .description = "Enable FPUv3 single float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hard_float)] = .{ + .llvm_name = "hard-float", + .description = "Use hard floating point features", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hard_float_abi)] = .{ + .llvm_name = "hard-float-abi", + .description = "Use hard floating point ABI to pass args", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hard_tp)] = .{ + .llvm_name = "hard-tp", + .description = "Enable TLS Pointer register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.high_registers)] = .{ + .llvm_name = "high-registers", + .description = "Enable r16-r31 registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hwdiv)] = .{ + .llvm_name = "hwdiv", + .description = "Enable divide instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.istack)] = .{ + .llvm_name = "istack", + .description = "Enable interrput attribute", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.java)] = .{ + .llvm_name = "java", + .description = "Enable java instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mp)] = .{ + .llvm_name = "mp", + .description = "Support CSKY mp instructions", + .dependencies = featureSet(&[_]Feature{ + .@"2e3", + }), + }; + result[@intFromEnum(Feature.mp1e2)] = .{ + .llvm_name = "mp1e2", + .description = "Support CSKY mp1e2 instructions", + .dependencies = featureSet(&[_]Feature{ + .@"3e7", + }), + }; + result[@intFromEnum(Feature.multiple_stld)] = .{ + .llvm_name = "multiple_stld", + .description = "Enable multiple load/store instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nvic)] = .{ + .llvm_name = "nvic", + .description = "Enable NVIC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pushpop)] = .{ + .llvm_name = "pushpop", + .description = "Enable push/pop instrutions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.smart)] = .{ + .llvm_name = "smart", + .description = "Let CPU work in Smart Mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_tp)] = .{ + .llvm_name = "soft-tp", + .description = "Disable TLS Pointer register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.stack_size)] = .{ + .llvm_name = "stack-size", + .description = "Output stack size information", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.trust)] = .{ + .llvm_name = "trust", + .description = "Enable trust instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vdsp2e3)] = .{ + .llvm_name = "vdsp2e3", + .description = "Support CSKY vdsp2e3 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vdsp2e60f)] = .{ + .llvm_name = "vdsp2e60f", + .description = "Support CSKY vdsp2e60f instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vdspv1)] = .{ + .llvm_name = "vdspv1", + .description = "Enable 128bit vdsp-v1 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vdspv2)] = .{ + .llvm_name = "vdspv2", + .description = "Enable vdsp-v2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const c807 = CpuModel{ + .name = "c807", + .llvm_name = "c807", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const c807f = CpuModel{ + .name = "c807f", + .llvm_name = "c807f", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .float1e3, + .float3e4, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const c810 = CpuModel{ + .name = "c810", + .llvm_name = "c810", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const c810t = CpuModel{ + .name = "c810t", + .llvm_name = "c810t", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const c810tv = CpuModel{ + .name = "c810tv", + .llvm_name = "c810tv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const c810v = CpuModel{ + .name = "c810v", + .llvm_name = "c810v", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const c860 = CpuModel{ + .name = "c860", + .llvm_name = "c860", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .dspe60, + .float7e60, + .fpuv3_df, + .fpuv3_hf, + .fpuv3_hi, + .fpuv3_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const c860v = CpuModel{ + .name = "c860v", + .llvm_name = "c860v", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .ck860v, + .dspe60, + .float7e60, + .fpuv3_df, + .fpuv3_hf, + .fpuv3_hi, + .fpuv3_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdsp2e60f, + .vdspv2, + }), + }; + pub const ck801 = CpuModel{ + .name = "ck801", + .llvm_name = "ck801", + .features = featureSet(&[_]Feature{ + .btst16, + .ck801, + .e1, + .trust, + }), + }; + pub const ck801t = CpuModel{ + .name = "ck801t", + .llvm_name = "ck801t", + .features = featureSet(&[_]Feature{ + .btst16, + .ck801, + .e1, + .trust, + }), + }; + pub const ck802 = CpuModel{ + .name = "ck802", + .llvm_name = "ck802", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const ck802j = CpuModel{ + .name = "ck802j", + .llvm_name = "ck802j", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .java, + .nvic, + .trust, + }), + }; + pub const ck802t = CpuModel{ + .name = "ck802t", + .llvm_name = "ck802t", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const ck803 = CpuModel{ + .name = "ck803", + .llvm_name = "ck803", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803e = CpuModel{ + .name = "ck803e", + .llvm_name = "ck803e", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ef = CpuModel{ + .name = "ck803ef", + .llvm_name = "ck803ef", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efh = CpuModel{ + .name = "ck803efh", + .llvm_name = "ck803efh", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhr1 = CpuModel{ + .name = "ck803efhr1", + .llvm_name = "ck803efhr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhr2 = CpuModel{ + .name = "ck803efhr2", + .llvm_name = "ck803efhr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhr3 = CpuModel{ + .name = "ck803efhr3", + .llvm_name = "ck803efhr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efht = CpuModel{ + .name = "ck803efht", + .llvm_name = "ck803efht", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhtr1 = CpuModel{ + .name = "ck803efhtr1", + .llvm_name = "ck803efhtr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhtr2 = CpuModel{ + .name = "ck803efhtr2", + .llvm_name = "ck803efhtr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efhtr3 = CpuModel{ + .name = "ck803efhtr3", + .llvm_name = "ck803efhtr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efr1 = CpuModel{ + .name = "ck803efr1", + .llvm_name = "ck803efr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efr2 = CpuModel{ + .name = "ck803efr2", + .llvm_name = "ck803efr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803efr3 = CpuModel{ + .name = "ck803efr3", + .llvm_name = "ck803efr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eft = CpuModel{ + .name = "ck803eft", + .llvm_name = "ck803eft", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eftr1 = CpuModel{ + .name = "ck803eftr1", + .llvm_name = "ck803eftr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eftr2 = CpuModel{ + .name = "ck803eftr2", + .llvm_name = "ck803eftr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eftr3 = CpuModel{ + .name = "ck803eftr3", + .llvm_name = "ck803eftr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eh = CpuModel{ + .name = "ck803eh", + .llvm_name = "ck803eh", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehr1 = CpuModel{ + .name = "ck803ehr1", + .llvm_name = "ck803ehr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehr2 = CpuModel{ + .name = "ck803ehr2", + .llvm_name = "ck803ehr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehr3 = CpuModel{ + .name = "ck803ehr3", + .llvm_name = "ck803ehr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803eht = CpuModel{ + .name = "ck803eht", + .llvm_name = "ck803eht", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehtr1 = CpuModel{ + .name = "ck803ehtr1", + .llvm_name = "ck803ehtr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehtr2 = CpuModel{ + .name = "ck803ehtr2", + .llvm_name = "ck803ehtr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ehtr3 = CpuModel{ + .name = "ck803ehtr3", + .llvm_name = "ck803ehtr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803er1 = CpuModel{ + .name = "ck803er1", + .llvm_name = "ck803er1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803er2 = CpuModel{ + .name = "ck803er2", + .llvm_name = "ck803er2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803er3 = CpuModel{ + .name = "ck803er3", + .llvm_name = "ck803er3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803et = CpuModel{ + .name = "ck803et", + .llvm_name = "ck803et", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803etr1 = CpuModel{ + .name = "ck803etr1", + .llvm_name = "ck803etr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803etr2 = CpuModel{ + .name = "ck803etr2", + .llvm_name = "ck803etr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803etr3 = CpuModel{ + .name = "ck803etr3", + .llvm_name = "ck803etr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dsp1e2, + .dspe60, + .dspv2, + .edsp, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803f = CpuModel{ + .name = "ck803f", + .llvm_name = "ck803f", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fh = CpuModel{ + .name = "ck803fh", + .llvm_name = "ck803fh", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fhr1 = CpuModel{ + .name = "ck803fhr1", + .llvm_name = "ck803fhr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fhr2 = CpuModel{ + .name = "ck803fhr2", + .llvm_name = "ck803fhr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fhr3 = CpuModel{ + .name = "ck803fhr3", + .llvm_name = "ck803fhr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fr1 = CpuModel{ + .name = "ck803fr1", + .llvm_name = "ck803fr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fr2 = CpuModel{ + .name = "ck803fr2", + .llvm_name = "ck803fr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803fr3 = CpuModel{ + .name = "ck803fr3", + .llvm_name = "ck803fr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ft = CpuModel{ + .name = "ck803ft", + .llvm_name = "ck803ft", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ftr1 = CpuModel{ + .name = "ck803ftr1", + .llvm_name = "ck803ftr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ftr2 = CpuModel{ + .name = "ck803ftr2", + .llvm_name = "ck803ftr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ftr3 = CpuModel{ + .name = "ck803ftr3", + .llvm_name = "ck803ftr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803h = CpuModel{ + .name = "ck803h", + .llvm_name = "ck803h", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803hr1 = CpuModel{ + .name = "ck803hr1", + .llvm_name = "ck803hr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803hr2 = CpuModel{ + .name = "ck803hr2", + .llvm_name = "ck803hr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803hr3 = CpuModel{ + .name = "ck803hr3", + .llvm_name = "ck803hr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803ht = CpuModel{ + .name = "ck803ht", + .llvm_name = "ck803ht", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803htr1 = CpuModel{ + .name = "ck803htr1", + .llvm_name = "ck803htr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803htr2 = CpuModel{ + .name = "ck803htr2", + .llvm_name = "ck803htr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803htr3 = CpuModel{ + .name = "ck803htr3", + .llvm_name = "ck803htr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803r1 = CpuModel{ + .name = "ck803r1", + .llvm_name = "ck803r1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803r2 = CpuModel{ + .name = "ck803r2", + .llvm_name = "ck803r2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803r3 = CpuModel{ + .name = "ck803r3", + .llvm_name = "ck803r3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803s = CpuModel{ + .name = "ck803s", + .llvm_name = "ck803s", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803se = CpuModel{ + .name = "ck803se", + .llvm_name = "ck803se", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sef = CpuModel{ + .name = "ck803sef", + .llvm_name = "ck803sef", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sefn = CpuModel{ + .name = "ck803sefn", + .llvm_name = "ck803sefn", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dsp_silan, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sefnt = CpuModel{ + .name = "ck803sefnt", + .llvm_name = "ck803sefnt", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dsp_silan, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803seft = CpuModel{ + .name = "ck803seft", + .llvm_name = "ck803seft", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dspe60, + .edsp, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sen = CpuModel{ + .name = "ck803sen", + .llvm_name = "ck803sen", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp1e2, + .dsp_silan, + .dspe60, + .edsp, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sf = CpuModel{ + .name = "ck803sf", + .llvm_name = "ck803sf", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sfn = CpuModel{ + .name = "ck803sfn", + .llvm_name = "ck803sfn", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp_silan, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803sn = CpuModel{ + .name = "ck803sn", + .llvm_name = "ck803sn", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp_silan, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803snt = CpuModel{ + .name = "ck803snt", + .llvm_name = "ck803snt", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .dsp_silan, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803st = CpuModel{ + .name = "ck803st", + .llvm_name = "ck803st", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .btst16, + .ck803, + .ck803s, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803t = CpuModel{ + .name = "ck803t", + .llvm_name = "ck803t", + .features = featureSet(&[_]Feature{ + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803tr1 = CpuModel{ + .name = "ck803tr1", + .llvm_name = "ck803tr1", + .features = featureSet(&[_]Feature{ + .@"3e3r1", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803tr2 = CpuModel{ + .name = "ck803tr2", + .llvm_name = "ck803tr2", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck803tr3 = CpuModel{ + .name = "ck803tr3", + .llvm_name = "ck803tr3", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .dspv2, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804 = CpuModel{ + .name = "ck804", + .llvm_name = "ck804", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804e = CpuModel{ + .name = "ck804e", + .llvm_name = "ck804e", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804ef = CpuModel{ + .name = "ck804ef", + .llvm_name = "ck804ef", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804efh = CpuModel{ + .name = "ck804efh", + .llvm_name = "ck804efh", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804efht = CpuModel{ + .name = "ck804efht", + .llvm_name = "ck804efht", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804eft = CpuModel{ + .name = "ck804eft", + .llvm_name = "ck804eft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804eh = CpuModel{ + .name = "ck804eh", + .llvm_name = "ck804eh", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804eht = CpuModel{ + .name = "ck804eht", + .llvm_name = "ck804eht", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804et = CpuModel{ + .name = "ck804et", + .llvm_name = "ck804et", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804f = CpuModel{ + .name = "ck804f", + .llvm_name = "ck804f", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804fh = CpuModel{ + .name = "ck804fh", + .llvm_name = "ck804fh", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804ft = CpuModel{ + .name = "ck804ft", + .llvm_name = "ck804ft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804h = CpuModel{ + .name = "ck804h", + .llvm_name = "ck804h", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804ht = CpuModel{ + .name = "ck804ht", + .llvm_name = "ck804ht", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck804t = CpuModel{ + .name = "ck804t", + .llvm_name = "ck804t", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const ck805 = CpuModel{ + .name = "ck805", + .llvm_name = "ck805", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805e = CpuModel{ + .name = "ck805e", + .llvm_name = "ck805e", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805ef = CpuModel{ + .name = "ck805ef", + .llvm_name = "ck805ef", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805eft = CpuModel{ + .name = "ck805eft", + .llvm_name = "ck805eft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805et = CpuModel{ + .name = "ck805et", + .llvm_name = "ck805et", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805f = CpuModel{ + .name = "ck805f", + .llvm_name = "ck805f", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805ft = CpuModel{ + .name = "ck805ft", + .llvm_name = "ck805ft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck805t = CpuModel{ + .name = "ck805t", + .llvm_name = "ck805t", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const ck807 = CpuModel{ + .name = "ck807", + .llvm_name = "ck807", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck807e = CpuModel{ + .name = "ck807e", + .llvm_name = "ck807e", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck807ef = CpuModel{ + .name = "ck807ef", + .llvm_name = "ck807ef", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .float1e3, + .float3e4, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck807f = CpuModel{ + .name = "ck807f", + .llvm_name = "ck807f", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .float1e3, + .float3e4, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810 = CpuModel{ + .name = "ck810", + .llvm_name = "ck810", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810e = CpuModel{ + .name = "ck810e", + .llvm_name = "ck810e", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810ef = CpuModel{ + .name = "ck810ef", + .llvm_name = "ck810ef", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810eft = CpuModel{ + .name = "ck810eft", + .llvm_name = "ck810eft", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810eftv = CpuModel{ + .name = "ck810eftv", + .llvm_name = "ck810eftv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810efv = CpuModel{ + .name = "ck810efv", + .llvm_name = "ck810efv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810et = CpuModel{ + .name = "ck810et", + .llvm_name = "ck810et", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810etv = CpuModel{ + .name = "ck810etv", + .llvm_name = "ck810etv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810ev = CpuModel{ + .name = "ck810ev", + .llvm_name = "ck810ev", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810f = CpuModel{ + .name = "ck810f", + .llvm_name = "ck810f", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810ft = CpuModel{ + .name = "ck810ft", + .llvm_name = "ck810ft", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810ftv = CpuModel{ + .name = "ck810ftv", + .llvm_name = "ck810ftv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810fv = CpuModel{ + .name = "ck810fv", + .llvm_name = "ck810fv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810t = CpuModel{ + .name = "ck810t", + .llvm_name = "ck810t", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck810tv = CpuModel{ + .name = "ck810tv", + .llvm_name = "ck810tv", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck810v = CpuModel{ + .name = "ck810v", + .llvm_name = "ck810v", + .features = featureSet(&[_]Feature{ + .@"7e10", + .cache, + .ck810, + .ck810v, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdspv1, + }), + }; + pub const ck860 = CpuModel{ + .name = "ck860", + .llvm_name = "ck860", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .dspe60, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck860f = CpuModel{ + .name = "ck860f", + .llvm_name = "ck860f", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .dspe60, + .float7e60, + .fpuv3_df, + .fpuv3_hf, + .fpuv3_hi, + .fpuv3_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const ck860fv = CpuModel{ + .name = "ck860fv", + .llvm_name = "ck860fv", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .ck860v, + .dspe60, + .float7e60, + .fpuv3_df, + .fpuv3_hf, + .fpuv3_hi, + .fpuv3_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdsp2e60f, + .vdspv2, + }), + }; + pub const ck860v = CpuModel{ + .name = "ck860v", + .llvm_name = "ck860v", + .features = featureSet(&[_]Feature{ + .@"10e60", + .@"3e3r2", + .@"3e3r3", + .btst16, + .cache, + .ck860, + .ck860v, + .dspe60, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + .vdsp2e60f, + .vdspv2, + }), + }; + pub const e801 = CpuModel{ + .name = "e801", + .llvm_name = "e801", + .features = featureSet(&[_]Feature{ + .btst16, + .ck801, + .e1, + .trust, + }), + }; + pub const e802 = CpuModel{ + .name = "e802", + .llvm_name = "e802", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const e802t = CpuModel{ + .name = "e802t", + .llvm_name = "e802t", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const e803 = CpuModel{ + .name = "e803", + .llvm_name = "e803", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e803t = CpuModel{ + .name = "e803t", + .llvm_name = "e803t", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804d = CpuModel{ + .name = "e804d", + .llvm_name = "e804d", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804df = CpuModel{ + .name = "e804df", + .llvm_name = "e804df", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804dft = CpuModel{ + .name = "e804dft", + .llvm_name = "e804dft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804dt = CpuModel{ + .name = "e804dt", + .llvm_name = "e804dt", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .dspv2, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804f = CpuModel{ + .name = "e804f", + .llvm_name = "e804f", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const e804ft = CpuModel{ + .name = "e804ft", + .llvm_name = "e804ft", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck804, + .float1e3, + .floate1, + .fpuv2_sf, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .btst16, + }), + }; + pub const @"i805" = CpuModel{ + .name = "i805", + .llvm_name = "i805", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const i805f = CpuModel{ + .name = "i805f", + .llvm_name = "i805f", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .ck805, + .float1e3, + .floate1, + .fpuv2_sf, + .high_registers, + .hwdiv, + .mp, + .nvic, + .trust, + .vdsp2e3, + .vdspv2, + }), + }; + pub const r807 = CpuModel{ + .name = "r807", + .llvm_name = "r807", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const r807f = CpuModel{ + .name = "r807f", + .llvm_name = "r807f", + .features = featureSet(&[_]Feature{ + .cache, + .ck807, + .dsp1e2, + .dspe60, + .edsp, + .fdivdu, + .float1e2, + .float1e3, + .float3e4, + .floate1, + .fpuv2_df, + .fpuv2_sf, + .hard_tp, + .high_registers, + .hwdiv, + .mp, + .mp1e2, + .nvic, + .trust, + }), + }; + pub const s802 = CpuModel{ + .name = "s802", + .llvm_name = "s802", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const s802t = CpuModel{ + .name = "s802t", + .llvm_name = "s802t", + .features = featureSet(&[_]Feature{ + .btst16, + .ck802, + .e2, + .nvic, + .trust, + }), + }; + pub const s803 = CpuModel{ + .name = "s803", + .llvm_name = "s803", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; + pub const s803t = CpuModel{ + .name = "s803t", + .llvm_name = "s803t", + .features = featureSet(&[_]Feature{ + .@"3e3r2", + .@"3e3r3", + .btst16, + .ck803, + .hwdiv, + .mp, + .nvic, + .trust, + }), + }; +}; diff --git a/lib/std/Target/hexagon.zig b/lib/std/Target/hexagon.zig new file mode 100644 index 0000000000000000000000000000000000000000..c84b2cb0c8b96d7f2b7d7be6aea19925a1a9df0e --- /dev/null +++ b/lib/std/Target/hexagon.zig @@ -0,0 +1,586 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + audio, + cabac, + compound, + duplex, + hvx, + hvx_ieee_fp, + hvx_length128b, + hvx_length64b, + hvx_qfloat, + hvxv60, + hvxv62, + hvxv65, + hvxv66, + hvxv67, + hvxv68, + hvxv69, + hvxv71, + hvxv73, + long_calls, + mem_noshuf, + memops, + noreturn_stack_elim, + nvj, + nvs, + packets, + prev65, + reserved_r19, + small_data, + tinycore, + unsafe_fp, + v5, + v55, + v60, + v62, + v65, + v66, + v67, + v68, + v69, + v71, + v73, + zreg, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.audio)] = .{ + .llvm_name = "audio", + .description = "Hexagon Audio extension instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cabac)] = .{ + .llvm_name = "cabac", + .description = "Emit the CABAC instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.compound)] = .{ + .llvm_name = "compound", + .description = "Use compound instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.duplex)] = .{ + .llvm_name = "duplex", + .description = "Enable generation of duplex instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hvx)] = .{ + .llvm_name = "hvx", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hvx_ieee_fp)] = .{ + .llvm_name = "hvx-ieee-fp", + .description = "Hexagon HVX IEEE floating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hvx_length128b)] = .{ + .llvm_name = "hvx-length128b", + .description = "Hexagon HVX 128B instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@intFromEnum(Feature.hvx_length64b)] = .{ + .llvm_name = "hvx-length64b", + .description = "Hexagon HVX 64B instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@intFromEnum(Feature.hvx_qfloat)] = .{ + .llvm_name = "hvx-qfloat", + .description = "Hexagon HVX QFloating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hvxv60)] = .{ + .llvm_name = "hvxv60", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@intFromEnum(Feature.hvxv62)] = .{ + .llvm_name = "hvxv62", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv60, + }), + }; + result[@intFromEnum(Feature.hvxv65)] = .{ + .llvm_name = "hvxv65", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv62, + }), + }; + result[@intFromEnum(Feature.hvxv66)] = .{ + .llvm_name = "hvxv66", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv65, + .zreg, + }), + }; + result[@intFromEnum(Feature.hvxv67)] = .{ + .llvm_name = "hvxv67", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv66, + }), + }; + result[@intFromEnum(Feature.hvxv68)] = .{ + .llvm_name = "hvxv68", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv67, + }), + }; + result[@intFromEnum(Feature.hvxv69)] = .{ + .llvm_name = "hvxv69", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv68, + }), + }; + result[@intFromEnum(Feature.hvxv71)] = .{ + .llvm_name = "hvxv71", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv69, + }), + }; + result[@intFromEnum(Feature.hvxv73)] = .{ + .llvm_name = "hvxv73", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvxv71, + }), + }; + result[@intFromEnum(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Use constant-extended calls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mem_noshuf)] = .{ + .llvm_name = "mem_noshuf", + .description = "Supports mem_noshuf feature", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.memops)] = .{ + .llvm_name = "memops", + .description = "Use memop instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.noreturn_stack_elim)] = .{ + .llvm_name = "noreturn-stack-elim", + .description = "Eliminate stack allocation in a noreturn function when possible", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nvj)] = .{ + .llvm_name = "nvj", + .description = "Support for new-value jumps", + .dependencies = featureSet(&[_]Feature{ + .packets, + }), + }; + result[@intFromEnum(Feature.nvs)] = .{ + .llvm_name = "nvs", + .description = "Support for new-value stores", + .dependencies = featureSet(&[_]Feature{ + .packets, + }), + }; + result[@intFromEnum(Feature.packets)] = .{ + .llvm_name = "packets", + .description = "Support for instruction packets", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prev65)] = .{ + .llvm_name = "prev65", + .description = "Support features deprecated in v65", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserved_r19)] = .{ + .llvm_name = "reserved-r19", + .description = "Reserve register R19", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.small_data)] = .{ + .llvm_name = "small-data", + .description = "Allow GP-relative addressing of global variables", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tinycore)] = .{ + .llvm_name = "tinycore", + .description = "Hexagon Tiny Core", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unsafe_fp)] = .{ + .llvm_name = "unsafe-fp", + .description = "Use unsafe FP math", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v5)] = .{ + .llvm_name = "v5", + .description = "Enable Hexagon V5 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v55)] = .{ + .llvm_name = "v55", + .description = "Enable Hexagon V55 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v60)] = .{ + .llvm_name = "v60", + .description = "Enable Hexagon V60 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v62)] = .{ + .llvm_name = "v62", + .description = "Enable Hexagon V62 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v65)] = .{ + .llvm_name = "v65", + .description = "Enable Hexagon V65 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v66)] = .{ + .llvm_name = "v66", + .description = "Enable Hexagon V66 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v67)] = .{ + .llvm_name = "v67", + .description = "Enable Hexagon V67 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v68)] = .{ + .llvm_name = "v68", + .description = "Enable Hexagon V68 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v69)] = .{ + .llvm_name = "v69", + .description = "Enable Hexagon V69 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v71)] = .{ + .llvm_name = "v71", + .description = "Enable Hexagon V71 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v73)] = .{ + .llvm_name = "v73", + .description = "Enable Hexagon V73 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zreg)] = .{ + .llvm_name = "zreg", + .description = "Hexagon ZReg extension instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .memops, + .nvj, + .nvs, + .prev65, + .small_data, + .v5, + .v55, + .v60, + }), + }; + pub const hexagonv5 = CpuModel{ + .name = "hexagonv5", + .llvm_name = "hexagonv5", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .memops, + .nvj, + .nvs, + .prev65, + .small_data, + .v5, + }), + }; + pub const hexagonv55 = CpuModel{ + .name = "hexagonv55", + .llvm_name = "hexagonv55", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .memops, + .nvj, + .nvs, + .prev65, + .small_data, + .v5, + .v55, + }), + }; + pub const hexagonv60 = CpuModel{ + .name = "hexagonv60", + .llvm_name = "hexagonv60", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .memops, + .nvj, + .nvs, + .prev65, + .small_data, + .v5, + .v55, + .v60, + }), + }; + pub const hexagonv62 = CpuModel{ + .name = "hexagonv62", + .llvm_name = "hexagonv62", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .memops, + .nvj, + .nvs, + .prev65, + .small_data, + .v5, + .v55, + .v60, + .v62, + }), + }; + pub const hexagonv65 = CpuModel{ + .name = "hexagonv65", + .llvm_name = "hexagonv65", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + }), + }; + pub const hexagonv66 = CpuModel{ + .name = "hexagonv66", + .llvm_name = "hexagonv66", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + }), + }; + pub const hexagonv67 = CpuModel{ + .name = "hexagonv67", + .llvm_name = "hexagonv67", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + }), + }; + pub const hexagonv67t = CpuModel{ + .name = "hexagonv67t", + .llvm_name = "hexagonv67t", + .features = featureSet(&[_]Feature{ + .audio, + .compound, + .mem_noshuf, + .memops, + .nvs, + .small_data, + .tinycore, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + }), + }; + pub const hexagonv68 = CpuModel{ + .name = "hexagonv68", + .llvm_name = "hexagonv68", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + .v68, + }), + }; + pub const hexagonv69 = CpuModel{ + .name = "hexagonv69", + .llvm_name = "hexagonv69", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + .v68, + .v69, + }), + }; + pub const hexagonv71 = CpuModel{ + .name = "hexagonv71", + .llvm_name = "hexagonv71", + .features = featureSet(&[_]Feature{ + .cabac, + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + .v68, + .v69, + .v71, + }), + }; + pub const hexagonv71t = CpuModel{ + .name = "hexagonv71t", + .llvm_name = "hexagonv71t", + .features = featureSet(&[_]Feature{ + .audio, + .compound, + .mem_noshuf, + .memops, + .nvs, + .small_data, + .tinycore, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + .v68, + .v69, + .v71, + }), + }; + pub const hexagonv73 = CpuModel{ + .name = "hexagonv73", + .llvm_name = "hexagonv73", + .features = featureSet(&[_]Feature{ + .compound, + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + .v67, + .v68, + .v69, + .v71, + .v73, + }), + }; +}; diff --git a/lib/std/Target/loongarch.zig b/lib/std/Target/loongarch.zig new file mode 100644 index 0000000000000000000000000000000000000000..65dc33d78487dc6c7e31a1d389e319b693b51de8 --- /dev/null +++ b/lib/std/Target/loongarch.zig @@ -0,0 +1,146 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"32bit", + @"64bit", + d, + f, + la_global_with_abs, + la_global_with_pcrel, + la_local_with_abs, + lasx, + lbt, + lsx, + lvz, + ual, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"32bit")] = .{ + .llvm_name = "32bit", + .description = "LA32 Basic Integer and Privilege Instruction Set", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "LA64 Basic Integer and Privilege Instruction Set", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.d)] = .{ + .llvm_name = "d", + .description = "'D' (Double-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.f)] = .{ + .llvm_name = "f", + .description = "'F' (Single-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.la_global_with_abs)] = .{ + .llvm_name = "la-global-with-abs", + .description = "Expand la.global as la.abs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.la_global_with_pcrel)] = .{ + .llvm_name = "la-global-with-pcrel", + .description = "Expand la.global as la.pcrel", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.la_local_with_abs)] = .{ + .llvm_name = "la-local-with-abs", + .description = "Expand la.local as la.abs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lasx)] = .{ + .llvm_name = "lasx", + .description = "'LASX' (Loongson Advanced SIMD Extension)", + .dependencies = featureSet(&[_]Feature{ + .lsx, + }), + }; + result[@intFromEnum(Feature.lbt)] = .{ + .llvm_name = "lbt", + .description = "'LBT' (Loongson Binary Translation Extension)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lsx)] = .{ + .llvm_name = "lsx", + .description = "'LSX' (Loongson SIMD Extension)", + .dependencies = featureSet(&[_]Feature{ + .d, + }), + }; + result[@intFromEnum(Feature.lvz)] = .{ + .llvm_name = "lvz", + .description = "'LVZ' (Loongson Virtualization Extension)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ual)] = .{ + .llvm_name = "ual", + .description = "Allow memory accesses to be unaligned", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const generic_la32 = CpuModel{ + .name = "generic_la32", + .llvm_name = "generic-la32", + .features = featureSet(&[_]Feature{ + .@"32bit", + }), + }; + pub const generic_la64 = CpuModel{ + .name = "generic_la64", + .llvm_name = "generic-la64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .ual, + }), + }; + pub const la464 = CpuModel{ + .name = "la464", + .llvm_name = "la464", + .features = featureSet(&[_]Feature{ + .@"64bit", + .lasx, + .lbt, + .lvz, + .ual, + }), + }; + pub const loongarch64 = CpuModel{ + .name = "loongarch64", + .llvm_name = "loongarch64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .d, + .ual, + }), + }; +}; diff --git a/lib/std/Target/m68k.zig b/lib/std/Target/m68k.zig new file mode 100644 index 0000000000000000000000000000000000000000..054b3974d1fc08eb06ccc2d4933b2e6d14b16d70 --- /dev/null +++ b/lib/std/Target/m68k.zig @@ -0,0 +1,228 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + isa_68000, + isa_68010, + isa_68020, + isa_68030, + isa_68040, + isa_68060, + isa_68881, + isa_68882, + reserve_a0, + reserve_a1, + reserve_a2, + reserve_a3, + reserve_a4, + reserve_a5, + reserve_a6, + reserve_d0, + reserve_d1, + reserve_d2, + reserve_d3, + reserve_d4, + reserve_d5, + reserve_d6, + reserve_d7, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.isa_68000)] = .{ + .llvm_name = "isa-68000", + .description = "Is M68000 ISA supported", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.isa_68010)] = .{ + .llvm_name = "isa-68010", + .description = "Is M68010 ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68000, + }), + }; + result[@intFromEnum(Feature.isa_68020)] = .{ + .llvm_name = "isa-68020", + .description = "Is M68020 ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68010, + }), + }; + result[@intFromEnum(Feature.isa_68030)] = .{ + .llvm_name = "isa-68030", + .description = "Is M68030 ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68020, + }), + }; + result[@intFromEnum(Feature.isa_68040)] = .{ + .llvm_name = "isa-68040", + .description = "Is M68040 ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68030, + .isa_68882, + }), + }; + result[@intFromEnum(Feature.isa_68060)] = .{ + .llvm_name = "isa-68060", + .description = "Is M68060 ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68040, + }), + }; + result[@intFromEnum(Feature.isa_68881)] = .{ + .llvm_name = "isa-68881", + .description = "Is M68881 (FPU) ISA supported", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.isa_68882)] = .{ + .llvm_name = "isa-68882", + .description = "Is M68882 (FPU) ISA supported", + .dependencies = featureSet(&[_]Feature{ + .isa_68881, + }), + }; + result[@intFromEnum(Feature.reserve_a0)] = .{ + .llvm_name = "reserve-a0", + .description = "Reserve A0 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a1)] = .{ + .llvm_name = "reserve-a1", + .description = "Reserve A1 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a2)] = .{ + .llvm_name = "reserve-a2", + .description = "Reserve A2 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a3)] = .{ + .llvm_name = "reserve-a3", + .description = "Reserve A3 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a4)] = .{ + .llvm_name = "reserve-a4", + .description = "Reserve A4 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a5)] = .{ + .llvm_name = "reserve-a5", + .description = "Reserve A5 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_a6)] = .{ + .llvm_name = "reserve-a6", + .description = "Reserve A6 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d0)] = .{ + .llvm_name = "reserve-d0", + .description = "Reserve D0 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d1)] = .{ + .llvm_name = "reserve-d1", + .description = "Reserve D1 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d2)] = .{ + .llvm_name = "reserve-d2", + .description = "Reserve D2 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d3)] = .{ + .llvm_name = "reserve-d3", + .description = "Reserve D3 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d4)] = .{ + .llvm_name = "reserve-d4", + .description = "Reserve D4 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d5)] = .{ + .llvm_name = "reserve-d5", + .description = "Reserve D5 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d6)] = .{ + .llvm_name = "reserve-d6", + .description = "Reserve D6 register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_d7)] = .{ + .llvm_name = "reserve-d7", + .description = "Reserve D7 register", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .isa_68000, + }), + }; + pub const M68000 = CpuModel{ + .name = "M68000", + .llvm_name = "M68000", + .features = featureSet(&[_]Feature{ + .isa_68000, + }), + }; + pub const M68010 = CpuModel{ + .name = "M68010", + .llvm_name = "M68010", + .features = featureSet(&[_]Feature{ + .isa_68010, + }), + }; + pub const M68020 = CpuModel{ + .name = "M68020", + .llvm_name = "M68020", + .features = featureSet(&[_]Feature{ + .isa_68020, + }), + }; + pub const M68030 = CpuModel{ + .name = "M68030", + .llvm_name = "M68030", + .features = featureSet(&[_]Feature{ + .isa_68030, + }), + }; + pub const M68040 = CpuModel{ + .name = "M68040", + .llvm_name = "M68040", + .features = featureSet(&[_]Feature{ + .isa_68040, + }), + }; + pub const M68060 = CpuModel{ + .name = "M68060", + .llvm_name = "M68060", + .features = featureSet(&[_]Feature{ + .isa_68060, + }), + }; +}; diff --git a/lib/std/Target/mips.zig b/lib/std/Target/mips.zig new file mode 100644 index 0000000000000000000000000000000000000000..8f3c0994d1dc08dc4edab589b94a000d979f8076 --- /dev/null +++ b/lib/std/Target/mips.zig @@ -0,0 +1,531 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + abs2008, + cnmips, + cnmipsp, + crc, + dsp, + dspr2, + dspr3, + eva, + fp64, + fpxx, + ginv, + gp64, + long_calls, + micromips, + mips1, + mips16, + mips2, + mips3, + mips32, + mips32r2, + mips32r3, + mips32r5, + mips32r6, + mips3_32, + mips3_32r2, + mips3d, + mips4, + mips4_32, + mips4_32r2, + mips5, + mips5_32r2, + mips64, + mips64r2, + mips64r3, + mips64r5, + mips64r6, + msa, + mt, + nan2008, + noabicalls, + nomadd4, + nooddspreg, + p5600, + ptr64, + single_float, + soft_float, + sym32, + use_indirect_jump_hazard, + use_tcc_in_div, + vfpu, + virt, + xgot, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.abs2008)] = .{ + .llvm_name = "abs2008", + .description = "Disable IEEE 754-2008 abs.fmt mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cnmips)] = .{ + .llvm_name = "cnmips", + .description = "Octeon cnMIPS Support", + .dependencies = featureSet(&[_]Feature{ + .mips64r2, + }), + }; + result[@intFromEnum(Feature.cnmipsp)] = .{ + .llvm_name = "cnmipsp", + .description = "Octeon+ cnMIPS Support", + .dependencies = featureSet(&[_]Feature{ + .cnmips, + }), + }; + result[@intFromEnum(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Mips R6 CRC ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dsp)] = .{ + .llvm_name = "dsp", + .description = "Mips DSP ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dspr2)] = .{ + .llvm_name = "dspr2", + .description = "Mips DSP-R2 ASE", + .dependencies = featureSet(&[_]Feature{ + .dsp, + }), + }; + result[@intFromEnum(Feature.dspr3)] = .{ + .llvm_name = "dspr3", + .description = "Mips DSP-R3 ASE", + .dependencies = featureSet(&[_]Feature{ + .dspr2, + }), + }; + result[@intFromEnum(Feature.eva)] = .{ + .llvm_name = "eva", + .description = "Mips EVA ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Support 64-bit FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fpxx)] = .{ + .llvm_name = "fpxx", + .description = "Support for FPXX", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ginv)] = .{ + .llvm_name = "ginv", + .description = "Mips Global Invalidate ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gp64)] = .{ + .llvm_name = "gp64", + .description = "General Purpose Registers are 64-bit wide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Disable use of the jal instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.micromips)] = .{ + .llvm_name = "micromips", + .description = "microMips mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips1)] = .{ + .llvm_name = "mips1", + .description = "Mips I ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips16)] = .{ + .llvm_name = "mips16", + .description = "Mips16 mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips2)] = .{ + .llvm_name = "mips2", + .description = "Mips II ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .mips1, + }), + }; + result[@intFromEnum(Feature.mips3)] = .{ + .llvm_name = "mips3", + .description = "MIPS III ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .gp64, + .mips2, + .mips3_32, + .mips3_32r2, + }), + }; + result[@intFromEnum(Feature.mips32)] = .{ + .llvm_name = "mips32", + .description = "Mips32 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips2, + .mips3_32, + .mips4_32, + }), + }; + result[@intFromEnum(Feature.mips32r2)] = .{ + .llvm_name = "mips32r2", + .description = "Mips32r2 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32, + .mips3_32r2, + .mips4_32r2, + .mips5_32r2, + }), + }; + result[@intFromEnum(Feature.mips32r3)] = .{ + .llvm_name = "mips32r3", + .description = "Mips32r3 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r2, + }), + }; + result[@intFromEnum(Feature.mips32r5)] = .{ + .llvm_name = "mips32r5", + .description = "Mips32r5 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r3, + }), + }; + result[@intFromEnum(Feature.mips32r6)] = .{ + .llvm_name = "mips32r6", + .description = "Mips32r6 ISA Support [experimental]", + .dependencies = featureSet(&[_]Feature{ + .abs2008, + .fp64, + .mips32r5, + .nan2008, + }), + }; + result[@intFromEnum(Feature.mips3_32)] = .{ + .llvm_name = "mips3_32", + .description = "Subset of MIPS-III that is also in MIPS32 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips3_32r2)] = .{ + .llvm_name = "mips3_32r2", + .description = "Subset of MIPS-III that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips3d)] = .{ + .llvm_name = "mips3d", + .description = "Mips 3D ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips4)] = .{ + .llvm_name = "mips4", + .description = "MIPS IV ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips3, + .mips4_32, + .mips4_32r2, + }), + }; + result[@intFromEnum(Feature.mips4_32)] = .{ + .llvm_name = "mips4_32", + .description = "Subset of MIPS-IV that is also in MIPS32 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips4_32r2)] = .{ + .llvm_name = "mips4_32r2", + .description = "Subset of MIPS-IV that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips5)] = .{ + .llvm_name = "mips5", + .description = "MIPS V ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .mips4, + .mips5_32r2, + }), + }; + result[@intFromEnum(Feature.mips5_32r2)] = .{ + .llvm_name = "mips5_32r2", + .description = "Subset of MIPS-V that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mips64)] = .{ + .llvm_name = "mips64", + .description = "Mips64 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32, + .mips5, + }), + }; + result[@intFromEnum(Feature.mips64r2)] = .{ + .llvm_name = "mips64r2", + .description = "Mips64r2 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r2, + .mips64, + }), + }; + result[@intFromEnum(Feature.mips64r3)] = .{ + .llvm_name = "mips64r3", + .description = "Mips64r3 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r3, + .mips64r2, + }), + }; + result[@intFromEnum(Feature.mips64r5)] = .{ + .llvm_name = "mips64r5", + .description = "Mips64r5 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r5, + .mips64r3, + }), + }; + result[@intFromEnum(Feature.mips64r6)] = .{ + .llvm_name = "mips64r6", + .description = "Mips64r6 ISA Support [experimental]", + .dependencies = featureSet(&[_]Feature{ + .mips32r6, + .mips64r5, + }), + }; + result[@intFromEnum(Feature.msa)] = .{ + .llvm_name = "msa", + .description = "Mips MSA ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mt)] = .{ + .llvm_name = "mt", + .description = "Mips MT ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nan2008)] = .{ + .llvm_name = "nan2008", + .description = "IEEE 754-2008 NaN encoding", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.noabicalls)] = .{ + .llvm_name = "noabicalls", + .description = "Disable SVR4-style position-independent code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nomadd4)] = .{ + .llvm_name = "nomadd4", + .description = "Disable 4-operand madd.fmt and related instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nooddspreg)] = .{ + .llvm_name = "nooddspreg", + .description = "Disable odd numbered single-precision registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.p5600)] = .{ + .llvm_name = "p5600", + .description = "The P5600 Processor", + .dependencies = featureSet(&[_]Feature{ + .mips32r5, + }), + }; + result[@intFromEnum(Feature.ptr64)] = .{ + .llvm_name = "ptr64", + .description = "Pointers are 64-bit wide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.single_float)] = .{ + .llvm_name = "single-float", + .description = "Only supports single precision float", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Does not support floating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sym32)] = .{ + .llvm_name = "sym32", + .description = "Symbols are 32 bit on Mips64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_indirect_jump_hazard)] = .{ + .llvm_name = "use-indirect-jump-hazard", + .description = "Use indirect jump guards to prevent certain speculation based attacks", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_tcc_in_div)] = .{ + .llvm_name = "use-tcc-in-div", + .description = "Force the assembler to use trapping", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vfpu)] = .{ + .llvm_name = "vfpu", + .description = "Enable vector FPU instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.virt)] = .{ + .llvm_name = "virt", + .description = "Mips Virtualization ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xgot)] = .{ + .llvm_name = "xgot", + .description = "Assume 32-bit GOT", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .mips32, + }), + }; + pub const mips1 = CpuModel{ + .name = "mips1", + .llvm_name = "mips1", + .features = featureSet(&[_]Feature{ + .mips1, + }), + }; + pub const mips2 = CpuModel{ + .name = "mips2", + .llvm_name = "mips2", + .features = featureSet(&[_]Feature{ + .mips2, + }), + }; + pub const mips3 = CpuModel{ + .name = "mips3", + .llvm_name = "mips3", + .features = featureSet(&[_]Feature{ + .mips3, + }), + }; + pub const mips32 = CpuModel{ + .name = "mips32", + .llvm_name = "mips32", + .features = featureSet(&[_]Feature{ + .mips32, + }), + }; + pub const mips32r2 = CpuModel{ + .name = "mips32r2", + .llvm_name = "mips32r2", + .features = featureSet(&[_]Feature{ + .mips32r2, + }), + }; + pub const mips32r3 = CpuModel{ + .name = "mips32r3", + .llvm_name = "mips32r3", + .features = featureSet(&[_]Feature{ + .mips32r3, + }), + }; + pub const mips32r5 = CpuModel{ + .name = "mips32r5", + .llvm_name = "mips32r5", + .features = featureSet(&[_]Feature{ + .mips32r5, + }), + }; + pub const mips32r6 = CpuModel{ + .name = "mips32r6", + .llvm_name = "mips32r6", + .features = featureSet(&[_]Feature{ + .mips32r6, + }), + }; + pub const mips4 = CpuModel{ + .name = "mips4", + .llvm_name = "mips4", + .features = featureSet(&[_]Feature{ + .mips4, + }), + }; + pub const mips5 = CpuModel{ + .name = "mips5", + .llvm_name = "mips5", + .features = featureSet(&[_]Feature{ + .mips5, + }), + }; + pub const mips64 = CpuModel{ + .name = "mips64", + .llvm_name = "mips64", + .features = featureSet(&[_]Feature{ + .mips64, + }), + }; + pub const mips64r2 = CpuModel{ + .name = "mips64r2", + .llvm_name = "mips64r2", + .features = featureSet(&[_]Feature{ + .mips64r2, + }), + }; + pub const mips64r3 = CpuModel{ + .name = "mips64r3", + .llvm_name = "mips64r3", + .features = featureSet(&[_]Feature{ + .mips64r3, + }), + }; + pub const mips64r5 = CpuModel{ + .name = "mips64r5", + .llvm_name = "mips64r5", + .features = featureSet(&[_]Feature{ + .mips64r5, + }), + }; + pub const mips64r6 = CpuModel{ + .name = "mips64r6", + .llvm_name = "mips64r6", + .features = featureSet(&[_]Feature{ + .mips64r6, + }), + }; + pub const octeon = CpuModel{ + .name = "octeon", + .llvm_name = "octeon", + .features = featureSet(&[_]Feature{ + .cnmips, + }), + }; + pub const @"octeon+" = CpuModel{ + .name = "octeon+", + .llvm_name = "octeon+", + .features = featureSet(&[_]Feature{ + .cnmipsp, + }), + }; + pub const p5600 = CpuModel{ + .name = "p5600", + .llvm_name = "p5600", + .features = featureSet(&[_]Feature{ + .p5600, + }), + }; +}; diff --git a/lib/std/Target/msp430.zig b/lib/std/Target/msp430.zig new file mode 100644 index 0000000000000000000000000000000000000000..98ea32d17fbbe33f2facd7d76c6cde3488e08499 --- /dev/null +++ b/lib/std/Target/msp430.zig @@ -0,0 +1,69 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + ext, + hwmult16, + hwmult32, + hwmultf5, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.ext)] = .{ + .llvm_name = "ext", + .description = "Enable MSP430-X extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hwmult16)] = .{ + .llvm_name = "hwmult16", + .description = "Enable 16-bit hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hwmult32)] = .{ + .llvm_name = "hwmult32", + .description = "Enable 32-bit hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hwmultf5)] = .{ + .llvm_name = "hwmultf5", + .description = "Enable F5 series hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const msp430 = CpuModel{ + .name = "msp430", + .llvm_name = "msp430", + .features = featureSet(&[_]Feature{}), + }; + pub const msp430x = CpuModel{ + .name = "msp430x", + .llvm_name = "msp430x", + .features = featureSet(&[_]Feature{ + .ext, + }), + }; +}; diff --git a/lib/std/Target/nvptx.zig b/lib/std/Target/nvptx.zig new file mode 100644 index 0000000000000000000000000000000000000000..99a281604b83aa6aed0b0251d060e611c86d39c3 --- /dev/null +++ b/lib/std/Target/nvptx.zig @@ -0,0 +1,439 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + ptx32, + ptx40, + ptx41, + ptx42, + ptx43, + ptx50, + ptx60, + ptx61, + ptx63, + ptx64, + ptx65, + ptx70, + ptx71, + ptx72, + ptx73, + ptx74, + ptx75, + ptx76, + ptx77, + ptx78, + ptx80, + ptx81, + sm_20, + sm_21, + sm_30, + sm_32, + sm_35, + sm_37, + sm_50, + sm_52, + sm_53, + sm_60, + sm_61, + sm_62, + sm_70, + sm_72, + sm_75, + sm_80, + sm_86, + sm_87, + sm_89, + sm_90, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.ptx32)] = .{ + .llvm_name = "ptx32", + .description = "Use PTX version 32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx40)] = .{ + .llvm_name = "ptx40", + .description = "Use PTX version 40", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx41)] = .{ + .llvm_name = "ptx41", + .description = "Use PTX version 41", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx42)] = .{ + .llvm_name = "ptx42", + .description = "Use PTX version 42", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx43)] = .{ + .llvm_name = "ptx43", + .description = "Use PTX version 43", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx50)] = .{ + .llvm_name = "ptx50", + .description = "Use PTX version 50", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx60)] = .{ + .llvm_name = "ptx60", + .description = "Use PTX version 60", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx61)] = .{ + .llvm_name = "ptx61", + .description = "Use PTX version 61", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx63)] = .{ + .llvm_name = "ptx63", + .description = "Use PTX version 63", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx64)] = .{ + .llvm_name = "ptx64", + .description = "Use PTX version 64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx65)] = .{ + .llvm_name = "ptx65", + .description = "Use PTX version 65", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx70)] = .{ + .llvm_name = "ptx70", + .description = "Use PTX version 70", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx71)] = .{ + .llvm_name = "ptx71", + .description = "Use PTX version 71", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx72)] = .{ + .llvm_name = "ptx72", + .description = "Use PTX version 72", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx73)] = .{ + .llvm_name = "ptx73", + .description = "Use PTX version 73", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx74)] = .{ + .llvm_name = "ptx74", + .description = "Use PTX version 74", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx75)] = .{ + .llvm_name = "ptx75", + .description = "Use PTX version 75", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx76)] = .{ + .llvm_name = "ptx76", + .description = "Use PTX version 76", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx77)] = .{ + .llvm_name = "ptx77", + .description = "Use PTX version 77", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx78)] = .{ + .llvm_name = "ptx78", + .description = "Use PTX version 78", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx80)] = .{ + .llvm_name = "ptx80", + .description = "Use PTX version 80", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptx81)] = .{ + .llvm_name = "ptx81", + .description = "Use PTX version 81", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_20)] = .{ + .llvm_name = "sm_20", + .description = "Target SM 20", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_21)] = .{ + .llvm_name = "sm_21", + .description = "Target SM 21", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_30)] = .{ + .llvm_name = "sm_30", + .description = "Target SM 30", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_32)] = .{ + .llvm_name = "sm_32", + .description = "Target SM 32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_35)] = .{ + .llvm_name = "sm_35", + .description = "Target SM 35", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_37)] = .{ + .llvm_name = "sm_37", + .description = "Target SM 37", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_50)] = .{ + .llvm_name = "sm_50", + .description = "Target SM 50", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_52)] = .{ + .llvm_name = "sm_52", + .description = "Target SM 52", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_53)] = .{ + .llvm_name = "sm_53", + .description = "Target SM 53", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_60)] = .{ + .llvm_name = "sm_60", + .description = "Target SM 60", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_61)] = .{ + .llvm_name = "sm_61", + .description = "Target SM 61", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_62)] = .{ + .llvm_name = "sm_62", + .description = "Target SM 62", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_70)] = .{ + .llvm_name = "sm_70", + .description = "Target SM 70", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_72)] = .{ + .llvm_name = "sm_72", + .description = "Target SM 72", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_75)] = .{ + .llvm_name = "sm_75", + .description = "Target SM 75", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_80)] = .{ + .llvm_name = "sm_80", + .description = "Target SM 80", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_86)] = .{ + .llvm_name = "sm_86", + .description = "Target SM 86", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_87)] = .{ + .llvm_name = "sm_87", + .description = "Target SM 87", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_89)] = .{ + .llvm_name = "sm_89", + .description = "Target SM 89", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm_90)] = .{ + .llvm_name = "sm_90", + .description = "Target SM 90", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const sm_20 = CpuModel{ + .name = "sm_20", + .llvm_name = "sm_20", + .features = featureSet(&[_]Feature{ + .ptx32, + .sm_20, + }), + }; + pub const sm_21 = CpuModel{ + .name = "sm_21", + .llvm_name = "sm_21", + .features = featureSet(&[_]Feature{ + .ptx32, + .sm_21, + }), + }; + pub const sm_30 = CpuModel{ + .name = "sm_30", + .llvm_name = "sm_30", + .features = featureSet(&[_]Feature{ + .sm_30, + }), + }; + pub const sm_32 = CpuModel{ + .name = "sm_32", + .llvm_name = "sm_32", + .features = featureSet(&[_]Feature{ + .ptx40, + .sm_32, + }), + }; + pub const sm_35 = CpuModel{ + .name = "sm_35", + .llvm_name = "sm_35", + .features = featureSet(&[_]Feature{ + .ptx32, + .sm_35, + }), + }; + pub const sm_37 = CpuModel{ + .name = "sm_37", + .llvm_name = "sm_37", + .features = featureSet(&[_]Feature{ + .ptx41, + .sm_37, + }), + }; + pub const sm_50 = CpuModel{ + .name = "sm_50", + .llvm_name = "sm_50", + .features = featureSet(&[_]Feature{ + .ptx40, + .sm_50, + }), + }; + pub const sm_52 = CpuModel{ + .name = "sm_52", + .llvm_name = "sm_52", + .features = featureSet(&[_]Feature{ + .ptx41, + .sm_52, + }), + }; + pub const sm_53 = CpuModel{ + .name = "sm_53", + .llvm_name = "sm_53", + .features = featureSet(&[_]Feature{ + .ptx42, + .sm_53, + }), + }; + pub const sm_60 = CpuModel{ + .name = "sm_60", + .llvm_name = "sm_60", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_60, + }), + }; + pub const sm_61 = CpuModel{ + .name = "sm_61", + .llvm_name = "sm_61", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_61, + }), + }; + pub const sm_62 = CpuModel{ + .name = "sm_62", + .llvm_name = "sm_62", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_62, + }), + }; + pub const sm_70 = CpuModel{ + .name = "sm_70", + .llvm_name = "sm_70", + .features = featureSet(&[_]Feature{ + .ptx60, + .sm_70, + }), + }; + pub const sm_72 = CpuModel{ + .name = "sm_72", + .llvm_name = "sm_72", + .features = featureSet(&[_]Feature{ + .ptx61, + .sm_72, + }), + }; + pub const sm_75 = CpuModel{ + .name = "sm_75", + .llvm_name = "sm_75", + .features = featureSet(&[_]Feature{ + .ptx63, + .sm_75, + }), + }; + pub const sm_80 = CpuModel{ + .name = "sm_80", + .llvm_name = "sm_80", + .features = featureSet(&[_]Feature{ + .ptx70, + .sm_80, + }), + }; + pub const sm_86 = CpuModel{ + .name = "sm_86", + .llvm_name = "sm_86", + .features = featureSet(&[_]Feature{ + .ptx71, + .sm_86, + }), + }; + pub const sm_87 = CpuModel{ + .name = "sm_87", + .llvm_name = "sm_87", + .features = featureSet(&[_]Feature{ + .ptx74, + .sm_87, + }), + }; + pub const sm_89 = CpuModel{ + .name = "sm_89", + .llvm_name = "sm_89", + .features = featureSet(&[_]Feature{ + .ptx78, + .sm_89, + }), + }; + pub const sm_90 = CpuModel{ + .name = "sm_90", + .llvm_name = "sm_90", + .features = featureSet(&[_]Feature{ + .ptx78, + .sm_90, + }), + }; +}; diff --git a/lib/std/Target/powerpc.zig b/lib/std/Target/powerpc.zig new file mode 100644 index 0000000000000000000000000000000000000000..c350c166ba892dab0f460d58c7308b6b35a243a7 --- /dev/null +++ b/lib/std/Target/powerpc.zig @@ -0,0 +1,1192 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"64bit", + @"64bitregs", + aix, + allow_unaligned_fp_access, + altivec, + booke, + bpermd, + cmpb, + crbits, + crypto, + direct_move, + e500, + efpu2, + extdiv, + fast_MFLR, + fcpsgn, + float128, + fpcvt, + fprnd, + fpu, + fre, + fres, + frsqrte, + frsqrtes, + fsqrt, + fuse_add_logical, + fuse_addi_load, + fuse_addis_load, + fuse_arith_add, + fuse_back2back, + fuse_cmp, + fuse_logical, + fuse_logical_add, + fuse_sha3, + fuse_store, + fuse_wideimm, + fuse_zeromove, + fusion, + hard_float, + htm, + icbt, + invariant_function_descriptors, + isa_future_instructions, + isa_v206_instructions, + isa_v207_instructions, + isa_v30_instructions, + isa_v31_instructions, + isel, + ldbrx, + lfiwax, + longcall, + mfocrf, + mma, + modern_aix_as, + msync, + paired_vector_memops, + partword_atomics, + pcrelative_memops, + popcntd, + power10_vector, + power8_altivec, + power8_vector, + power9_altivec, + power9_vector, + ppc4xx, + ppc6xx, + ppc_postra_sched, + ppc_prera_sched, + predictable_select_expensive, + prefix_instrs, + privileged, + quadword_atomics, + recipprec, + rop_protect, + secure_plt, + slow_popcntd, + spe, + stfiwx, + two_const_nr, + vectors_use_two_units, + vsx, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Enable 64-bit instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"64bitregs")] = .{ + .llvm_name = "64bitregs", + .description = "Enable 64-bit registers usage for ppc32 [beta]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aix)] = .{ + .llvm_name = "aix", + .description = "AIX OS", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.allow_unaligned_fp_access)] = .{ + .llvm_name = "allow-unaligned-fp-access", + .description = "CPU does not trap on unaligned FP access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.altivec)] = .{ + .llvm_name = "altivec", + .description = "Enable Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.booke)] = .{ + .llvm_name = "booke", + .description = "Enable Book E instructions", + .dependencies = featureSet(&[_]Feature{ + .icbt, + }), + }; + result[@intFromEnum(Feature.bpermd)] = .{ + .llvm_name = "bpermd", + .description = "Enable the bpermd instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cmpb)] = .{ + .llvm_name = "cmpb", + .description = "Enable the cmpb instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crbits)] = .{ + .llvm_name = "crbits", + .description = "Use condition-register bits individually", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable POWER8 Crypto instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_altivec, + }), + }; + result[@intFromEnum(Feature.direct_move)] = .{ + .llvm_name = "direct-move", + .description = "Enable Power8 direct move instructions", + .dependencies = featureSet(&[_]Feature{ + .vsx, + }), + }; + result[@intFromEnum(Feature.e500)] = .{ + .llvm_name = "e500", + .description = "Enable E500/E500mc instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.efpu2)] = .{ + .llvm_name = "efpu2", + .description = "Enable Embedded Floating-Point APU 2 instructions", + .dependencies = featureSet(&[_]Feature{ + .spe, + }), + }; + result[@intFromEnum(Feature.extdiv)] = .{ + .llvm_name = "extdiv", + .description = "Enable extended divide instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_MFLR)] = .{ + .llvm_name = "fast-MFLR", + .description = "MFLR is a fast instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fcpsgn)] = .{ + .llvm_name = "fcpsgn", + .description = "Enable the fcpsgn instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.float128)] = .{ + .llvm_name = "float128", + .description = "Enable the __float128 data type for IEEE-754R Binary128.", + .dependencies = featureSet(&[_]Feature{ + .vsx, + }), + }; + result[@intFromEnum(Feature.fpcvt)] = .{ + .llvm_name = "fpcvt", + .description = "Enable fc[ft]* (unsigned and single-precision) and lfiwzx instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.fprnd)] = .{ + .llvm_name = "fprnd", + .description = "Enable the fri[mnpz] instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.fpu)] = .{ + .llvm_name = "fpu", + .description = "Enable classic FPU instructions", + .dependencies = featureSet(&[_]Feature{ + .hard_float, + }), + }; + result[@intFromEnum(Feature.fre)] = .{ + .llvm_name = "fre", + .description = "Enable the fre instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.fres)] = .{ + .llvm_name = "fres", + .description = "Enable the fres instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.frsqrte)] = .{ + .llvm_name = "frsqrte", + .description = "Enable the frsqrte instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.frsqrtes)] = .{ + .llvm_name = "frsqrtes", + .description = "Enable the frsqrtes instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.fsqrt)] = .{ + .llvm_name = "fsqrt", + .description = "Enable the fsqrt instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.fuse_add_logical)] = .{ + .llvm_name = "fuse-add-logical", + .description = "Target supports Add with Logical Operations fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_addi_load)] = .{ + .llvm_name = "fuse-addi-load", + .description = "Power8 Addi-Load fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_addis_load)] = .{ + .llvm_name = "fuse-addis-load", + .description = "Power8 Addis-Load fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_arith_add)] = .{ + .llvm_name = "fuse-arith-add", + .description = "Target supports Arithmetic Operations with Add fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_back2back)] = .{ + .llvm_name = "fuse-back2back", + .description = "Target supports general back to back fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_cmp)] = .{ + .llvm_name = "fuse-cmp", + .description = "Target supports Comparison Operations fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_logical)] = .{ + .llvm_name = "fuse-logical", + .description = "Target supports Logical Operations fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_logical_add)] = .{ + .llvm_name = "fuse-logical-add", + .description = "Target supports Logical with Add Operations fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_sha3)] = .{ + .llvm_name = "fuse-sha3", + .description = "Target supports SHA3 assist fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_store)] = .{ + .llvm_name = "fuse-store", + .description = "Target supports store clustering", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_wideimm)] = .{ + .llvm_name = "fuse-wideimm", + .description = "Target supports Wide-Immediate fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fuse_zeromove)] = .{ + .llvm_name = "fuse-zeromove", + .description = "Target supports move to SPR with branch fusion", + .dependencies = featureSet(&[_]Feature{ + .fusion, + }), + }; + result[@intFromEnum(Feature.fusion)] = .{ + .llvm_name = "fusion", + .description = "Target supports instruction fusion", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hard_float)] = .{ + .llvm_name = "hard-float", + .description = "Enable floating-point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.htm)] = .{ + .llvm_name = "htm", + .description = "Enable Hardware Transactional Memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.icbt)] = .{ + .llvm_name = "icbt", + .description = "Enable icbt instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.invariant_function_descriptors)] = .{ + .llvm_name = "invariant-function-descriptors", + .description = "Assume function descriptors are invariant", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.isa_future_instructions)] = .{ + .llvm_name = "isa-future-instructions", + .description = "Enable instructions for Future ISA.", + .dependencies = featureSet(&[_]Feature{ + .isa_v31_instructions, + }), + }; + result[@intFromEnum(Feature.isa_v206_instructions)] = .{ + .llvm_name = "isa-v206-instructions", + .description = "Enable instructions in ISA 2.06.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.isa_v207_instructions)] = .{ + .llvm_name = "isa-v207-instructions", + .description = "Enable instructions in ISA 2.07.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.isa_v30_instructions)] = .{ + .llvm_name = "isa-v30-instructions", + .description = "Enable instructions in ISA 3.0.", + .dependencies = featureSet(&[_]Feature{ + .isa_v207_instructions, + }), + }; + result[@intFromEnum(Feature.isa_v31_instructions)] = .{ + .llvm_name = "isa-v31-instructions", + .description = "Enable instructions in ISA 3.1.", + .dependencies = featureSet(&[_]Feature{ + .isa_v30_instructions, + }), + }; + result[@intFromEnum(Feature.isel)] = .{ + .llvm_name = "isel", + .description = "Enable the isel instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ldbrx)] = .{ + .llvm_name = "ldbrx", + .description = "Enable the ldbrx instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lfiwax)] = .{ + .llvm_name = "lfiwax", + .description = "Enable the lfiwax instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.longcall)] = .{ + .llvm_name = "longcall", + .description = "Always use indirect calls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mfocrf)] = .{ + .llvm_name = "mfocrf", + .description = "Enable the MFOCRF instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mma)] = .{ + .llvm_name = "mma", + .description = "Enable MMA instructions", + .dependencies = featureSet(&[_]Feature{ + .paired_vector_memops, + .power8_vector, + .power9_altivec, + }), + }; + result[@intFromEnum(Feature.modern_aix_as)] = .{ + .llvm_name = "modern-aix-as", + .description = "AIX system assembler is modern enough to support new mnes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.msync)] = .{ + .llvm_name = "msync", + .description = "Has only the msync instruction instead of sync", + .dependencies = featureSet(&[_]Feature{ + .booke, + }), + }; + result[@intFromEnum(Feature.paired_vector_memops)] = .{ + .llvm_name = "paired-vector-memops", + .description = "32Byte load and store instructions", + .dependencies = featureSet(&[_]Feature{ + .isa_v30_instructions, + }), + }; + result[@intFromEnum(Feature.partword_atomics)] = .{ + .llvm_name = "partword-atomics", + .description = "Enable l[bh]arx and st[bh]cx.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pcrelative_memops)] = .{ + .llvm_name = "pcrelative-memops", + .description = "Enable PC relative Memory Ops", + .dependencies = featureSet(&[_]Feature{ + .prefix_instrs, + }), + }; + result[@intFromEnum(Feature.popcntd)] = .{ + .llvm_name = "popcntd", + .description = "Enable the popcnt[dw] instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.power10_vector)] = .{ + .llvm_name = "power10-vector", + .description = "Enable POWER10 vector instructions", + .dependencies = featureSet(&[_]Feature{ + .isa_v31_instructions, + .power9_vector, + }), + }; + result[@intFromEnum(Feature.power8_altivec)] = .{ + .llvm_name = "power8-altivec", + .description = "Enable POWER8 Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .altivec, + }), + }; + result[@intFromEnum(Feature.power8_vector)] = .{ + .llvm_name = "power8-vector", + .description = "Enable POWER8 vector instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_altivec, + .vsx, + }), + }; + result[@intFromEnum(Feature.power9_altivec)] = .{ + .llvm_name = "power9-altivec", + .description = "Enable POWER9 Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .isa_v30_instructions, + .power8_altivec, + }), + }; + result[@intFromEnum(Feature.power9_vector)] = .{ + .llvm_name = "power9-vector", + .description = "Enable POWER9 vector instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_vector, + .power9_altivec, + }), + }; + result[@intFromEnum(Feature.ppc4xx)] = .{ + .llvm_name = "ppc4xx", + .description = "Enable PPC 4xx instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ppc6xx)] = .{ + .llvm_name = "ppc6xx", + .description = "Enable PPC 6xx instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ppc_postra_sched)] = .{ + .llvm_name = "ppc-postra-sched", + .description = "Use PowerPC post-RA scheduling strategy", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ppc_prera_sched)] = .{ + .llvm_name = "ppc-prera-sched", + .description = "Use PowerPC pre-RA scheduling strategy", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.predictable_select_expensive)] = .{ + .llvm_name = "predictable-select-expensive", + .description = "Prefer likely predicted branches over selects", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefix_instrs)] = .{ + .llvm_name = "prefix-instrs", + .description = "Enable prefixed instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_vector, + .power9_altivec, + }), + }; + result[@intFromEnum(Feature.privileged)] = .{ + .llvm_name = "privileged", + .description = "Add privileged instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.quadword_atomics)] = .{ + .llvm_name = "quadword-atomics", + .description = "Enable lqarx and stqcx.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.recipprec)] = .{ + .llvm_name = "recipprec", + .description = "Assume higher precision reciprocal estimates", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rop_protect)] = .{ + .llvm_name = "rop-protect", + .description = "Add ROP protect", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.secure_plt)] = .{ + .llvm_name = "secure-plt", + .description = "Enable secure plt mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_popcntd)] = .{ + .llvm_name = "slow-popcntd", + .description = "Has slow popcnt[dw] instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.spe)] = .{ + .llvm_name = "spe", + .description = "Enable SPE instructions", + .dependencies = featureSet(&[_]Feature{ + .hard_float, + }), + }; + result[@intFromEnum(Feature.stfiwx)] = .{ + .llvm_name = "stfiwx", + .description = "Enable the stfiwx instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@intFromEnum(Feature.two_const_nr)] = .{ + .llvm_name = "two-const-nr", + .description = "Requires two constant Newton-Raphson computation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vectors_use_two_units)] = .{ + .llvm_name = "vectors-use-two-units", + .description = "Vectors use two units", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vsx)] = .{ + .llvm_name = "vsx", + .description = "Enable VSX instructions", + .dependencies = featureSet(&[_]Feature{ + .altivec, + }), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const @"440" = CpuModel{ + .name = "440", + .llvm_name = "440", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + .isel, + .msync, + }), + }; + pub const @"450" = CpuModel{ + .name = "450", + .llvm_name = "450", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + .isel, + .msync, + }), + }; + pub const @"601" = CpuModel{ + .name = "601", + .llvm_name = "601", + .features = featureSet(&[_]Feature{ + .fpu, + }), + }; + pub const @"602" = CpuModel{ + .name = "602", + .llvm_name = "602", + .features = featureSet(&[_]Feature{ + .fpu, + }), + }; + pub const @"603" = CpuModel{ + .name = "603", + .llvm_name = "603", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"603e" = CpuModel{ + .name = "603e", + .llvm_name = "603e", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"603ev" = CpuModel{ + .name = "603ev", + .llvm_name = "603ev", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"604" = CpuModel{ + .name = "604", + .llvm_name = "604", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"604e" = CpuModel{ + .name = "604e", + .llvm_name = "604e", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"620" = CpuModel{ + .name = "620", + .llvm_name = "620", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"7400" = CpuModel{ + .name = "7400", + .llvm_name = "7400", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"7450" = CpuModel{ + .name = "7450", + .llvm_name = "7450", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"750" = CpuModel{ + .name = "750", + .llvm_name = "750", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"970" = CpuModel{ + .name = "970", + .llvm_name = "970", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const a2 = CpuModel{ + .name = "a2", + .llvm_name = "a2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .booke, + .cmpb, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .isa_v206_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .recipprec, + .slow_popcntd, + .stfiwx, + }), + }; + pub const e500 = CpuModel{ + .name = "e500", + .llvm_name = "e500", + .features = featureSet(&[_]Feature{ + .isel, + .msync, + .spe, + }), + }; + pub const e500mc = CpuModel{ + .name = "e500mc", + .llvm_name = "e500mc", + .features = featureSet(&[_]Feature{ + .booke, + .isel, + .stfiwx, + }), + }; + pub const e5500 = CpuModel{ + .name = "e5500", + .llvm_name = "e5500", + .features = featureSet(&[_]Feature{ + .@"64bit", + .booke, + .isel, + .mfocrf, + .stfiwx, + }), + }; + pub const future = CpuModel{ + .name = "future", + .llvm_name = "future", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .crbits, + .crypto, + .direct_move, + .extdiv, + .fast_MFLR, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .fuse_add_logical, + .fuse_arith_add, + .fuse_logical, + .fuse_logical_add, + .fuse_sha3, + .fuse_store, + .htm, + .icbt, + .isa_future_instructions, + .isa_v206_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .mma, + .partword_atomics, + .pcrelative_memops, + .popcntd, + .power10_vector, + .ppc_postra_sched, + .ppc_prera_sched, + .predictable_select_expensive, + .quadword_atomics, + .recipprec, + .stfiwx, + .two_const_nr, + }), + }; + pub const g3 = CpuModel{ + .name = "g3", + .llvm_name = "g3", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const g4 = CpuModel{ + .name = "g4", + .llvm_name = "g4", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"g4+" = CpuModel{ + .name = "g4+", + .llvm_name = "g4+", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const g5 = CpuModel{ + .name = "g5", + .llvm_name = "g5", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .hard_float, + }), + }; + pub const ppc = CpuModel{ + .name = "ppc", + .llvm_name = "ppc", + .features = featureSet(&[_]Feature{ + .hard_float, + }), + }; + pub const ppc64 = CpuModel{ + .name = "ppc64", + .llvm_name = "ppc64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const ppc64le = CpuModel{ + .name = "ppc64le", + .llvm_name = "ppc64le", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .crbits, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .fuse_addi_load, + .fuse_addis_load, + .htm, + .icbt, + .isa_v206_instructions, + .isa_v207_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power8_vector, + .predictable_select_expensive, + .quadword_atomics, + .recipprec, + .stfiwx, + .two_const_nr, + }), + }; + pub const pwr10 = CpuModel{ + .name = "pwr10", + .llvm_name = "pwr10", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .crbits, + .crypto, + .direct_move, + .extdiv, + .fast_MFLR, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .fuse_add_logical, + .fuse_arith_add, + .fuse_logical, + .fuse_logical_add, + .fuse_sha3, + .fuse_store, + .htm, + .icbt, + .isa_v206_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .mma, + .partword_atomics, + .pcrelative_memops, + .popcntd, + .power10_vector, + .ppc_postra_sched, + .ppc_prera_sched, + .predictable_select_expensive, + .quadword_atomics, + .recipprec, + .stfiwx, + .two_const_nr, + }), + }; + pub const pwr3 = CpuModel{ + .name = "pwr3", + .llvm_name = "pwr3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr4 = CpuModel{ + .name = "pwr4", + .llvm_name = "pwr4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr5 = CpuModel{ + .name = "pwr5", + .llvm_name = "pwr5", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr5x = CpuModel{ + .name = "pwr5x", + .llvm_name = "pwr5x", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr6 = CpuModel{ + .name = "pwr6", + .llvm_name = "pwr6", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .cmpb, + .fcpsgn, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .lfiwax, + .mfocrf, + .recipprec, + .stfiwx, + }), + }; + pub const pwr6x = CpuModel{ + .name = "pwr6x", + .llvm_name = "pwr6x", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .cmpb, + .fcpsgn, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .lfiwax, + .mfocrf, + .recipprec, + .stfiwx, + }), + }; + pub const pwr7 = CpuModel{ + .name = "pwr7", + .llvm_name = "pwr7", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .isa_v206_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .popcntd, + .recipprec, + .stfiwx, + .two_const_nr, + .vsx, + }), + }; + pub const pwr8 = CpuModel{ + .name = "pwr8", + .llvm_name = "pwr8", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .crbits, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .fuse_addi_load, + .fuse_addis_load, + .htm, + .icbt, + .isa_v206_instructions, + .isa_v207_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power8_vector, + .predictable_select_expensive, + .quadword_atomics, + .recipprec, + .stfiwx, + .two_const_nr, + }), + }; + pub const pwr9 = CpuModel{ + .name = "pwr9", + .llvm_name = "pwr9", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_unaligned_fp_access, + .bpermd, + .cmpb, + .crbits, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .htm, + .icbt, + .isa_v206_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power9_vector, + .ppc_postra_sched, + .ppc_prera_sched, + .predictable_select_expensive, + .quadword_atomics, + .recipprec, + .stfiwx, + .two_const_nr, + .vectors_use_two_units, + }), + }; +}; diff --git a/lib/std/Target/riscv.zig b/lib/std/Target/riscv.zig new file mode 100644 index 0000000000000000000000000000000000000000..66c02ae6d093d0057d5f8d7a012017015301ccf7 --- /dev/null +++ b/lib/std/Target/riscv.zig @@ -0,0 +1,1341 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"32bit", + @"64bit", + a, + c, + d, + dlen_factor_2, + e, + experimental_smaia, + experimental_ssaia, + experimental_zacas, + experimental_zfa, + experimental_zfbfmin, + experimental_zicond, + experimental_zihintntl, + experimental_ztso, + experimental_zvbb, + experimental_zvbc, + experimental_zvfbfmin, + experimental_zvfbfwma, + experimental_zvkg, + experimental_zvkn, + experimental_zvknc, + experimental_zvkned, + experimental_zvkng, + experimental_zvknha, + experimental_zvknhb, + experimental_zvks, + experimental_zvksc, + experimental_zvksed, + experimental_zvksg, + experimental_zvksh, + experimental_zvkt, + f, + forced_atomics, + h, + lui_addi_fusion, + m, + no_default_unroll, + no_optimized_zero_stride_load, + no_rvc_hints, + relax, + reserve_x1, + reserve_x10, + reserve_x11, + reserve_x12, + reserve_x13, + reserve_x14, + reserve_x15, + reserve_x16, + reserve_x17, + reserve_x18, + reserve_x19, + reserve_x2, + reserve_x20, + reserve_x21, + reserve_x22, + reserve_x23, + reserve_x24, + reserve_x25, + reserve_x26, + reserve_x27, + reserve_x28, + reserve_x29, + reserve_x3, + reserve_x30, + reserve_x31, + reserve_x4, + reserve_x5, + reserve_x6, + reserve_x7, + reserve_x8, + reserve_x9, + save_restore, + seq_cst_trailing_fence, + short_forward_branch_opt, + svinval, + svnapot, + svpbmt, + tagged_globals, + unaligned_scalar_mem, + unaligned_vector_mem, + v, + xcvbitmanip, + xcvmac, + xsfcie, + xsfvcp, + xtheadba, + xtheadbb, + xtheadbs, + xtheadcmo, + xtheadcondmov, + xtheadfmemidx, + xtheadmac, + xtheadmemidx, + xtheadmempair, + xtheadsync, + xtheadvdot, + xventanacondops, + zawrs, + zba, + zbb, + zbc, + zbkb, + zbkc, + zbkx, + zbs, + zca, + zcb, + zcd, + zce, + zcf, + zcmp, + zcmt, + zdinx, + zfh, + zfhmin, + zfinx, + zhinx, + zhinxmin, + zicbom, + zicbop, + zicboz, + zicntr, + zicsr, + zifencei, + zihintpause, + zihpm, + zk, + zkn, + zknd, + zkne, + zknh, + zkr, + zks, + zksed, + zksh, + zkt, + zmmul, + zve32f, + zve32x, + zve64d, + zve64f, + zve64x, + zvfh, + zvl1024b, + zvl128b, + zvl16384b, + zvl2048b, + zvl256b, + zvl32768b, + zvl32b, + zvl4096b, + zvl512b, + zvl64b, + zvl65536b, + zvl8192b, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"32bit")] = .{ + .llvm_name = "32bit", + .description = "Implements RV32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Implements RV64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.a)] = .{ + .llvm_name = "a", + .description = "'A' (Atomic Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.c)] = .{ + .llvm_name = "c", + .description = "'C' (Compressed Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.d)] = .{ + .llvm_name = "d", + .description = "'D' (Double-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.dlen_factor_2)] = .{ + .llvm_name = "dlen-factor-2", + .description = "Vector unit DLEN(data path width) is half of VLEN", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.e)] = .{ + .llvm_name = "e", + .description = "Implements RV{32,64}E (provides 16 rather than 32 GPRs)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_smaia)] = .{ + .llvm_name = "experimental-smaia", + .description = "'Smaia' (Smaia encompasses all added CSRs and all modifications to interrupt response behavior that the AIA specifies for a hart, over all privilege levels.)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_ssaia)] = .{ + .llvm_name = "experimental-ssaia", + .description = "'Ssaia' (Ssaia is essentially the same as Smaia except excluding the machine-level CSRs and behavior not directly visible to supervisor level.)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zacas)] = .{ + .llvm_name = "experimental-zacas", + .description = "'Zacas' (Atomic Compare-And-Swap Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zfa)] = .{ + .llvm_name = "experimental-zfa", + .description = "'Zfa' (Additional Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.experimental_zfbfmin)] = .{ + .llvm_name = "experimental-zfbfmin", + .description = "'Zfbfmin' (Scalar BF16 Converts)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.experimental_zicond)] = .{ + .llvm_name = "experimental-zicond", + .description = "'Zicond' (Integer Conditional Operations)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zihintntl)] = .{ + .llvm_name = "experimental-zihintntl", + .description = "'Zihintntl' (Non-Temporal Locality Hints)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_ztso)] = .{ + .llvm_name = "experimental-ztso", + .description = "'Ztso' (Memory Model - Total Store Order)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvbb)] = .{ + .llvm_name = "experimental-zvbb", + .description = "'Zvbb' (Vector Bit-manipulation used in Cryptography)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvbc)] = .{ + .llvm_name = "experimental-zvbc", + .description = "'Zvbc' (Vector Carryless Multiplication)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvfbfmin)] = .{ + .llvm_name = "experimental-zvfbfmin", + .description = "'Zvbfmin' (Vector BF16 Converts)", + .dependencies = featureSet(&[_]Feature{ + .zve32f, + }), + }; + result[@intFromEnum(Feature.experimental_zvfbfwma)] = .{ + .llvm_name = "experimental-zvfbfwma", + .description = "'Zvfbfwma' (Vector BF16 widening mul-add)", + .dependencies = featureSet(&[_]Feature{ + .zve32f, + }), + }; + result[@intFromEnum(Feature.experimental_zvkg)] = .{ + .llvm_name = "experimental-zvkg", + .description = "'Zvkg' (Vector GCM instructions for Cryptography)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvkn)] = .{ + .llvm_name = "experimental-zvkn", + .description = "This extension is shorthand for the following set of other extensions: Zvkned, Zvknhb, Zvbb, Zvbc, and Zvkt.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvknc)] = .{ + .llvm_name = "experimental-zvknc", + .description = "This extension is shorthand for the following set of other extensions: Zvkn and Zvbc.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvkned)] = .{ + .llvm_name = "experimental-zvkned", + .description = "'Zvkned' (Vector AES Encryption & Decryption (Single Round))", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvkng)] = .{ + .llvm_name = "experimental-zvkng", + .description = "This extension is shorthand for the following set of other extensions: Zvkn and Zvkg.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvknha)] = .{ + .llvm_name = "experimental-zvknha", + .description = "'Zvknha' (Vector SHA-2 (SHA-256 only))", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvknhb)] = .{ + .llvm_name = "experimental-zvknhb", + .description = "'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))", + .dependencies = featureSet(&[_]Feature{ + .experimental_zvknha, + }), + }; + result[@intFromEnum(Feature.experimental_zvks)] = .{ + .llvm_name = "experimental-zvks", + .description = "This extension is shorthand for the following set of other extensions: Zvksed, Zvksh, Zvbb, Zvbc, and Zvkt.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvksc)] = .{ + .llvm_name = "experimental-zvksc", + .description = "This extension is shorthand for the following set of other extensions: Zvks and Zvbc.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvksed)] = .{ + .llvm_name = "experimental-zvksed", + .description = "'Zvksed' (SM4 Block Cipher Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvksg)] = .{ + .llvm_name = "experimental-zvksg", + .description = "This extension is shorthand for the following set of other extensions: Zvks and Zvkg.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvksh)] = .{ + .llvm_name = "experimental-zvksh", + .description = "'Zvksh' (SM3 Hash Function Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.experimental_zvkt)] = .{ + .llvm_name = "experimental-zvkt", + .description = "'Zvkt' (Vector Data-Independent Execution Latency)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.f)] = .{ + .llvm_name = "f", + .description = "'F' (Single-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .zicsr, + }), + }; + result[@intFromEnum(Feature.forced_atomics)] = .{ + .llvm_name = "forced-atomics", + .description = "Assume that lock-free native-width atomics are available", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.h)] = .{ + .llvm_name = "h", + .description = "'H' (Hypervisor)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lui_addi_fusion)] = .{ + .llvm_name = "lui-addi-fusion", + .description = "Enable LUI+ADDI macrofusion", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.m)] = .{ + .llvm_name = "m", + .description = "'M' (Integer Multiplication and Division)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_default_unroll)] = .{ + .llvm_name = "no-default-unroll", + .description = "Disable default unroll preference.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_optimized_zero_stride_load)] = .{ + .llvm_name = "no-optimized-zero-stride-load", + .description = "Hasn't optimized (perform fewer memory operations)zero-stride vector load", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_rvc_hints)] = .{ + .llvm_name = "no-rvc-hints", + .description = "Disable RVC Hint Instructions.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.relax)] = .{ + .llvm_name = "relax", + .description = "Enable Linker relaxation.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x1)] = .{ + .llvm_name = "reserve-x1", + .description = "Reserve X1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x10)] = .{ + .llvm_name = "reserve-x10", + .description = "Reserve X10", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x11)] = .{ + .llvm_name = "reserve-x11", + .description = "Reserve X11", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x12)] = .{ + .llvm_name = "reserve-x12", + .description = "Reserve X12", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x13)] = .{ + .llvm_name = "reserve-x13", + .description = "Reserve X13", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x14)] = .{ + .llvm_name = "reserve-x14", + .description = "Reserve X14", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x15)] = .{ + .llvm_name = "reserve-x15", + .description = "Reserve X15", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x16)] = .{ + .llvm_name = "reserve-x16", + .description = "Reserve X16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x17)] = .{ + .llvm_name = "reserve-x17", + .description = "Reserve X17", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x18)] = .{ + .llvm_name = "reserve-x18", + .description = "Reserve X18", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x19)] = .{ + .llvm_name = "reserve-x19", + .description = "Reserve X19", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x2)] = .{ + .llvm_name = "reserve-x2", + .description = "Reserve X2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x20)] = .{ + .llvm_name = "reserve-x20", + .description = "Reserve X20", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x21)] = .{ + .llvm_name = "reserve-x21", + .description = "Reserve X21", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x22)] = .{ + .llvm_name = "reserve-x22", + .description = "Reserve X22", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x23)] = .{ + .llvm_name = "reserve-x23", + .description = "Reserve X23", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x24)] = .{ + .llvm_name = "reserve-x24", + .description = "Reserve X24", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x25)] = .{ + .llvm_name = "reserve-x25", + .description = "Reserve X25", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x26)] = .{ + .llvm_name = "reserve-x26", + .description = "Reserve X26", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x27)] = .{ + .llvm_name = "reserve-x27", + .description = "Reserve X27", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x28)] = .{ + .llvm_name = "reserve-x28", + .description = "Reserve X28", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x29)] = .{ + .llvm_name = "reserve-x29", + .description = "Reserve X29", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x3)] = .{ + .llvm_name = "reserve-x3", + .description = "Reserve X3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x30)] = .{ + .llvm_name = "reserve-x30", + .description = "Reserve X30", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x31)] = .{ + .llvm_name = "reserve-x31", + .description = "Reserve X31", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x4)] = .{ + .llvm_name = "reserve-x4", + .description = "Reserve X4", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x5)] = .{ + .llvm_name = "reserve-x5", + .description = "Reserve X5", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x6)] = .{ + .llvm_name = "reserve-x6", + .description = "Reserve X6", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x7)] = .{ + .llvm_name = "reserve-x7", + .description = "Reserve X7", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x8)] = .{ + .llvm_name = "reserve-x8", + .description = "Reserve X8", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reserve_x9)] = .{ + .llvm_name = "reserve-x9", + .description = "Reserve X9", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.save_restore)] = .{ + .llvm_name = "save-restore", + .description = "Enable save/restore.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.seq_cst_trailing_fence)] = .{ + .llvm_name = "seq-cst-trailing-fence", + .description = "Enable trailing fence for seq-cst store.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.short_forward_branch_opt)] = .{ + .llvm_name = "short-forward-branch-opt", + .description = "Enable short forward branch optimization", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.svinval)] = .{ + .llvm_name = "svinval", + .description = "'Svinval' (Fine-Grained Address-Translation Cache Invalidation)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.svnapot)] = .{ + .llvm_name = "svnapot", + .description = "'Svnapot' (NAPOT Translation Contiguity)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.svpbmt)] = .{ + .llvm_name = "svpbmt", + .description = "'Svpbmt' (Page-Based Memory Types)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tagged_globals)] = .{ + .llvm_name = "tagged-globals", + .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_scalar_mem)] = .{ + .llvm_name = "unaligned-scalar-mem", + .description = "Has reasonably performant unaligned scalar loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.unaligned_vector_mem)] = .{ + .llvm_name = "unaligned-vector-mem", + .description = "Has reasonably performant unaligned vector loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v)] = .{ + .llvm_name = "v", + .description = "'V' (Vector Extension for Application Processors)", + .dependencies = featureSet(&[_]Feature{ + .zve64d, + .zvl128b, + }), + }; + result[@intFromEnum(Feature.xcvbitmanip)] = .{ + .llvm_name = "xcvbitmanip", + .description = "'XCVbitmanip' (CORE-V Bit Manipulation)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xcvmac)] = .{ + .llvm_name = "xcvmac", + .description = "'XCVmac' (CORE-V Multiply-Accumulate)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xsfcie)] = .{ + .llvm_name = "xsfcie", + .description = "'XSfcie' (SiFive Custom Instruction Extension SCIE.)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xsfvcp)] = .{ + .llvm_name = "xsfvcp", + .description = "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)", + .dependencies = featureSet(&[_]Feature{ + .zve32x, + }), + }; + result[@intFromEnum(Feature.xtheadba)] = .{ + .llvm_name = "xtheadba", + .description = "'xtheadba' (T-Head address calculation instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadbb)] = .{ + .llvm_name = "xtheadbb", + .description = "'xtheadbb' (T-Head basic bit-manipulation instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadbs)] = .{ + .llvm_name = "xtheadbs", + .description = "'xtheadbs' (T-Head single-bit instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadcmo)] = .{ + .llvm_name = "xtheadcmo", + .description = "'xtheadcmo' (T-Head cache management instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadcondmov)] = .{ + .llvm_name = "xtheadcondmov", + .description = "'xtheadcondmov' (T-Head conditional move instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadfmemidx)] = .{ + .llvm_name = "xtheadfmemidx", + .description = "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.xtheadmac)] = .{ + .llvm_name = "xtheadmac", + .description = "'xtheadmac' (T-Head Multiply-Accumulate Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadmemidx)] = .{ + .llvm_name = "xtheadmemidx", + .description = "'xtheadmemidx' (T-Head Indexed Memory Operations)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadmempair)] = .{ + .llvm_name = "xtheadmempair", + .description = "'xtheadmempair' (T-Head two-GPR Memory Operations)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadsync)] = .{ + .llvm_name = "xtheadsync", + .description = "'xtheadsync' (T-Head multicore synchronization instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xtheadvdot)] = .{ + .llvm_name = "xtheadvdot", + .description = "'xtheadvdot' (T-Head Vector Extensions for Dot)", + .dependencies = featureSet(&[_]Feature{ + .v, + }), + }; + result[@intFromEnum(Feature.xventanacondops)] = .{ + .llvm_name = "xventanacondops", + .description = "'XVentanaCondOps' (Ventana Conditional Ops)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zawrs)] = .{ + .llvm_name = "zawrs", + .description = "'Zawrs' (Wait on Reservation Set)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zba)] = .{ + .llvm_name = "zba", + .description = "'Zba' (Address Generation Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbb)] = .{ + .llvm_name = "zbb", + .description = "'Zbb' (Basic Bit-Manipulation)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbc)] = .{ + .llvm_name = "zbc", + .description = "'Zbc' (Carry-Less Multiplication)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbkb)] = .{ + .llvm_name = "zbkb", + .description = "'Zbkb' (Bitmanip instructions for Cryptography)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbkc)] = .{ + .llvm_name = "zbkc", + .description = "'Zbkc' (Carry-less multiply instructions for Cryptography)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbkx)] = .{ + .llvm_name = "zbkx", + .description = "'Zbkx' (Crossbar permutation instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zbs)] = .{ + .llvm_name = "zbs", + .description = "'Zbs' (Single-Bit Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zca)] = .{ + .llvm_name = "zca", + .description = "'Zca' (part of the C extension, excluding compressed floating point loads/stores)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zcb)] = .{ + .llvm_name = "zcb", + .description = "'Zcb' (Compressed basic bit manipulation instructions)", + .dependencies = featureSet(&[_]Feature{ + .zca, + }), + }; + result[@intFromEnum(Feature.zcd)] = .{ + .llvm_name = "zcd", + .description = "'Zcd' (Compressed Double-Precision Floating-Point Instructions)", + .dependencies = featureSet(&[_]Feature{ + .zca, + }), + }; + result[@intFromEnum(Feature.zce)] = .{ + .llvm_name = "zce", + .description = "'Zce' (Compressed extensions for microcontrollers)", + .dependencies = featureSet(&[_]Feature{ + .zcb, + .zcmp, + .zcmt, + }), + }; + result[@intFromEnum(Feature.zcf)] = .{ + .llvm_name = "zcf", + .description = "'Zcf' (Compressed Single-Precision Floating-Point Instructions)", + .dependencies = featureSet(&[_]Feature{ + .zca, + }), + }; + result[@intFromEnum(Feature.zcmp)] = .{ + .llvm_name = "zcmp", + .description = "'Zcmp' (sequenced instuctions for code-size reduction)", + .dependencies = featureSet(&[_]Feature{ + .zca, + }), + }; + result[@intFromEnum(Feature.zcmt)] = .{ + .llvm_name = "zcmt", + .description = "'Zcmt' (table jump instuctions for code-size reduction)", + .dependencies = featureSet(&[_]Feature{ + .zca, + .zicsr, + }), + }; + result[@intFromEnum(Feature.zdinx)] = .{ + .llvm_name = "zdinx", + .description = "'Zdinx' (Double in Integer)", + .dependencies = featureSet(&[_]Feature{ + .zfinx, + }), + }; + result[@intFromEnum(Feature.zfh)] = .{ + .llvm_name = "zfh", + .description = "'Zfh' (Half-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.zfhmin)] = .{ + .llvm_name = "zfhmin", + .description = "'Zfhmin' (Half-Precision Floating-Point Minimal)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@intFromEnum(Feature.zfinx)] = .{ + .llvm_name = "zfinx", + .description = "'Zfinx' (Float in Integer)", + .dependencies = featureSet(&[_]Feature{ + .zicsr, + }), + }; + result[@intFromEnum(Feature.zhinx)] = .{ + .llvm_name = "zhinx", + .description = "'Zhinx' (Half Float in Integer)", + .dependencies = featureSet(&[_]Feature{ + .zfinx, + }), + }; + result[@intFromEnum(Feature.zhinxmin)] = .{ + .llvm_name = "zhinxmin", + .description = "'Zhinxmin' (Half Float in Integer Minimal)", + .dependencies = featureSet(&[_]Feature{ + .zfinx, + }), + }; + result[@intFromEnum(Feature.zicbom)] = .{ + .llvm_name = "zicbom", + .description = "'Zicbom' (Cache-Block Management Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zicbop)] = .{ + .llvm_name = "zicbop", + .description = "'Zicbop' (Cache-Block Prefetch Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zicboz)] = .{ + .llvm_name = "zicboz", + .description = "'Zicboz' (Cache-Block Zero Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zicntr)] = .{ + .llvm_name = "zicntr", + .description = "'Zicntr' (Base Counters and Timers)", + .dependencies = featureSet(&[_]Feature{ + .zicsr, + }), + }; + result[@intFromEnum(Feature.zicsr)] = .{ + .llvm_name = "zicsr", + .description = "'zicsr' (CSRs)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zifencei)] = .{ + .llvm_name = "zifencei", + .description = "'Zifencei' (fence.i)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zihintpause)] = .{ + .llvm_name = "zihintpause", + .description = "'Zihintpause' (Pause Hint)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zihpm)] = .{ + .llvm_name = "zihpm", + .description = "'Zihpm' (Hardware Performance Counters)", + .dependencies = featureSet(&[_]Feature{ + .zicsr, + }), + }; + result[@intFromEnum(Feature.zk)] = .{ + .llvm_name = "zk", + .description = "'Zk' (Standard scalar cryptography extension)", + .dependencies = featureSet(&[_]Feature{ + .zkn, + .zkr, + .zkt, + }), + }; + result[@intFromEnum(Feature.zkn)] = .{ + .llvm_name = "zkn", + .description = "'Zkn' (NIST Algorithm Suite)", + .dependencies = featureSet(&[_]Feature{ + .zbkb, + .zbkc, + .zbkx, + .zknd, + .zkne, + .zknh, + }), + }; + result[@intFromEnum(Feature.zknd)] = .{ + .llvm_name = "zknd", + .description = "'Zknd' (NIST Suite: AES Decryption)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zkne)] = .{ + .llvm_name = "zkne", + .description = "'Zkne' (NIST Suite: AES Encryption)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zknh)] = .{ + .llvm_name = "zknh", + .description = "'Zknh' (NIST Suite: Hash Function Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zkr)] = .{ + .llvm_name = "zkr", + .description = "'Zkr' (Entropy Source Extension)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zks)] = .{ + .llvm_name = "zks", + .description = "'Zks' (ShangMi Algorithm Suite)", + .dependencies = featureSet(&[_]Feature{ + .zbkb, + .zbkc, + .zbkx, + .zksed, + .zksh, + }), + }; + result[@intFromEnum(Feature.zksed)] = .{ + .llvm_name = "zksed", + .description = "'Zksed' (ShangMi Suite: SM4 Block Cipher Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zksh)] = .{ + .llvm_name = "zksh", + .description = "'Zksh' (ShangMi Suite: SM3 Hash Function Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zkt)] = .{ + .llvm_name = "zkt", + .description = "'Zkt' (Data Independent Execution Latency)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zmmul)] = .{ + .llvm_name = "zmmul", + .description = "'Zmmul' (Integer Multiplication)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zve32f)] = .{ + .llvm_name = "zve32f", + .description = "'Zve32f' (Vector Extensions for Embedded Processors with maximal 32 EEW and F extension)", + .dependencies = featureSet(&[_]Feature{ + .f, + .zve32x, + }), + }; + result[@intFromEnum(Feature.zve32x)] = .{ + .llvm_name = "zve32x", + .description = "'Zve32x' (Vector Extensions for Embedded Processors with maximal 32 EEW)", + .dependencies = featureSet(&[_]Feature{ + .zicsr, + .zvl32b, + }), + }; + result[@intFromEnum(Feature.zve64d)] = .{ + .llvm_name = "zve64d", + .description = "'Zve64d' (Vector Extensions for Embedded Processors with maximal 64 EEW, F and D extension)", + .dependencies = featureSet(&[_]Feature{ + .d, + .zve64f, + }), + }; + result[@intFromEnum(Feature.zve64f)] = .{ + .llvm_name = "zve64f", + .description = "'Zve64f' (Vector Extensions for Embedded Processors with maximal 64 EEW and F extension)", + .dependencies = featureSet(&[_]Feature{ + .zve32f, + .zve64x, + }), + }; + result[@intFromEnum(Feature.zve64x)] = .{ + .llvm_name = "zve64x", + .description = "'Zve64x' (Vector Extensions for Embedded Processors with maximal 64 EEW)", + .dependencies = featureSet(&[_]Feature{ + .zve32x, + .zvl64b, + }), + }; + result[@intFromEnum(Feature.zvfh)] = .{ + .llvm_name = "zvfh", + .description = "'Zvfh' (Vector Half-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .zfhmin, + .zve32f, + }), + }; + result[@intFromEnum(Feature.zvl1024b)] = .{ + .llvm_name = "zvl1024b", + .description = "'Zvl' (Minimum Vector Length) 1024", + .dependencies = featureSet(&[_]Feature{ + .zvl512b, + }), + }; + result[@intFromEnum(Feature.zvl128b)] = .{ + .llvm_name = "zvl128b", + .description = "'Zvl' (Minimum Vector Length) 128", + .dependencies = featureSet(&[_]Feature{ + .zvl64b, + }), + }; + result[@intFromEnum(Feature.zvl16384b)] = .{ + .llvm_name = "zvl16384b", + .description = "'Zvl' (Minimum Vector Length) 16384", + .dependencies = featureSet(&[_]Feature{ + .zvl8192b, + }), + }; + result[@intFromEnum(Feature.zvl2048b)] = .{ + .llvm_name = "zvl2048b", + .description = "'Zvl' (Minimum Vector Length) 2048", + .dependencies = featureSet(&[_]Feature{ + .zvl1024b, + }), + }; + result[@intFromEnum(Feature.zvl256b)] = .{ + .llvm_name = "zvl256b", + .description = "'Zvl' (Minimum Vector Length) 256", + .dependencies = featureSet(&[_]Feature{ + .zvl128b, + }), + }; + result[@intFromEnum(Feature.zvl32768b)] = .{ + .llvm_name = "zvl32768b", + .description = "'Zvl' (Minimum Vector Length) 32768", + .dependencies = featureSet(&[_]Feature{ + .zvl16384b, + }), + }; + result[@intFromEnum(Feature.zvl32b)] = .{ + .llvm_name = "zvl32b", + .description = "'Zvl' (Minimum Vector Length) 32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.zvl4096b)] = .{ + .llvm_name = "zvl4096b", + .description = "'Zvl' (Minimum Vector Length) 4096", + .dependencies = featureSet(&[_]Feature{ + .zvl2048b, + }), + }; + result[@intFromEnum(Feature.zvl512b)] = .{ + .llvm_name = "zvl512b", + .description = "'Zvl' (Minimum Vector Length) 512", + .dependencies = featureSet(&[_]Feature{ + .zvl256b, + }), + }; + result[@intFromEnum(Feature.zvl64b)] = .{ + .llvm_name = "zvl64b", + .description = "'Zvl' (Minimum Vector Length) 64", + .dependencies = featureSet(&[_]Feature{ + .zvl32b, + }), + }; + result[@intFromEnum(Feature.zvl65536b)] = .{ + .llvm_name = "zvl65536b", + .description = "'Zvl' (Minimum Vector Length) 65536", + .dependencies = featureSet(&[_]Feature{ + .zvl32768b, + }), + }; + result[@intFromEnum(Feature.zvl8192b)] = .{ + .llvm_name = "zvl8192b", + .description = "'Zvl' (Minimum Vector Length) 8192", + .dependencies = featureSet(&[_]Feature{ + .zvl4096b, + }), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const baseline_rv32 = CpuModel{ + .name = "baseline_rv32", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .d, + .m, + }), + }; + pub const baseline_rv64 = CpuModel{ + .name = "baseline_rv64", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .m, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const generic_rv32 = CpuModel{ + .name = "generic_rv32", + .llvm_name = "generic-rv32", + .features = featureSet(&[_]Feature{ + .@"32bit", + }), + }; + pub const generic_rv64 = CpuModel{ + .name = "generic_rv64", + .llvm_name = "generic-rv64", + .features = featureSet(&[_]Feature{ + .@"64bit", + }), + }; + pub const rocket = CpuModel{ + .name = "rocket", + .llvm_name = "rocket", + .features = featureSet(&[_]Feature{}), + }; + pub const rocket_rv32 = CpuModel{ + .name = "rocket_rv32", + .llvm_name = "rocket-rv32", + .features = featureSet(&[_]Feature{ + .@"32bit", + .zicsr, + .zifencei, + }), + }; + pub const rocket_rv64 = CpuModel{ + .name = "rocket_rv64", + .llvm_name = "rocket-rv64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .zicsr, + .zifencei, + }), + }; + pub const sifive_7_series = CpuModel{ + .name = "sifive_7_series", + .llvm_name = "sifive-7-series", + .features = featureSet(&[_]Feature{ + .no_default_unroll, + .short_forward_branch_opt, + }), + }; + pub const sifive_e20 = CpuModel{ + .name = "sifive_e20", + .llvm_name = "sifive-e20", + .features = featureSet(&[_]Feature{ + .@"32bit", + .c, + .m, + .zicsr, + .zifencei, + }), + }; + pub const sifive_e21 = CpuModel{ + .name = "sifive_e21", + .llvm_name = "sifive-e21", + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .m, + .zicsr, + .zifencei, + }), + }; + pub const sifive_e24 = CpuModel{ + .name = "sifive_e24", + .llvm_name = "sifive-e24", + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .f, + .m, + .zifencei, + }), + }; + pub const sifive_e31 = CpuModel{ + .name = "sifive_e31", + .llvm_name = "sifive-e31", + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .m, + .zicsr, + .zifencei, + }), + }; + pub const sifive_e34 = CpuModel{ + .name = "sifive_e34", + .llvm_name = "sifive-e34", + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .f, + .m, + .zifencei, + }), + }; + pub const sifive_e76 = CpuModel{ + .name = "sifive_e76", + .llvm_name = "sifive-e76", + .features = featureSet(&[_]Feature{ + .@"32bit", + .a, + .c, + .f, + .m, + .no_default_unroll, + .short_forward_branch_opt, + .zifencei, + }), + }; + pub const sifive_s21 = CpuModel{ + .name = "sifive_s21", + .llvm_name = "sifive-s21", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .m, + .zicsr, + .zifencei, + }), + }; + pub const sifive_s51 = CpuModel{ + .name = "sifive_s51", + .llvm_name = "sifive-s51", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .m, + .zicsr, + .zifencei, + }), + }; + pub const sifive_s54 = CpuModel{ + .name = "sifive_s54", + .llvm_name = "sifive-s54", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .m, + .zifencei, + }), + }; + pub const sifive_s76 = CpuModel{ + .name = "sifive_s76", + .llvm_name = "sifive-s76", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .m, + .no_default_unroll, + .short_forward_branch_opt, + .xsfcie, + .zifencei, + .zihintpause, + }), + }; + pub const sifive_u54 = CpuModel{ + .name = "sifive_u54", + .llvm_name = "sifive-u54", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .m, + .zifencei, + }), + }; + pub const sifive_u74 = CpuModel{ + .name = "sifive_u74", + .llvm_name = "sifive-u74", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .m, + .no_default_unroll, + .short_forward_branch_opt, + .zifencei, + }), + }; + pub const sifive_x280 = CpuModel{ + .name = "sifive_x280", + .llvm_name = "sifive-x280", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .dlen_factor_2, + .m, + .no_default_unroll, + .short_forward_branch_opt, + .v, + .zba, + .zbb, + .zfh, + .zifencei, + .zvfh, + .zvl512b, + }), + }; + pub const syntacore_scr1_base = CpuModel{ + .name = "syntacore_scr1_base", + .llvm_name = "syntacore-scr1-base", + .features = featureSet(&[_]Feature{ + .@"32bit", + .c, + .no_default_unroll, + .zicsr, + .zifencei, + }), + }; + pub const syntacore_scr1_max = CpuModel{ + .name = "syntacore_scr1_max", + .llvm_name = "syntacore-scr1-max", + .features = featureSet(&[_]Feature{ + .@"32bit", + .c, + .m, + .no_default_unroll, + .zicsr, + .zifencei, + }), + }; +}; diff --git a/lib/std/Target/s390x.zig b/lib/std/Target/s390x.zig new file mode 100644 index 0000000000000000000000000000000000000000..b64284725833d45e4f02fe96570411e65f4ca4d4 --- /dev/null +++ b/lib/std/Target/s390x.zig @@ -0,0 +1,667 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + bear_enhancement, + deflate_conversion, + dfp_packed_conversion, + dfp_zoned_conversion, + distinct_ops, + enhanced_dat_2, + enhanced_sort, + execution_hint, + fast_serialization, + fp_extension, + guarded_storage, + high_word, + insert_reference_bits_multiple, + interlocked_access1, + load_and_trap, + load_and_zero_rightmost_byte, + load_store_on_cond, + load_store_on_cond_2, + message_security_assist_extension3, + message_security_assist_extension4, + message_security_assist_extension5, + message_security_assist_extension7, + message_security_assist_extension8, + message_security_assist_extension9, + miscellaneous_extensions, + miscellaneous_extensions_2, + miscellaneous_extensions_3, + nnp_assist, + population_count, + processor_activity_instrumentation, + processor_assist, + reset_dat_protection, + reset_reference_bits_multiple, + soft_float, + transactional_execution, + vector, + vector_enhancements_1, + vector_enhancements_2, + vector_packed_decimal, + vector_packed_decimal_enhancement, + vector_packed_decimal_enhancement_2, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.bear_enhancement)] = .{ + .llvm_name = "bear-enhancement", + .description = "Assume that the BEAR-enhancement facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.deflate_conversion)] = .{ + .llvm_name = "deflate-conversion", + .description = "Assume that the deflate-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dfp_packed_conversion)] = .{ + .llvm_name = "dfp-packed-conversion", + .description = "Assume that the DFP packed-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.dfp_zoned_conversion)] = .{ + .llvm_name = "dfp-zoned-conversion", + .description = "Assume that the DFP zoned-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.distinct_ops)] = .{ + .llvm_name = "distinct-ops", + .description = "Assume that the distinct-operands facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.enhanced_dat_2)] = .{ + .llvm_name = "enhanced-dat-2", + .description = "Assume that the enhanced-DAT facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.enhanced_sort)] = .{ + .llvm_name = "enhanced-sort", + .description = "Assume that the enhanced-sort facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.execution_hint)] = .{ + .llvm_name = "execution-hint", + .description = "Assume that the execution-hint facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_serialization)] = .{ + .llvm_name = "fast-serialization", + .description = "Assume that the fast-serialization facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fp_extension)] = .{ + .llvm_name = "fp-extension", + .description = "Assume that the floating-point extension facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.guarded_storage)] = .{ + .llvm_name = "guarded-storage", + .description = "Assume that the guarded-storage facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.high_word)] = .{ + .llvm_name = "high-word", + .description = "Assume that the high-word facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.insert_reference_bits_multiple)] = .{ + .llvm_name = "insert-reference-bits-multiple", + .description = "Assume that the insert-reference-bits-multiple facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.interlocked_access1)] = .{ + .llvm_name = "interlocked-access1", + .description = "Assume that interlocked-access facility 1 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.load_and_trap)] = .{ + .llvm_name = "load-and-trap", + .description = "Assume that the load-and-trap facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.load_and_zero_rightmost_byte)] = .{ + .llvm_name = "load-and-zero-rightmost-byte", + .description = "Assume that the load-and-zero-rightmost-byte facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.load_store_on_cond)] = .{ + .llvm_name = "load-store-on-cond", + .description = "Assume that the load/store-on-condition facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.load_store_on_cond_2)] = .{ + .llvm_name = "load-store-on-cond-2", + .description = "Assume that the load/store-on-condition facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension3)] = .{ + .llvm_name = "message-security-assist-extension3", + .description = "Assume that the message-security-assist extension facility 3 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension4)] = .{ + .llvm_name = "message-security-assist-extension4", + .description = "Assume that the message-security-assist extension facility 4 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension5)] = .{ + .llvm_name = "message-security-assist-extension5", + .description = "Assume that the message-security-assist extension facility 5 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension7)] = .{ + .llvm_name = "message-security-assist-extension7", + .description = "Assume that the message-security-assist extension facility 7 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension8)] = .{ + .llvm_name = "message-security-assist-extension8", + .description = "Assume that the message-security-assist extension facility 8 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.message_security_assist_extension9)] = .{ + .llvm_name = "message-security-assist-extension9", + .description = "Assume that the message-security-assist extension facility 9 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.miscellaneous_extensions)] = .{ + .llvm_name = "miscellaneous-extensions", + .description = "Assume that the miscellaneous-extensions facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.miscellaneous_extensions_2)] = .{ + .llvm_name = "miscellaneous-extensions-2", + .description = "Assume that the miscellaneous-extensions facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.miscellaneous_extensions_3)] = .{ + .llvm_name = "miscellaneous-extensions-3", + .description = "Assume that the miscellaneous-extensions facility 3 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nnp_assist)] = .{ + .llvm_name = "nnp-assist", + .description = "Assume that the NNP-assist facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.population_count)] = .{ + .llvm_name = "population-count", + .description = "Assume that the population-count facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.processor_activity_instrumentation)] = .{ + .llvm_name = "processor-activity-instrumentation", + .description = "Assume that the processor-activity-instrumentation facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.processor_assist)] = .{ + .llvm_name = "processor-assist", + .description = "Assume that the processor-assist facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reset_dat_protection)] = .{ + .llvm_name = "reset-dat-protection", + .description = "Assume that the reset-DAT-protection facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reset_reference_bits_multiple)] = .{ + .llvm_name = "reset-reference-bits-multiple", + .description = "Assume that the reset-reference-bits-multiple facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software emulation for floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.transactional_execution)] = .{ + .llvm_name = "transactional-execution", + .description = "Assume that the transactional-execution facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector)] = .{ + .llvm_name = "vector", + .description = "Assume that the vectory facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector_enhancements_1)] = .{ + .llvm_name = "vector-enhancements-1", + .description = "Assume that the vector enhancements facility 1 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector_enhancements_2)] = .{ + .llvm_name = "vector-enhancements-2", + .description = "Assume that the vector enhancements facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector_packed_decimal)] = .{ + .llvm_name = "vector-packed-decimal", + .description = "Assume that the vector packed decimal facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector_packed_decimal_enhancement)] = .{ + .llvm_name = "vector-packed-decimal-enhancement", + .description = "Assume that the vector packed decimal enhancement facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vector_packed_decimal_enhancement_2)] = .{ + .llvm_name = "vector-packed-decimal-enhancement-2", + .description = "Assume that the vector packed decimal enhancement facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const arch10 = CpuModel{ + .name = "arch10", + .llvm_name = "arch10", + .features = featureSet(&[_]Feature{ + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + }), + }; + pub const arch11 = CpuModel{ + .name = "arch11", + .llvm_name = "arch11", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + }), + }; + pub const arch12 = CpuModel{ + .name = "arch12", + .llvm_name = "arch12", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_packed_decimal, + }), + }; + pub const arch13 = CpuModel{ + .name = "arch13", + .llvm_name = "arch13", + .features = featureSet(&[_]Feature{ + .deflate_conversion, + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .enhanced_sort, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .message_security_assist_extension9, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .miscellaneous_extensions_3, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_enhancements_2, + .vector_packed_decimal, + .vector_packed_decimal_enhancement, + }), + }; + pub const arch14 = CpuModel{ + .name = "arch14", + .llvm_name = "arch14", + .features = featureSet(&[_]Feature{ + .bear_enhancement, + .deflate_conversion, + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .enhanced_sort, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .message_security_assist_extension9, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .miscellaneous_extensions_3, + .nnp_assist, + .population_count, + .processor_activity_instrumentation, + .processor_assist, + .reset_dat_protection, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_enhancements_2, + .vector_packed_decimal, + .vector_packed_decimal_enhancement, + .vector_packed_decimal_enhancement_2, + }), + }; + pub const arch8 = CpuModel{ + .name = "arch8", + .llvm_name = "arch8", + .features = featureSet(&[_]Feature{}), + }; + pub const arch9 = CpuModel{ + .name = "arch9", + .llvm_name = "arch9", + .features = featureSet(&[_]Feature{ + .distinct_ops, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .population_count, + .reset_reference_bits_multiple, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const z10 = CpuModel{ + .name = "z10", + .llvm_name = "z10", + .features = featureSet(&[_]Feature{}), + }; + pub const z13 = CpuModel{ + .name = "z13", + .llvm_name = "z13", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + }), + }; + pub const z14 = CpuModel{ + .name = "z14", + .llvm_name = "z14", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_packed_decimal, + }), + }; + pub const z15 = CpuModel{ + .name = "z15", + .llvm_name = "z15", + .features = featureSet(&[_]Feature{ + .deflate_conversion, + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .enhanced_sort, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .message_security_assist_extension9, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .miscellaneous_extensions_3, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_enhancements_2, + .vector_packed_decimal, + .vector_packed_decimal_enhancement, + }), + }; + pub const z16 = CpuModel{ + .name = "z16", + .llvm_name = "z16", + .features = featureSet(&[_]Feature{ + .bear_enhancement, + .deflate_conversion, + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .enhanced_sort, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .message_security_assist_extension9, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .miscellaneous_extensions_3, + .nnp_assist, + .population_count, + .processor_activity_instrumentation, + .processor_assist, + .reset_dat_protection, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_enhancements_2, + .vector_packed_decimal, + .vector_packed_decimal_enhancement, + .vector_packed_decimal_enhancement_2, + }), + }; + pub const z196 = CpuModel{ + .name = "z196", + .llvm_name = "z196", + .features = featureSet(&[_]Feature{ + .distinct_ops, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .population_count, + .reset_reference_bits_multiple, + }), + }; + pub const zEC12 = CpuModel{ + .name = "zEC12", + .llvm_name = "zEC12", + .features = featureSet(&[_]Feature{ + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + }), + }; +}; diff --git a/lib/std/Target/sparc.zig b/lib/std/Target/sparc.zig new file mode 100644 index 0000000000000000000000000000000000000000..87bd95697c2081d3c34dfb47ba57b76c1f678628 --- /dev/null +++ b/lib/std/Target/sparc.zig @@ -0,0 +1,455 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + deprecated_v8, + detectroundchange, + fixallfdivsqrt, + hard_quad_float, + hasleoncasa, + hasumacsmac, + insertnopload, + leon, + leoncyclecounter, + leonpwrpsr, + no_fmuls, + no_fsmuld, + popc, + soft_float, + soft_mul_div, + v9, + vis, + vis2, + vis3, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.deprecated_v8)] = .{ + .llvm_name = "deprecated-v8", + .description = "Enable deprecated V8 instructions in V9 mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.detectroundchange)] = .{ + .llvm_name = "detectroundchange", + .description = "LEON3 erratum detection: Detects any rounding mode change request: use only the round-to-nearest rounding mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fixallfdivsqrt)] = .{ + .llvm_name = "fixallfdivsqrt", + .description = "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hard_quad_float)] = .{ + .llvm_name = "hard-quad-float", + .description = "Enable quad-word floating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hasleoncasa)] = .{ + .llvm_name = "hasleoncasa", + .description = "Enable CASA instruction for LEON3 and LEON4 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hasumacsmac)] = .{ + .llvm_name = "hasumacsmac", + .description = "Enable UMAC and SMAC for LEON3 and LEON4 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.insertnopload)] = .{ + .llvm_name = "insertnopload", + .description = "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.leon)] = .{ + .llvm_name = "leon", + .description = "Enable LEON extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.leoncyclecounter)] = .{ + .llvm_name = "leoncyclecounter", + .description = "Use the Leon cycle counter register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.leonpwrpsr)] = .{ + .llvm_name = "leonpwrpsr", + .description = "Enable the PWRPSR instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_fmuls)] = .{ + .llvm_name = "no-fmuls", + .description = "Disable the fmuls instruction.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_fsmuld)] = .{ + .llvm_name = "no-fsmuld", + .description = "Disable the fsmuld instruction.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.popc)] = .{ + .llvm_name = "popc", + .description = "Use the popc (population count) instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software emulation for floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.soft_mul_div)] = .{ + .llvm_name = "soft-mul-div", + .description = "Use software emulation for integer multiply and divide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v9)] = .{ + .llvm_name = "v9", + .description = "Enable SPARC-V9 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vis)] = .{ + .llvm_name = "vis", + .description = "Enable UltraSPARC Visual Instruction Set extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vis2)] = .{ + .llvm_name = "vis2", + .description = "Enable Visual Instruction Set extensions II", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vis3)] = .{ + .llvm_name = "vis3", + .description = "Enable Visual Instruction Set extensions III", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const at697e = CpuModel{ + .name = "at697e", + .llvm_name = "at697e", + .features = featureSet(&[_]Feature{ + .insertnopload, + .leon, + }), + }; + pub const at697f = CpuModel{ + .name = "at697f", + .llvm_name = "at697f", + .features = featureSet(&[_]Feature{ + .insertnopload, + .leon, + }), + }; + pub const f934 = CpuModel{ + .name = "f934", + .llvm_name = "f934", + .features = featureSet(&[_]Feature{}), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const gr712rc = CpuModel{ + .name = "gr712rc", + .llvm_name = "gr712rc", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const gr740 = CpuModel{ + .name = "gr740", + .llvm_name = "gr740", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .hasumacsmac, + .leon, + .leoncyclecounter, + .leonpwrpsr, + }), + }; + pub const hypersparc = CpuModel{ + .name = "hypersparc", + .llvm_name = "hypersparc", + .features = featureSet(&[_]Feature{}), + }; + pub const leon2 = CpuModel{ + .name = "leon2", + .llvm_name = "leon2", + .features = featureSet(&[_]Feature{ + .leon, + }), + }; + pub const leon3 = CpuModel{ + .name = "leon3", + .llvm_name = "leon3", + .features = featureSet(&[_]Feature{ + .hasumacsmac, + .leon, + }), + }; + pub const leon4 = CpuModel{ + .name = "leon4", + .llvm_name = "leon4", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .hasumacsmac, + .leon, + }), + }; + pub const ma2080 = CpuModel{ + .name = "ma2080", + .llvm_name = "ma2080", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2085 = CpuModel{ + .name = "ma2085", + .llvm_name = "ma2085", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2100 = CpuModel{ + .name = "ma2100", + .llvm_name = "ma2100", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2150 = CpuModel{ + .name = "ma2150", + .llvm_name = "ma2150", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2155 = CpuModel{ + .name = "ma2155", + .llvm_name = "ma2155", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2450 = CpuModel{ + .name = "ma2450", + .llvm_name = "ma2450", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2455 = CpuModel{ + .name = "ma2455", + .llvm_name = "ma2455", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2480 = CpuModel{ + .name = "ma2480", + .llvm_name = "ma2480", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2485 = CpuModel{ + .name = "ma2485", + .llvm_name = "ma2485", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2x5x = CpuModel{ + .name = "ma2x5x", + .llvm_name = "ma2x5x", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2x8x = CpuModel{ + .name = "ma2x8x", + .llvm_name = "ma2x8x", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2 = CpuModel{ + .name = "myriad2", + .llvm_name = "myriad2", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_1 = CpuModel{ + .name = "myriad2_1", + .llvm_name = "myriad2.1", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_2 = CpuModel{ + .name = "myriad2_2", + .llvm_name = "myriad2.2", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_3 = CpuModel{ + .name = "myriad2_3", + .llvm_name = "myriad2.3", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const niagara = CpuModel{ + .name = "niagara", + .llvm_name = "niagara", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara2 = CpuModel{ + .name = "niagara2", + .llvm_name = "niagara2", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara3 = CpuModel{ + .name = "niagara3", + .llvm_name = "niagara3", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara4 = CpuModel{ + .name = "niagara4", + .llvm_name = "niagara4", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + .vis3, + }), + }; + pub const sparclet = CpuModel{ + .name = "sparclet", + .llvm_name = "sparclet", + .features = featureSet(&[_]Feature{}), + }; + pub const sparclite = CpuModel{ + .name = "sparclite", + .llvm_name = "sparclite", + .features = featureSet(&[_]Feature{}), + }; + pub const sparclite86x = CpuModel{ + .name = "sparclite86x", + .llvm_name = "sparclite86x", + .features = featureSet(&[_]Feature{}), + }; + pub const supersparc = CpuModel{ + .name = "supersparc", + .llvm_name = "supersparc", + .features = featureSet(&[_]Feature{}), + }; + pub const tsc701 = CpuModel{ + .name = "tsc701", + .llvm_name = "tsc701", + .features = featureSet(&[_]Feature{}), + }; + pub const ultrasparc = CpuModel{ + .name = "ultrasparc", + .llvm_name = "ultrasparc", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + }), + }; + pub const ultrasparc3 = CpuModel{ + .name = "ultrasparc3", + .llvm_name = "ultrasparc3", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + .vis2, + }), + }; + pub const ut699 = CpuModel{ + .name = "ut699", + .llvm_name = "ut699", + .features = featureSet(&[_]Feature{ + .fixallfdivsqrt, + .insertnopload, + .leon, + .no_fmuls, + .no_fsmuld, + }), + }; + pub const v7 = CpuModel{ + .name = "v7", + .llvm_name = "v7", + .features = featureSet(&[_]Feature{ + .no_fsmuld, + .soft_mul_div, + }), + }; + pub const v8 = CpuModel{ + .name = "v8", + .llvm_name = "v8", + .features = featureSet(&[_]Feature{}), + }; + pub const v9 = CpuModel{ + .name = "v9", + .llvm_name = "v9", + .features = featureSet(&[_]Feature{ + .v9, + }), + }; +}; diff --git a/lib/std/Target/spirv.zig b/lib/std/Target/spirv.zig new file mode 100644 index 0000000000000000000000000000000000000000..9d79aff2212cf6b687898b08897cf0185f28fa7b --- /dev/null +++ b/lib/std/Target/spirv.zig @@ -0,0 +1,2091 @@ +//! This file is auto-generated by tools/update_spirv_features.zig. +//! TODO: Dependencies of capabilities on extensions. +//! TODO: Dependencies of extensions on extensions. +//! TODO: Dependencies of extensions on versions. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + v1_1, + v1_2, + v1_3, + v1_4, + v1_5, + SPV_AMD_shader_fragment_mask, + SPV_AMD_gpu_shader_int16, + SPV_AMD_gpu_shader_half_float, + SPV_AMD_texture_gather_bias_lod, + SPV_AMD_shader_ballot, + SPV_AMD_gcn_shader, + SPV_AMD_shader_image_load_store_lod, + SPV_AMD_shader_explicit_vertex_parameter, + SPV_AMD_shader_trinary_minmax, + SPV_AMD_gpu_shader_half_float_fetch, + SPV_GOOGLE_hlsl_functionality1, + SPV_GOOGLE_user_type, + SPV_GOOGLE_decorate_string, + SPV_EXT_demote_to_helper_invocation, + SPV_EXT_descriptor_indexing, + SPV_EXT_fragment_fully_covered, + SPV_EXT_shader_stencil_export, + SPV_EXT_physical_storage_buffer, + SPV_EXT_shader_atomic_float_add, + SPV_EXT_shader_atomic_float_min_max, + SPV_EXT_shader_image_int64, + SPV_EXT_fragment_shader_interlock, + SPV_EXT_fragment_invocation_density, + SPV_EXT_shader_viewport_index_layer, + SPV_INTEL_loop_fuse, + SPV_INTEL_fpga_dsp_control, + SPV_INTEL_fpga_reg, + SPV_INTEL_fpga_memory_accesses, + SPV_INTEL_fpga_loop_controls, + SPV_INTEL_io_pipes, + SPV_INTEL_unstructured_loop_controls, + SPV_INTEL_blocking_pipes, + SPV_INTEL_device_side_avc_motion_estimation, + SPV_INTEL_fpga_memory_attributes, + SPV_INTEL_fp_fast_math_mode, + SPV_INTEL_media_block_io, + SPV_INTEL_shader_integer_functions2, + SPV_INTEL_subgroups, + SPV_INTEL_fpga_cluster_attributes, + SPV_INTEL_kernel_attributes, + SPV_INTEL_arbitrary_precision_integers, + SPV_KHR_8bit_storage, + SPV_KHR_shader_clock, + SPV_KHR_device_group, + SPV_KHR_16bit_storage, + SPV_KHR_variable_pointers, + SPV_KHR_no_integer_wrap_decoration, + SPV_KHR_subgroup_vote, + SPV_KHR_multiview, + SPV_KHR_shader_ballot, + SPV_KHR_vulkan_memory_model, + SPV_KHR_physical_storage_buffer, + SPV_KHR_workgroup_memory_explicit_layout, + SPV_KHR_fragment_shading_rate, + SPV_KHR_shader_atomic_counter_ops, + SPV_KHR_shader_draw_parameters, + SPV_KHR_storage_buffer_storage_class, + SPV_KHR_linkonce_odr, + SPV_KHR_terminate_invocation, + SPV_KHR_non_semantic_info, + SPV_KHR_post_depth_coverage, + SPV_KHR_expect_assume, + SPV_KHR_ray_tracing, + SPV_KHR_ray_query, + SPV_KHR_float_controls, + SPV_NV_viewport_array2, + SPV_NV_shader_subgroup_partitioned, + SPV_NVX_multiview_per_view_attributes, + SPV_NV_ray_tracing, + SPV_NV_shader_image_footprint, + SPV_NV_shading_rate, + SPV_NV_stereo_view_rendering, + SPV_NV_compute_shader_derivatives, + SPV_NV_shader_sm_builtins, + SPV_NV_mesh_shader, + SPV_NV_geometry_shader_passthrough, + SPV_NV_fragment_shader_barycentric, + SPV_NV_cooperative_matrix, + SPV_NV_sample_mask_override_coverage, + Matrix, + Shader, + Geometry, + Tessellation, + Addresses, + Linkage, + Kernel, + Vector16, + Float16Buffer, + Float16, + Float64, + Int64, + Int64Atomics, + ImageBasic, + ImageReadWrite, + ImageMipmap, + Pipes, + Groups, + DeviceEnqueue, + LiteralSampler, + AtomicStorage, + Int16, + TessellationPointSize, + GeometryPointSize, + ImageGatherExtended, + StorageImageMultisample, + UniformBufferArrayDynamicIndexing, + SampledImageArrayDynamicIndexing, + StorageBufferArrayDynamicIndexing, + StorageImageArrayDynamicIndexing, + ClipDistance, + CullDistance, + ImageCubeArray, + SampleRateShading, + ImageRect, + SampledRect, + GenericPointer, + Int8, + InputAttachment, + SparseResidency, + MinLod, + Sampled1D, + Image1D, + SampledCubeArray, + SampledBuffer, + ImageBuffer, + ImageMSArray, + StorageImageExtendedFormats, + ImageQuery, + DerivativeControl, + InterpolationFunction, + TransformFeedback, + GeometryStreams, + StorageImageReadWithoutFormat, + StorageImageWriteWithoutFormat, + MultiViewport, + SubgroupDispatch, + NamedBarrier, + PipeStorage, + GroupNonUniform, + GroupNonUniformVote, + GroupNonUniformArithmetic, + GroupNonUniformBallot, + GroupNonUniformShuffle, + GroupNonUniformShuffleRelative, + GroupNonUniformClustered, + GroupNonUniformQuad, + ShaderLayer, + ShaderViewportIndex, + FragmentShadingRateKHR, + SubgroupBallotKHR, + DrawParameters, + WorkgroupMemoryExplicitLayoutKHR, + WorkgroupMemoryExplicitLayout8BitAccessKHR, + WorkgroupMemoryExplicitLayout16BitAccessKHR, + SubgroupVoteKHR, + StorageBuffer16BitAccess, + StorageUniformBufferBlock16, + UniformAndStorageBuffer16BitAccess, + StorageUniform16, + StoragePushConstant16, + StorageInputOutput16, + DeviceGroup, + MultiView, + VariablePointersStorageBuffer, + VariablePointers, + AtomicStorageOps, + SampleMaskPostDepthCoverage, + StorageBuffer8BitAccess, + UniformAndStorageBuffer8BitAccess, + StoragePushConstant8, + DenormPreserve, + DenormFlushToZero, + SignedZeroInfNanPreserve, + RoundingModeRTE, + RoundingModeRTZ, + RayQueryProvisionalKHR, + RayQueryKHR, + RayTraversalPrimitiveCullingKHR, + RayTracingKHR, + Float16ImageAMD, + ImageGatherBiasLodAMD, + FragmentMaskAMD, + StencilExportEXT, + ImageReadWriteLodAMD, + Int64ImageEXT, + ShaderClockKHR, + SampleMaskOverrideCoverageNV, + GeometryShaderPassthroughNV, + ShaderViewportIndexLayerEXT, + ShaderViewportIndexLayerNV, + ShaderViewportMaskNV, + ShaderStereoViewNV, + PerViewAttributesNV, + FragmentFullyCoveredEXT, + MeshShadingNV, + ImageFootprintNV, + FragmentBarycentricNV, + ComputeDerivativeGroupQuadsNV, + FragmentDensityEXT, + ShadingRateNV, + GroupNonUniformPartitionedNV, + ShaderNonUniform, + ShaderNonUniformEXT, + RuntimeDescriptorArray, + RuntimeDescriptorArrayEXT, + InputAttachmentArrayDynamicIndexing, + InputAttachmentArrayDynamicIndexingEXT, + UniformTexelBufferArrayDynamicIndexing, + UniformTexelBufferArrayDynamicIndexingEXT, + StorageTexelBufferArrayDynamicIndexing, + StorageTexelBufferArrayDynamicIndexingEXT, + UniformBufferArrayNonUniformIndexing, + UniformBufferArrayNonUniformIndexingEXT, + SampledImageArrayNonUniformIndexing, + SampledImageArrayNonUniformIndexingEXT, + StorageBufferArrayNonUniformIndexing, + StorageBufferArrayNonUniformIndexingEXT, + StorageImageArrayNonUniformIndexing, + StorageImageArrayNonUniformIndexingEXT, + InputAttachmentArrayNonUniformIndexing, + InputAttachmentArrayNonUniformIndexingEXT, + UniformTexelBufferArrayNonUniformIndexing, + UniformTexelBufferArrayNonUniformIndexingEXT, + StorageTexelBufferArrayNonUniformIndexing, + StorageTexelBufferArrayNonUniformIndexingEXT, + RayTracingNV, + VulkanMemoryModel, + VulkanMemoryModelKHR, + VulkanMemoryModelDeviceScope, + VulkanMemoryModelDeviceScopeKHR, + PhysicalStorageBufferAddresses, + PhysicalStorageBufferAddressesEXT, + ComputeDerivativeGroupLinearNV, + RayTracingProvisionalKHR, + CooperativeMatrixNV, + FragmentShaderSampleInterlockEXT, + FragmentShaderShadingRateInterlockEXT, + ShaderSMBuiltinsNV, + FragmentShaderPixelInterlockEXT, + DemoteToHelperInvocationEXT, + SubgroupShuffleINTEL, + SubgroupBufferBlockIOINTEL, + SubgroupImageBlockIOINTEL, + SubgroupImageMediaBlockIOINTEL, + RoundToInfinityINTEL, + FloatingPointModeINTEL, + IntegerFunctions2INTEL, + FunctionPointersINTEL, + IndirectReferencesINTEL, + AsmINTEL, + AtomicFloat32MinMaxEXT, + AtomicFloat64MinMaxEXT, + AtomicFloat16MinMaxEXT, + VectorComputeINTEL, + VectorAnyINTEL, + ExpectAssumeKHR, + SubgroupAvcMotionEstimationINTEL, + SubgroupAvcMotionEstimationIntraINTEL, + SubgroupAvcMotionEstimationChromaINTEL, + VariableLengthArrayINTEL, + FunctionFloatControlINTEL, + FPGAMemoryAttributesINTEL, + FPFastMathModeINTEL, + ArbitraryPrecisionIntegersINTEL, + UnstructuredLoopControlsINTEL, + FPGALoopControlsINTEL, + KernelAttributesINTEL, + FPGAKernelAttributesINTEL, + FPGAMemoryAccessesINTEL, + FPGAClusterAttributesINTEL, + LoopFuseINTEL, + FPGABufferLocationINTEL, + USMStorageClassesINTEL, + IOPipesINTEL, + BlockingPipesINTEL, + FPGARegINTEL, + AtomicFloat32AddEXT, + AtomicFloat64AddEXT, + LongConstantCompositeINTEL, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + @setEvalBranchQuota(2000); + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.v1_1)] = .{ + .llvm_name = null, + .description = "SPIR-V version 1.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.v1_2)] = .{ + .llvm_name = null, + .description = "SPIR-V version 1.2", + .dependencies = featureSet(&[_]Feature{ + .v1_1, + }), + }; + result[@intFromEnum(Feature.v1_3)] = .{ + .llvm_name = null, + .description = "SPIR-V version 1.3", + .dependencies = featureSet(&[_]Feature{ + .v1_2, + }), + }; + result[@intFromEnum(Feature.v1_4)] = .{ + .llvm_name = null, + .description = "SPIR-V version 1.4", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.v1_5)] = .{ + .llvm_name = null, + .description = "SPIR-V version 1.5", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.SPV_AMD_shader_fragment_mask)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_shader_fragment_mask", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_gpu_shader_int16)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_gpu_shader_int16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_texture_gather_bias_lod)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_texture_gather_bias_lod", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_shader_ballot)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_shader_ballot", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_gcn_shader)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_gcn_shader", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_shader_image_load_store_lod)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_shader_image_load_store_lod", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_shader_explicit_vertex_parameter)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_shader_explicit_vertex_parameter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_shader_trinary_minmax)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_shader_trinary_minmax", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float_fetch)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float_fetch", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_GOOGLE_hlsl_functionality1)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_GOOGLE_hlsl_functionality1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_GOOGLE_user_type)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_GOOGLE_user_type", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_GOOGLE_decorate_string)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_GOOGLE_decorate_string", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_demote_to_helper_invocation)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_demote_to_helper_invocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_descriptor_indexing)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_descriptor_indexing", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_fragment_fully_covered)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_fragment_fully_covered", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_shader_stencil_export)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_shader_stencil_export", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_physical_storage_buffer)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_physical_storage_buffer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_add)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_shader_atomic_float_add", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_shader_atomic_float_min_max", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_shader_image_int64)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_shader_image_int64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_fragment_shader_interlock)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_fragment_shader_interlock", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_fragment_invocation_density)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_fragment_invocation_density", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_EXT_shader_viewport_index_layer)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_EXT_shader_viewport_index_layer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_loop_fuse)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_loop_fuse", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_dsp_control)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_dsp_control", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_reg)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_reg", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_accesses)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_memory_accesses", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_loop_controls)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_loop_controls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_io_pipes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_io_pipes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_unstructured_loop_controls)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_unstructured_loop_controls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_blocking_pipes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_blocking_pipes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_device_side_avc_motion_estimation)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_device_side_avc_motion_estimation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_attributes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_memory_attributes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fp_fast_math_mode)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fp_fast_math_mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_media_block_io)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_media_block_io", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_shader_integer_functions2)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_shader_integer_functions2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_subgroups)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_subgroups", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_fpga_cluster_attributes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_fpga_cluster_attributes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_kernel_attributes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_kernel_attributes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_integers)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_integers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_8bit_storage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_shader_clock)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_shader_clock", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_device_group)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_device_group", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_16bit_storage)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_16bit_storage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_variable_pointers)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_variable_pointers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_no_integer_wrap_decoration)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_no_integer_wrap_decoration", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_subgroup_vote)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_subgroup_vote", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_multiview)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_multiview", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_shader_ballot)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_shader_ballot", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_vulkan_memory_model)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_vulkan_memory_model", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_physical_storage_buffer)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_physical_storage_buffer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_workgroup_memory_explicit_layout", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_fragment_shading_rate)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_fragment_shading_rate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_shader_atomic_counter_ops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_shader_draw_parameters)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_shader_draw_parameters", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_storage_buffer_storage_class)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_storage_buffer_storage_class", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_linkonce_odr)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_linkonce_odr", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_terminate_invocation)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_terminate_invocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_non_semantic_info)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_non_semantic_info", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_post_depth_coverage)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_post_depth_coverage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_expect_assume)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_expect_assume", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_ray_tracing)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_ray_tracing", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_ray_query", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_KHR_float_controls)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_KHR_float_controls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_viewport_array2)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_viewport_array2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_shader_subgroup_partitioned)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_shader_subgroup_partitioned", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NVX_multiview_per_view_attributes)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NVX_multiview_per_view_attributes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_ray_tracing)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_ray_tracing", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_shader_image_footprint)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_shader_image_footprint", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_shading_rate)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_shading_rate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_stereo_view_rendering)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_stereo_view_rendering", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_compute_shader_derivatives)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_compute_shader_derivatives", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_shader_sm_builtins)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_shader_sm_builtins", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_mesh_shader)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_mesh_shader", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_geometry_shader_passthrough)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_fragment_shader_barycentric)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_cooperative_matrix)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_cooperative_matrix", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SPV_NV_sample_mask_override_coverage)] = .{ + .llvm_name = null, + .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Matrix)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Matrix", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Shader)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Shader", + .dependencies = featureSet(&[_]Feature{ + .Matrix, + }), + }; + result[@intFromEnum(Feature.Geometry)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Geometry", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Tessellation)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Tessellation", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Addresses)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Addresses", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Linkage)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Linkage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Kernel)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Kernel", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Vector16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Vector16", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.Float16Buffer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Float16Buffer", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.Float16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Float16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Float64)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Float64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Int64)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Int64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Int64Atomics)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Int64Atomics", + .dependencies = featureSet(&[_]Feature{ + .Int64, + }), + }; + result[@intFromEnum(Feature.ImageBasic)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageBasic", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.ImageReadWrite)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageReadWrite", + .dependencies = featureSet(&[_]Feature{ + .ImageBasic, + }), + }; + result[@intFromEnum(Feature.ImageMipmap)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageMipmap", + .dependencies = featureSet(&[_]Feature{ + .ImageBasic, + }), + }; + result[@intFromEnum(Feature.Pipes)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Pipes", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.Groups)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Groups", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.DeviceEnqueue)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DeviceEnqueue", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.LiteralSampler)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability LiteralSampler", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.AtomicStorage)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicStorage", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Int16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Int16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.TessellationPointSize)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability TessellationPointSize", + .dependencies = featureSet(&[_]Feature{ + .Tessellation, + }), + }; + result[@intFromEnum(Feature.GeometryPointSize)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GeometryPointSize", + .dependencies = featureSet(&[_]Feature{ + .Geometry, + }), + }; + result[@intFromEnum(Feature.ImageGatherExtended)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageGatherExtended", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StorageImageMultisample)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageMultisample", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.UniformBufferArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformBufferArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SampledImageArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledImageArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StorageBufferArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageBufferArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StorageImageArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ClipDistance)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ClipDistance", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.CullDistance)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability CullDistance", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageCubeArray)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageCubeArray", + .dependencies = featureSet(&[_]Feature{ + .SampledCubeArray, + }), + }; + result[@intFromEnum(Feature.SampleRateShading)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampleRateShading", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageRect)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageRect", + .dependencies = featureSet(&[_]Feature{ + .SampledRect, + }), + }; + result[@intFromEnum(Feature.SampledRect)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledRect", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.GenericPointer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GenericPointer", + .dependencies = featureSet(&[_]Feature{ + .Addresses, + }), + }; + result[@intFromEnum(Feature.Int8)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Int8", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.InputAttachment)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InputAttachment", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SparseResidency)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SparseResidency", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.MinLod)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability MinLod", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Sampled1D)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Sampled1D", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.Image1D)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Image1D", + .dependencies = featureSet(&[_]Feature{ + .Sampled1D, + }), + }; + result[@intFromEnum(Feature.SampledCubeArray)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledCubeArray", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SampledBuffer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledBuffer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ImageBuffer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageBuffer", + .dependencies = featureSet(&[_]Feature{ + .SampledBuffer, + }), + }; + result[@intFromEnum(Feature.ImageMSArray)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageMSArray", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StorageImageExtendedFormats)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageExtendedFormats", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageQuery)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageQuery", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.DerivativeControl)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DerivativeControl", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.InterpolationFunction)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InterpolationFunction", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.TransformFeedback)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability TransformFeedback", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.GeometryStreams)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GeometryStreams", + .dependencies = featureSet(&[_]Feature{ + .Geometry, + }), + }; + result[@intFromEnum(Feature.StorageImageReadWithoutFormat)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageReadWithoutFormat", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StorageImageWriteWithoutFormat)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageWriteWithoutFormat", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.MultiViewport)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability MultiViewport", + .dependencies = featureSet(&[_]Feature{ + .Geometry, + }), + }; + result[@intFromEnum(Feature.SubgroupDispatch)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupDispatch", + .dependencies = featureSet(&[_]Feature{ + .v1_1, + .DeviceEnqueue, + }), + }; + result[@intFromEnum(Feature.NamedBarrier)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability NamedBarrier", + .dependencies = featureSet(&[_]Feature{ + .v1_1, + .Kernel, + }), + }; + result[@intFromEnum(Feature.PipeStorage)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability PipeStorage", + .dependencies = featureSet(&[_]Feature{ + .v1_1, + .Pipes, + }), + }; + result[@intFromEnum(Feature.GroupNonUniform)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniform", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformVote)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformVote", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformArithmetic)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformArithmetic", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformBallot)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformBallot", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformShuffle)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformShuffle", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformShuffleRelative)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformShuffleRelative", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformClustered)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformClustered", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformQuad)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformQuad", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .GroupNonUniform, + }), + }; + result[@intFromEnum(Feature.ShaderLayer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderLayer", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.ShaderViewportIndex)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderViewportIndex", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.FragmentShadingRateKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentShadingRateKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SubgroupBallotKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupBallotKHR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.DrawParameters)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DrawParameters", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .Shader, + }), + }; + result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayoutKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayoutKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout8BitAccessKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout8BitAccessKHR", + .dependencies = featureSet(&[_]Feature{ + .WorkgroupMemoryExplicitLayoutKHR, + }), + }; + result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout16BitAccessKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout16BitAccessKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SubgroupVoteKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupVoteKHR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.StorageBuffer16BitAccess)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageBuffer16BitAccess", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.StorageUniformBufferBlock16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageUniformBufferBlock16", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.UniformAndStorageBuffer16BitAccess)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformAndStorageBuffer16BitAccess", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .StorageBuffer16BitAccess, + .StorageUniformBufferBlock16, + }), + }; + result[@intFromEnum(Feature.StorageUniform16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageUniform16", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .StorageBuffer16BitAccess, + .StorageUniformBufferBlock16, + }), + }; + result[@intFromEnum(Feature.StoragePushConstant16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StoragePushConstant16", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.StorageInputOutput16)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageInputOutput16", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.DeviceGroup)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DeviceGroup", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), + }; + result[@intFromEnum(Feature.MultiView)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability MultiView", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .Shader, + }), + }; + result[@intFromEnum(Feature.VariablePointersStorageBuffer)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VariablePointersStorageBuffer", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .Shader, + }), + }; + result[@intFromEnum(Feature.VariablePointers)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VariablePointers", + .dependencies = featureSet(&[_]Feature{ + .v1_3, + .VariablePointersStorageBuffer, + }), + }; + result[@intFromEnum(Feature.AtomicStorageOps)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicStorageOps", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SampleMaskPostDepthCoverage)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampleMaskPostDepthCoverage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.StorageBuffer8BitAccess)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageBuffer8BitAccess", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.UniformAndStorageBuffer8BitAccess)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformAndStorageBuffer8BitAccess", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .StorageBuffer8BitAccess, + }), + }; + result[@intFromEnum(Feature.StoragePushConstant8)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StoragePushConstant8", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.DenormPreserve)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DenormPreserve", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.DenormFlushToZero)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DenormFlushToZero", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.SignedZeroInfNanPreserve)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SignedZeroInfNanPreserve", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.RoundingModeRTE)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RoundingModeRTE", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.RoundingModeRTZ)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RoundingModeRTZ", + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), + }; + result[@intFromEnum(Feature.RayQueryProvisionalKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayQueryProvisionalKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.RayQueryKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayQueryKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.RayTraversalPrimitiveCullingKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayTraversalPrimitiveCullingKHR", + .dependencies = featureSet(&[_]Feature{ + .RayQueryKHR, + .RayTracingKHR, + }), + }; + result[@intFromEnum(Feature.RayTracingKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayTracingKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Float16ImageAMD)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Float16ImageAMD", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageGatherBiasLodAMD)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageGatherBiasLodAMD", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.FragmentMaskAMD)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentMaskAMD", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.StencilExportEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StencilExportEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageReadWriteLodAMD)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageReadWriteLodAMD", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.Int64ImageEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability Int64ImageEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ShaderClockKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderClockKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SampleMaskOverrideCoverageNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampleMaskOverrideCoverageNV", + .dependencies = featureSet(&[_]Feature{ + .SampleRateShading, + }), + }; + result[@intFromEnum(Feature.GeometryShaderPassthroughNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GeometryShaderPassthroughNV", + .dependencies = featureSet(&[_]Feature{ + .Geometry, + }), + }; + result[@intFromEnum(Feature.ShaderViewportIndexLayerEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderViewportIndexLayerEXT", + .dependencies = featureSet(&[_]Feature{ + .MultiViewport, + }), + }; + result[@intFromEnum(Feature.ShaderViewportIndexLayerNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderViewportIndexLayerNV", + .dependencies = featureSet(&[_]Feature{ + .MultiViewport, + }), + }; + result[@intFromEnum(Feature.ShaderViewportMaskNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderViewportMaskNV", + .dependencies = featureSet(&[_]Feature{ + .ShaderViewportIndexLayerNV, + }), + }; + result[@intFromEnum(Feature.ShaderStereoViewNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderStereoViewNV", + .dependencies = featureSet(&[_]Feature{ + .ShaderViewportMaskNV, + }), + }; + result[@intFromEnum(Feature.PerViewAttributesNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability PerViewAttributesNV", + .dependencies = featureSet(&[_]Feature{ + .MultiView, + }), + }; + result[@intFromEnum(Feature.FragmentFullyCoveredEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentFullyCoveredEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.MeshShadingNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability MeshShadingNV", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ImageFootprintNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ImageFootprintNV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FragmentBarycentricNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentBarycentricNV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ComputeDerivativeGroupQuadsNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ComputeDerivativeGroupQuadsNV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FragmentDensityEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentDensityEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ShadingRateNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShadingRateNV", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.GroupNonUniformPartitionedNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability GroupNonUniformPartitionedNV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ShaderNonUniform)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderNonUniform", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.ShaderNonUniformEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderNonUniformEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.RuntimeDescriptorArray)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RuntimeDescriptorArray", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.RuntimeDescriptorArrayEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RuntimeDescriptorArrayEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .InputAttachment, + }), + }; + result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .InputAttachment, + }), + }; + result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .SampledBuffer, + }), + }; + result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .SampledBuffer, + }), + }; + result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ImageBuffer, + }), + }; + result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ImageBuffer, + }), + }; + result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .InputAttachment, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .InputAttachment, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .SampledBuffer, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .SampledBuffer, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexing)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexing", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ImageBuffer, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexingEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexingEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .ImageBuffer, + .ShaderNonUniform, + }), + }; + result[@intFromEnum(Feature.RayTracingNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayTracingNV", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.VulkanMemoryModel)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VulkanMemoryModel", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.VulkanMemoryModelKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VulkanMemoryModelKHR", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.VulkanMemoryModelDeviceScope)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScope", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.VulkanMemoryModelDeviceScopeKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScopeKHR", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), + }; + result[@intFromEnum(Feature.PhysicalStorageBufferAddresses)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability PhysicalStorageBufferAddresses", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.PhysicalStorageBufferAddressesEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability PhysicalStorageBufferAddressesEXT", + .dependencies = featureSet(&[_]Feature{ + .v1_5, + .Shader, + }), + }; + result[@intFromEnum(Feature.ComputeDerivativeGroupLinearNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ComputeDerivativeGroupLinearNV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.RayTracingProvisionalKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RayTracingProvisionalKHR", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.CooperativeMatrixNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability CooperativeMatrixNV", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.FragmentShaderSampleInterlockEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentShaderSampleInterlockEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.FragmentShaderShadingRateInterlockEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentShaderShadingRateInterlockEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.ShaderSMBuiltinsNV)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ShaderSMBuiltinsNV", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.FragmentShaderPixelInterlockEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FragmentShaderPixelInterlockEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.DemoteToHelperInvocationEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability DemoteToHelperInvocationEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.SubgroupShuffleINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupShuffleINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupBufferBlockIOINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupBufferBlockIOINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupImageBlockIOINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupImageBlockIOINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupImageMediaBlockIOINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupImageMediaBlockIOINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.RoundToInfinityINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability RoundToInfinityINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FloatingPointModeINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FloatingPointModeINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.IntegerFunctions2INTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability IntegerFunctions2INTEL", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.FunctionPointersINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FunctionPointersINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.IndirectReferencesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability IndirectReferencesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.AsmINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AsmINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.AtomicFloat32MinMaxEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicFloat32MinMaxEXT", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.AtomicFloat64MinMaxEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicFloat64MinMaxEXT", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.AtomicFloat16MinMaxEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicFloat16MinMaxEXT", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.VectorComputeINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VectorComputeINTEL", + .dependencies = featureSet(&[_]Feature{ + .VectorAnyINTEL, + }), + }; + result[@intFromEnum(Feature.VectorAnyINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VectorAnyINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ExpectAssumeKHR)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ExpectAssumeKHR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupAvcMotionEstimationINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupAvcMotionEstimationIntraINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationIntraINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.SubgroupAvcMotionEstimationChromaINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationChromaINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.VariableLengthArrayINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability VariableLengthArrayINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FunctionFloatControlINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FunctionFloatControlINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGAMemoryAttributesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGAMemoryAttributesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPFastMathModeINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPFastMathModeINTEL", + .dependencies = featureSet(&[_]Feature{ + .Kernel, + }), + }; + result[@intFromEnum(Feature.ArbitraryPrecisionIntegersINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability ArbitraryPrecisionIntegersINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.UnstructuredLoopControlsINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability UnstructuredLoopControlsINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGALoopControlsINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGALoopControlsINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.KernelAttributesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability KernelAttributesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGAKernelAttributesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGAKernelAttributesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGAMemoryAccessesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGAMemoryAccessesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGAClusterAttributesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGAClusterAttributesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.LoopFuseINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability LoopFuseINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGABufferLocationINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGABufferLocationINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.USMStorageClassesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability USMStorageClassesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.IOPipesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability IOPipesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.BlockingPipesINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability BlockingPipesINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.FPGARegINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability FPGARegINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.AtomicFloat32AddEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicFloat32AddEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.AtomicFloat64AddEXT)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability AtomicFloat64AddEXT", + .dependencies = featureSet(&[_]Feature{ + .Shader, + }), + }; + result[@intFromEnum(Feature.LongConstantCompositeINTEL)] = .{ + .llvm_name = null, + .description = "Enable SPIR-V capability LongConstantCompositeINTEL", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/lib/std/Target/ve.zig b/lib/std/Target/ve.zig new file mode 100644 index 0000000000000000000000000000000000000000..09ee056ef9035466500ed83d8055aba1de13c076 --- /dev/null +++ b/lib/std/Target/ve.zig @@ -0,0 +1,39 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + vpu, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.vpu)] = .{ + .llvm_name = "vpu", + .description = "Enable the VPU", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/lib/std/Target/wasm.zig b/lib/std/Target/wasm.zig new file mode 100644 index 0000000000000000000000000000000000000000..a06d37cf7dd910bac908bf5dc063335a536b5a65 --- /dev/null +++ b/lib/std/Target/wasm.zig @@ -0,0 +1,126 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + atomics, + bulk_memory, + exception_handling, + extended_const, + multivalue, + mutable_globals, + nontrapping_fptoint, + reference_types, + relaxed_simd, + sign_ext, + simd128, + tail_call, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.atomics)] = .{ + .llvm_name = "atomics", + .description = "Enable Atomics", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.bulk_memory)] = .{ + .llvm_name = "bulk-memory", + .description = "Enable bulk memory operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.exception_handling)] = .{ + .llvm_name = "exception-handling", + .description = "Enable Wasm exception handling", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.extended_const)] = .{ + .llvm_name = "extended-const", + .description = "Enable extended const expressions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.multivalue)] = .{ + .llvm_name = "multivalue", + .description = "Enable multivalue blocks, instructions, and functions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mutable_globals)] = .{ + .llvm_name = "mutable-globals", + .description = "Enable mutable globals", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nontrapping_fptoint)] = .{ + .llvm_name = "nontrapping-fptoint", + .description = "Enable non-trapping float-to-int conversion operators", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.reference_types)] = .{ + .llvm_name = "reference-types", + .description = "Enable reference types", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.relaxed_simd)] = .{ + .llvm_name = "relaxed-simd", + .description = "Enable relaxed-simd instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sign_ext)] = .{ + .llvm_name = "sign-ext", + .description = "Enable sign extension operators", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.simd128)] = .{ + .llvm_name = "simd128", + .description = "Enable 128-bit SIMD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tail_call)] = .{ + .llvm_name = "tail-call", + .description = "Enable tail call instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const bleeding_edge = CpuModel{ + .name = "bleeding_edge", + .llvm_name = "bleeding-edge", + .features = featureSet(&[_]Feature{ + .atomics, + .bulk_memory, + .mutable_globals, + .nontrapping_fptoint, + .sign_ext, + .simd128, + .tail_call, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .mutable_globals, + .sign_ext, + }), + }; + pub const mvp = CpuModel{ + .name = "mvp", + .llvm_name = "mvp", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/lib/std/Target/x86.zig b/lib/std/Target/x86.zig new file mode 100644 index 0000000000000000000000000000000000000000..43ec04f41cdddc81b52281c91e2dba12695851a3 --- /dev/null +++ b/lib/std/Target/x86.zig @@ -0,0 +1,4179 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + @"16bit_mode", + @"32bit_mode", + @"3dnow", + @"3dnowa", + @"64bit", + adx, + aes, + allow_light_256_bit, + amx_bf16, + amx_complex, + amx_fp16, + amx_int8, + amx_tile, + avx, + avx2, + avx512bf16, + avx512bitalg, + avx512bw, + avx512cd, + avx512dq, + avx512er, + avx512f, + avx512fp16, + avx512ifma, + avx512pf, + avx512vbmi, + avx512vbmi2, + avx512vl, + avx512vnni, + avx512vp2intersect, + avx512vpopcntdq, + avxifma, + avxneconvert, + avxvnni, + avxvnniint16, + avxvnniint8, + bmi, + bmi2, + branchfusion, + cldemote, + clflushopt, + clwb, + clzero, + cmov, + cmpccxadd, + crc32, + cx16, + cx8, + enqcmd, + ermsb, + f16c, + false_deps_getmant, + false_deps_lzcnt_tzcnt, + false_deps_mulc, + false_deps_mullq, + false_deps_perm, + false_deps_popcnt, + false_deps_range, + fast_11bytenop, + fast_15bytenop, + fast_7bytenop, + fast_bextr, + fast_gather, + fast_hops, + fast_lzcnt, + fast_movbe, + fast_scalar_fsqrt, + fast_scalar_shift_masks, + fast_shld_rotate, + fast_variable_crosslane_shuffle, + fast_variable_perlane_shuffle, + fast_vector_fsqrt, + fast_vector_shift_masks, + faster_shift_than_shuffle, + fma, + fma4, + fsgsbase, + fsrm, + fxsr, + gfni, + harden_sls_ijmp, + harden_sls_ret, + hreset, + idivl_to_divb, + idivq_to_divl, + invpcid, + kl, + lea_sp, + lea_uses_ag, + lvi_cfi, + lvi_load_hardening, + lwp, + lzcnt, + macrofusion, + mmx, + movbe, + movdir64b, + movdiri, + mwaitx, + no_bypass_delay, + no_bypass_delay_blend, + no_bypass_delay_mov, + no_bypass_delay_shuffle, + nopl, + pad_short_functions, + pclmul, + pconfig, + pku, + popcnt, + prefer_128_bit, + prefer_256_bit, + prefer_mask_registers, + prefer_movmsk_over_vtest, + prefetchi, + prefetchwt1, + prfchw, + ptwrite, + raoint, + rdpid, + rdpru, + rdrnd, + rdseed, + retpoline, + retpoline_external_thunk, + retpoline_indirect_branches, + retpoline_indirect_calls, + rtm, + sahf, + sbb_dep_breaking, + serialize, + seses, + sgx, + sha, + sha512, + shstk, + slow_3ops_lea, + slow_incdec, + slow_lea, + slow_pmaddwd, + slow_pmulld, + slow_shld, + slow_two_mem_ops, + slow_unaligned_mem_16, + slow_unaligned_mem_32, + sm3, + sm4, + soft_float, + sse, + sse2, + sse3, + sse4_1, + sse4_2, + sse4a, + sse_unaligned_mem, + ssse3, + tagged_globals, + tbm, + tsxldtrk, + tuning_fast_imm_vector_shift, + uintr, + use_glm_div_sqrt_costs, + use_slm_arith_costs, + vaes, + vpclmulqdq, + vzeroupper, + waitpkg, + wbnoinvd, + widekl, + x87, + xop, + xsave, + xsavec, + xsaveopt, + xsaves, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.@"16bit_mode")] = .{ + .llvm_name = "16bit-mode", + .description = "16-bit mode (i8086)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"32bit_mode")] = .{ + .llvm_name = "32bit-mode", + .description = "32-bit mode (80386)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.@"3dnow")] = .{ + .llvm_name = "3dnow", + .description = "Enable 3DNow! instructions", + .dependencies = featureSet(&[_]Feature{ + .mmx, + }), + }; + result[@intFromEnum(Feature.@"3dnowa")] = .{ + .llvm_name = "3dnowa", + .description = "Enable 3DNow! Athlon instructions", + .dependencies = featureSet(&[_]Feature{ + .@"3dnow", + }), + }; + result[@intFromEnum(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Support 64-bit instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.adx)] = .{ + .llvm_name = "adx", + .description = "Support ADX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.allow_light_256_bit)] = .{ + .llvm_name = "allow-light-256-bit", + .description = "Enable generation of 256-bit load/stores even if we prefer 128-bit", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.amx_bf16)] = .{ + .llvm_name = "amx-bf16", + .description = "Support AMX-BF16 instructions", + .dependencies = featureSet(&[_]Feature{ + .amx_tile, + }), + }; + result[@intFromEnum(Feature.amx_complex)] = .{ + .llvm_name = "amx-complex", + .description = "Support AMX-COMPLEX instructions", + .dependencies = featureSet(&[_]Feature{ + .amx_tile, + }), + }; + result[@intFromEnum(Feature.amx_fp16)] = .{ + .llvm_name = "amx-fp16", + .description = "Support AMX amx-fp16 instructions", + .dependencies = featureSet(&[_]Feature{ + .amx_tile, + }), + }; + result[@intFromEnum(Feature.amx_int8)] = .{ + .llvm_name = "amx-int8", + .description = "Support AMX-INT8 instructions", + .dependencies = featureSet(&[_]Feature{ + .amx_tile, + }), + }; + result[@intFromEnum(Feature.amx_tile)] = .{ + .llvm_name = "amx-tile", + .description = "Support AMX-TILE instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.avx)] = .{ + .llvm_name = "avx", + .description = "Enable AVX instructions", + .dependencies = featureSet(&[_]Feature{ + .sse4_2, + }), + }; + result[@intFromEnum(Feature.avx2)] = .{ + .llvm_name = "avx2", + .description = "Enable AVX2 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.avx512bf16)] = .{ + .llvm_name = "avx512bf16", + .description = "Support bfloat16 floating point", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@intFromEnum(Feature.avx512bitalg)] = .{ + .llvm_name = "avx512bitalg", + .description = "Enable AVX-512 Bit Algorithms", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@intFromEnum(Feature.avx512bw)] = .{ + .llvm_name = "avx512bw", + .description = "Enable AVX-512 Byte and Word Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512cd)] = .{ + .llvm_name = "avx512cd", + .description = "Enable AVX-512 Conflict Detection Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512dq)] = .{ + .llvm_name = "avx512dq", + .description = "Enable AVX-512 Doubleword and Quadword Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512er)] = .{ + .llvm_name = "avx512er", + .description = "Enable AVX-512 Exponential and Reciprocal Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512f)] = .{ + .llvm_name = "avx512f", + .description = "Enable AVX-512 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx2, + .f16c, + .fma, + }), + }; + result[@intFromEnum(Feature.avx512fp16)] = .{ + .llvm_name = "avx512fp16", + .description = "Support 16-bit floating point", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + .avx512dq, + .avx512vl, + }), + }; + result[@intFromEnum(Feature.avx512ifma)] = .{ + .llvm_name = "avx512ifma", + .description = "Enable AVX-512 Integer Fused Multiple-Add", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512pf)] = .{ + .llvm_name = "avx512pf", + .description = "Enable AVX-512 PreFetch Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512vbmi)] = .{ + .llvm_name = "avx512vbmi", + .description = "Enable AVX-512 Vector Byte Manipulation Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@intFromEnum(Feature.avx512vbmi2)] = .{ + .llvm_name = "avx512vbmi2", + .description = "Enable AVX-512 further Vector Byte Manipulation Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@intFromEnum(Feature.avx512vl)] = .{ + .llvm_name = "avx512vl", + .description = "Enable AVX-512 Vector Length eXtensions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512vnni)] = .{ + .llvm_name = "avx512vnni", + .description = "Enable AVX-512 Vector Neural Network Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512vp2intersect)] = .{ + .llvm_name = "avx512vp2intersect", + .description = "Enable AVX-512 vp2intersect", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avx512vpopcntdq)] = .{ + .llvm_name = "avx512vpopcntdq", + .description = "Enable AVX-512 Population Count Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@intFromEnum(Feature.avxifma)] = .{ + .llvm_name = "avxifma", + .description = "Enable AVX-IFMA", + .dependencies = featureSet(&[_]Feature{ + .avx2, + }), + }; + result[@intFromEnum(Feature.avxneconvert)] = .{ + .llvm_name = "avxneconvert", + .description = "Support AVX-NE-CONVERT instructions", + .dependencies = featureSet(&[_]Feature{ + .avx2, + }), + }; + result[@intFromEnum(Feature.avxvnni)] = .{ + .llvm_name = "avxvnni", + .description = "Support AVX_VNNI encoding", + .dependencies = featureSet(&[_]Feature{ + .avx2, + }), + }; + result[@intFromEnum(Feature.avxvnniint16)] = .{ + .llvm_name = "avxvnniint16", + .description = "Enable AVX-VNNI-INT16", + .dependencies = featureSet(&[_]Feature{ + .avx2, + }), + }; + result[@intFromEnum(Feature.avxvnniint8)] = .{ + .llvm_name = "avxvnniint8", + .description = "Enable AVX-VNNI-INT8", + .dependencies = featureSet(&[_]Feature{ + .avx2, + }), + }; + result[@intFromEnum(Feature.bmi)] = .{ + .llvm_name = "bmi", + .description = "Support BMI instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.bmi2)] = .{ + .llvm_name = "bmi2", + .description = "Support BMI2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.branchfusion)] = .{ + .llvm_name = "branchfusion", + .description = "CMP/TEST can be fused with conditional branches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cldemote)] = .{ + .llvm_name = "cldemote", + .description = "Enable Cache Line Demote", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.clflushopt)] = .{ + .llvm_name = "clflushopt", + .description = "Flush A Cache Line Optimized", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.clwb)] = .{ + .llvm_name = "clwb", + .description = "Cache Line Write Back", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.clzero)] = .{ + .llvm_name = "clzero", + .description = "Enable Cache Line Zero", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cmov)] = .{ + .llvm_name = "cmov", + .description = "Enable conditional move instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cmpccxadd)] = .{ + .llvm_name = "cmpccxadd", + .description = "Support CMPCCXADD instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.crc32)] = .{ + .llvm_name = "crc32", + .description = "Enable SSE 4.2 CRC32 instruction (used when SSE4.2 is supported but function is GPR only)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.cx16)] = .{ + .llvm_name = "cx16", + .description = "64-bit with cmpxchg16b (this is true for most x86-64 chips, but not the first AMD chips)", + .dependencies = featureSet(&[_]Feature{ + .cx8, + }), + }; + result[@intFromEnum(Feature.cx8)] = .{ + .llvm_name = "cx8", + .description = "Support CMPXCHG8B instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.enqcmd)] = .{ + .llvm_name = "enqcmd", + .description = "Has ENQCMD instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ermsb)] = .{ + .llvm_name = "ermsb", + .description = "REP MOVS/STOS are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.f16c)] = .{ + .llvm_name = "f16c", + .description = "Support 16-bit floating point conversion instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.false_deps_getmant)] = .{ + .llvm_name = "false-deps-getmant", + .description = "VGETMANTSS/SD/SH and VGETMANDPS/PD(memory version) has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_lzcnt_tzcnt)] = .{ + .llvm_name = "false-deps-lzcnt-tzcnt", + .description = "LZCNT/TZCNT have a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_mulc)] = .{ + .llvm_name = "false-deps-mulc", + .description = "VF[C]MULCPH/SH has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_mullq)] = .{ + .llvm_name = "false-deps-mullq", + .description = "VPMULLQ has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_perm)] = .{ + .llvm_name = "false-deps-perm", + .description = "VPERMD/Q/PS/PD has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_popcnt)] = .{ + .llvm_name = "false-deps-popcnt", + .description = "POPCNT has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.false_deps_range)] = .{ + .llvm_name = "false-deps-range", + .description = "VRANGEPD/PS/SD/SS has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_11bytenop)] = .{ + .llvm_name = "fast-11bytenop", + .description = "Target can quickly decode up to 11 byte NOPs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_15bytenop)] = .{ + .llvm_name = "fast-15bytenop", + .description = "Target can quickly decode up to 15 byte NOPs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_7bytenop)] = .{ + .llvm_name = "fast-7bytenop", + .description = "Target can quickly decode up to 7 byte NOPs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_bextr)] = .{ + .llvm_name = "fast-bextr", + .description = "Indicates that the BEXTR instruction is implemented as a single uop with good throughput", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_gather)] = .{ + .llvm_name = "fast-gather", + .description = "Indicates if gather is reasonably fast (this is true for Skylake client and all AVX-512 CPUs)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_hops)] = .{ + .llvm_name = "fast-hops", + .description = "Prefer horizontal vector math instructions (haddp, phsub, etc.) over normal vector instructions with shuffles", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_lzcnt)] = .{ + .llvm_name = "fast-lzcnt", + .description = "LZCNT instructions are as fast as most simple integer ops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_movbe)] = .{ + .llvm_name = "fast-movbe", + .description = "Prefer a movbe over a single-use load + bswap / single-use bswap + store", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_scalar_fsqrt)] = .{ + .llvm_name = "fast-scalar-fsqrt", + .description = "Scalar SQRT is fast (disable Newton-Raphson)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_scalar_shift_masks)] = .{ + .llvm_name = "fast-scalar-shift-masks", + .description = "Prefer a left/right scalar logical shift pair over a shift+and pair", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_shld_rotate)] = .{ + .llvm_name = "fast-shld-rotate", + .description = "SHLD can be used as a faster rotate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_variable_crosslane_shuffle)] = .{ + .llvm_name = "fast-variable-crosslane-shuffle", + .description = "Cross-lane shuffles with variable masks are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_variable_perlane_shuffle)] = .{ + .llvm_name = "fast-variable-perlane-shuffle", + .description = "Per-lane shuffles with variable masks are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_vector_fsqrt)] = .{ + .llvm_name = "fast-vector-fsqrt", + .description = "Vector SQRT is fast (disable Newton-Raphson)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fast_vector_shift_masks)] = .{ + .llvm_name = "fast-vector-shift-masks", + .description = "Prefer a left/right vector logical shift pair over a shift+and pair", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.faster_shift_than_shuffle)] = .{ + .llvm_name = "faster-shift-than-shuffle", + .description = "Shifts are faster (or as fast) as shuffle", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fma)] = .{ + .llvm_name = "fma", + .description = "Enable three-operand fused multiple-add", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.fma4)] = .{ + .llvm_name = "fma4", + .description = "Enable four-operand fused multiple-add", + .dependencies = featureSet(&[_]Feature{ + .avx, + .sse4a, + }), + }; + result[@intFromEnum(Feature.fsgsbase)] = .{ + .llvm_name = "fsgsbase", + .description = "Support FS/GS Base instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fsrm)] = .{ + .llvm_name = "fsrm", + .description = "REP MOVSB of short lengths is faster", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.fxsr)] = .{ + .llvm_name = "fxsr", + .description = "Support fxsave/fxrestore instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.gfni)] = .{ + .llvm_name = "gfni", + .description = "Enable Galois Field Arithmetic Instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.harden_sls_ijmp)] = .{ + .llvm_name = "harden-sls-ijmp", + .description = "Harden against straight line speculation across indirect JMP instructions.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.harden_sls_ret)] = .{ + .llvm_name = "harden-sls-ret", + .description = "Harden against straight line speculation across RET instructions.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.hreset)] = .{ + .llvm_name = "hreset", + .description = "Has hreset instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.idivl_to_divb)] = .{ + .llvm_name = "idivl-to-divb", + .description = "Use 8-bit divide for positive values less than 256", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.idivq_to_divl)] = .{ + .llvm_name = "idivq-to-divl", + .description = "Use 32-bit divide for positive values less than 2^32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.invpcid)] = .{ + .llvm_name = "invpcid", + .description = "Invalidate Process-Context Identifier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.kl)] = .{ + .llvm_name = "kl", + .description = "Support Key Locker kl Instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.lea_sp)] = .{ + .llvm_name = "lea-sp", + .description = "Use LEA for adjusting the stack pointer (this is an optimization for Intel Atom processors)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lea_uses_ag)] = .{ + .llvm_name = "lea-uses-ag", + .description = "LEA instruction needs inputs at AG stage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lvi_cfi)] = .{ + .llvm_name = "lvi-cfi", + .description = "Prevent indirect calls/branches from using a memory operand, and precede all indirect calls/branches from a register with an LFENCE instruction to serialize control flow. Also decompose RET instructions into a POP+LFENCE+JMP sequence.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lvi_load_hardening)] = .{ + .llvm_name = "lvi-load-hardening", + .description = "Insert LFENCE instructions to prevent data speculatively injected into loads from being used maliciously.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lwp)] = .{ + .llvm_name = "lwp", + .description = "Enable LWP instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.lzcnt)] = .{ + .llvm_name = "lzcnt", + .description = "Support LZCNT instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.macrofusion)] = .{ + .llvm_name = "macrofusion", + .description = "Various instructions can be fused with conditional branches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mmx)] = .{ + .llvm_name = "mmx", + .description = "Enable MMX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.movbe)] = .{ + .llvm_name = "movbe", + .description = "Support MOVBE instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.movdir64b)] = .{ + .llvm_name = "movdir64b", + .description = "Support movdir64b instruction (direct store 64 bytes)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.movdiri)] = .{ + .llvm_name = "movdiri", + .description = "Support movdiri instruction (direct store integer)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.mwaitx)] = .{ + .llvm_name = "mwaitx", + .description = "Enable MONITORX/MWAITX timer functionality", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bypass_delay)] = .{ + .llvm_name = "no-bypass-delay", + .description = "Has no bypass delay when using the 'wrong' domain", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bypass_delay_blend)] = .{ + .llvm_name = "no-bypass-delay-blend", + .description = "Has no bypass delay when using the 'wrong' blend type", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bypass_delay_mov)] = .{ + .llvm_name = "no-bypass-delay-mov", + .description = "Has no bypass delay when using the 'wrong' mov type", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.no_bypass_delay_shuffle)] = .{ + .llvm_name = "no-bypass-delay-shuffle", + .description = "Has no bypass delay when using the 'wrong' shuffle type", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.nopl)] = .{ + .llvm_name = "nopl", + .description = "Enable NOPL instruction (generally pentium pro+)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pad_short_functions)] = .{ + .llvm_name = "pad-short-functions", + .description = "Pad short functions (to prevent a stall when returning too early)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pclmul)] = .{ + .llvm_name = "pclmul", + .description = "Enable packed carry-less multiplication instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.pconfig)] = .{ + .llvm_name = "pconfig", + .description = "platform configuration instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.pku)] = .{ + .llvm_name = "pku", + .description = "Enable protection keys", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.popcnt)] = .{ + .llvm_name = "popcnt", + .description = "Support POPCNT instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_128_bit)] = .{ + .llvm_name = "prefer-128-bit", + .description = "Prefer 128-bit AVX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_256_bit)] = .{ + .llvm_name = "prefer-256-bit", + .description = "Prefer 256-bit AVX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_mask_registers)] = .{ + .llvm_name = "prefer-mask-registers", + .description = "Prefer AVX512 mask registers over PTEST/MOVMSK", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefer_movmsk_over_vtest)] = .{ + .llvm_name = "prefer-movmsk-over-vtest", + .description = "Prefer movmsk over vtest instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefetchi)] = .{ + .llvm_name = "prefetchi", + .description = "Prefetch instruction with T0 or T1 Hint", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prefetchwt1)] = .{ + .llvm_name = "prefetchwt1", + .description = "Prefetch with Intent to Write and T1 Hint", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.prfchw)] = .{ + .llvm_name = "prfchw", + .description = "Support PRFCHW instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ptwrite)] = .{ + .llvm_name = "ptwrite", + .description = "Support ptwrite instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.raoint)] = .{ + .llvm_name = "raoint", + .description = "Support RAO-INT instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rdpid)] = .{ + .llvm_name = "rdpid", + .description = "Support RDPID instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rdpru)] = .{ + .llvm_name = "rdpru", + .description = "Support RDPRU instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rdrnd)] = .{ + .llvm_name = "rdrnd", + .description = "Support RDRAND instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rdseed)] = .{ + .llvm_name = "rdseed", + .description = "Support RDSEED instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.retpoline)] = .{ + .llvm_name = "retpoline", + .description = "Remove speculation of indirect branches from the generated code, either by avoiding them entirely or lowering them with a speculation blocking construct", + .dependencies = featureSet(&[_]Feature{ + .retpoline_indirect_branches, + .retpoline_indirect_calls, + }), + }; + result[@intFromEnum(Feature.retpoline_external_thunk)] = .{ + .llvm_name = "retpoline-external-thunk", + .description = "When lowering an indirect call or branch using a `retpoline`, rely on the specified user provided thunk rather than emitting one ourselves. Only has effect when combined with some other retpoline feature", + .dependencies = featureSet(&[_]Feature{ + .retpoline_indirect_calls, + }), + }; + result[@intFromEnum(Feature.retpoline_indirect_branches)] = .{ + .llvm_name = "retpoline-indirect-branches", + .description = "Remove speculation of indirect branches from the generated code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.retpoline_indirect_calls)] = .{ + .llvm_name = "retpoline-indirect-calls", + .description = "Remove speculation of indirect calls from the generated code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.rtm)] = .{ + .llvm_name = "rtm", + .description = "Support RTM instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sahf)] = .{ + .llvm_name = "sahf", + .description = "Support LAHF and SAHF instructions in 64-bit mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sbb_dep_breaking)] = .{ + .llvm_name = "sbb-dep-breaking", + .description = "SBB with same register has no source dependency", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.serialize)] = .{ + .llvm_name = "serialize", + .description = "Has serialize instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.seses)] = .{ + .llvm_name = "seses", + .description = "Prevent speculative execution side channel timing attacks by inserting a speculation barrier before memory reads, memory writes, and conditional branches. Implies LVI Control Flow integrity.", + .dependencies = featureSet(&[_]Feature{ + .lvi_cfi, + }), + }; + result[@intFromEnum(Feature.sgx)] = .{ + .llvm_name = "sgx", + .description = "Enable Software Guard Extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sha)] = .{ + .llvm_name = "sha", + .description = "Enable SHA instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.sha512)] = .{ + .llvm_name = "sha512", + .description = "Support SHA512 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.shstk)] = .{ + .llvm_name = "shstk", + .description = "Support CET Shadow-Stack instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_3ops_lea)] = .{ + .llvm_name = "slow-3ops-lea", + .description = "LEA instruction with 3 ops or certain registers is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_incdec)] = .{ + .llvm_name = "slow-incdec", + .description = "INC and DEC instructions are slower than ADD and SUB", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_lea)] = .{ + .llvm_name = "slow-lea", + .description = "LEA instruction with certain arguments is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_pmaddwd)] = .{ + .llvm_name = "slow-pmaddwd", + .description = "PMADDWD is slower than PMULLD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_pmulld)] = .{ + .llvm_name = "slow-pmulld", + .description = "PMULLD instruction is slow (compared to PMULLW/PMULHW and PMULUDQ)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_shld)] = .{ + .llvm_name = "slow-shld", + .description = "SHLD instruction is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_two_mem_ops)] = .{ + .llvm_name = "slow-two-mem-ops", + .description = "Two memory operand instructions are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_unaligned_mem_16)] = .{ + .llvm_name = "slow-unaligned-mem-16", + .description = "Slow unaligned 16-byte memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.slow_unaligned_mem_32)] = .{ + .llvm_name = "slow-unaligned-mem-32", + .description = "Slow unaligned 32-byte memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sm3)] = .{ + .llvm_name = "sm3", + .description = "Support SM3 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.sm4)] = .{ + .llvm_name = "sm4", + .description = "Support SM4 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@intFromEnum(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software floating point features", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sse)] = .{ + .llvm_name = "sse", + .description = "Enable SSE instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.sse2)] = .{ + .llvm_name = "sse2", + .description = "Enable SSE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse, + }), + }; + result[@intFromEnum(Feature.sse3)] = .{ + .llvm_name = "sse3", + .description = "Enable SSE3 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@intFromEnum(Feature.sse4_1)] = .{ + .llvm_name = "sse4.1", + .description = "Enable SSE 4.1 instructions", + .dependencies = featureSet(&[_]Feature{ + .ssse3, + }), + }; + result[@intFromEnum(Feature.sse4_2)] = .{ + .llvm_name = "sse4.2", + .description = "Enable SSE 4.2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse4_1, + }), + }; + result[@intFromEnum(Feature.sse4a)] = .{ + .llvm_name = "sse4a", + .description = "Support SSE 4a instructions", + .dependencies = featureSet(&[_]Feature{ + .sse3, + }), + }; + result[@intFromEnum(Feature.sse_unaligned_mem)] = .{ + .llvm_name = "sse-unaligned-mem", + .description = "Allow unaligned memory operands with SSE instructions (this may require setting a configuration bit in the processor)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.ssse3)] = .{ + .llvm_name = "ssse3", + .description = "Enable SSSE3 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse3, + }), + }; + result[@intFromEnum(Feature.tagged_globals)] = .{ + .llvm_name = "tagged-globals", + .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tbm)] = .{ + .llvm_name = "tbm", + .description = "Enable TBM instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tsxldtrk)] = .{ + .llvm_name = "tsxldtrk", + .description = "Support TSXLDTRK instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.tuning_fast_imm_vector_shift)] = .{ + .llvm_name = "tuning-fast-imm-vector-shift", + .description = "Vector shifts are fast (2/cycle) as opposed to slow (1/cycle)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.uintr)] = .{ + .llvm_name = "uintr", + .description = "Has UINTR Instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_glm_div_sqrt_costs)] = .{ + .llvm_name = "use-glm-div-sqrt-costs", + .description = "Use Goldmont specific floating point div/sqrt costs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.use_slm_arith_costs)] = .{ + .llvm_name = "use-slm-arith-costs", + .description = "Use Silvermont specific arithmetic costs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.vaes)] = .{ + .llvm_name = "vaes", + .description = "Promote selected AES instructions to AVX512/AVX registers", + .dependencies = featureSet(&[_]Feature{ + .aes, + .avx, + }), + }; + result[@intFromEnum(Feature.vpclmulqdq)] = .{ + .llvm_name = "vpclmulqdq", + .description = "Enable vpclmulqdq instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + .pclmul, + }), + }; + result[@intFromEnum(Feature.vzeroupper)] = .{ + .llvm_name = "vzeroupper", + .description = "Should insert vzeroupper instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.waitpkg)] = .{ + .llvm_name = "waitpkg", + .description = "Wait and pause enhancements", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.wbnoinvd)] = .{ + .llvm_name = "wbnoinvd", + .description = "Write Back No Invalidate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.widekl)] = .{ + .llvm_name = "widekl", + .description = "Support Key Locker wide Instructions", + .dependencies = featureSet(&[_]Feature{ + .kl, + }), + }; + result[@intFromEnum(Feature.x87)] = .{ + .llvm_name = "x87", + .description = "Enable X87 float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xop)] = .{ + .llvm_name = "xop", + .description = "Enable XOP instructions", + .dependencies = featureSet(&[_]Feature{ + .fma4, + }), + }; + result[@intFromEnum(Feature.xsave)] = .{ + .llvm_name = "xsave", + .description = "Support xsave instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@intFromEnum(Feature.xsavec)] = .{ + .llvm_name = "xsavec", + .description = "Support xsavec instructions", + .dependencies = featureSet(&[_]Feature{ + .xsave, + }), + }; + result[@intFromEnum(Feature.xsaveopt)] = .{ + .llvm_name = "xsaveopt", + .description = "Support xsaveopt instructions", + .dependencies = featureSet(&[_]Feature{ + .xsave, + }), + }; + result[@intFromEnum(Feature.xsaves)] = .{ + .llvm_name = "xsaves", + .description = "Support xsaves instructions", + .dependencies = featureSet(&[_]Feature{ + .xsave, + }), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const alderlake = CpuModel{ + .name = "alderlake", + .llvm_name = "alderlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .f16c, + .false_deps_perm, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .hreset, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_movmsk_over_vtest, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .widekl, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const amdfam10 = CpuModel{ + .name = "amdfam10", + .llvm_name = "amdfam10", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .fast_scalar_shift_masks, + .fxsr, + .lzcnt, + .nopl, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .sse4a, + .vzeroupper, + .x87, + }), + }; + pub const athlon = CpuModel{ + .name = "athlon", + .llvm_name = "athlon", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const athlon64 = CpuModel{ + .name = "athlon64", + .llvm_name = "athlon64", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const athlon64_sse3 = CpuModel{ + .name = "athlon64_sse3", + .llvm_name = "athlon64-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const athlon_4 = CpuModel{ + .name = "athlon_4", + .llvm_name = "athlon-4", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const athlon_fx = CpuModel{ + .name = "athlon_fx", + .llvm_name = "athlon-fx", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const athlon_mp = CpuModel{ + .name = "athlon_mp", + .llvm_name = "athlon-mp", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const athlon_tbird = CpuModel{ + .name = "athlon_tbird", + .llvm_name = "athlon-tbird", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const athlon_xp = CpuModel{ + .name = "athlon_xp", + .llvm_name = "athlon-xp", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const atom = CpuModel{ + .name = "atom", + .llvm_name = "atom", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fxsr, + .idivl_to_divb, + .idivq_to_divl, + .lea_sp, + .lea_uses_ag, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pad_short_functions, + .sahf, + .slow_two_mem_ops, + .slow_unaligned_mem_16, + .ssse3, + .vzeroupper, + .x87, + }), + }; + pub const atom_sse4_2_movbe = CpuModel{ + .name = "atom_sse4_2_movbe", + .llvm_name = "atom_sse4_2_movbe", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_7bytenop, + .fast_movbe, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_incdec, + .slow_lea, + .slow_pmulld, + .slow_two_mem_ops, + .sse4_2, + .use_slm_arith_costs, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const barcelona = CpuModel{ + .name = "barcelona", + .llvm_name = "barcelona", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .fast_scalar_shift_masks, + .fxsr, + .lzcnt, + .nopl, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .sse4a, + .vzeroupper, + .x87, + }), + }; + pub const bdver1 = CpuModel{ + .name = "bdver1", + .llvm_name = "bdver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .branchfusion, + .cmov, + .crc32, + .cx16, + .fast_11bytenop, + .fast_scalar_shift_masks, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .vzeroupper, + .x87, + .xop, + .xsave, + }), + }; + pub const bdver2 = CpuModel{ + .name = "bdver2", + .llvm_name = "bdver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .bmi, + .branchfusion, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_movbe, + .fast_scalar_shift_masks, + .fma, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .tbm, + .vzeroupper, + .x87, + .xop, + .xsave, + }), + }; + pub const bdver3 = CpuModel{ + .name = "bdver3", + .llvm_name = "bdver3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .bmi, + .branchfusion, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_movbe, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .tbm, + .vzeroupper, + .x87, + .xop, + .xsaveopt, + }), + }; + pub const bdver4 = CpuModel{ + .name = "bdver4", + .llvm_name = "bdver4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_movbe, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .tbm, + .vzeroupper, + .x87, + .xop, + .xsaveopt, + }), + }; + pub const bonnell = CpuModel{ + .name = "bonnell", + .llvm_name = "bonnell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fxsr, + .idivl_to_divb, + .idivq_to_divl, + .lea_sp, + .lea_uses_ag, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pad_short_functions, + .sahf, + .slow_two_mem_ops, + .slow_unaligned_mem_16, + .ssse3, + .vzeroupper, + .x87, + }), + }; + pub const broadwell = CpuModel{ + .name = "broadwell", + .llvm_name = "broadwell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .ermsb, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .vzeroupper, + .x87, + .xsaveopt, + }), + }; + pub const btver1 = CpuModel{ + .name = "btver1", + .llvm_name = "btver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fast_15bytenop, + .fast_scalar_shift_masks, + .fast_vector_shift_masks, + .fxsr, + .lzcnt, + .mmx, + .nopl, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .sse4a, + .ssse3, + .vzeroupper, + .x87, + }), + }; + pub const btver2 = CpuModel{ + .name = "btver2", + .llvm_name = "btver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .bmi, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_hops, + .fast_lzcnt, + .fast_movbe, + .fast_scalar_shift_masks, + .fast_vector_shift_masks, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .sbb_dep_breaking, + .slow_shld, + .sse4a, + .x87, + .xsaveopt, + }), + }; + pub const c3 = CpuModel{ + .name = "c3", + .llvm_name = "c3", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const c3_2 = CpuModel{ + .name = "c3_2", + .llvm_name = "c3-2", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const cannonlake = CpuModel{ + .name = "cannonlake", + .llvm_name = "cannonlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .crc32, + .cx16, + .ermsb, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const cascadelake = CpuModel{ + .name = "cascadelake", + .llvm_name = "cascadelake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512vl, + .avx512vnni, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .faster_shift_than_shuffle, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const cooperlake = CpuModel{ + .name = "cooperlake", + .llvm_name = "cooperlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx512bf16, + .avx512cd, + .avx512dq, + .avx512vl, + .avx512vnni, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .faster_shift_than_shuffle, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const core2 = CpuModel{ + .name = "core2", + .llvm_name = "core2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .sahf, + .slow_unaligned_mem_16, + .ssse3, + .vzeroupper, + .x87, + }), + }; + pub const corei7 = CpuModel{ + .name = "corei7", + .llvm_name = "corei7", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .fxsr, + .macrofusion, + .mmx, + .no_bypass_delay_mov, + .nopl, + .popcnt, + .sahf, + .sse4_2, + .vzeroupper, + .x87, + }), + }; + pub const emeraldrapids = CpuModel{ + .name = "emeraldrapids", + .llvm_name = "emeraldrapids", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .amx_bf16, + .amx_int8, + .avx512bf16, + .avx512bitalg, + .avx512cd, + .avx512fp16, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vnni, + .avx512vpopcntdq, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .enqcmd, + .ermsb, + .false_deps_getmant, + .false_deps_mulc, + .false_deps_mullq, + .false_deps_perm, + .false_deps_range, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .tsxldtrk, + .tuning_fast_imm_vector_shift, + .uintr, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cx8, + .fast_15bytenop, + .fast_scalar_fsqrt, + .idivq_to_divl, + .macrofusion, + .slow_3ops_lea, + .vzeroupper, + .x87, + }), + }; + pub const geode = CpuModel{ + .name = "geode", + .llvm_name = "geode", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const goldmont = CpuModel{ + .name = "goldmont", + .llvm_name = "goldmont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_movbe, + .fsgsbase, + .fxsr, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .use_glm_div_sqrt_costs, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const goldmont_plus = CpuModel{ + .name = "goldmont_plus", + .llvm_name = "goldmont-plus", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .cmov, + .crc32, + .cx16, + .fast_movbe, + .fsgsbase, + .fxsr, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .use_glm_div_sqrt_costs, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const grandridge = CpuModel{ + .name = "grandridge", + .llvm_name = "grandridge", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .avxifma, + .avxneconvert, + .avxvnni, + .avxvnniint8, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .cmpccxadd, + .crc32, + .cx16, + .enqcmd, + .f16c, + .fast_movbe, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .hreset, + .invpcid, + .lzcnt, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay, + .nopl, + .pconfig, + .pku, + .popcnt, + .prfchw, + .ptwrite, + .raoint, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .uintr, + .use_glm_div_sqrt_costs, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .widekl, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const graniterapids = CpuModel{ + .name = "graniterapids", + .llvm_name = "graniterapids", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .amx_bf16, + .amx_fp16, + .amx_int8, + .avx512bf16, + .avx512bitalg, + .avx512cd, + .avx512fp16, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vnni, + .avx512vpopcntdq, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .enqcmd, + .ermsb, + .false_deps_getmant, + .false_deps_mulc, + .false_deps_mullq, + .false_deps_perm, + .false_deps_range, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_256_bit, + .prefetchi, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .tsxldtrk, + .tuning_fast_imm_vector_shift, + .uintr, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const graniterapids_d = CpuModel{ + .name = "graniterapids_d", + .llvm_name = "graniterapids-d", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .amx_bf16, + .amx_complex, + .amx_fp16, + .amx_int8, + .avx512bf16, + .avx512bitalg, + .avx512cd, + .avx512fp16, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vnni, + .avx512vpopcntdq, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .enqcmd, + .ermsb, + .false_deps_getmant, + .false_deps_mulc, + .false_deps_mullq, + .false_deps_perm, + .false_deps_range, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_256_bit, + .prefetchi, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .tsxldtrk, + .tuning_fast_imm_vector_shift, + .uintr, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const haswell = CpuModel{ + .name = "haswell", + .llvm_name = "haswell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .ermsb, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .vzeroupper, + .x87, + .xsaveopt, + }), + }; + pub const @"i386" = CpuModel{ + .name = "i386", + .llvm_name = "i386", + .features = featureSet(&[_]Feature{ + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const @"i486" = CpuModel{ + .name = "i486", + .llvm_name = "i486", + .features = featureSet(&[_]Feature{ + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const @"i586" = CpuModel{ + .name = "i586", + .llvm_name = "i586", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const @"i686" = CpuModel{ + .name = "i686", + .llvm_name = "i686", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const icelake_client = CpuModel{ + .name = "icelake_client", + .llvm_name = "icelake-client", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx512bitalg, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .crc32, + .cx16, + .ermsb, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const icelake_server = CpuModel{ + .name = "icelake_server", + .llvm_name = "icelake-server", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx512bitalg, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const ivybridge = CpuModel{ + .name = "ivybridge", + .llvm_name = "ivybridge", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .f16c, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .macrofusion, + .mmx, + .no_bypass_delay_mov, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .vzeroupper, + .x87, + .xsaveopt, + }), + }; + pub const k6 = CpuModel{ + .name = "k6", + .llvm_name = "k6", + .features = featureSet(&[_]Feature{ + .cx8, + .mmx, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const k6_2 = CpuModel{ + .name = "k6_2", + .llvm_name = "k6-2", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const k6_3 = CpuModel{ + .name = "k6_3", + .llvm_name = "k6-3", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const k8 = CpuModel{ + .name = "k8", + .llvm_name = "k8", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const k8_sse3 = CpuModel{ + .name = "k8_sse3", + .llvm_name = "k8-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const knl = CpuModel{ + .name = "knl", + .llvm_name = "knl", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx512cd, + .avx512er, + .avx512pf, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .fast_gather, + .fast_movbe, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prefer_mask_registers, + .prefetchwt1, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .slow_incdec, + .slow_pmaddwd, + .slow_two_mem_ops, + .x87, + .xsaveopt, + }), + }; + pub const knm = CpuModel{ + .name = "knm", + .llvm_name = "knm", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx512cd, + .avx512er, + .avx512pf, + .avx512vpopcntdq, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .fast_gather, + .fast_movbe, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prefer_mask_registers, + .prefetchwt1, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .slow_incdec, + .slow_pmaddwd, + .slow_two_mem_ops, + .x87, + .xsaveopt, + }), + }; + pub const lakemont = CpuModel{ + .name = "lakemont", + .llvm_name = "lakemont", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .soft_float, + .vzeroupper, + }), + }; + pub const meteorlake = CpuModel{ + .name = "meteorlake", + .llvm_name = "meteorlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .f16c, + .false_deps_perm, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .hreset, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_movmsk_over_vtest, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .widekl, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const nehalem = CpuModel{ + .name = "nehalem", + .llvm_name = "nehalem", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .fxsr, + .macrofusion, + .mmx, + .no_bypass_delay_mov, + .nopl, + .popcnt, + .sahf, + .sse4_2, + .vzeroupper, + .x87, + }), + }; + pub const nocona = CpuModel{ + .name = "nocona", + .llvm_name = "nocona", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const opteron = CpuModel{ + .name = "opteron", + .llvm_name = "opteron", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const opteron_sse3 = CpuModel{ + .name = "opteron_sse3", + .llvm_name = "opteron-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .sbb_dep_breaking, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const penryn = CpuModel{ + .name = "penryn", + .llvm_name = "penryn", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .sahf, + .slow_unaligned_mem_16, + .sse4_1, + .vzeroupper, + .x87, + }), + }; + pub const pentium = CpuModel{ + .name = "pentium", + .llvm_name = "pentium", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const pentium2 = CpuModel{ + .name = "pentium2", + .llvm_name = "pentium2", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const pentium3 = CpuModel{ + .name = "pentium3", + .llvm_name = "pentium3", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const pentium3m = CpuModel{ + .name = "pentium3m", + .llvm_name = "pentium3m", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse, + .vzeroupper, + .x87, + }), + }; + pub const pentium4 = CpuModel{ + .name = "pentium4", + .llvm_name = "pentium4", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const pentium_m = CpuModel{ + .name = "pentium_m", + .llvm_name = "pentium-m", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const pentium_mmx = CpuModel{ + .name = "pentium_mmx", + .llvm_name = "pentium-mmx", + .features = featureSet(&[_]Feature{ + .cx8, + .mmx, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const pentiumpro = CpuModel{ + .name = "pentiumpro", + .llvm_name = "pentiumpro", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .nopl, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const prescott = CpuModel{ + .name = "prescott", + .llvm_name = "prescott", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const raptorlake = CpuModel{ + .name = "raptorlake", + .llvm_name = "raptorlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .f16c, + .false_deps_perm, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .hreset, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_movmsk_over_vtest, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .widekl, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const rocketlake = CpuModel{ + .name = "rocketlake", + .llvm_name = "rocketlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx512bitalg, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .crc32, + .cx16, + .ermsb, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const sandybridge = CpuModel{ + .name = "sandybridge", + .llvm_name = "sandybridge", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fxsr, + .idivq_to_divl, + .macrofusion, + .mmx, + .no_bypass_delay_mov, + .nopl, + .pclmul, + .popcnt, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .vzeroupper, + .x87, + .xsaveopt, + }), + }; + pub const sapphirerapids = CpuModel{ + .name = "sapphirerapids", + .llvm_name = "sapphirerapids", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .amx_bf16, + .amx_int8, + .avx512bf16, + .avx512bitalg, + .avx512cd, + .avx512fp16, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vnni, + .avx512vpopcntdq, + .avxvnni, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .enqcmd, + .ermsb, + .false_deps_getmant, + .false_deps_mulc, + .false_deps_mullq, + .false_deps_perm, + .false_deps_range, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pconfig, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .tsxldtrk, + .tuning_fast_imm_vector_shift, + .uintr, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const sierraforest = CpuModel{ + .name = "sierraforest", + .llvm_name = "sierraforest", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .avxifma, + .avxneconvert, + .avxvnni, + .avxvnniint8, + .bmi, + .bmi2, + .cldemote, + .clflushopt, + .clwb, + .cmov, + .cmpccxadd, + .crc32, + .cx16, + .enqcmd, + .f16c, + .fast_movbe, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .hreset, + .invpcid, + .lzcnt, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay, + .nopl, + .pconfig, + .pku, + .popcnt, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .serialize, + .sha, + .shstk, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .uintr, + .use_glm_div_sqrt_costs, + .vaes, + .vpclmulqdq, + .vzeroupper, + .waitpkg, + .widekl, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const silvermont = CpuModel{ + .name = "silvermont", + .llvm_name = "silvermont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_7bytenop, + .fast_movbe, + .fxsr, + .idivq_to_divl, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .sahf, + .slow_incdec, + .slow_lea, + .slow_pmulld, + .slow_two_mem_ops, + .sse4_2, + .use_slm_arith_costs, + .vzeroupper, + .x87, + }), + }; + pub const skx = CpuModel{ + .name = "skx", + .llvm_name = "skx", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .faster_shift_than_shuffle, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const skylake = CpuModel{ + .name = "skylake", + .llvm_name = "skylake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .crc32, + .cx16, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const skylake_avx512 = CpuModel{ + .name = "skylake_avx512", + .llvm_name = "skylake-avx512", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .faster_shift_than_shuffle, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pclmul, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .tuning_fast_imm_vector_shift, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const slm = CpuModel{ + .name = "slm", + .llvm_name = "slm", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_7bytenop, + .fast_movbe, + .fxsr, + .idivq_to_divl, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .sahf, + .slow_incdec, + .slow_lea, + .slow_pmulld, + .slow_two_mem_ops, + .sse4_2, + .use_slm_arith_costs, + .vzeroupper, + .x87, + }), + }; + pub const tigerlake = CpuModel{ + .name = "tigerlake", + .llvm_name = "tigerlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx512bitalg, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vp2intersect, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .ermsb, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .no_bypass_delay_blend, + .no_bypass_delay_mov, + .no_bypass_delay_shuffle, + .nopl, + .pku, + .popcnt, + .prefer_256_bit, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .shstk, + .tuning_fast_imm_vector_shift, + .vaes, + .vpclmulqdq, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const tremont = CpuModel{ + .name = "tremont", + .llvm_name = "tremont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .clwb, + .cmov, + .crc32, + .cx16, + .fast_movbe, + .fsgsbase, + .fxsr, + .gfni, + .mmx, + .movbe, + .no_bypass_delay, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .use_glm_div_sqrt_costs, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const westmere = CpuModel{ + .name = "westmere", + .llvm_name = "westmere", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .fxsr, + .macrofusion, + .mmx, + .no_bypass_delay_mov, + .nopl, + .pclmul, + .popcnt, + .sahf, + .sse4_2, + .vzeroupper, + .x87, + }), + }; + pub const winchip2 = CpuModel{ + .name = "winchip2", + .llvm_name = "winchip2", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const winchip_c6 = CpuModel{ + .name = "winchip_c6", + .llvm_name = "winchip-c6", + .features = featureSet(&[_]Feature{ + .mmx, + .slow_unaligned_mem_16, + .vzeroupper, + .x87, + }), + }; + pub const x86_64 = CpuModel{ + .name = "x86_64", + .llvm_name = "x86-64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx8, + .fxsr, + .idivq_to_divl, + .macrofusion, + .mmx, + .nopl, + .slow_3ops_lea, + .slow_incdec, + .sse2, + .vzeroupper, + .x87, + }), + }; + pub const x86_64_v2 = CpuModel{ + .name = "x86_64_v2", + .llvm_name = "x86-64-v2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fxsr, + .idivq_to_divl, + .macrofusion, + .mmx, + .nopl, + .popcnt, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .sse4_2, + .vzeroupper, + .x87, + }), + }; + pub const x86_64_v3 = CpuModel{ + .name = "x86_64_v3", + .llvm_name = "x86-64-v3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_15bytenop, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fma, + .fxsr, + .idivq_to_divl, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .nopl, + .popcnt, + .sahf, + .slow_3ops_lea, + .vzeroupper, + .x87, + .xsave, + }), + }; + pub const x86_64_v4 = CpuModel{ + .name = "x86_64_v4", + .llvm_name = "x86-64-v4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .allow_light_256_bit, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512vl, + .bmi, + .bmi2, + .cmov, + .crc32, + .cx16, + .false_deps_popcnt, + .fast_15bytenop, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_crosslane_shuffle, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fxsr, + .idivq_to_divl, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .nopl, + .popcnt, + .prefer_256_bit, + .sahf, + .slow_3ops_lea, + .vzeroupper, + .x87, + .xsave, + }), + }; + pub const yonah = CpuModel{ + .name = "yonah", + .llvm_name = "yonah", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .vzeroupper, + .x87, + }), + }; + pub const znver1 = CpuModel{ + .name = "znver1", + .llvm_name = "znver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clzero, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_movbe, + .fast_scalar_fsqrt, + .fast_scalar_shift_masks, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sbb_dep_breaking, + .sha, + .slow_shld, + .sse4a, + .vzeroupper, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const znver2 = CpuModel{ + .name = "znver2", + .llvm_name = "znver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clwb, + .clzero, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_movbe, + .fast_scalar_fsqrt, + .fast_scalar_shift_masks, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdpid, + .rdpru, + .rdrnd, + .rdseed, + .sahf, + .sbb_dep_breaking, + .sha, + .slow_shld, + .sse4a, + .vzeroupper, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const znver3 = CpuModel{ + .name = "znver3", + .llvm_name = "znver3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clwb, + .clzero, + .cmov, + .crc32, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_movbe, + .fast_scalar_fsqrt, + .fast_scalar_shift_masks, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fsrm, + .fxsr, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pku, + .popcnt, + .prfchw, + .rdpid, + .rdpru, + .rdrnd, + .rdseed, + .sahf, + .sbb_dep_breaking, + .sha, + .slow_shld, + .sse4a, + .vaes, + .vpclmulqdq, + .vzeroupper, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const znver4 = CpuModel{ + .name = "znver4", + .llvm_name = "znver4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .allow_light_256_bit, + .avx512bf16, + .avx512bitalg, + .avx512cd, + .avx512dq, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clwb, + .clzero, + .cmov, + .crc32, + .cx16, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_movbe, + .fast_scalar_fsqrt, + .fast_scalar_shift_masks, + .fast_variable_perlane_shuffle, + .fast_vector_fsqrt, + .fsgsbase, + .fsrm, + .fxsr, + .gfni, + .invpcid, + .lzcnt, + .macrofusion, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pku, + .popcnt, + .prfchw, + .rdpid, + .rdpru, + .rdrnd, + .rdseed, + .sahf, + .sbb_dep_breaking, + .sha, + .shstk, + .slow_shld, + .sse4a, + .vaes, + .vpclmulqdq, + .vzeroupper, + .wbnoinvd, + .x87, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; +}; diff --git a/lib/std/Target/xtensa.zig b/lib/std/Target/xtensa.zig new file mode 100644 index 0000000000000000000000000000000000000000..22851c4554cf86cb9c22a61fc290fe3884faf4e3 --- /dev/null +++ b/lib/std/Target/xtensa.zig @@ -0,0 +1,39 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum { + density, +}; + +pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; +pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.density)] = .{ + .llvm_name = "density", + .description = "Enable Density instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index a88a102bd426042f951b7346badb313b001221eb..c79007b87a5b587b0c53e8d3e68496e804da9ce2 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 { diff --git a/lib/std/fs/AtomicFile.zig b/lib/std/fs/AtomicFile.zig index b090bc95828ec693369ee73a3ec91fc5cc057c96..c95ae9bcf2bb5764ab98b413d9421b22e3523387 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/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index b637e664f1ee577afcd9cb5b07adb64b315a2fd5..4a45975ccc1858afb145e18e70fd375dda84b454 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); diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 40e0991e5fc884245e02c788e699e2b2d8a64519..490e12350624eb212453d0d1753afe2d135c8c62 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; } diff --git a/lib/std/std.zig b/lib/std/std.zig index 7342cadbefdb24d34b6d4b7f81d44c5c91e93e6e..66e30c4b4ee162fac562348d34f55ee72a40d30b 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; @@ -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/target.zig b/lib/std/target.zig deleted file mode 100644 index bb03c8e0cd93268d910b14c17ac3ac5bb6f878fb..0000000000000000000000000000000000000000 --- a/lib/std/target.zig +++ /dev/null @@ -1,2608 +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, - }, - ); - } -}; - -test { - std.testing.refAllDecls(Target.Cpu.Arch); -} diff --git a/lib/std/target/aarch64.zig b/lib/std/target/aarch64.zig deleted file mode 100644 index 011cb20aefbced7e2f787921de5d01e6d85f0b85..0000000000000000000000000000000000000000 --- a/lib/std/target/aarch64.zig +++ /dev/null @@ -1,2656 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - a510, - a65, - a710, - a76, - a78, - a78c, - aes, - aggressive_fma, - alternate_sextload_cvt_f32_pattern, - altnzcv, - am, - amvs, - arith_bcc_fusion, - arith_cbz_fusion, - ascend_store_address, - b16b16, - balance_fp_ops, - bf16, - brbe, - bti, - call_saved_x10, - call_saved_x11, - call_saved_x12, - call_saved_x13, - call_saved_x14, - call_saved_x15, - call_saved_x18, - call_saved_x8, - call_saved_x9, - ccdp, - ccidx, - ccpp, - chk, - clrbhb, - cmp_bcc_fusion, - complxnum, - contextidr_el2, - cortex_r82, - crc, - crypto, - cssc, - custom_cheap_as_move, - d128, - disable_latency_sched_heuristic, - dit, - dotprod, - ecv, - el2vmsa, - el3, - enable_select_opt, - ete, - exynos_cheap_as_move, - f32mm, - f64mm, - fgt, - fix_cortex_a53_835769, - flagm, - fmv, - force_32bit_jump_tables, - fp16fml, - fp_armv8, - fptoint, - fullfp16, - fuse_address, - fuse_addsub_2reg_const1, - fuse_adrp_add, - fuse_aes, - fuse_arith_logic, - fuse_crypto_eor, - fuse_csel, - fuse_literals, - gcs, - harden_sls_blr, - harden_sls_nocomdat, - harden_sls_retbr, - hbc, - hcx, - i8mm, - ite, - jsconv, - lor, - ls64, - lse, - lse128, - lse2, - lsl_fast, - mec, - mops, - mpam, - mte, - neon, - nmi, - no_bti_at_return_twice, - no_neg_immediates, - no_sve_fp_ld1r, - no_zcz_fp, - nv, - outline_atomics, - pan, - pan_rwv, - pauth, - perfmon, - predictable_select_expensive, - predres, - prfm_slc_target, - rand, - ras, - rasv2, - rcpc, - rcpc3, - rcpc_immo, - rdm, - reserve_x1, - reserve_x10, - reserve_x11, - reserve_x12, - reserve_x13, - reserve_x14, - reserve_x15, - reserve_x18, - reserve_x2, - reserve_x20, - reserve_x21, - reserve_x22, - reserve_x23, - reserve_x24, - reserve_x25, - reserve_x26, - reserve_x27, - reserve_x28, - reserve_x3, - reserve_x30, - reserve_x4, - reserve_x5, - reserve_x6, - reserve_x7, - reserve_x9, - rme, - sb, - sel2, - sha2, - sha3, - slow_misaligned_128store, - slow_paired_128, - slow_strqro_store, - sm4, - sme, - sme2, - sme2p1, - sme_f16f16, - sme_f64f64, - sme_i16i64, - spe, - spe_eef, - specres2, - specrestrict, - ssbs, - strict_align, - sve, - sve2, - sve2_aes, - sve2_bitperm, - sve2_sha3, - sve2_sm4, - sve2p1, - tagged_globals, - the, - tlb_rmi, - tme, - tpidr_el1, - tpidr_el2, - tpidr_el3, - tpidrro_el0, - tracev8_4, - trbe, - uaops, - use_experimental_zeroing_pseudos, - use_postra_scheduler, - use_reciprocal_square_root, - use_scalar_inc_vl, - v8_1a, - v8_2a, - v8_3a, - v8_4a, - v8_5a, - v8_6a, - v8_7a, - v8_8a, - v8_9a, - v8a, - v8r, - v9_1a, - v9_2a, - v9_3a, - v9_4a, - v9a, - vh, - wfxt, - xs, - zcm, - zcz, - zcz_fp_workaround, - zcz_gp, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - @setEvalBranchQuota(2000); - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.a510)] = .{ - .llvm_name = "a510", - .description = "Cortex-A510 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .fuse_adrp_add, - .fuse_aes, - .use_postra_scheduler, - }), - }; - result[@intFromEnum(Feature.a65)] = .{ - .llvm_name = "a65", - .description = "Cortex-A65 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .enable_select_opt, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_literals, - .predictable_select_expensive, - }), - }; - result[@intFromEnum(Feature.a710)] = .{ - .llvm_name = "a710", - .description = "Cortex-A710 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@intFromEnum(Feature.a76)] = .{ - .llvm_name = "a76", - .description = "Cortex-A76 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .predictable_select_expensive, - }), - }; - result[@intFromEnum(Feature.a78)] = .{ - .llvm_name = "a78", - .description = "Cortex-A78 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@intFromEnum(Feature.a78c)] = .{ - .llvm_name = "a78c", - .description = "Cortex-A78C ARM processors", - .dependencies = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .predictable_select_expensive, - .use_postra_scheduler, - }), - }; - result[@intFromEnum(Feature.aes)] = .{ - .llvm_name = "aes", - .description = "Enable AES support (FEAT_AES, FEAT_PMULL)", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.aggressive_fma)] = .{ - .llvm_name = "aggressive-fma", - .description = "Enable Aggressive FMA for floating-point.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.alternate_sextload_cvt_f32_pattern)] = .{ - .llvm_name = "alternate-sextload-cvt-f32-pattern", - .description = "Use alternative pattern for sextload convert to f32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.altnzcv)] = .{ - .llvm_name = "altnzcv", - .description = "Enable alternative NZCV format for floating point comparisons (FEAT_FlagM2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.am)] = .{ - .llvm_name = "am", - .description = "Enable v8.4-A Activity Monitors extension (FEAT_AMUv1)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.amvs)] = .{ - .llvm_name = "amvs", - .description = "Enable v8.6-A Activity Monitors Virtualization support (FEAT_AMUv1p1)", - .dependencies = featureSet(&[_]Feature{ - .am, - }), - }; - result[@intFromEnum(Feature.arith_bcc_fusion)] = .{ - .llvm_name = "arith-bcc-fusion", - .description = "CPU fuses arithmetic+bcc operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.arith_cbz_fusion)] = .{ - .llvm_name = "arith-cbz-fusion", - .description = "CPU fuses arithmetic + cbz/cbnz operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ascend_store_address)] = .{ - .llvm_name = "ascend-store-address", - .description = "Schedule vector stores by ascending address", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.b16b16)] = .{ - .llvm_name = "b16b16", - .description = "Enable SVE2.1 or SME2.1 non-widening BFloat16 to BFloat16 instructions (FEAT_B16B16)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.balance_fp_ops)] = .{ - .llvm_name = "balance-fp-ops", - .description = "balance mix of odd and even D-registers for fp multiply(-accumulate) ops", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.bf16)] = .{ - .llvm_name = "bf16", - .description = "Enable BFloat16 Extension (FEAT_BF16)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.brbe)] = .{ - .llvm_name = "brbe", - .description = "Enable Branch Record Buffer Extension (FEAT_BRBE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.bti)] = .{ - .llvm_name = "bti", - .description = "Enable Branch Target Identification (FEAT_BTI)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x10)] = .{ - .llvm_name = "call-saved-x10", - .description = "Make X10 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x11)] = .{ - .llvm_name = "call-saved-x11", - .description = "Make X11 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x12)] = .{ - .llvm_name = "call-saved-x12", - .description = "Make X12 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x13)] = .{ - .llvm_name = "call-saved-x13", - .description = "Make X13 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x14)] = .{ - .llvm_name = "call-saved-x14", - .description = "Make X14 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x15)] = .{ - .llvm_name = "call-saved-x15", - .description = "Make X15 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x18)] = .{ - .llvm_name = "call-saved-x18", - .description = "Make X18 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x8)] = .{ - .llvm_name = "call-saved-x8", - .description = "Make X8 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.call_saved_x9)] = .{ - .llvm_name = "call-saved-x9", - .description = "Make X9 callee saved.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ccdp)] = .{ - .llvm_name = "ccdp", - .description = "Enable v8.5 Cache Clean to Point of Deep Persistence (FEAT_DPB2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ccidx)] = .{ - .llvm_name = "ccidx", - .description = "Enable v8.3-A Extend of the CCSIDR number of sets (FEAT_CCIDX)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ccpp)] = .{ - .llvm_name = "ccpp", - .description = "Enable v8.2 data Cache Clean to Point of Persistence (FEAT_DPB)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.chk)] = .{ - .llvm_name = "chk", - .description = "Enable Armv8.0-A Check Feature Status Extension (FEAT_CHK)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.clrbhb)] = .{ - .llvm_name = "clrbhb", - .description = "Enable Clear BHB instruction (FEAT_CLRBHB)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cmp_bcc_fusion)] = .{ - .llvm_name = "cmp-bcc-fusion", - .description = "CPU fuses cmp+bcc operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.complxnum)] = .{ - .llvm_name = "complxnum", - .description = "Enable v8.3-A Floating-point complex number support (FEAT_FCMA)", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.contextidr_el2)] = .{ - .llvm_name = "CONTEXTIDREL2", - .description = "Enable RW operand Context ID Register (EL2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cortex_r82)] = .{ - .llvm_name = "cortex-r82", - .description = "Cortex-R82 ARM processors", - .dependencies = featureSet(&[_]Feature{ - .use_postra_scheduler, - }), - }; - result[@intFromEnum(Feature.crc)] = .{ - .llvm_name = "crc", - .description = "Enable ARMv8 CRC-32 checksum instructions (FEAT_CRC32)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crypto)] = .{ - .llvm_name = "crypto", - .description = "Enable cryptographic instructions", - .dependencies = featureSet(&[_]Feature{ - .aes, - .sha2, - }), - }; - result[@intFromEnum(Feature.cssc)] = .{ - .llvm_name = "cssc", - .description = "Enable Common Short Sequence Compression (CSSC) instructions (FEAT_CSSC)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.custom_cheap_as_move)] = .{ - .llvm_name = "custom-cheap-as-move", - .description = "Use custom handling of cheap instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.d128)] = .{ - .llvm_name = "d128", - .description = "Enable Armv9.4-A 128-bit Page Table Descriptors, System Registers and Instructions (FEAT_D128, FEAT_LVA3, FEAT_SYSREG128, FEAT_SYSINSTR128)", - .dependencies = featureSet(&[_]Feature{ - .lse128, - }), - }; - result[@intFromEnum(Feature.disable_latency_sched_heuristic)] = .{ - .llvm_name = "disable-latency-sched-heuristic", - .description = "Disable latency scheduling heuristic", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dit)] = .{ - .llvm_name = "dit", - .description = "Enable v8.4-A Data Independent Timing instructions (FEAT_DIT)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dotprod)] = .{ - .llvm_name = "dotprod", - .description = "Enable dot product support (FEAT_DotProd)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ecv)] = .{ - .llvm_name = "ecv", - .description = "Enable enhanced counter virtualization extension (FEAT_ECV)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.el2vmsa)] = .{ - .llvm_name = "el2vmsa", - .description = "Enable Exception Level 2 Virtual Memory System Architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.el3)] = .{ - .llvm_name = "el3", - .description = "Enable Exception Level 3", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.enable_select_opt)] = .{ - .llvm_name = "enable-select-opt", - .description = "Enable the select optimize pass for select loop heuristics", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ete)] = .{ - .llvm_name = "ete", - .description = "Enable Embedded Trace Extension (FEAT_ETE)", - .dependencies = featureSet(&[_]Feature{ - .trbe, - }), - }; - result[@intFromEnum(Feature.exynos_cheap_as_move)] = .{ - .llvm_name = "exynos-cheap-as-move", - .description = "Use Exynos specific handling of cheap instructions", - .dependencies = featureSet(&[_]Feature{ - .custom_cheap_as_move, - }), - }; - result[@intFromEnum(Feature.f32mm)] = .{ - .llvm_name = "f32mm", - .description = "Enable Matrix Multiply FP32 Extension (FEAT_F32MM)", - .dependencies = featureSet(&[_]Feature{ - .sve, - }), - }; - result[@intFromEnum(Feature.f64mm)] = .{ - .llvm_name = "f64mm", - .description = "Enable Matrix Multiply FP64 Extension (FEAT_F64MM)", - .dependencies = featureSet(&[_]Feature{ - .sve, - }), - }; - result[@intFromEnum(Feature.fgt)] = .{ - .llvm_name = "fgt", - .description = "Enable fine grained virtualization traps extension (FEAT_FGT)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fix_cortex_a53_835769)] = .{ - .llvm_name = "fix-cortex-a53-835769", - .description = "Mitigate Cortex-A53 Erratum 835769", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flagm)] = .{ - .llvm_name = "flagm", - .description = "Enable v8.4-A Flag Manipulation Instructions (FEAT_FlagM)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fmv)] = .{ - .llvm_name = "fmv", - .description = "Enable Function Multi Versioning support.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.force_32bit_jump_tables)] = .{ - .llvm_name = "force-32bit-jump-tables", - .description = "Force jump table entries to be 32-bits wide except at MinSize", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp16fml)] = .{ - .llvm_name = "fp16fml", - .description = "Enable FP16 FML instructions (FEAT_FHM)", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@intFromEnum(Feature.fp_armv8)] = .{ - .llvm_name = "fp-armv8", - .description = "Enable ARMv8 FP (FEAT_FP)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fptoint)] = .{ - .llvm_name = "fptoint", - .description = "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int (FEAT_FRINTTS)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fullfp16)] = .{ - .llvm_name = "fullfp16", - .description = "Full FP16 (FEAT_FP16)", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8, - }), - }; - result[@intFromEnum(Feature.fuse_address)] = .{ - .llvm_name = "fuse-address", - .description = "CPU fuses address generation and memory operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_addsub_2reg_const1)] = .{ - .llvm_name = "fuse-addsub-2reg-const1", - .description = "CPU fuses (a + b + 1) and (a - b - 1)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_adrp_add)] = .{ - .llvm_name = "fuse-adrp-add", - .description = "CPU fuses adrp+add operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_aes)] = .{ - .llvm_name = "fuse-aes", - .description = "CPU fuses AES crypto operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_arith_logic)] = .{ - .llvm_name = "fuse-arith-logic", - .description = "CPU fuses arithmetic and logic operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_crypto_eor)] = .{ - .llvm_name = "fuse-crypto-eor", - .description = "CPU fuses AES/PMULL and EOR operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_csel)] = .{ - .llvm_name = "fuse-csel", - .description = "CPU fuses conditional select operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_literals)] = .{ - .llvm_name = "fuse-literals", - .description = "CPU fuses literal generation operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gcs)] = .{ - .llvm_name = "gcs", - .description = "Enable Armv9.4-A Guarded Call Stack Extension", - .dependencies = featureSet(&[_]Feature{ - .chk, - }), - }; - result[@intFromEnum(Feature.harden_sls_blr)] = .{ - .llvm_name = "harden-sls-blr", - .description = "Harden against straight line speculation across BLR instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_nocomdat)] = .{ - .llvm_name = "harden-sls-nocomdat", - .description = "Generate thunk code for SLS mitigation in the normal text section", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_retbr)] = .{ - .llvm_name = "harden-sls-retbr", - .description = "Harden against straight line speculation across RET and BR instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hbc)] = .{ - .llvm_name = "hbc", - .description = "Enable Armv8.8-A Hinted Conditional Branches Extension (FEAT_HBC)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hcx)] = .{ - .llvm_name = "hcx", - .description = "Enable Armv8.7-A HCRX_EL2 system register (FEAT_HCX)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.i8mm)] = .{ - .llvm_name = "i8mm", - .description = "Enable Matrix Multiply Int8 Extension (FEAT_I8MM)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ite)] = .{ - .llvm_name = "ite", - .description = "Enable Armv9.4-A Instrumentation Extension FEAT_ITE", - .dependencies = featureSet(&[_]Feature{ - .ete, - }), - }; - result[@intFromEnum(Feature.jsconv)] = .{ - .llvm_name = "jsconv", - .description = "Enable v8.3-A JavaScript FP conversion instructions (FEAT_JSCVT)", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8, - }), - }; - result[@intFromEnum(Feature.lor)] = .{ - .llvm_name = "lor", - .description = "Enables ARM v8.1 Limited Ordering Regions extension (FEAT_LOR)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ls64)] = .{ - .llvm_name = "ls64", - .description = "Enable Armv8.7-A LD64B/ST64B Accelerator Extension (FEAT_LS64, FEAT_LS64_V, FEAT_LS64_ACCDATA)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lse)] = .{ - .llvm_name = "lse", - .description = "Enable ARMv8.1 Large System Extension (LSE) atomic instructions (FEAT_LSE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lse128)] = .{ - .llvm_name = "lse128", - .description = "Enable Armv9.4-A 128-bit Atomic Instructions (FEAT_LSE128)", - .dependencies = featureSet(&[_]Feature{ - .lse, - }), - }; - result[@intFromEnum(Feature.lse2)] = .{ - .llvm_name = "lse2", - .description = "Enable ARMv8.4 Large System Extension 2 (LSE2) atomicity rules (FEAT_LSE2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lsl_fast)] = .{ - .llvm_name = "lsl-fast", - .description = "CPU has a fastpath logical shift of up to 3 places", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mec)] = .{ - .llvm_name = "mec", - .description = "Enable Memory Encryption Contexts Extension", - .dependencies = featureSet(&[_]Feature{ - .rme, - }), - }; - result[@intFromEnum(Feature.mops)] = .{ - .llvm_name = "mops", - .description = "Enable Armv8.8-A memcpy and memset acceleration instructions (FEAT_MOPS)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mpam)] = .{ - .llvm_name = "mpam", - .description = "Enable v8.4-A Memory system Partitioning and Monitoring extension (FEAT_MPAM)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mte)] = .{ - .llvm_name = "mte", - .description = "Enable Memory Tagging Extension (FEAT_MTE, FEAT_MTE2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.neon)] = .{ - .llvm_name = "neon", - .description = "Enable Advanced SIMD instructions (FEAT_AdvSIMD)", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8, - }), - }; - result[@intFromEnum(Feature.nmi)] = .{ - .llvm_name = "nmi", - .description = "Enable Armv8.8-A Non-maskable Interrupts (FEAT_NMI, FEAT_GICv3_NMI)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bti_at_return_twice)] = .{ - .llvm_name = "no-bti-at-return-twice", - .description = "Don't place a BTI instruction after a return-twice", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_neg_immediates)] = .{ - .llvm_name = "no-neg-immediates", - .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_sve_fp_ld1r)] = .{ - .llvm_name = "no-sve-fp-ld1r", - .description = "Avoid using LD1RX instructions for FP", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_zcz_fp)] = .{ - .llvm_name = "no-zcz-fp", - .description = "Has no zero-cycle zeroing instructions for FP registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nv)] = .{ - .llvm_name = "nv", - .description = "Enable v8.4-A Nested Virtualization Enchancement (FEAT_NV, FEAT_NV2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.outline_atomics)] = .{ - .llvm_name = "outline-atomics", - .description = "Enable out of line atomics to support LSE instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pan)] = .{ - .llvm_name = "pan", - .description = "Enables ARM v8.1 Privileged Access-Never extension (FEAT_PAN)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pan_rwv)] = .{ - .llvm_name = "pan-rwv", - .description = "Enable v8.2 PAN s1e1R and s1e1W Variants (FEAT_PAN2)", - .dependencies = featureSet(&[_]Feature{ - .pan, - }), - }; - result[@intFromEnum(Feature.pauth)] = .{ - .llvm_name = "pauth", - .description = "Enable v8.3-A Pointer Authentication extension (FEAT_PAuth)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.perfmon)] = .{ - .llvm_name = "perfmon", - .description = "Enable Code Generation for ARMv8 PMUv3 Performance Monitors extension (FEAT_PMUv3)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.predictable_select_expensive)] = .{ - .llvm_name = "predictable-select-expensive", - .description = "Prefer likely predicted branches over selects", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.predres)] = .{ - .llvm_name = "predres", - .description = "Enable v8.5a execution and data prediction invalidation instructions (FEAT_SPECRES)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prfm_slc_target)] = .{ - .llvm_name = "prfm-slc-target", - .description = "Enable SLC target for PRFM instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rand)] = .{ - .llvm_name = "rand", - .description = "Enable Random Number generation instructions (FEAT_RNG)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ras)] = .{ - .llvm_name = "ras", - .description = "Enable ARMv8 Reliability, Availability and Serviceability Extensions (FEAT_RAS, FEAT_RASv1p1)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rasv2)] = .{ - .llvm_name = "rasv2", - .description = "Enable ARMv8.9-A Reliability, Availability and Serviceability Extensions (FEAT_RASv2)", - .dependencies = featureSet(&[_]Feature{ - .ras, - }), - }; - result[@intFromEnum(Feature.rcpc)] = .{ - .llvm_name = "rcpc", - .description = "Enable support for RCPC extension (FEAT_LRCPC)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rcpc3)] = .{ - .llvm_name = "rcpc3", - .description = "Enable Armv8.9-A RCPC instructions for A64 and Advanced SIMD and floating-point instruction set (FEAT_LRCPC3)", - .dependencies = featureSet(&[_]Feature{ - .rcpc_immo, - }), - }; - result[@intFromEnum(Feature.rcpc_immo)] = .{ - .llvm_name = "rcpc-immo", - .description = "Enable v8.4-A RCPC instructions with Immediate Offsets (FEAT_LRCPC2)", - .dependencies = featureSet(&[_]Feature{ - .rcpc, - }), - }; - result[@intFromEnum(Feature.rdm)] = .{ - .llvm_name = "rdm", - .description = "Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions (FEAT_RDM)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x1)] = .{ - .llvm_name = "reserve-x1", - .description = "Reserve X1, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x10)] = .{ - .llvm_name = "reserve-x10", - .description = "Reserve X10, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x11)] = .{ - .llvm_name = "reserve-x11", - .description = "Reserve X11, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x12)] = .{ - .llvm_name = "reserve-x12", - .description = "Reserve X12, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x13)] = .{ - .llvm_name = "reserve-x13", - .description = "Reserve X13, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x14)] = .{ - .llvm_name = "reserve-x14", - .description = "Reserve X14, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x15)] = .{ - .llvm_name = "reserve-x15", - .description = "Reserve X15, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x18)] = .{ - .llvm_name = "reserve-x18", - .description = "Reserve X18, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x2)] = .{ - .llvm_name = "reserve-x2", - .description = "Reserve X2, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x20)] = .{ - .llvm_name = "reserve-x20", - .description = "Reserve X20, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x21)] = .{ - .llvm_name = "reserve-x21", - .description = "Reserve X21, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x22)] = .{ - .llvm_name = "reserve-x22", - .description = "Reserve X22, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x23)] = .{ - .llvm_name = "reserve-x23", - .description = "Reserve X23, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x24)] = .{ - .llvm_name = "reserve-x24", - .description = "Reserve X24, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x25)] = .{ - .llvm_name = "reserve-x25", - .description = "Reserve X25, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x26)] = .{ - .llvm_name = "reserve-x26", - .description = "Reserve X26, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x27)] = .{ - .llvm_name = "reserve-x27", - .description = "Reserve X27, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x28)] = .{ - .llvm_name = "reserve-x28", - .description = "Reserve X28, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x3)] = .{ - .llvm_name = "reserve-x3", - .description = "Reserve X3, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x30)] = .{ - .llvm_name = "reserve-x30", - .description = "Reserve X30, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x4)] = .{ - .llvm_name = "reserve-x4", - .description = "Reserve X4, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x5)] = .{ - .llvm_name = "reserve-x5", - .description = "Reserve X5, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x6)] = .{ - .llvm_name = "reserve-x6", - .description = "Reserve X6, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x7)] = .{ - .llvm_name = "reserve-x7", - .description = "Reserve X7, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x9)] = .{ - .llvm_name = "reserve-x9", - .description = "Reserve X9, making it unavailable as a GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rme)] = .{ - .llvm_name = "rme", - .description = "Enable Realm Management Extension (FEAT_RME)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sb)] = .{ - .llvm_name = "sb", - .description = "Enable v8.5 Speculation Barrier (FEAT_SB)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sel2)] = .{ - .llvm_name = "sel2", - .description = "Enable v8.4-A Secure Exception Level 2 extension (FEAT_SEL2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sha2)] = .{ - .llvm_name = "sha2", - .description = "Enable SHA1 and SHA256 support (FEAT_SHA1, FEAT_SHA256)", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.sha3)] = .{ - .llvm_name = "sha3", - .description = "Enable SHA512 and SHA3 support (FEAT_SHA3, FEAT_SHA512)", - .dependencies = featureSet(&[_]Feature{ - .sha2, - }), - }; - result[@intFromEnum(Feature.slow_misaligned_128store)] = .{ - .llvm_name = "slow-misaligned-128store", - .description = "Misaligned 128 bit stores are slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_paired_128)] = .{ - .llvm_name = "slow-paired-128", - .description = "Paired 128 bit loads and stores are slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_strqro_store)] = .{ - .llvm_name = "slow-strqro-store", - .description = "STR of Q register with register offset is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm4)] = .{ - .llvm_name = "sm4", - .description = "Enable SM3 and SM4 support (FEAT_SM4, FEAT_SM3)", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.sme)] = .{ - .llvm_name = "sme", - .description = "Enable Scalable Matrix Extension (SME) (FEAT_SME)", - .dependencies = featureSet(&[_]Feature{ - .bf16, - .use_scalar_inc_vl, - }), - }; - result[@intFromEnum(Feature.sme2)] = .{ - .llvm_name = "sme2", - .description = "Enable Scalable Matrix Extension 2 (SME2) instructions", - .dependencies = featureSet(&[_]Feature{ - .sme, - }), - }; - result[@intFromEnum(Feature.sme2p1)] = .{ - .llvm_name = "sme2p1", - .description = "Enable Scalable Matrix Extension 2.1 (FEAT_SME2p1) instructions", - .dependencies = featureSet(&[_]Feature{ - .sme2, - }), - }; - result[@intFromEnum(Feature.sme_f16f16)] = .{ - .llvm_name = "sme-f16f16", - .description = "Enable SME2.1 non-widening Float16 instructions (FEAT_SME_F16F16)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sme_f64f64)] = .{ - .llvm_name = "sme-f64f64", - .description = "Enable Scalable Matrix Extension (SME) F64F64 instructions (FEAT_SME_F64F64)", - .dependencies = featureSet(&[_]Feature{ - .sme, - }), - }; - result[@intFromEnum(Feature.sme_i16i64)] = .{ - .llvm_name = "sme-i16i64", - .description = "Enable Scalable Matrix Extension (SME) I16I64 instructions (FEAT_SME_I16I64)", - .dependencies = featureSet(&[_]Feature{ - .sme, - }), - }; - result[@intFromEnum(Feature.spe)] = .{ - .llvm_name = "spe", - .description = "Enable Statistical Profiling extension (FEAT_SPE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.spe_eef)] = .{ - .llvm_name = "spe-eef", - .description = "Enable extra register in the Statistical Profiling Extension (FEAT_SPEv1p2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.specres2)] = .{ - .llvm_name = "specres2", - .description = "Enable Speculation Restriction Instruction (FEAT_SPECRES2)", - .dependencies = featureSet(&[_]Feature{ - .predres, - }), - }; - result[@intFromEnum(Feature.specrestrict)] = .{ - .llvm_name = "specrestrict", - .description = "Enable architectural speculation restriction (FEAT_CSV2_2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ssbs)] = .{ - .llvm_name = "ssbs", - .description = "Enable Speculative Store Bypass Safe bit (FEAT_SSBS, FEAT_SSBS2)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.strict_align)] = .{ - .llvm_name = "strict-align", - .description = "Disallow all unaligned memory access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sve)] = .{ - .llvm_name = "sve", - .description = "Enable Scalable Vector Extension (SVE) instructions (FEAT_SVE)", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@intFromEnum(Feature.sve2)] = .{ - .llvm_name = "sve2", - .description = "Enable Scalable Vector Extension 2 (SVE2) instructions (FEAT_SVE2)", - .dependencies = featureSet(&[_]Feature{ - .sve, - .use_scalar_inc_vl, - }), - }; - result[@intFromEnum(Feature.sve2_aes)] = .{ - .llvm_name = "sve2-aes", - .description = "Enable AES SVE2 instructions (FEAT_SVE_AES, FEAT_SVE_PMULL128)", - .dependencies = featureSet(&[_]Feature{ - .aes, - .sve2, - }), - }; - result[@intFromEnum(Feature.sve2_bitperm)] = .{ - .llvm_name = "sve2-bitperm", - .description = "Enable bit permutation SVE2 instructions (FEAT_SVE_BitPerm)", - .dependencies = featureSet(&[_]Feature{ - .sve2, - }), - }; - result[@intFromEnum(Feature.sve2_sha3)] = .{ - .llvm_name = "sve2-sha3", - .description = "Enable SHA3 SVE2 instructions (FEAT_SVE_SHA3)", - .dependencies = featureSet(&[_]Feature{ - .sha3, - .sve2, - }), - }; - result[@intFromEnum(Feature.sve2_sm4)] = .{ - .llvm_name = "sve2-sm4", - .description = "Enable SM4 SVE2 instructions (FEAT_SVE_SM4)", - .dependencies = featureSet(&[_]Feature{ - .sm4, - .sve2, - }), - }; - result[@intFromEnum(Feature.sve2p1)] = .{ - .llvm_name = "sve2p1", - .description = "Enable Scalable Vector Extension 2.1 instructions", - .dependencies = featureSet(&[_]Feature{ - .sve2, - }), - }; - result[@intFromEnum(Feature.tagged_globals)] = .{ - .llvm_name = "tagged-globals", - .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.the)] = .{ - .llvm_name = "the", - .description = "Enable Armv8.9-A Translation Hardening Extension (FEAT_THE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tlb_rmi)] = .{ - .llvm_name = "tlb-rmi", - .description = "Enable v8.4-A TLB Range and Maintenance Instructions (FEAT_TLBIOS, FEAT_TLBIRANGE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tme)] = .{ - .llvm_name = "tme", - .description = "Enable Transactional Memory Extension (FEAT_TME)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tpidr_el1)] = .{ - .llvm_name = "tpidr-el1", - .description = "Permit use of TPIDR_EL1 for the TLS base", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tpidr_el2)] = .{ - .llvm_name = "tpidr-el2", - .description = "Permit use of TPIDR_EL2 for the TLS base", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tpidr_el3)] = .{ - .llvm_name = "tpidr-el3", - .description = "Permit use of TPIDR_EL3 for the TLS base", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tpidrro_el0)] = .{ - .llvm_name = "tpidrro-el0", - .description = "Permit use of TPIDRRO_EL0 for the TLS base", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tracev8_4)] = .{ - .llvm_name = "tracev8.4", - .description = "Enable v8.4-A Trace extension (FEAT_TRF)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.trbe)] = .{ - .llvm_name = "trbe", - .description = "Enable Trace Buffer Extension (FEAT_TRBE)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.uaops)] = .{ - .llvm_name = "uaops", - .description = "Enable v8.2 UAO PState (FEAT_UAO)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_experimental_zeroing_pseudos)] = .{ - .llvm_name = "use-experimental-zeroing-pseudos", - .description = "Hint to the compiler that the MOVPRFX instruction is merged with destructive operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_postra_scheduler)] = .{ - .llvm_name = "use-postra-scheduler", - .description = "Schedule again after register allocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_reciprocal_square_root)] = .{ - .llvm_name = "use-reciprocal-square-root", - .description = "Use the reciprocal square root approximation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_scalar_inc_vl)] = .{ - .llvm_name = "use-scalar-inc-vl", - .description = "Prefer inc/dec over add+cnt", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v8_1a)] = .{ - .llvm_name = "v8.1a", - .description = "Support ARM v8.1a instructions", - .dependencies = featureSet(&[_]Feature{ - .crc, - .lor, - .lse, - .pan, - .rdm, - .v8a, - .vh, - }), - }; - result[@intFromEnum(Feature.v8_2a)] = .{ - .llvm_name = "v8.2a", - .description = "Support ARM v8.2a instructions", - .dependencies = featureSet(&[_]Feature{ - .ccpp, - .pan_rwv, - .ras, - .uaops, - .v8_1a, - }), - }; - result[@intFromEnum(Feature.v8_3a)] = .{ - .llvm_name = "v8.3a", - .description = "Support ARM v8.3a instructions", - .dependencies = featureSet(&[_]Feature{ - .ccidx, - .complxnum, - .jsconv, - .pauth, - .rcpc, - .v8_2a, - }), - }; - result[@intFromEnum(Feature.v8_4a)] = .{ - .llvm_name = "v8.4a", - .description = "Support ARM v8.4a instructions", - .dependencies = featureSet(&[_]Feature{ - .am, - .dit, - .dotprod, - .flagm, - .lse2, - .mpam, - .nv, - .rcpc_immo, - .sel2, - .tlb_rmi, - .tracev8_4, - .v8_3a, - }), - }; - result[@intFromEnum(Feature.v8_5a)] = .{ - .llvm_name = "v8.5a", - .description = "Support ARM v8.5a instructions", - .dependencies = featureSet(&[_]Feature{ - .altnzcv, - .bti, - .ccdp, - .fptoint, - .predres, - .sb, - .specrestrict, - .ssbs, - .v8_4a, - }), - }; - result[@intFromEnum(Feature.v8_6a)] = .{ - .llvm_name = "v8.6a", - .description = "Support ARM v8.6a instructions", - .dependencies = featureSet(&[_]Feature{ - .amvs, - .bf16, - .ecv, - .fgt, - .i8mm, - .v8_5a, - }), - }; - result[@intFromEnum(Feature.v8_7a)] = .{ - .llvm_name = "v8.7a", - .description = "Support ARM v8.7a instructions", - .dependencies = featureSet(&[_]Feature{ - .hcx, - .v8_6a, - .wfxt, - .xs, - }), - }; - result[@intFromEnum(Feature.v8_8a)] = .{ - .llvm_name = "v8.8a", - .description = "Support ARM v8.8a instructions", - .dependencies = featureSet(&[_]Feature{ - .hbc, - .mops, - .nmi, - .v8_7a, - }), - }; - result[@intFromEnum(Feature.v8_9a)] = .{ - .llvm_name = "v8.9a", - .description = "Support ARM v8.9a instructions", - .dependencies = featureSet(&[_]Feature{ - .chk, - .clrbhb, - .cssc, - .prfm_slc_target, - .rasv2, - .specres2, - .v8_8a, - }), - }; - result[@intFromEnum(Feature.v8a)] = .{ - .llvm_name = "v8a", - .description = "Support ARM v8.0a instructions", - .dependencies = featureSet(&[_]Feature{ - .el2vmsa, - .el3, - .neon, - }), - }; - result[@intFromEnum(Feature.v8r)] = .{ - .llvm_name = "v8r", - .description = "Support ARM v8r instructions", - .dependencies = featureSet(&[_]Feature{ - .ccidx, - .ccpp, - .complxnum, - .contextidr_el2, - .crc, - .dit, - .dotprod, - .flagm, - .jsconv, - .lse, - .pan_rwv, - .pauth, - .ras, - .rcpc_immo, - .rdm, - .sel2, - .specrestrict, - .tlb_rmi, - .tracev8_4, - .uaops, - }), - }; - result[@intFromEnum(Feature.v9_1a)] = .{ - .llvm_name = "v9.1a", - .description = "Support ARM v9.1a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_6a, - .v9a, - }), - }; - result[@intFromEnum(Feature.v9_2a)] = .{ - .llvm_name = "v9.2a", - .description = "Support ARM v9.2a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_7a, - .v9_1a, - }), - }; - result[@intFromEnum(Feature.v9_3a)] = .{ - .llvm_name = "v9.3a", - .description = "Support ARM v9.3a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_8a, - .v9_2a, - }), - }; - result[@intFromEnum(Feature.v9_4a)] = .{ - .llvm_name = "v9.4a", - .description = "Support ARM v9.4a instructions", - .dependencies = featureSet(&[_]Feature{ - .v8_9a, - .v9_3a, - }), - }; - result[@intFromEnum(Feature.v9a)] = .{ - .llvm_name = "v9a", - .description = "Support ARM v9a instructions", - .dependencies = featureSet(&[_]Feature{ - .mec, - .sve2, - .v8_5a, - }), - }; - result[@intFromEnum(Feature.vh)] = .{ - .llvm_name = "vh", - .description = "Enables ARM v8.1 Virtual Host extension (FEAT_VHE)", - .dependencies = featureSet(&[_]Feature{ - .contextidr_el2, - }), - }; - result[@intFromEnum(Feature.wfxt)] = .{ - .llvm_name = "wfxt", - .description = "Enable Armv8.7-A WFET and WFIT instruction (FEAT_WFxT)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xs)] = .{ - .llvm_name = "xs", - .description = "Enable Armv8.7-A limited-TLB-maintenance instruction (FEAT_XS)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zcm)] = .{ - .llvm_name = "zcm", - .description = "Has zero-cycle register moves", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zcz)] = .{ - .llvm_name = "zcz", - .description = "Has zero-cycle zeroing instructions", - .dependencies = featureSet(&[_]Feature{ - .zcz_gp, - }), - }; - result[@intFromEnum(Feature.zcz_fp_workaround)] = .{ - .llvm_name = "zcz-fp-workaround", - .description = "The zero-cycle floating-point zeroing instruction has a bug", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zcz_gp)] = .{ - .llvm_name = "zcz-gp", - .description = "Has zero-cycle zeroing instructions for generic registers", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const a64fx = CpuModel{ - .name = "a64fx", - .llvm_name = "a64fx", - .features = featureSet(&[_]Feature{ - .aggressive_fma, - .arith_bcc_fusion, - .complxnum, - .perfmon, - .predictable_select_expensive, - .sha2, - .sve, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const ampere1 = CpuModel{ - .name = "ampere1", - .llvm_name = "ampere1", - .features = featureSet(&[_]Feature{ - .aes, - .aggressive_fma, - .arith_bcc_fusion, - .cmp_bcc_fusion, - .fuse_address, - .fuse_aes, - .fuse_literals, - .lsl_fast, - .perfmon, - .rand, - .sha3, - .use_postra_scheduler, - .v8_6a, - }), - }; - pub const ampere1a = CpuModel{ - .name = "ampere1a", - .llvm_name = "ampere1a", - .features = featureSet(&[_]Feature{ - .aes, - .aggressive_fma, - .arith_bcc_fusion, - .cmp_bcc_fusion, - .fuse_address, - .fuse_aes, - .fuse_literals, - .lsl_fast, - .mte, - .perfmon, - .rand, - .sha3, - .sm4, - .use_postra_scheduler, - .v8_6a, - }), - }; - pub const apple_a10 = CpuModel{ - .name = "apple_a10", - .llvm_name = "apple-a10", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crc, - .crypto, - .disable_latency_sched_heuristic, - .fuse_aes, - .fuse_crypto_eor, - .lor, - .pan, - .perfmon, - .rdm, - .v8a, - .vh, - .zcm, - .zcz, - }), - }; - pub const apple_a11 = CpuModel{ - .name = "apple_a11", - .llvm_name = "apple-a11", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fullfp16, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8_2a, - .zcm, - .zcz, - }), - }; - pub const apple_a12 = CpuModel{ - .name = "apple_a12", - .llvm_name = "apple-a12", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fullfp16, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8_3a, - .zcm, - .zcz, - }), - }; - pub const apple_a13 = CpuModel{ - .name = "apple_a13", - .llvm_name = "apple-a13", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .sha3, - .v8_4a, - .zcm, - .zcz, - }), - }; - pub const apple_a14 = CpuModel{ - .name = "apple_a14", - .llvm_name = "apple-a14", - .features = featureSet(&[_]Feature{ - .aggressive_fma, - .alternate_sextload_cvt_f32_pattern, - .altnzcv, - .arith_bcc_fusion, - .arith_cbz_fusion, - .ccdp, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fptoint, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .perfmon, - .predres, - .sb, - .sha3, - .specrestrict, - .ssbs, - .v8_4a, - .zcm, - .zcz, - }), - }; - pub const apple_a15 = CpuModel{ - .name = "apple_a15", - .llvm_name = "apple-a15", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fuse_address, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .perfmon, - .sha3, - .v8_6a, - .zcm, - .zcz, - }), - }; - pub const apple_a16 = CpuModel{ - .name = "apple_a16", - .llvm_name = "apple-a16", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fuse_address, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .hcx, - .perfmon, - .sha3, - .v8_6a, - .zcm, - .zcz, - }), - }; - pub const apple_a7 = CpuModel{ - .name = "apple_a7", - .llvm_name = "apple-a7", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8a, - .zcm, - .zcz, - .zcz_fp_workaround, - }), - }; - pub const apple_a8 = CpuModel{ - .name = "apple_a8", - .llvm_name = "apple-a8", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8a, - .zcm, - .zcz, - .zcz_fp_workaround, - }), - }; - pub const apple_a9 = CpuModel{ - .name = "apple_a9", - .llvm_name = "apple-a9", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8a, - .zcm, - .zcz, - .zcz_fp_workaround, - }), - }; - pub const apple_latest = CpuModel{ - .name = "apple_latest", - .llvm_name = "apple-latest", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fuse_address, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .hcx, - .perfmon, - .sha3, - .v8_6a, - .zcm, - .zcz, - }), - }; - pub const apple_m1 = CpuModel{ - .name = "apple_m1", - .llvm_name = "apple-m1", - .features = featureSet(&[_]Feature{ - .aggressive_fma, - .alternate_sextload_cvt_f32_pattern, - .altnzcv, - .arith_bcc_fusion, - .arith_cbz_fusion, - .ccdp, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fptoint, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .perfmon, - .predres, - .sb, - .sha3, - .specrestrict, - .ssbs, - .v8_4a, - .zcm, - .zcz, - }), - }; - pub const apple_m2 = CpuModel{ - .name = "apple_m2", - .llvm_name = "apple-m2", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fp16fml, - .fuse_address, - .fuse_aes, - .fuse_arith_logic, - .fuse_crypto_eor, - .fuse_csel, - .fuse_literals, - .perfmon, - .sha3, - .v8_6a, - .zcm, - .zcz, - }), - }; - pub const apple_s4 = CpuModel{ - .name = "apple_s4", - .llvm_name = "apple-s4", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fullfp16, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8_3a, - .zcm, - .zcz, - }), - }; - pub const apple_s5 = CpuModel{ - .name = "apple_s5", - .llvm_name = "apple-s5", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fullfp16, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8_3a, - .zcm, - .zcz, - }), - }; - pub const carmel = CpuModel{ - .name = "carmel", - .llvm_name = "carmel", - .features = featureSet(&[_]Feature{ - .crypto, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a34 = CpuModel{ - .name = "cortex_a34", - .llvm_name = "cortex-a34", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .v8a, - }), - }; - pub const cortex_a35 = CpuModel{ - .name = "cortex_a35", - .llvm_name = "cortex-a35", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .v8a, - }), - }; - pub const cortex_a510 = CpuModel{ - .name = "cortex_a510", - .llvm_name = "cortex-a510", - .features = featureSet(&[_]Feature{ - .a510, - .bf16, - .ete, - .fp16fml, - .i8mm, - .mte, - .perfmon, - .sve2_bitperm, - .v9a, - }), - }; - pub const cortex_a53 = CpuModel{ - .name = "cortex_a53", - .llvm_name = "cortex-a53", - .features = featureSet(&[_]Feature{ - .balance_fp_ops, - .crc, - .crypto, - .custom_cheap_as_move, - .fuse_adrp_add, - .fuse_aes, - .perfmon, - .use_postra_scheduler, - .v8a, - }), - }; - pub const cortex_a55 = CpuModel{ - .name = "cortex_a55", - .llvm_name = "cortex-a55", - .features = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .fullfp16, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .perfmon, - .rcpc, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const cortex_a57 = CpuModel{ - .name = "cortex_a57", - .llvm_name = "cortex-a57", - .features = featureSet(&[_]Feature{ - .balance_fp_ops, - .crc, - .crypto, - .custom_cheap_as_move, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .fuse_literals, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const cortex_a65 = CpuModel{ - .name = "cortex_a65", - .llvm_name = "cortex-a65", - .features = featureSet(&[_]Feature{ - .a65, - .crypto, - .dotprod, - .fullfp16, - .perfmon, - .rcpc, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a65ae = CpuModel{ - .name = "cortex_a65ae", - .llvm_name = "cortex-a65ae", - .features = featureSet(&[_]Feature{ - .a65, - .crypto, - .dotprod, - .fullfp16, - .perfmon, - .rcpc, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a710 = CpuModel{ - .name = "cortex_a710", - .llvm_name = "cortex-a710", - .features = featureSet(&[_]Feature{ - .a710, - .bf16, - .ete, - .fp16fml, - .i8mm, - .mte, - .perfmon, - .sve2_bitperm, - .v9a, - }), - }; - pub const cortex_a715 = CpuModel{ - .name = "cortex_a715", - .llvm_name = "cortex-a715", - .features = featureSet(&[_]Feature{ - .bf16, - .cmp_bcc_fusion, - .enable_select_opt, - .ete, - .fp16fml, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .mte, - .perfmon, - .predictable_select_expensive, - .spe, - .sve2_bitperm, - .use_postra_scheduler, - .v9a, - }), - }; - pub const cortex_a72 = CpuModel{ - .name = "cortex_a72", - .llvm_name = "cortex-a72", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .fuse_literals, - .perfmon, - .predictable_select_expensive, - .v8a, - }), - }; - pub const cortex_a73 = CpuModel{ - .name = "cortex_a73", - .llvm_name = "cortex-a73", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .enable_select_opt, - .fuse_adrp_add, - .fuse_aes, - .perfmon, - .predictable_select_expensive, - .v8a, - }), - }; - pub const cortex_a75 = CpuModel{ - .name = "cortex_a75", - .llvm_name = "cortex-a75", - .features = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .enable_select_opt, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .perfmon, - .predictable_select_expensive, - .rcpc, - .v8_2a, - }), - }; - pub const cortex_a76 = CpuModel{ - .name = "cortex_a76", - .llvm_name = "cortex-a76", - .features = featureSet(&[_]Feature{ - .a76, - .crypto, - .dotprod, - .fullfp16, - .perfmon, - .rcpc, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a76ae = CpuModel{ - .name = "cortex_a76ae", - .llvm_name = "cortex-a76ae", - .features = featureSet(&[_]Feature{ - .a76, - .crypto, - .dotprod, - .fullfp16, - .perfmon, - .rcpc, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a77 = CpuModel{ - .name = "cortex_a77", - .llvm_name = "cortex-a77", - .features = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .crypto, - .dotprod, - .enable_select_opt, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .rcpc, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a78 = CpuModel{ - .name = "cortex_a78", - .llvm_name = "cortex-a78", - .features = featureSet(&[_]Feature{ - .a78, - .crypto, - .dotprod, - .fullfp16, - .perfmon, - .rcpc, - .spe, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_a78c = CpuModel{ - .name = "cortex_a78c", - .llvm_name = "cortex-a78c", - .features = featureSet(&[_]Feature{ - .a78c, - .crypto, - .dotprod, - .flagm, - .fp16fml, - .pauth, - .perfmon, - .rcpc, - .spe, - .ssbs, - .v8_2a, - }), - }; - pub const cortex_r82 = CpuModel{ - .name = "cortex_r82", - .llvm_name = "cortex-r82", - .features = featureSet(&[_]Feature{ - .cortex_r82, - .fp16fml, - .perfmon, - .predres, - .sb, - .ssbs, - .v8r, - }), - }; - pub const cortex_x1 = CpuModel{ - .name = "cortex_x1", - .llvm_name = "cortex-x1", - .features = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .crypto, - .dotprod, - .enable_select_opt, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .rcpc, - .spe, - .ssbs, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const cortex_x1c = CpuModel{ - .name = "cortex_x1c", - .llvm_name = "cortex-x1c", - .features = featureSet(&[_]Feature{ - .cmp_bcc_fusion, - .crypto, - .dotprod, - .enable_select_opt, - .flagm, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .lse2, - .lsl_fast, - .pauth, - .perfmon, - .predictable_select_expensive, - .rcpc_immo, - .spe, - .ssbs, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const cortex_x2 = CpuModel{ - .name = "cortex_x2", - .llvm_name = "cortex-x2", - .features = featureSet(&[_]Feature{ - .bf16, - .cmp_bcc_fusion, - .enable_select_opt, - .ete, - .fp16fml, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .mte, - .perfmon, - .predictable_select_expensive, - .sve2_bitperm, - .use_postra_scheduler, - .v9a, - }), - }; - pub const cortex_x3 = CpuModel{ - .name = "cortex_x3", - .llvm_name = "cortex-x3", - .features = featureSet(&[_]Feature{ - .bf16, - .enable_select_opt, - .ete, - .fp16fml, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .mte, - .perfmon, - .predictable_select_expensive, - .spe, - .sve2_bitperm, - .use_postra_scheduler, - .v9a, - }), - }; - pub const cyclone = CpuModel{ - .name = "cyclone", - .llvm_name = "cyclone", - .features = featureSet(&[_]Feature{ - .alternate_sextload_cvt_f32_pattern, - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .disable_latency_sched_heuristic, - .fuse_aes, - .fuse_crypto_eor, - .perfmon, - .v8a, - .zcm, - .zcz, - .zcz_fp_workaround, - }), - }; - pub const emag = CpuModel{ - .name = "emag", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .v8a, - }), - }; - pub const exynos_m1 = CpuModel{ - .name = "exynos_m1", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_aes, - .perfmon, - .slow_misaligned_128store, - .slow_paired_128, - .use_postra_scheduler, - .use_reciprocal_square_root, - .v8a, - }), - }; - pub const exynos_m2 = CpuModel{ - .name = "exynos_m2", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_aes, - .perfmon, - .slow_misaligned_128store, - .slow_paired_128, - .use_postra_scheduler, - .v8a, - }), - }; - pub const exynos_m3 = CpuModel{ - .name = "exynos_m3", - .llvm_name = "exynos-m3", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_csel, - .fuse_literals, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const exynos_m4 = CpuModel{ - .name = "exynos_m4", - .llvm_name = "exynos-m4", - .features = featureSet(&[_]Feature{ - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .dotprod, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fullfp16, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_arith_logic, - .fuse_csel, - .fuse_literals, - .lsl_fast, - .perfmon, - .use_postra_scheduler, - .v8_2a, - .zcz, - }), - }; - pub const exynos_m5 = CpuModel{ - .name = "exynos_m5", - .llvm_name = "exynos-m5", - .features = featureSet(&[_]Feature{ - .arith_bcc_fusion, - .arith_cbz_fusion, - .crypto, - .dotprod, - .exynos_cheap_as_move, - .force_32bit_jump_tables, - .fullfp16, - .fuse_address, - .fuse_adrp_add, - .fuse_aes, - .fuse_arith_logic, - .fuse_csel, - .fuse_literals, - .lsl_fast, - .perfmon, - .use_postra_scheduler, - .v8_2a, - .zcz, - }), - }; - pub const falkor = CpuModel{ - .name = "falkor", - .llvm_name = "falkor", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .custom_cheap_as_move, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .rdm, - .slow_strqro_store, - .use_postra_scheduler, - .v8a, - .zcz, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .enable_select_opt, - .ete, - .fuse_adrp_add, - .fuse_aes, - .neon, - .use_postra_scheduler, - }), - }; - pub const kryo = CpuModel{ - .name = "kryo", - .llvm_name = "kryo", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .custom_cheap_as_move, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - .zcz, - }), - }; - pub const neoverse_512tvb = CpuModel{ - .name = "neoverse_512tvb", - .llvm_name = "neoverse-512tvb", - .features = featureSet(&[_]Feature{ - .bf16, - .ccdp, - .crypto, - .enable_select_opt, - .fp16fml, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .rand, - .spe, - .ssbs, - .sve, - .use_postra_scheduler, - .v8_4a, - }), - }; - pub const neoverse_e1 = CpuModel{ - .name = "neoverse_e1", - .llvm_name = "neoverse-e1", - .features = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .perfmon, - .rcpc, - .ssbs, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const neoverse_n1 = CpuModel{ - .name = "neoverse_n1", - .llvm_name = "neoverse-n1", - .features = featureSet(&[_]Feature{ - .crypto, - .dotprod, - .enable_select_opt, - .fullfp16, - .fuse_adrp_add, - .fuse_aes, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .rcpc, - .spe, - .ssbs, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const neoverse_n2 = CpuModel{ - .name = "neoverse_n2", - .llvm_name = "neoverse-n2", - .features = featureSet(&[_]Feature{ - .bf16, - .crypto, - .enable_select_opt, - .ete, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .mte, - .perfmon, - .predictable_select_expensive, - .sve2_bitperm, - .use_postra_scheduler, - .v8_5a, - }), - }; - pub const neoverse_v1 = CpuModel{ - .name = "neoverse_v1", - .llvm_name = "neoverse-v1", - .features = featureSet(&[_]Feature{ - .bf16, - .ccdp, - .crypto, - .enable_select_opt, - .fp16fml, - .fuse_adrp_add, - .fuse_aes, - .i8mm, - .lsl_fast, - .no_sve_fp_ld1r, - .perfmon, - .predictable_select_expensive, - .rand, - .spe, - .ssbs, - .sve, - .use_postra_scheduler, - .v8_4a, - }), - }; - pub const neoverse_v2 = CpuModel{ - .name = "neoverse_v2", - .llvm_name = "neoverse-v2", - .features = featureSet(&[_]Feature{ - .bf16, - .enable_select_opt, - .ete, - .fp16fml, - .fuse_aes, - .i8mm, - .lsl_fast, - .mte, - .perfmon, - .predictable_select_expensive, - .rand, - .spe, - .sve2_bitperm, - .use_postra_scheduler, - .v9a, - }), - }; - pub const saphira = CpuModel{ - .name = "saphira", - .llvm_name = "saphira", - .features = featureSet(&[_]Feature{ - .crypto, - .custom_cheap_as_move, - .lsl_fast, - .perfmon, - .predictable_select_expensive, - .spe, - .use_postra_scheduler, - .v8_4a, - .zcz, - }), - }; - pub const thunderx = CpuModel{ - .name = "thunderx", - .llvm_name = "thunderx", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const thunderx2t99 = CpuModel{ - .name = "thunderx2t99", - .llvm_name = "thunderx2t99", - .features = featureSet(&[_]Feature{ - .aggressive_fma, - .arith_bcc_fusion, - .crypto, - .predictable_select_expensive, - .use_postra_scheduler, - .v8_1a, - }), - }; - pub const thunderx3t110 = CpuModel{ - .name = "thunderx3t110", - .llvm_name = "thunderx3t110", - .features = featureSet(&[_]Feature{ - .aggressive_fma, - .arith_bcc_fusion, - .balance_fp_ops, - .crypto, - .perfmon, - .predictable_select_expensive, - .strict_align, - .use_postra_scheduler, - .v8_3a, - }), - }; - pub const thunderxt81 = CpuModel{ - .name = "thunderxt81", - .llvm_name = "thunderxt81", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const thunderxt83 = CpuModel{ - .name = "thunderxt83", - .llvm_name = "thunderxt83", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const thunderxt88 = CpuModel{ - .name = "thunderxt88", - .llvm_name = "thunderxt88", - .features = featureSet(&[_]Feature{ - .crc, - .crypto, - .perfmon, - .predictable_select_expensive, - .use_postra_scheduler, - .v8a, - }), - }; - pub const tsv110 = CpuModel{ - .name = "tsv110", - .llvm_name = "tsv110", - .features = featureSet(&[_]Feature{ - .crypto, - .custom_cheap_as_move, - .dotprod, - .fp16fml, - .fuse_aes, - .perfmon, - .spe, - .use_postra_scheduler, - .v8_2a, - }), - }; - pub const xgene1 = CpuModel{ - .name = "xgene1", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .perfmon, - .v8a, - }), - }; -}; diff --git a/lib/std/target/amdgpu.zig b/lib/std/target/amdgpu.zig deleted file mode 100644 index 012f652088a0d74236e640d15e3490cdd4abaa89..0000000000000000000000000000000000000000 --- a/lib/std/target/amdgpu.zig +++ /dev/null @@ -1,2153 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"16_bit_insts", - a16, - add_no_carry_insts, - aperture_regs, - architected_flat_scratch, - architected_sgprs, - atomic_buffer_global_pk_add_f16_insts, - atomic_buffer_global_pk_add_f16_no_rtn_insts, - atomic_ds_pk_add_16_insts, - atomic_fadd_no_rtn_insts, - atomic_fadd_rtn_insts, - atomic_flat_pk_add_16_insts, - atomic_global_pk_add_bf16_inst, - auto_waitcnt_before_barrier, - back_off_barrier, - ci_insts, - cumode, - dl_insts, - dot10_insts, - dot1_insts, - dot2_insts, - dot3_insts, - dot4_insts, - dot5_insts, - dot6_insts, - dot7_insts, - dot8_insts, - dot9_insts, - dpp, - dpp8, - dpp_64bit, - ds128, - ds_src2_insts, - extended_image_insts, - fast_denormal_f32, - fast_fmaf, - flat_address_space, - flat_atomic_fadd_f32_inst, - flat_for_global, - flat_global_insts, - flat_inst_offsets, - flat_scratch, - flat_scratch_insts, - flat_segment_offset_bug, - fma_mix_insts, - fmacf64_inst, - fmaf, - force_store_sc0_sc1, - fp64, - fp8_insts, - full_rate_64_ops, - g16, - gcn3_encoding, - get_wave_id_inst, - gfx10, - gfx10_3_insts, - gfx10_a_encoding, - gfx10_b_encoding, - gfx10_insts, - gfx11, - gfx11_full_vgprs, - gfx11_insts, - gfx7_gfx8_gfx9_insts, - gfx8_insts, - gfx9, - gfx90a_insts, - gfx940_insts, - gfx9_insts, - half_rate_64_ops, - image_gather4_d16_bug, - image_insts, - image_store_d16_bug, - inst_fwd_prefetch_bug, - int_clamp_insts, - inv_2pi_inline_imm, - lds_branch_vmem_war_hazard, - lds_misaligned_bug, - ldsbankcount16, - ldsbankcount32, - load_store_opt, - localmemorysize32768, - localmemorysize65536, - mad_intra_fwd_bug, - mad_mac_f32_insts, - mad_mix_insts, - mai_insts, - max_private_element_size_16, - max_private_element_size_4, - max_private_element_size_8, - mfma_inline_literal_bug, - mimg_r128, - movrel, - negative_scratch_offset_bug, - negative_unaligned_scratch_offset_bug, - no_data_dep_hazard, - no_sdst_cmpx, - nsa_clause_bug, - nsa_encoding, - nsa_to_vmem_bug, - offset_3f_bug, - packed_fp32_ops, - packed_tid, - partial_nsa_encoding, - pk_fmac_f16_inst, - promote_alloca, - prt_strict_null, - r128_a16, - s_memrealtime, - s_memtime_inst, - scalar_atomics, - scalar_flat_scratch_insts, - scalar_stores, - sdwa, - sdwa_mav, - sdwa_omod, - sdwa_out_mods_vopc, - sdwa_scalar, - sdwa_sdst, - sea_islands, - sgpr_init_bug, - shader_cycles_register, - si_scheduler, - smem_to_vector_write_hazard, - southern_islands, - sramecc, - sramecc_support, - tgsplit, - trap_handler, - trig_reduced_range, - true16, - unaligned_access_mode, - unaligned_buffer_access, - unaligned_ds_access, - unaligned_scratch_access, - unpacked_d16_vmem, - unsafe_ds_offset_folding, - user_sgpr_init16_bug, - valu_trans_use_hazard, - vcmpx_exec_war_hazard, - vcmpx_permlane_hazard, - vgpr_index_mode, - vmem_to_scalar_write_hazard, - volcanic_islands, - vop3_literal, - vop3p, - vopd, - vscnt, - wavefrontsize16, - wavefrontsize32, - wavefrontsize64, - xnack, - xnack_support, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"16_bit_insts")] = .{ - .llvm_name = "16-bit-insts", - .description = "Has i16/f16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.a16)] = .{ - .llvm_name = "a16", - .description = "Support A16 for 16-bit coordinates/gradients/lod/clamp/mip image operands", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.add_no_carry_insts)] = .{ - .llvm_name = "add-no-carry-insts", - .description = "Have VALU add/sub instructions without carry out", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aperture_regs)] = .{ - .llvm_name = "aperture-regs", - .description = "Has Memory Aperture Base and Size Registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.architected_flat_scratch)] = .{ - .llvm_name = "architected-flat-scratch", - .description = "Flat Scratch register is a readonly SPI initialized architected register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.architected_sgprs)] = .{ - .llvm_name = "architected-sgprs", - .description = "Enable the architected SGPRs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.atomic_buffer_global_pk_add_f16_insts)] = .{ - .llvm_name = "atomic-buffer-global-pk-add-f16-insts", - .description = "Has buffer_atomic_pk_add_f16 and global_atomic_pk_add_f16 instructions that can return original value", - .dependencies = featureSet(&[_]Feature{ - .flat_global_insts, - }), - }; - result[@intFromEnum(Feature.atomic_buffer_global_pk_add_f16_no_rtn_insts)] = .{ - .llvm_name = "atomic-buffer-global-pk-add-f16-no-rtn-insts", - .description = "Has buffer_atomic_pk_add_f16 and global_atomic_pk_add_f16 instructions that don't return original value", - .dependencies = featureSet(&[_]Feature{ - .flat_global_insts, - }), - }; - result[@intFromEnum(Feature.atomic_ds_pk_add_16_insts)] = .{ - .llvm_name = "atomic-ds-pk-add-16-insts", - .description = "Has ds_pk_add_bf16, ds_pk_add_f16, ds_pk_add_rtn_bf16, ds_pk_add_rtn_f16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.atomic_fadd_no_rtn_insts)] = .{ - .llvm_name = "atomic-fadd-no-rtn-insts", - .description = "Has buffer_atomic_add_f32 and global_atomic_add_f32 instructions that don't return original value", - .dependencies = featureSet(&[_]Feature{ - .flat_global_insts, - }), - }; - result[@intFromEnum(Feature.atomic_fadd_rtn_insts)] = .{ - .llvm_name = "atomic-fadd-rtn-insts", - .description = "Has buffer_atomic_add_f32 and global_atomic_add_f32 instructions that return original value", - .dependencies = featureSet(&[_]Feature{ - .flat_global_insts, - }), - }; - result[@intFromEnum(Feature.atomic_flat_pk_add_16_insts)] = .{ - .llvm_name = "atomic-flat-pk-add-16-insts", - .description = "Has flat_atomic_pk_add_f16 and flat_atomic_pk_add_bf16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.atomic_global_pk_add_bf16_inst)] = .{ - .llvm_name = "atomic-global-pk-add-bf16-inst", - .description = "Has global_atomic_pk_add_bf16 instruction", - .dependencies = featureSet(&[_]Feature{ - .flat_global_insts, - }), - }; - result[@intFromEnum(Feature.auto_waitcnt_before_barrier)] = .{ - .llvm_name = "auto-waitcnt-before-barrier", - .description = "Hardware automatically inserts waitcnt before barrier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.back_off_barrier)] = .{ - .llvm_name = "back-off-barrier", - .description = "Hardware supports backing off s_barrier if an exception occurs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ci_insts)] = .{ - .llvm_name = "ci-insts", - .description = "Additional instructions for CI+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cumode)] = .{ - .llvm_name = "cumode", - .description = "Enable CU wavefront execution mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dl_insts)] = .{ - .llvm_name = "dl-insts", - .description = "Has v_fmac_f32 and v_xnor_b32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot10_insts)] = .{ - .llvm_name = "dot10-insts", - .description = "Has v_dot2_f32_f16 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot1_insts)] = .{ - .llvm_name = "dot1-insts", - .description = "Has v_dot4_i32_i8 and v_dot8_i32_i4 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot2_insts)] = .{ - .llvm_name = "dot2-insts", - .description = "Has v_dot2_i32_i16, v_dot2_u32_u16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot3_insts)] = .{ - .llvm_name = "dot3-insts", - .description = "Has v_dot8c_i32_i4 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot4_insts)] = .{ - .llvm_name = "dot4-insts", - .description = "Has v_dot2c_i32_i16 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot5_insts)] = .{ - .llvm_name = "dot5-insts", - .description = "Has v_dot2c_f32_f16 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot6_insts)] = .{ - .llvm_name = "dot6-insts", - .description = "Has v_dot4c_i32_i8 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot7_insts)] = .{ - .llvm_name = "dot7-insts", - .description = "Has v_dot4_u32_u8, v_dot8_u32_u4 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot8_insts)] = .{ - .llvm_name = "dot8-insts", - .description = "Has v_dot4_i32_iu8, v_dot8_i32_iu4 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dot9_insts)] = .{ - .llvm_name = "dot9-insts", - .description = "Has v_dot2_f16_f16, v_dot2_bf16_bf16, v_dot2_f32_bf16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dpp)] = .{ - .llvm_name = "dpp", - .description = "Support DPP (Data Parallel Primitives) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dpp8)] = .{ - .llvm_name = "dpp8", - .description = "Support DPP8 (Data Parallel Primitives) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dpp_64bit)] = .{ - .llvm_name = "dpp-64bit", - .description = "Support DPP (Data Parallel Primitives) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ds128)] = .{ - .llvm_name = "enable-ds128", - .description = "Use ds_{read|write}_b128", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ds_src2_insts)] = .{ - .llvm_name = "ds-src2-insts", - .description = "Has ds_*_src2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.extended_image_insts)] = .{ - .llvm_name = "extended-image-insts", - .description = "Support mips != 0, lod != 0, gather4, and get_lod", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_denormal_f32)] = .{ - .llvm_name = "fast-denormal-f32", - .description = "Enabling denormals does not cause f32 instructions to run at f64 rates", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_fmaf)] = .{ - .llvm_name = "fast-fmaf", - .description = "Assuming f32 fma is at least as fast as mul + add", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_address_space)] = .{ - .llvm_name = "flat-address-space", - .description = "Support flat address space", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_atomic_fadd_f32_inst)] = .{ - .llvm_name = "flat-atomic-fadd-f32-inst", - .description = "Has flat_atomic_add_f32 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_for_global)] = .{ - .llvm_name = "flat-for-global", - .description = "Force to generate flat instruction for global", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_global_insts)] = .{ - .llvm_name = "flat-global-insts", - .description = "Have global_* flat memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_inst_offsets)] = .{ - .llvm_name = "flat-inst-offsets", - .description = "Flat instructions have immediate offset addressing mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_scratch)] = .{ - .llvm_name = "enable-flat-scratch", - .description = "Use scratch_* flat memory instructions to access scratch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_scratch_insts)] = .{ - .llvm_name = "flat-scratch-insts", - .description = "Have scratch_* flat memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.flat_segment_offset_bug)] = .{ - .llvm_name = "flat-segment-offset-bug", - .description = "GFX10 bug where inst_offset is ignored when flat instructions access global memory", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fma_mix_insts)] = .{ - .llvm_name = "fma-mix-insts", - .description = "Has v_fma_mix_f32, v_fma_mixlo_f16, v_fma_mixhi_f16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fmacf64_inst)] = .{ - .llvm_name = "fmacf64-inst", - .description = "Has v_fmac_f64 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fmaf)] = .{ - .llvm_name = "fmaf", - .description = "Enable single precision FMA (not as fast as mul+add, but fused)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.force_store_sc0_sc1)] = .{ - .llvm_name = "force-store-sc0-sc1", - .description = "Has SC0 and SC1 on stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Enable double precision operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp8_insts)] = .{ - .llvm_name = "fp8-insts", - .description = "Has fp8 and bf8 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.full_rate_64_ops)] = .{ - .llvm_name = "full-rate-64-ops", - .description = "Most fp64 instructions are full rate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.g16)] = .{ - .llvm_name = "g16", - .description = "Support G16 for 16-bit gradient image operands", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gcn3_encoding)] = .{ - .llvm_name = "gcn3-encoding", - .description = "Encoding format for VI", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.get_wave_id_inst)] = .{ - .llvm_name = "get-wave-id-inst", - .description = "Has s_get_waveid_in_workgroup instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx10)] = .{ - .llvm_name = "gfx10", - .description = "GFX10 GPU generation", - .dependencies = featureSet(&[_]Feature{ - .@"16_bit_insts", - .a16, - .add_no_carry_insts, - .aperture_regs, - .ci_insts, - .dpp, - .dpp8, - .extended_image_insts, - .fast_denormal_f32, - .fast_fmaf, - .flat_address_space, - .flat_global_insts, - .flat_inst_offsets, - .flat_scratch_insts, - .fma_mix_insts, - .fp64, - .g16, - .gfx10_insts, - .gfx8_insts, - .gfx9_insts, - .image_insts, - .int_clamp_insts, - .inv_2pi_inline_imm, - .localmemorysize65536, - .mimg_r128, - .movrel, - .no_data_dep_hazard, - .no_sdst_cmpx, - .pk_fmac_f16_inst, - .s_memrealtime, - .s_memtime_inst, - .sdwa, - .sdwa_omod, - .sdwa_scalar, - .sdwa_sdst, - .unaligned_buffer_access, - .unaligned_ds_access, - .vop3_literal, - .vop3p, - .vscnt, - }), - }; - result[@intFromEnum(Feature.gfx10_3_insts)] = .{ - .llvm_name = "gfx10-3-insts", - .description = "Additional instructions for GFX10.3", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx10_a_encoding)] = .{ - .llvm_name = "gfx10_a-encoding", - .description = "Has BVH ray tracing instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx10_b_encoding)] = .{ - .llvm_name = "gfx10_b-encoding", - .description = "Encoding format GFX10_B", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx10_insts)] = .{ - .llvm_name = "gfx10-insts", - .description = "Additional instructions for GFX10+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx11)] = .{ - .llvm_name = "gfx11", - .description = "GFX11 GPU generation", - .dependencies = featureSet(&[_]Feature{ - .@"16_bit_insts", - .a16, - .add_no_carry_insts, - .aperture_regs, - .ci_insts, - .dpp, - .dpp8, - .extended_image_insts, - .fast_denormal_f32, - .fast_fmaf, - .flat_address_space, - .flat_global_insts, - .flat_inst_offsets, - .flat_scratch_insts, - .fma_mix_insts, - .fp64, - .g16, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .gfx10_insts, - .gfx11_insts, - .gfx8_insts, - .gfx9_insts, - .int_clamp_insts, - .inv_2pi_inline_imm, - .localmemorysize65536, - .mimg_r128, - .movrel, - .no_data_dep_hazard, - .no_sdst_cmpx, - .pk_fmac_f16_inst, - .true16, - .unaligned_buffer_access, - .unaligned_ds_access, - .vop3_literal, - .vop3p, - .vopd, - .vscnt, - }), - }; - result[@intFromEnum(Feature.gfx11_full_vgprs)] = .{ - .llvm_name = "gfx11-full-vgprs", - .description = "GFX11 with 50% more physical VGPRs and 50% larger allocation granule than GFX10", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx11_insts)] = .{ - .llvm_name = "gfx11-insts", - .description = "Additional instructions for GFX11+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx7_gfx8_gfx9_insts)] = .{ - .llvm_name = "gfx7-gfx8-gfx9-insts", - .description = "Instructions shared in GFX7, GFX8, GFX9", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx8_insts)] = .{ - .llvm_name = "gfx8-insts", - .description = "Additional instructions for GFX8+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx9)] = .{ - .llvm_name = "gfx9", - .description = "GFX9 GPU generation", - .dependencies = featureSet(&[_]Feature{ - .@"16_bit_insts", - .a16, - .add_no_carry_insts, - .aperture_regs, - .ci_insts, - .dpp, - .fast_denormal_f32, - .fast_fmaf, - .flat_address_space, - .flat_global_insts, - .flat_inst_offsets, - .flat_scratch_insts, - .fp64, - .gcn3_encoding, - .gfx7_gfx8_gfx9_insts, - .gfx8_insts, - .gfx9_insts, - .int_clamp_insts, - .inv_2pi_inline_imm, - .localmemorysize65536, - .negative_scratch_offset_bug, - .r128_a16, - .s_memrealtime, - .s_memtime_inst, - .scalar_atomics, - .scalar_flat_scratch_insts, - .scalar_stores, - .sdwa, - .sdwa_omod, - .sdwa_scalar, - .sdwa_sdst, - .unaligned_buffer_access, - .unaligned_ds_access, - .vgpr_index_mode, - .vop3p, - .wavefrontsize64, - .xnack_support, - }), - }; - result[@intFromEnum(Feature.gfx90a_insts)] = .{ - .llvm_name = "gfx90a-insts", - .description = "Additional instructions for GFX90A+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx940_insts)] = .{ - .llvm_name = "gfx940-insts", - .description = "Additional instructions for GFX940+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfx9_insts)] = .{ - .llvm_name = "gfx9-insts", - .description = "Additional instructions for GFX9+", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.half_rate_64_ops)] = .{ - .llvm_name = "half-rate-64-ops", - .description = "Most fp64 instructions are half rate instead of quarter", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.image_gather4_d16_bug)] = .{ - .llvm_name = "image-gather4-d16-bug", - .description = "Image Gather4 D16 hardware bug", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.image_insts)] = .{ - .llvm_name = "image-insts", - .description = "Support image instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.image_store_d16_bug)] = .{ - .llvm_name = "image-store-d16-bug", - .description = "Image Store D16 hardware bug", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.inst_fwd_prefetch_bug)] = .{ - .llvm_name = "inst-fwd-prefetch-bug", - .description = "S_INST_PREFETCH instruction causes shader to hang", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.int_clamp_insts)] = .{ - .llvm_name = "int-clamp-insts", - .description = "Support clamp for integer destination", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.inv_2pi_inline_imm)] = .{ - .llvm_name = "inv-2pi-inline-imm", - .description = "Has 1 / (2 * pi) as inline immediate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lds_branch_vmem_war_hazard)] = .{ - .llvm_name = "lds-branch-vmem-war-hazard", - .description = "Switching between LDS and VMEM-tex not waiting VM_VSRC=0", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lds_misaligned_bug)] = .{ - .llvm_name = "lds-misaligned-bug", - .description = "Some GFX10 bug with multi-dword LDS and flat access that is not naturally aligned in WGP mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ldsbankcount16)] = .{ - .llvm_name = "ldsbankcount16", - .description = "The number of LDS banks per compute unit.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ldsbankcount32)] = .{ - .llvm_name = "ldsbankcount32", - .description = "The number of LDS banks per compute unit.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.load_store_opt)] = .{ - .llvm_name = "load-store-opt", - .description = "Enable SI load/store optimizer pass", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.localmemorysize32768)] = .{ - .llvm_name = "localmemorysize32768", - .description = "The size of local memory in bytes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.localmemorysize65536)] = .{ - .llvm_name = "localmemorysize65536", - .description = "The size of local memory in bytes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mad_intra_fwd_bug)] = .{ - .llvm_name = "mad-intra-fwd-bug", - .description = "MAD_U64/I64 intra instruction forwarding bug", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mad_mac_f32_insts)] = .{ - .llvm_name = "mad-mac-f32-insts", - .description = "Has v_mad_f32/v_mac_f32/v_madak_f32/v_madmk_f32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mad_mix_insts)] = .{ - .llvm_name = "mad-mix-insts", - .description = "Has v_mad_mix_f32, v_mad_mixlo_f16, v_mad_mixhi_f16 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mai_insts)] = .{ - .llvm_name = "mai-insts", - .description = "Has mAI instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.max_private_element_size_16)] = .{ - .llvm_name = "max-private-element-size-16", - .description = "Maximum private access size may be 16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.max_private_element_size_4)] = .{ - .llvm_name = "max-private-element-size-4", - .description = "Maximum private access size may be 4", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.max_private_element_size_8)] = .{ - .llvm_name = "max-private-element-size-8", - .description = "Maximum private access size may be 8", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mfma_inline_literal_bug)] = .{ - .llvm_name = "mfma-inline-literal-bug", - .description = "MFMA cannot use inline literal as SrcC", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mimg_r128)] = .{ - .llvm_name = "mimg-r128", - .description = "Support 128-bit texture resources", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.movrel)] = .{ - .llvm_name = "movrel", - .description = "Has v_movrel*_b32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.negative_scratch_offset_bug)] = .{ - .llvm_name = "negative-scratch-offset-bug", - .description = "Negative immediate offsets in scratch instructions with an SGPR offset page fault on GFX9", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.negative_unaligned_scratch_offset_bug)] = .{ - .llvm_name = "negative-unaligned-scratch-offset-bug", - .description = "Scratch instructions with a VGPR offset and a negative immediate offset that is not a multiple of 4 read wrong memory on GFX10", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_data_dep_hazard)] = .{ - .llvm_name = "no-data-dep-hazard", - .description = "Does not need SW waitstates", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_sdst_cmpx)] = .{ - .llvm_name = "no-sdst-cmpx", - .description = "V_CMPX does not write VCC/SGPR in addition to EXEC", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nsa_clause_bug)] = .{ - .llvm_name = "nsa-clause-bug", - .description = "MIMG-NSA in a hard clause has unpredictable results on GFX10.1", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nsa_encoding)] = .{ - .llvm_name = "nsa-encoding", - .description = "Support NSA encoding for image instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nsa_to_vmem_bug)] = .{ - .llvm_name = "nsa-to-vmem-bug", - .description = "MIMG-NSA followed by VMEM fail if EXEC_LO or EXEC_HI equals zero", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.offset_3f_bug)] = .{ - .llvm_name = "offset-3f-bug", - .description = "Branch offset of 3f hardware bug", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.packed_fp32_ops)] = .{ - .llvm_name = "packed-fp32-ops", - .description = "Support packed fp32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.packed_tid)] = .{ - .llvm_name = "packed-tid", - .description = "Workitem IDs are packed into v0 at kernel launch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.partial_nsa_encoding)] = .{ - .llvm_name = "partial-nsa-encoding", - .description = "Support partial NSA encoding for image instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pk_fmac_f16_inst)] = .{ - .llvm_name = "pk-fmac-f16-inst", - .description = "Has v_pk_fmac_f16 instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.promote_alloca)] = .{ - .llvm_name = "promote-alloca", - .description = "Enable promote alloca pass", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prt_strict_null)] = .{ - .llvm_name = "enable-prt-strict-null", - .description = "Enable zeroing of result registers for sparse texture fetches", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.r128_a16)] = .{ - .llvm_name = "r128-a16", - .description = "Support gfx9-style A16 for 16-bit coordinates/gradients/lod/clamp/mip image operands, where a16 is aliased with r128", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.s_memrealtime)] = .{ - .llvm_name = "s-memrealtime", - .description = "Has s_memrealtime instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.s_memtime_inst)] = .{ - .llvm_name = "s-memtime-inst", - .description = "Has s_memtime instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.scalar_atomics)] = .{ - .llvm_name = "scalar-atomics", - .description = "Has atomic scalar memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.scalar_flat_scratch_insts)] = .{ - .llvm_name = "scalar-flat-scratch-insts", - .description = "Have s_scratch_* flat memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.scalar_stores)] = .{ - .llvm_name = "scalar-stores", - .description = "Has store scalar memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa)] = .{ - .llvm_name = "sdwa", - .description = "Support SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa_mav)] = .{ - .llvm_name = "sdwa-mav", - .description = "Support v_mac_f32/f16 with SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa_omod)] = .{ - .llvm_name = "sdwa-omod", - .description = "Support OMod with SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa_out_mods_vopc)] = .{ - .llvm_name = "sdwa-out-mods-vopc", - .description = "Support clamp for VOPC with SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa_scalar)] = .{ - .llvm_name = "sdwa-scalar", - .description = "Support scalar register with SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sdwa_sdst)] = .{ - .llvm_name = "sdwa-sdst", - .description = "Support scalar dst for VOPC with SDWA (Sub-DWORD Addressing) extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sea_islands)] = .{ - .llvm_name = "sea-islands", - .description = "SEA_ISLANDS GPU generation", - .dependencies = featureSet(&[_]Feature{ - .ci_insts, - .ds_src2_insts, - .extended_image_insts, - .flat_address_space, - .fp64, - .gfx7_gfx8_gfx9_insts, - .image_insts, - .localmemorysize65536, - .mad_mac_f32_insts, - .mimg_r128, - .movrel, - .s_memtime_inst, - .trig_reduced_range, - .unaligned_buffer_access, - .wavefrontsize64, - }), - }; - result[@intFromEnum(Feature.sgpr_init_bug)] = .{ - .llvm_name = "sgpr-init-bug", - .description = "VI SGPR initialization bug requiring a fixed SGPR allocation size", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.shader_cycles_register)] = .{ - .llvm_name = "shader-cycles-register", - .description = "Has SHADER_CYCLES hardware register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.si_scheduler)] = .{ - .llvm_name = "si-scheduler", - .description = "Enable SI Machine Scheduler", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.smem_to_vector_write_hazard)] = .{ - .llvm_name = "smem-to-vector-write-hazard", - .description = "s_load_dword followed by v_cmp page faults", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.southern_islands)] = .{ - .llvm_name = "southern-islands", - .description = "SOUTHERN_ISLANDS GPU generation", - .dependencies = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .fp64, - .image_insts, - .ldsbankcount32, - .localmemorysize32768, - .mad_mac_f32_insts, - .mimg_r128, - .movrel, - .s_memtime_inst, - .trig_reduced_range, - .wavefrontsize64, - }), - }; - result[@intFromEnum(Feature.sramecc)] = .{ - .llvm_name = "sramecc", - .description = "Enable SRAMECC", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sramecc_support)] = .{ - .llvm_name = "sramecc-support", - .description = "Hardware supports SRAMECC", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tgsplit)] = .{ - .llvm_name = "tgsplit", - .description = "Enable threadgroup split execution", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.trap_handler)] = .{ - .llvm_name = "trap-handler", - .description = "Trap handler support", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.trig_reduced_range)] = .{ - .llvm_name = "trig-reduced-range", - .description = "Requires use of fract on arguments to trig instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.true16)] = .{ - .llvm_name = "true16", - .description = "True 16-bit operand instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_access_mode)] = .{ - .llvm_name = "unaligned-access-mode", - .description = "Enable unaligned global, local and region loads and stores if the hardware supports it", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_buffer_access)] = .{ - .llvm_name = "unaligned-buffer-access", - .description = "Hardware supports unaligned global loads and stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_ds_access)] = .{ - .llvm_name = "unaligned-ds-access", - .description = "Hardware supports unaligned local and region loads and stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_scratch_access)] = .{ - .llvm_name = "unaligned-scratch-access", - .description = "Support unaligned scratch loads and stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unpacked_d16_vmem)] = .{ - .llvm_name = "unpacked-d16-vmem", - .description = "Has unpacked d16 vmem instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unsafe_ds_offset_folding)] = .{ - .llvm_name = "unsafe-ds-offset-folding", - .description = "Force using DS instruction immediate offsets on SI", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.user_sgpr_init16_bug)] = .{ - .llvm_name = "user-sgpr-init16-bug", - .description = "Bug requiring at least 16 user+system SGPRs to be enabled", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.valu_trans_use_hazard)] = .{ - .llvm_name = "valu-trans-use-hazard", - .description = "Hazard when TRANS instructions are closely followed by a use of the result", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vcmpx_exec_war_hazard)] = .{ - .llvm_name = "vcmpx-exec-war-hazard", - .description = "V_CMPX WAR hazard on EXEC (V_CMPX issue ONLY)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vcmpx_permlane_hazard)] = .{ - .llvm_name = "vcmpx-permlane-hazard", - .description = "TODO: describe me", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vgpr_index_mode)] = .{ - .llvm_name = "vgpr-index-mode", - .description = "Has VGPR mode register indexing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vmem_to_scalar_write_hazard)] = .{ - .llvm_name = "vmem-to-scalar-write-hazard", - .description = "VMEM instruction followed by scalar writing to EXEC mask, M0 or SGPR leads to incorrect execution.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.volcanic_islands)] = .{ - .llvm_name = "volcanic-islands", - .description = "VOLCANIC_ISLANDS GPU generation", - .dependencies = featureSet(&[_]Feature{ - .@"16_bit_insts", - .ci_insts, - .dpp, - .ds_src2_insts, - .extended_image_insts, - .fast_denormal_f32, - .flat_address_space, - .fp64, - .gcn3_encoding, - .gfx7_gfx8_gfx9_insts, - .gfx8_insts, - .image_insts, - .int_clamp_insts, - .inv_2pi_inline_imm, - .localmemorysize65536, - .mad_mac_f32_insts, - .mimg_r128, - .movrel, - .s_memrealtime, - .s_memtime_inst, - .scalar_stores, - .sdwa, - .sdwa_mav, - .sdwa_out_mods_vopc, - .trig_reduced_range, - .unaligned_buffer_access, - .vgpr_index_mode, - .wavefrontsize64, - }), - }; - result[@intFromEnum(Feature.vop3_literal)] = .{ - .llvm_name = "vop3-literal", - .description = "Can use one literal in VOP3", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vop3p)] = .{ - .llvm_name = "vop3p", - .description = "Has VOP3P packed instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vopd)] = .{ - .llvm_name = "vopd", - .description = "Has VOPD dual issue wave32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vscnt)] = .{ - .llvm_name = "vscnt", - .description = "Has separate store vscnt counter", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.wavefrontsize16)] = .{ - .llvm_name = "wavefrontsize16", - .description = "The number of threads per wavefront", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.wavefrontsize32)] = .{ - .llvm_name = "wavefrontsize32", - .description = "The number of threads per wavefront", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.wavefrontsize64)] = .{ - .llvm_name = "wavefrontsize64", - .description = "The number of threads per wavefront", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xnack)] = .{ - .llvm_name = "xnack", - .description = "Enable XNACK support", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xnack_support)] = .{ - .llvm_name = "xnack-support", - .description = "Hardware supports XNACK", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const bonaire = CpuModel{ - .name = "bonaire", - .llvm_name = "bonaire", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sea_islands, - }), - }; - pub const carrizo = CpuModel{ - .name = "carrizo", - .llvm_name = "carrizo", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - .xnack_support, - }), - }; - pub const fiji = CpuModel{ - .name = "fiji", - .llvm_name = "fiji", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .wavefrontsize64, - }), - }; - pub const generic_hsa = CpuModel{ - .name = "generic_hsa", - .llvm_name = "generic-hsa", - .features = featureSet(&[_]Feature{ - .flat_address_space, - .wavefrontsize64, - }), - }; - pub const gfx1010 = CpuModel{ - .name = "gfx1010", - .llvm_name = "gfx1010", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .ds_src2_insts, - .flat_segment_offset_bug, - .get_wave_id_inst, - .gfx10, - .inst_fwd_prefetch_bug, - .lds_branch_vmem_war_hazard, - .lds_misaligned_bug, - .ldsbankcount32, - .mad_mac_f32_insts, - .negative_unaligned_scratch_offset_bug, - .nsa_clause_bug, - .nsa_encoding, - .nsa_to_vmem_bug, - .offset_3f_bug, - .scalar_atomics, - .scalar_flat_scratch_insts, - .scalar_stores, - .smem_to_vector_write_hazard, - .vcmpx_exec_war_hazard, - .vcmpx_permlane_hazard, - .vmem_to_scalar_write_hazard, - .wavefrontsize32, - .xnack_support, - }), - }; - pub const gfx1011 = CpuModel{ - .name = "gfx1011", - .llvm_name = "gfx1011", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .ds_src2_insts, - .flat_segment_offset_bug, - .get_wave_id_inst, - .gfx10, - .inst_fwd_prefetch_bug, - .lds_branch_vmem_war_hazard, - .lds_misaligned_bug, - .ldsbankcount32, - .mad_mac_f32_insts, - .negative_unaligned_scratch_offset_bug, - .nsa_clause_bug, - .nsa_encoding, - .nsa_to_vmem_bug, - .offset_3f_bug, - .scalar_atomics, - .scalar_flat_scratch_insts, - .scalar_stores, - .smem_to_vector_write_hazard, - .vcmpx_exec_war_hazard, - .vcmpx_permlane_hazard, - .vmem_to_scalar_write_hazard, - .wavefrontsize32, - .xnack_support, - }), - }; - pub const gfx1012 = CpuModel{ - .name = "gfx1012", - .llvm_name = "gfx1012", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .ds_src2_insts, - .flat_segment_offset_bug, - .get_wave_id_inst, - .gfx10, - .inst_fwd_prefetch_bug, - .lds_branch_vmem_war_hazard, - .lds_misaligned_bug, - .ldsbankcount32, - .mad_mac_f32_insts, - .negative_unaligned_scratch_offset_bug, - .nsa_clause_bug, - .nsa_encoding, - .nsa_to_vmem_bug, - .offset_3f_bug, - .scalar_atomics, - .scalar_flat_scratch_insts, - .scalar_stores, - .smem_to_vector_write_hazard, - .vcmpx_exec_war_hazard, - .vcmpx_permlane_hazard, - .vmem_to_scalar_write_hazard, - .wavefrontsize32, - .xnack_support, - }), - }; - pub const gfx1013 = CpuModel{ - .name = "gfx1013", - .llvm_name = "gfx1013", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .ds_src2_insts, - .flat_segment_offset_bug, - .get_wave_id_inst, - .gfx10, - .gfx10_a_encoding, - .inst_fwd_prefetch_bug, - .lds_branch_vmem_war_hazard, - .lds_misaligned_bug, - .ldsbankcount32, - .mad_mac_f32_insts, - .negative_unaligned_scratch_offset_bug, - .nsa_clause_bug, - .nsa_encoding, - .nsa_to_vmem_bug, - .offset_3f_bug, - .scalar_atomics, - .scalar_flat_scratch_insts, - .scalar_stores, - .smem_to_vector_write_hazard, - .vcmpx_exec_war_hazard, - .vcmpx_permlane_hazard, - .vmem_to_scalar_write_hazard, - .wavefrontsize32, - .xnack_support, - }), - }; - pub const gfx1030 = CpuModel{ - .name = "gfx1030", - .llvm_name = "gfx1030", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1031 = CpuModel{ - .name = "gfx1031", - .llvm_name = "gfx1031", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1032 = CpuModel{ - .name = "gfx1032", - .llvm_name = "gfx1032", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1033 = CpuModel{ - .name = "gfx1033", - .llvm_name = "gfx1033", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1034 = CpuModel{ - .name = "gfx1034", - .llvm_name = "gfx1034", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1035 = CpuModel{ - .name = "gfx1035", - .llvm_name = "gfx1035", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1036 = CpuModel{ - .name = "gfx1036", - .llvm_name = "gfx1036", - .features = featureSet(&[_]Feature{ - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .gfx10, - .gfx10_3_insts, - .gfx10_a_encoding, - .gfx10_b_encoding, - .ldsbankcount32, - .nsa_encoding, - .shader_cycles_register, - .wavefrontsize32, - }), - }; - pub const gfx1100 = CpuModel{ - .name = "gfx1100", - .llvm_name = "gfx1100", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .gfx11_full_vgprs, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .user_sgpr_init16_bug, - .valu_trans_use_hazard, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx1101 = CpuModel{ - .name = "gfx1101", - .llvm_name = "gfx1101", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .gfx11_full_vgprs, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .valu_trans_use_hazard, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx1102 = CpuModel{ - .name = "gfx1102", - .llvm_name = "gfx1102", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .user_sgpr_init16_bug, - .valu_trans_use_hazard, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx1103 = CpuModel{ - .name = "gfx1103", - .llvm_name = "gfx1103", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .valu_trans_use_hazard, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx1150 = CpuModel{ - .name = "gfx1150", - .llvm_name = "gfx1150", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx1151 = CpuModel{ - .name = "gfx1151", - .llvm_name = "gfx1151", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .dl_insts, - .dot10_insts, - .dot5_insts, - .dot7_insts, - .dot8_insts, - .dot9_insts, - .flat_atomic_fadd_f32_inst, - .gfx11, - .gfx11_full_vgprs, - .image_insts, - .ldsbankcount32, - .mad_intra_fwd_bug, - .nsa_encoding, - .packed_tid, - .partial_nsa_encoding, - .shader_cycles_register, - .vcmpx_permlane_hazard, - .wavefrontsize32, - }), - }; - pub const gfx600 = CpuModel{ - .name = "gfx600", - .llvm_name = "gfx600", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .southern_islands, - }), - }; - pub const gfx601 = CpuModel{ - .name = "gfx601", - .llvm_name = "gfx601", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; - pub const gfx602 = CpuModel{ - .name = "gfx602", - .llvm_name = "gfx602", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; - pub const gfx700 = CpuModel{ - .name = "gfx700", - .llvm_name = "gfx700", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sea_islands, - }), - }; - pub const gfx701 = CpuModel{ - .name = "gfx701", - .llvm_name = "gfx701", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .ldsbankcount32, - .sea_islands, - }), - }; - pub const gfx702 = CpuModel{ - .name = "gfx702", - .llvm_name = "gfx702", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .ldsbankcount16, - .sea_islands, - }), - }; - pub const gfx703 = CpuModel{ - .name = "gfx703", - .llvm_name = "gfx703", - .features = featureSet(&[_]Feature{ - .ldsbankcount16, - .sea_islands, - }), - }; - pub const gfx704 = CpuModel{ - .name = "gfx704", - .llvm_name = "gfx704", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sea_islands, - }), - }; - pub const gfx705 = CpuModel{ - .name = "gfx705", - .llvm_name = "gfx705", - .features = featureSet(&[_]Feature{ - .ldsbankcount16, - .sea_islands, - }), - }; - pub const gfx801 = CpuModel{ - .name = "gfx801", - .llvm_name = "gfx801", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - .xnack_support, - }), - }; - pub const gfx802 = CpuModel{ - .name = "gfx802", - .llvm_name = "gfx802", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sgpr_init_bug, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const gfx803 = CpuModel{ - .name = "gfx803", - .llvm_name = "gfx803", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const gfx805 = CpuModel{ - .name = "gfx805", - .llvm_name = "gfx805", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sgpr_init_bug, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const gfx810 = CpuModel{ - .name = "gfx810", - .llvm_name = "gfx810", - .features = featureSet(&[_]Feature{ - .image_gather4_d16_bug, - .image_store_d16_bug, - .ldsbankcount16, - .volcanic_islands, - .xnack_support, - }), - }; - pub const gfx900 = CpuModel{ - .name = "gfx900", - .llvm_name = "gfx900", - .features = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .gfx9, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mad_mix_insts, - }), - }; - pub const gfx902 = CpuModel{ - .name = "gfx902", - .llvm_name = "gfx902", - .features = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .gfx9, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mad_mix_insts, - }), - }; - pub const gfx904 = CpuModel{ - .name = "gfx904", - .llvm_name = "gfx904", - .features = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .fma_mix_insts, - .gfx9, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - }), - }; - pub const gfx906 = CpuModel{ - .name = "gfx906", - .llvm_name = "gfx906", - .features = featureSet(&[_]Feature{ - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot7_insts, - .ds_src2_insts, - .extended_image_insts, - .fma_mix_insts, - .gfx9, - .half_rate_64_ops, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .sramecc_support, - }), - }; - pub const gfx908 = CpuModel{ - .name = "gfx908", - .llvm_name = "gfx908", - .features = featureSet(&[_]Feature{ - .atomic_buffer_global_pk_add_f16_no_rtn_insts, - .atomic_fadd_no_rtn_insts, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot3_insts, - .dot4_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .ds_src2_insts, - .extended_image_insts, - .fma_mix_insts, - .gfx9, - .half_rate_64_ops, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mai_insts, - .mfma_inline_literal_bug, - .pk_fmac_f16_inst, - .sramecc_support, - }), - }; - pub const gfx909 = CpuModel{ - .name = "gfx909", - .llvm_name = "gfx909", - .features = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .gfx9, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mad_mix_insts, - }), - }; - pub const gfx90a = CpuModel{ - .name = "gfx90a", - .llvm_name = "gfx90a", - .features = featureSet(&[_]Feature{ - .atomic_buffer_global_pk_add_f16_insts, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot3_insts, - .dot4_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .dpp_64bit, - .fma_mix_insts, - .fmacf64_inst, - .full_rate_64_ops, - .gfx9, - .gfx90a_insts, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mai_insts, - .packed_fp32_ops, - .packed_tid, - .pk_fmac_f16_inst, - .sramecc_support, - }), - }; - pub const gfx90c = CpuModel{ - .name = "gfx90c", - .llvm_name = "gfx90c", - .features = featureSet(&[_]Feature{ - .ds_src2_insts, - .extended_image_insts, - .gfx9, - .image_gather4_d16_bug, - .image_insts, - .ldsbankcount32, - .mad_mac_f32_insts, - .mad_mix_insts, - }), - }; - pub const gfx940 = CpuModel{ - .name = "gfx940", - .llvm_name = "gfx940", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_buffer_global_pk_add_f16_insts, - .atomic_ds_pk_add_16_insts, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .atomic_flat_pk_add_16_insts, - .atomic_global_pk_add_bf16_inst, - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot3_insts, - .dot4_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .dpp_64bit, - .flat_atomic_fadd_f32_inst, - .fma_mix_insts, - .fmacf64_inst, - .force_store_sc0_sc1, - .fp8_insts, - .full_rate_64_ops, - .gfx9, - .gfx90a_insts, - .gfx940_insts, - .ldsbankcount32, - .mai_insts, - .packed_fp32_ops, - .packed_tid, - .pk_fmac_f16_inst, - .sramecc_support, - }), - }; - pub const gfx941 = CpuModel{ - .name = "gfx941", - .llvm_name = "gfx941", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_buffer_global_pk_add_f16_insts, - .atomic_ds_pk_add_16_insts, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .atomic_flat_pk_add_16_insts, - .atomic_global_pk_add_bf16_inst, - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot3_insts, - .dot4_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .dpp_64bit, - .flat_atomic_fadd_f32_inst, - .fma_mix_insts, - .fmacf64_inst, - .force_store_sc0_sc1, - .fp8_insts, - .full_rate_64_ops, - .gfx9, - .gfx90a_insts, - .gfx940_insts, - .ldsbankcount32, - .mai_insts, - .packed_fp32_ops, - .packed_tid, - .pk_fmac_f16_inst, - .sramecc_support, - }), - }; - pub const gfx942 = CpuModel{ - .name = "gfx942", - .llvm_name = "gfx942", - .features = featureSet(&[_]Feature{ - .architected_flat_scratch, - .atomic_buffer_global_pk_add_f16_insts, - .atomic_ds_pk_add_16_insts, - .atomic_fadd_no_rtn_insts, - .atomic_fadd_rtn_insts, - .atomic_flat_pk_add_16_insts, - .atomic_global_pk_add_bf16_inst, - .back_off_barrier, - .dl_insts, - .dot10_insts, - .dot1_insts, - .dot2_insts, - .dot3_insts, - .dot4_insts, - .dot5_insts, - .dot6_insts, - .dot7_insts, - .dpp_64bit, - .flat_atomic_fadd_f32_inst, - .fma_mix_insts, - .fmacf64_inst, - .fp8_insts, - .full_rate_64_ops, - .gfx9, - .gfx90a_insts, - .gfx940_insts, - .ldsbankcount32, - .mai_insts, - .packed_fp32_ops, - .packed_tid, - .pk_fmac_f16_inst, - .sramecc_support, - }), - }; - pub const hainan = CpuModel{ - .name = "hainan", - .llvm_name = "hainan", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; - pub const hawaii = CpuModel{ - .name = "hawaii", - .llvm_name = "hawaii", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .ldsbankcount32, - .sea_islands, - }), - }; - pub const iceland = CpuModel{ - .name = "iceland", - .llvm_name = "iceland", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sgpr_init_bug, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const kabini = CpuModel{ - .name = "kabini", - .llvm_name = "kabini", - .features = featureSet(&[_]Feature{ - .ldsbankcount16, - .sea_islands, - }), - }; - pub const kaveri = CpuModel{ - .name = "kaveri", - .llvm_name = "kaveri", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sea_islands, - }), - }; - pub const mullins = CpuModel{ - .name = "mullins", - .llvm_name = "mullins", - .features = featureSet(&[_]Feature{ - .ldsbankcount16, - .sea_islands, - }), - }; - pub const oland = CpuModel{ - .name = "oland", - .llvm_name = "oland", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; - pub const pitcairn = CpuModel{ - .name = "pitcairn", - .llvm_name = "pitcairn", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; - pub const polaris10 = CpuModel{ - .name = "polaris10", - .llvm_name = "polaris10", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const polaris11 = CpuModel{ - .name = "polaris11", - .llvm_name = "polaris11", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const stoney = CpuModel{ - .name = "stoney", - .llvm_name = "stoney", - .features = featureSet(&[_]Feature{ - .image_gather4_d16_bug, - .image_store_d16_bug, - .ldsbankcount16, - .volcanic_islands, - .xnack_support, - }), - }; - pub const tahiti = CpuModel{ - .name = "tahiti", - .llvm_name = "tahiti", - .features = featureSet(&[_]Feature{ - .fast_fmaf, - .half_rate_64_ops, - .southern_islands, - }), - }; - pub const tonga = CpuModel{ - .name = "tonga", - .llvm_name = "tonga", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sgpr_init_bug, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const tongapro = CpuModel{ - .name = "tongapro", - .llvm_name = "tongapro", - .features = featureSet(&[_]Feature{ - .ldsbankcount32, - .sgpr_init_bug, - .unpacked_d16_vmem, - .volcanic_islands, - }), - }; - pub const verde = CpuModel{ - .name = "verde", - .llvm_name = "verde", - .features = featureSet(&[_]Feature{ - .southern_islands, - }), - }; -}; diff --git a/lib/std/target/arc.zig b/lib/std/target/arc.zig deleted file mode 100644 index eff13c66375f656181370362f3e763fbbae794ea..0000000000000000000000000000000000000000 --- a/lib/std/target/arc.zig +++ /dev/null @@ -1,39 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - norm, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.norm)] = .{ - .llvm_name = "norm", - .description = "Enable support for norm instruction.", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; -}; diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig deleted file mode 100644 index 5245b3357e470275c178249fb7a834beed0e244a..0000000000000000000000000000000000000000 --- a/lib/std/target/arm.zig +++ /dev/null @@ -1,2604 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"32bit", - @"8msecext", - a76, - aapcs_frame_chain, - aapcs_frame_chain_leaf, - aclass, - acquire_release, - aes, - atomics_32, - avoid_movs_shop, - avoid_partial_cpsr, - bf16, - big_endian_instructions, - cde, - cdecp0, - cdecp1, - cdecp2, - cdecp3, - cdecp4, - cdecp5, - cdecp6, - cdecp7, - cheap_predicable_cpsr, - clrbhb, - crc, - crypto, - d32, - db, - dfb, - disable_postra_scheduler, - dont_widen_vmovs, - dotprod, - dsp, - execute_only, - expand_fp_mlx, - exynos, - fix_cmse_cve_2021_35465, - fix_cortex_a57_aes_1742098, - fp16, - fp16fml, - fp64, - fp_armv8, - fp_armv8d16, - fp_armv8d16sp, - fp_armv8sp, - fpao, - fpregs, - fpregs16, - fpregs64, - fullfp16, - fuse_aes, - fuse_literals, - harden_sls_blr, - harden_sls_nocomdat, - harden_sls_retbr, - has_v4t, - has_v5t, - has_v5te, - has_v6, - has_v6k, - has_v6m, - has_v6t2, - has_v7, - has_v7clrex, - has_v8, - has_v8_1a, - has_v8_1m_main, - has_v8_2a, - has_v8_3a, - has_v8_4a, - has_v8_5a, - has_v8_6a, - has_v8_7a, - has_v8_8a, - has_v8_9a, - has_v8m, - has_v8m_main, - has_v9_1a, - has_v9_2a, - has_v9_3a, - has_v9_4a, - has_v9a, - hwdiv, - hwdiv_arm, - i8mm, - iwmmxt, - iwmmxt2, - lob, - long_calls, - loop_align, - m3, - mclass, - mp, - muxed_units, - mve, - mve1beat, - mve2beat, - mve4beat, - mve_fp, - nacl_trap, - neon, - neon_fpmovs, - neonfp, - no_branch_predictor, - no_bti_at_return_twice, - no_movt, - no_neg_immediates, - noarm, - nonpipelined_vfp, - pacbti, - perfmon, - prefer_ishst, - prefer_vmovsr, - prof_unpr, - r4, - ras, - rclass, - read_tp_tpidrprw, - read_tp_tpidruro, - read_tp_tpidrurw, - reserve_r9, - ret_addr_stack, - sb, - sha2, - slow_fp_brcc, - slow_load_D_subreg, - slow_odd_reg, - slow_vdup32, - slow_vgetlni32, - slowfpvfmx, - slowfpvmlx, - soft_float, - splat_vfp_neon, - strict_align, - swift, - thumb2, - thumb_mode, - trustzone, - use_mipipeliner, - use_misched, - v2, - v2a, - v3, - v3m, - v4, - v4t, - v5t, - v5te, - v5tej, - v6, - v6j, - v6k, - v6kz, - v6m, - v6sm, - v6t2, - v7a, - v7em, - v7k, - v7m, - v7r, - v7s, - v7ve, - v8_1a, - v8_1m_main, - v8_2a, - v8_3a, - v8_4a, - v8_5a, - v8_6a, - v8_7a, - v8_8a, - v8_9a, - v8a, - v8m, - v8m_main, - v8r, - v9_1a, - v9_2a, - v9_3a, - v9_4a, - v9a, - vfp2, - vfp2sp, - vfp3, - vfp3d16, - vfp3d16sp, - vfp3sp, - vfp4, - vfp4d16, - vfp4d16sp, - vfp4sp, - virtualization, - vldn_align, - vmlx_forwarding, - vmlx_hazards, - wide_stride_vfp, - xscale, - zcz, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - @setEvalBranchQuota(10000); - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"32bit")] = .{ - .llvm_name = "32bit", - .description = "Prefer 32-bit Thumb instrs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"8msecext")] = .{ - .llvm_name = "8msecext", - .description = "Enable support for ARMv8-M Security Extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.a76)] = .{ - .llvm_name = "a76", - .description = "Cortex-A76 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aapcs_frame_chain)] = .{ - .llvm_name = "aapcs-frame-chain", - .description = "Create an AAPCS compliant frame chain", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aapcs_frame_chain_leaf)] = .{ - .llvm_name = "aapcs-frame-chain-leaf", - .description = "Create an AAPCS compliant frame chain for leaf functions", - .dependencies = featureSet(&[_]Feature{ - .aapcs_frame_chain, - }), - }; - result[@intFromEnum(Feature.aclass)] = .{ - .llvm_name = "aclass", - .description = "Is application profile ('A' series)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.acquire_release)] = .{ - .llvm_name = "acquire-release", - .description = "Has v8 acquire/release (lda/ldaex etc) instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aes)] = .{ - .llvm_name = "aes", - .description = "Enable AES support", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.atomics_32)] = .{ - .llvm_name = "atomics-32", - .description = "Assume that lock-free 32-bit atomics are available", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.avoid_movs_shop)] = .{ - .llvm_name = "avoid-movs-shop", - .description = "Avoid movs instructions with shifter operand", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.avoid_partial_cpsr)] = .{ - .llvm_name = "avoid-partial-cpsr", - .description = "Avoid CPSR partial update for OOO execution", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.bf16)] = .{ - .llvm_name = "bf16", - .description = "Enable support for BFloat16 instructions", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.big_endian_instructions)] = .{ - .llvm_name = "big-endian-instructions", - .description = "Expect instructions to be stored big-endian.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cde)] = .{ - .llvm_name = "cde", - .description = "Support CDE instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8m_main, - }), - }; - result[@intFromEnum(Feature.cdecp0)] = .{ - .llvm_name = "cdecp0", - .description = "Coprocessor 0 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp1)] = .{ - .llvm_name = "cdecp1", - .description = "Coprocessor 1 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp2)] = .{ - .llvm_name = "cdecp2", - .description = "Coprocessor 2 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp3)] = .{ - .llvm_name = "cdecp3", - .description = "Coprocessor 3 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp4)] = .{ - .llvm_name = "cdecp4", - .description = "Coprocessor 4 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp5)] = .{ - .llvm_name = "cdecp5", - .description = "Coprocessor 5 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp6)] = .{ - .llvm_name = "cdecp6", - .description = "Coprocessor 6 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cdecp7)] = .{ - .llvm_name = "cdecp7", - .description = "Coprocessor 7 ISA is CDEv1", - .dependencies = featureSet(&[_]Feature{ - .cde, - }), - }; - result[@intFromEnum(Feature.cheap_predicable_cpsr)] = .{ - .llvm_name = "cheap-predicable-cpsr", - .description = "Disable +1 predication cost for instructions updating CPSR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.clrbhb)] = .{ - .llvm_name = "clrbhb", - .description = "Enable Clear BHB instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crc)] = .{ - .llvm_name = "crc", - .description = "Enable support for CRC instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crypto)] = .{ - .llvm_name = "crypto", - .description = "Enable support for Cryptography extensions", - .dependencies = featureSet(&[_]Feature{ - .aes, - .sha2, - }), - }; - result[@intFromEnum(Feature.d32)] = .{ - .llvm_name = "d32", - .description = "Extend FP to 32 double registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.db)] = .{ - .llvm_name = "db", - .description = "Has data barrier (dmb/dsb) instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dfb)] = .{ - .llvm_name = "dfb", - .description = "Has full data barrier (dfb) instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.disable_postra_scheduler)] = .{ - .llvm_name = "disable-postra-scheduler", - .description = "Don't schedule again after register allocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dont_widen_vmovs)] = .{ - .llvm_name = "dont-widen-vmovs", - .description = "Don't widen VMOVS to VMOVD", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dotprod)] = .{ - .llvm_name = "dotprod", - .description = "Enable support for dot product instructions", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.dsp)] = .{ - .llvm_name = "dsp", - .description = "Supports DSP instructions in ARM and/or Thumb2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.execute_only)] = .{ - .llvm_name = "execute-only", - .description = "Enable the generation of execute only code.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.expand_fp_mlx)] = .{ - .llvm_name = "expand-fp-mlx", - .description = "Expand VFP/NEON MLA/MLS instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.exynos)] = .{ - .llvm_name = "exynos", - .description = "Samsung Exynos processors", - .dependencies = featureSet(&[_]Feature{ - .crc, - .crypto, - .expand_fp_mlx, - .fuse_aes, - .fuse_literals, - .hwdiv, - .hwdiv_arm, - .prof_unpr, - .ret_addr_stack, - .slow_fp_brcc, - .slow_vdup32, - .slow_vgetlni32, - .slowfpvfmx, - .slowfpvmlx, - .splat_vfp_neon, - .wide_stride_vfp, - .zcz, - }), - }; - result[@intFromEnum(Feature.fix_cmse_cve_2021_35465)] = .{ - .llvm_name = "fix-cmse-cve-2021-35465", - .description = "Mitigate against the cve-2021-35465 security vulnurability", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fix_cortex_a57_aes_1742098)] = .{ - .llvm_name = "fix-cortex-a57-aes-1742098", - .description = "Work around Cortex-A57 Erratum 1742098 / Cortex-A72 Erratum 1655431 (AES)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp16)] = .{ - .llvm_name = "fp16", - .description = "Enable half-precision floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp16fml)] = .{ - .llvm_name = "fp16fml", - .description = "Enable full half-precision floating point fml instructions", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - }), - }; - result[@intFromEnum(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Floating point unit supports double precision", - .dependencies = featureSet(&[_]Feature{ - .fpregs64, - }), - }; - result[@intFromEnum(Feature.fp_armv8)] = .{ - .llvm_name = "fp-armv8", - .description = "Enable ARMv8 FP", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8d16, - .fp_armv8sp, - .vfp4, - }), - }; - result[@intFromEnum(Feature.fp_armv8d16)] = .{ - .llvm_name = "fp-armv8d16", - .description = "Enable ARMv8 FP with only 16 d-registers", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8d16sp, - .vfp4d16, - }), - }; - result[@intFromEnum(Feature.fp_armv8d16sp)] = .{ - .llvm_name = "fp-armv8d16sp", - .description = "Enable ARMv8 FP with only 16 d-registers and no double precision", - .dependencies = featureSet(&[_]Feature{ - .vfp4d16sp, - }), - }; - result[@intFromEnum(Feature.fp_armv8sp)] = .{ - .llvm_name = "fp-armv8sp", - .description = "Enable ARMv8 FP with no double precision", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8d16sp, - .vfp4sp, - }), - }; - result[@intFromEnum(Feature.fpao)] = .{ - .llvm_name = "fpao", - .description = "Enable fast computation of positive address offsets", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpregs)] = .{ - .llvm_name = "fpregs", - .description = "Enable FP registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpregs16)] = .{ - .llvm_name = "fpregs16", - .description = "Enable 16-bit FP registers", - .dependencies = featureSet(&[_]Feature{ - .fpregs, - }), - }; - result[@intFromEnum(Feature.fpregs64)] = .{ - .llvm_name = "fpregs64", - .description = "Enable 64-bit FP registers", - .dependencies = featureSet(&[_]Feature{ - .fpregs, - }), - }; - result[@intFromEnum(Feature.fullfp16)] = .{ - .llvm_name = "fullfp16", - .description = "Enable full half-precision floating point", - .dependencies = featureSet(&[_]Feature{ - .fp_armv8d16sp, - .fpregs16, - }), - }; - result[@intFromEnum(Feature.fuse_aes)] = .{ - .llvm_name = "fuse-aes", - .description = "CPU fuses AES crypto operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fuse_literals)] = .{ - .llvm_name = "fuse-literals", - .description = "CPU fuses literal generation operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_blr)] = .{ - .llvm_name = "harden-sls-blr", - .description = "Harden against straight line speculation across indirect calls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_nocomdat)] = .{ - .llvm_name = "harden-sls-nocomdat", - .description = "Generate thunk code for SLS mitigation in the normal text section", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_retbr)] = .{ - .llvm_name = "harden-sls-retbr", - .description = "Harden against straight line speculation across RETurn and BranchRegister instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.has_v4t)] = .{ - .llvm_name = "v4t", - .description = "Support ARM v4T instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.has_v5t)] = .{ - .llvm_name = "v5t", - .description = "Support ARM v5T instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v4t, - }), - }; - result[@intFromEnum(Feature.has_v5te)] = .{ - .llvm_name = "v5te", - .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v5t, - }), - }; - result[@intFromEnum(Feature.has_v6)] = .{ - .llvm_name = "v6", - .description = "Support ARM v6 instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v5te, - }), - }; - result[@intFromEnum(Feature.has_v6k)] = .{ - .llvm_name = "v6k", - .description = "Support ARM v6k instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v6, - }), - }; - result[@intFromEnum(Feature.has_v6m)] = .{ - .llvm_name = "v6m", - .description = "Support ARM v6M instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v6, - }), - }; - result[@intFromEnum(Feature.has_v6t2)] = .{ - .llvm_name = "v6t2", - .description = "Support ARM v6t2 instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v6k, - .has_v8m, - .thumb2, - }), - }; - result[@intFromEnum(Feature.has_v7)] = .{ - .llvm_name = "v7", - .description = "Support ARM v7 instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v6t2, - .has_v7clrex, - }), - }; - result[@intFromEnum(Feature.has_v7clrex)] = .{ - .llvm_name = "v7clrex", - .description = "Has v7 clrex instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.has_v8)] = .{ - .llvm_name = "v8", - .description = "Support ARM v8 instructions", - .dependencies = featureSet(&[_]Feature{ - .acquire_release, - .has_v7, - .perfmon, - }), - }; - result[@intFromEnum(Feature.has_v8_1a)] = .{ - .llvm_name = "v8.1a", - .description = "Support ARM v8.1a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8, - }), - }; - result[@intFromEnum(Feature.has_v8_1m_main)] = .{ - .llvm_name = "v8.1m.main", - .description = "Support ARM v8-1M Mainline instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8m_main, - }), - }; - result[@intFromEnum(Feature.has_v8_2a)] = .{ - .llvm_name = "v8.2a", - .description = "Support ARM v8.2a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_1a, - }), - }; - result[@intFromEnum(Feature.has_v8_3a)] = .{ - .llvm_name = "v8.3a", - .description = "Support ARM v8.3a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_2a, - }), - }; - result[@intFromEnum(Feature.has_v8_4a)] = .{ - .llvm_name = "v8.4a", - .description = "Support ARM v8.4a instructions", - .dependencies = featureSet(&[_]Feature{ - .dotprod, - .has_v8_3a, - }), - }; - result[@intFromEnum(Feature.has_v8_5a)] = .{ - .llvm_name = "v8.5a", - .description = "Support ARM v8.5a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_4a, - .sb, - }), - }; - result[@intFromEnum(Feature.has_v8_6a)] = .{ - .llvm_name = "v8.6a", - .description = "Support ARM v8.6a instructions", - .dependencies = featureSet(&[_]Feature{ - .bf16, - .has_v8_5a, - .i8mm, - }), - }; - result[@intFromEnum(Feature.has_v8_7a)] = .{ - .llvm_name = "v8.7a", - .description = "Support ARM v8.7a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_6a, - }), - }; - result[@intFromEnum(Feature.has_v8_8a)] = .{ - .llvm_name = "v8.8a", - .description = "Support ARM v8.8a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_7a, - }), - }; - result[@intFromEnum(Feature.has_v8_9a)] = .{ - .llvm_name = "v8.9a", - .description = "Support ARM v8.9a instructions", - .dependencies = featureSet(&[_]Feature{ - .clrbhb, - .has_v8_8a, - }), - }; - result[@intFromEnum(Feature.has_v8m)] = .{ - .llvm_name = "v8m", - .description = "Support ARM v8M Baseline instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v6m, - }), - }; - result[@intFromEnum(Feature.has_v8m_main)] = .{ - .llvm_name = "v8m.main", - .description = "Support ARM v8M Mainline instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v7, - }), - }; - result[@intFromEnum(Feature.has_v9_1a)] = .{ - .llvm_name = "v9.1a", - .description = "Support ARM v9.1a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_6a, - .has_v9a, - }), - }; - result[@intFromEnum(Feature.has_v9_2a)] = .{ - .llvm_name = "v9.2a", - .description = "Support ARM v9.2a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_7a, - .has_v9_1a, - }), - }; - result[@intFromEnum(Feature.has_v9_3a)] = .{ - .llvm_name = "v9.3a", - .description = "Support ARM v9.3a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_8a, - .has_v9_2a, - }), - }; - result[@intFromEnum(Feature.has_v9_4a)] = .{ - .llvm_name = "v9.4a", - .description = "Support ARM v9.4a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_9a, - .has_v9_3a, - }), - }; - result[@intFromEnum(Feature.has_v9a)] = .{ - .llvm_name = "v9a", - .description = "Support ARM v9a instructions", - .dependencies = featureSet(&[_]Feature{ - .has_v8_5a, - }), - }; - result[@intFromEnum(Feature.hwdiv)] = .{ - .llvm_name = "hwdiv", - .description = "Enable divide instructions in Thumb", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hwdiv_arm)] = .{ - .llvm_name = "hwdiv-arm", - .description = "Enable divide instructions in ARM mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.i8mm)] = .{ - .llvm_name = "i8mm", - .description = "Enable Matrix Multiply Int8 Extension", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.iwmmxt)] = .{ - .llvm_name = "iwmmxt", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@intFromEnum(Feature.iwmmxt2)] = .{ - .llvm_name = "iwmmxt2", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@intFromEnum(Feature.lob)] = .{ - .llvm_name = "lob", - .description = "Enable Low Overhead Branch extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.long_calls)] = .{ - .llvm_name = "long-calls", - .description = "Generate calls via indirect call instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.loop_align)] = .{ - .llvm_name = "loop-align", - .description = "Prefer 32-bit alignment for loops", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.m3)] = .{ - .llvm_name = "m3", - .description = "Cortex-M3 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mclass)] = .{ - .llvm_name = "mclass", - .description = "Is microcontroller profile ('M' series)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mp)] = .{ - .llvm_name = "mp", - .description = "Supports Multiprocessing extension", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.muxed_units)] = .{ - .llvm_name = "muxed-units", - .description = "Has muxed AGU and NEON/FPU", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mve)] = .{ - .llvm_name = "mve", - .description = "Support M-Class Vector Extension with integer ops", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .fpregs16, - .fpregs64, - .has_v8_1m_main, - }), - }; - result[@intFromEnum(Feature.mve1beat)] = .{ - .llvm_name = "mve1beat", - .description = "Model MVE instructions as a 1 beat per tick architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mve2beat)] = .{ - .llvm_name = "mve2beat", - .description = "Model MVE instructions as a 2 beats per tick architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mve4beat)] = .{ - .llvm_name = "mve4beat", - .description = "Model MVE instructions as a 4 beats per tick architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mve_fp)] = .{ - .llvm_name = "mve.fp", - .description = "Support M-Class Vector Extension with integer and floating ops", - .dependencies = featureSet(&[_]Feature{ - .fullfp16, - .mve, - }), - }; - result[@intFromEnum(Feature.nacl_trap)] = .{ - .llvm_name = "nacl-trap", - .description = "NaCl trap", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.neon)] = .{ - .llvm_name = "neon", - .description = "Enable NEON instructions", - .dependencies = featureSet(&[_]Feature{ - .vfp3, - }), - }; - result[@intFromEnum(Feature.neon_fpmovs)] = .{ - .llvm_name = "neon-fpmovs", - .description = "Convert VMOVSR, VMOVRS, VMOVS to NEON", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.neonfp)] = .{ - .llvm_name = "neonfp", - .description = "Use NEON for single precision FP", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_branch_predictor)] = .{ - .llvm_name = "no-branch-predictor", - .description = "Has no branch predictor", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bti_at_return_twice)] = .{ - .llvm_name = "no-bti-at-return-twice", - .description = "Don't place a BTI instruction after a return-twice", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_movt)] = .{ - .llvm_name = "no-movt", - .description = "Don't use movt/movw pairs for 32-bit imms", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_neg_immediates)] = .{ - .llvm_name = "no-neg-immediates", - .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.noarm)] = .{ - .llvm_name = "noarm", - .description = "Does not support ARM mode execution", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nonpipelined_vfp)] = .{ - .llvm_name = "nonpipelined-vfp", - .description = "VFP instructions are not pipelined", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pacbti)] = .{ - .llvm_name = "pacbti", - .description = "Enable Pointer Authentication and Branch Target Identification", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.perfmon)] = .{ - .llvm_name = "perfmon", - .description = "Enable support for Performance Monitor extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_ishst)] = .{ - .llvm_name = "prefer-ishst", - .description = "Prefer ISHST barriers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_vmovsr)] = .{ - .llvm_name = "prefer-vmovsr", - .description = "Prefer VMOVSR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prof_unpr)] = .{ - .llvm_name = "prof-unpr", - .description = "Is profitable to unpredicate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.r4)] = .{ - .llvm_name = "r4", - .description = "Cortex-R4 ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ras)] = .{ - .llvm_name = "ras", - .description = "Enable Reliability, Availability and Serviceability extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rclass)] = .{ - .llvm_name = "rclass", - .description = "Is realtime profile ('R' series)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.read_tp_tpidrprw)] = .{ - .llvm_name = "read-tp-tpidrprw", - .description = "Reading thread pointer from TPIDRPRW register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.read_tp_tpidruro)] = .{ - .llvm_name = "read-tp-tpidruro", - .description = "Reading thread pointer from TPIDRURO register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.read_tp_tpidrurw)] = .{ - .llvm_name = "read-tp-tpidrurw", - .description = "Reading thread pointer from TPIDRURW register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_r9)] = .{ - .llvm_name = "reserve-r9", - .description = "Reserve R9, making it unavailable as GPR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ret_addr_stack)] = .{ - .llvm_name = "ret-addr-stack", - .description = "Has return address stack", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sb)] = .{ - .llvm_name = "sb", - .description = "Enable v8.5a Speculation Barrier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sha2)] = .{ - .llvm_name = "sha2", - .description = "Enable SHA1 and SHA256 support", - .dependencies = featureSet(&[_]Feature{ - .neon, - }), - }; - result[@intFromEnum(Feature.slow_fp_brcc)] = .{ - .llvm_name = "slow-fp-brcc", - .description = "FP compare + branch is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_load_D_subreg)] = .{ - .llvm_name = "slow-load-D-subreg", - .description = "Loading into D subregs is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_odd_reg)] = .{ - .llvm_name = "slow-odd-reg", - .description = "VLDM/VSTM starting with an odd register is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_vdup32)] = .{ - .llvm_name = "slow-vdup32", - .description = "Has slow VDUP32 - prefer VMOV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_vgetlni32)] = .{ - .llvm_name = "slow-vgetlni32", - .description = "Has slow VGETLNi32 - prefer VMOV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slowfpvfmx)] = .{ - .llvm_name = "slowfpvfmx", - .description = "Disable VFP / NEON FMA instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slowfpvmlx)] = .{ - .llvm_name = "slowfpvmlx", - .description = "Disable VFP / NEON MAC instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_float)] = .{ - .llvm_name = "soft-float", - .description = "Use software floating point features.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.splat_vfp_neon)] = .{ - .llvm_name = "splat-vfp-neon", - .description = "Splat register from VFP to NEON", - .dependencies = featureSet(&[_]Feature{ - .dont_widen_vmovs, - }), - }; - result[@intFromEnum(Feature.strict_align)] = .{ - .llvm_name = "strict-align", - .description = "Disallow all unaligned memory access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.swift)] = .{ - .llvm_name = "swift", - .description = "Swift ARM processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.thumb2)] = .{ - .llvm_name = "thumb2", - .description = "Enable Thumb2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.thumb_mode)] = .{ - .llvm_name = "thumb-mode", - .description = "Thumb mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.trustzone)] = .{ - .llvm_name = "trustzone", - .description = "Enable support for TrustZone security extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_mipipeliner)] = .{ - .llvm_name = "use-mipipeliner", - .description = "Use the MachinePipeliner", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_misched)] = .{ - .llvm_name = "use-misched", - .description = "Use the MachineScheduler", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v2)] = .{ - .llvm_name = null, - .description = "ARMv2 architecture", - .dependencies = featureSet(&[_]Feature{ - .strict_align, - }), - }; - result[@intFromEnum(Feature.v2a)] = .{ - .llvm_name = null, - .description = "ARMv2a architecture", - .dependencies = featureSet(&[_]Feature{ - .strict_align, - }), - }; - result[@intFromEnum(Feature.v3)] = .{ - .llvm_name = null, - .description = "ARMv3 architecture", - .dependencies = featureSet(&[_]Feature{ - .strict_align, - }), - }; - result[@intFromEnum(Feature.v3m)] = .{ - .llvm_name = null, - .description = "ARMv3m architecture", - .dependencies = featureSet(&[_]Feature{ - .strict_align, - }), - }; - result[@intFromEnum(Feature.v4)] = .{ - .llvm_name = "armv4", - .description = "ARMv4 architecture", - .dependencies = featureSet(&[_]Feature{ - .strict_align, - }), - }; - result[@intFromEnum(Feature.v4t)] = .{ - .llvm_name = "armv4t", - .description = "ARMv4t architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v4t, - .strict_align, - }), - }; - result[@intFromEnum(Feature.v5t)] = .{ - .llvm_name = "armv5t", - .description = "ARMv5t architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v5t, - .strict_align, - }), - }; - result[@intFromEnum(Feature.v5te)] = .{ - .llvm_name = "armv5te", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v5te, - .strict_align, - }), - }; - result[@intFromEnum(Feature.v5tej)] = .{ - .llvm_name = "armv5tej", - .description = "ARMv5tej architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v5te, - .strict_align, - }), - }; - result[@intFromEnum(Feature.v6)] = .{ - .llvm_name = "armv6", - .description = "ARMv6 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .has_v6, - }), - }; - result[@intFromEnum(Feature.v6j)] = .{ - .llvm_name = "armv6j", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v6, - }), - }; - result[@intFromEnum(Feature.v6k)] = .{ - .llvm_name = "armv6k", - .description = "ARMv6k architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v6k, - }), - }; - result[@intFromEnum(Feature.v6kz)] = .{ - .llvm_name = "armv6kz", - .description = "ARMv6kz architecture", - .dependencies = featureSet(&[_]Feature{ - .has_v6k, - .trustzone, - }), - }; - result[@intFromEnum(Feature.v6m)] = .{ - .llvm_name = "armv6-m", - .description = "ARMv6m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .has_v6m, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v6sm)] = .{ - .llvm_name = "armv6s-m", - .description = "ARMv6sm architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .has_v6m, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v6t2)] = .{ - .llvm_name = "armv6t2", - .description = "ARMv6t2 architecture", - .dependencies = featureSet(&[_]Feature{ - .dsp, - .has_v6t2, - }), - }; - result[@intFromEnum(Feature.v7a)] = .{ - .llvm_name = "armv7-a", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .has_v7, - .neon, - .perfmon, - }), - }; - result[@intFromEnum(Feature.v7em)] = .{ - .llvm_name = "armv7e-m", - .description = "ARMv7em architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .has_v7, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v7k)] = .{ - .llvm_name = "armv7k", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v7a, - }), - }; - result[@intFromEnum(Feature.v7m)] = .{ - .llvm_name = "armv7-m", - .description = "ARMv7m architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .has_v7, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v7r)] = .{ - .llvm_name = "armv7-r", - .description = "ARMv7r architecture", - .dependencies = featureSet(&[_]Feature{ - .db, - .dsp, - .has_v7, - .hwdiv, - .perfmon, - .rclass, - }), - }; - result[@intFromEnum(Feature.v7s)] = .{ - .llvm_name = "armv7s", - .description = "ARMv7a architecture", - .dependencies = featureSet(&[_]Feature{ - .v7a, - }), - }; - result[@intFromEnum(Feature.v7ve)] = .{ - .llvm_name = "armv7ve", - .description = "ARMv7ve architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .db, - .dsp, - .has_v7, - .mp, - .neon, - .perfmon, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_1a)] = .{ - .llvm_name = "armv8.1-a", - .description = "ARMv81a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_1a, - .mp, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_1m_main)] = .{ - .llvm_name = "armv8.1-m.main", - .description = "ARMv81mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .has_v8_1m_main, - .hwdiv, - .lob, - .mclass, - .noarm, - .ras, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v8_2a)] = .{ - .llvm_name = "armv8.2-a", - .description = "ARMv82a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_2a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_3a)] = .{ - .llvm_name = "armv8.3-a", - .description = "ARMv83a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_3a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_4a)] = .{ - .llvm_name = "armv8.4-a", - .description = "ARMv84a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_4a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_5a)] = .{ - .llvm_name = "armv8.5-a", - .description = "ARMv85a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_5a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_6a)] = .{ - .llvm_name = "armv8.6-a", - .description = "ARMv86a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_6a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_7a)] = .{ - .llvm_name = "armv8.7-a", - .description = "ARMv87a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_7a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_8a)] = .{ - .llvm_name = "armv8.8-a", - .description = "ARMv88a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_8a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8_9a)] = .{ - .llvm_name = "armv8.9-a", - .description = "ARMv89a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8_9a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8a)] = .{ - .llvm_name = "armv8-a", - .description = "ARMv8a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v8, - .mp, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v8m)] = .{ - .llvm_name = "armv8-m.base", - .description = "ARMv8mBaseline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .has_v7clrex, - .has_v8m, - .hwdiv, - .mclass, - .noarm, - .strict_align, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v8m_main)] = .{ - .llvm_name = "armv8-m.main", - .description = "ARMv8mMainline architecture", - .dependencies = featureSet(&[_]Feature{ - .@"8msecext", - .acquire_release, - .db, - .has_v8m_main, - .hwdiv, - .mclass, - .noarm, - .thumb_mode, - }), - }; - result[@intFromEnum(Feature.v8r)] = .{ - .llvm_name = "armv8-r", - .description = "ARMv8r architecture", - .dependencies = featureSet(&[_]Feature{ - .crc, - .db, - .dfb, - .dsp, - .fp_armv8, - .has_v8, - .mp, - .neon, - .rclass, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v9_1a)] = .{ - .llvm_name = "armv9.1-a", - .description = "ARMv91a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .db, - .dsp, - .fp_armv8, - .has_v9_1a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v9_2a)] = .{ - .llvm_name = "armv9.2-a", - .description = "ARMv92a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .db, - .dsp, - .fp_armv8, - .has_v9_2a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v9_3a)] = .{ - .llvm_name = "armv9.3-a", - .description = "ARMv93a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .crypto, - .db, - .dsp, - .fp_armv8, - .has_v9_3a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v9_4a)] = .{ - .llvm_name = "armv9.4-a", - .description = "ARMv94a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .db, - .dsp, - .fp_armv8, - .has_v9_4a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.v9a)] = .{ - .llvm_name = "armv9-a", - .description = "ARMv9a architecture", - .dependencies = featureSet(&[_]Feature{ - .aclass, - .crc, - .db, - .dsp, - .fp_armv8, - .has_v9a, - .mp, - .ras, - .trustzone, - .virtualization, - }), - }; - result[@intFromEnum(Feature.vfp2)] = .{ - .llvm_name = "vfp2", - .description = "Enable VFP2 instructions", - .dependencies = featureSet(&[_]Feature{ - .fp64, - .vfp2sp, - }), - }; - result[@intFromEnum(Feature.vfp2sp)] = .{ - .llvm_name = "vfp2sp", - .description = "Enable VFP2 instructions with no double precision", - .dependencies = featureSet(&[_]Feature{ - .fpregs, - }), - }; - result[@intFromEnum(Feature.vfp3)] = .{ - .llvm_name = "vfp3", - .description = "Enable VFP3 instructions", - .dependencies = featureSet(&[_]Feature{ - .vfp3d16, - .vfp3sp, - }), - }; - result[@intFromEnum(Feature.vfp3d16)] = .{ - .llvm_name = "vfp3d16", - .description = "Enable VFP3 instructions with only 16 d-registers", - .dependencies = featureSet(&[_]Feature{ - .vfp2, - .vfp3d16sp, - }), - }; - result[@intFromEnum(Feature.vfp3d16sp)] = .{ - .llvm_name = "vfp3d16sp", - .description = "Enable VFP3 instructions with only 16 d-registers and no double precision", - .dependencies = featureSet(&[_]Feature{ - .vfp2sp, - }), - }; - result[@intFromEnum(Feature.vfp3sp)] = .{ - .llvm_name = "vfp3sp", - .description = "Enable VFP3 instructions with no double precision", - .dependencies = featureSet(&[_]Feature{ - .d32, - .vfp3d16sp, - }), - }; - result[@intFromEnum(Feature.vfp4)] = .{ - .llvm_name = "vfp4", - .description = "Enable VFP4 instructions", - .dependencies = featureSet(&[_]Feature{ - .vfp3, - .vfp4d16, - .vfp4sp, - }), - }; - result[@intFromEnum(Feature.vfp4d16)] = .{ - .llvm_name = "vfp4d16", - .description = "Enable VFP4 instructions with only 16 d-registers", - .dependencies = featureSet(&[_]Feature{ - .vfp3d16, - .vfp4d16sp, - }), - }; - result[@intFromEnum(Feature.vfp4d16sp)] = .{ - .llvm_name = "vfp4d16sp", - .description = "Enable VFP4 instructions with only 16 d-registers and no double precision", - .dependencies = featureSet(&[_]Feature{ - .fp16, - .vfp3d16sp, - }), - }; - result[@intFromEnum(Feature.vfp4sp)] = .{ - .llvm_name = "vfp4sp", - .description = "Enable VFP4 instructions with no double precision", - .dependencies = featureSet(&[_]Feature{ - .vfp3sp, - .vfp4d16sp, - }), - }; - result[@intFromEnum(Feature.virtualization)] = .{ - .llvm_name = "virtualization", - .description = "Supports Virtualization extension", - .dependencies = featureSet(&[_]Feature{ - .hwdiv, - .hwdiv_arm, - }), - }; - result[@intFromEnum(Feature.vldn_align)] = .{ - .llvm_name = "vldn-align", - .description = "Check for VLDn unaligned access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vmlx_forwarding)] = .{ - .llvm_name = "vmlx-forwarding", - .description = "Has multiplier accumulator forwarding", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vmlx_hazards)] = .{ - .llvm_name = "vmlx-hazards", - .description = "Has VMLx hazards", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.wide_stride_vfp)] = .{ - .llvm_name = "wide-stride-vfp", - .description = "Use a wide stride when allocating VFP registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xscale)] = .{ - .llvm_name = "xscale", - .description = "ARMv5te architecture", - .dependencies = featureSet(&[_]Feature{ - .v5te, - }), - }; - result[@intFromEnum(Feature.zcz)] = .{ - .llvm_name = "zcz", - .description = "Has zero-cycle zeroing instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const arm1020e = CpuModel{ - .name = "arm1020e", - .llvm_name = "arm1020e", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm1020t = CpuModel{ - .name = "arm1020t", - .llvm_name = "arm1020t", - .features = featureSet(&[_]Feature{ - .v5t, - }), - }; - pub const arm1022e = CpuModel{ - .name = "arm1022e", - .llvm_name = "arm1022e", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm10e = CpuModel{ - .name = "arm10e", - .llvm_name = "arm10e", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm10tdmi = CpuModel{ - .name = "arm10tdmi", - .llvm_name = "arm10tdmi", - .features = featureSet(&[_]Feature{ - .v5t, - }), - }; - pub const arm1136j_s = CpuModel{ - .name = "arm1136j_s", - .llvm_name = "arm1136j-s", - .features = featureSet(&[_]Feature{ - .v6, - }), - }; - pub const arm1136jf_s = CpuModel{ - .name = "arm1136jf_s", - .llvm_name = "arm1136jf-s", - .features = featureSet(&[_]Feature{ - .slowfpvmlx, - .v6, - .vfp2, - }), - }; - pub const arm1156t2_s = CpuModel{ - .name = "arm1156t2_s", - .llvm_name = "arm1156t2-s", - .features = featureSet(&[_]Feature{ - .v6t2, - }), - }; - pub const arm1156t2f_s = CpuModel{ - .name = "arm1156t2f_s", - .llvm_name = "arm1156t2f-s", - .features = featureSet(&[_]Feature{ - .slowfpvmlx, - .v6t2, - .vfp2, - }), - }; - pub const arm1176jz_s = CpuModel{ - .name = "arm1176jz_s", - .llvm_name = "arm1176jz-s", - .features = featureSet(&[_]Feature{ - .v6kz, - }), - }; - pub const arm1176jzf_s = CpuModel{ - .name = "arm1176jzf_s", - .llvm_name = "arm1176jzf-s", - .features = featureSet(&[_]Feature{ - .slowfpvmlx, - .v6kz, - .vfp2, - }), - }; - pub const arm710t = CpuModel{ - .name = "arm710t", - .llvm_name = "arm710t", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm720t = CpuModel{ - .name = "arm720t", - .llvm_name = "arm720t", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm7tdmi = CpuModel{ - .name = "arm7tdmi", - .llvm_name = "arm7tdmi", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm7tdmi_s = CpuModel{ - .name = "arm7tdmi_s", - .llvm_name = "arm7tdmi-s", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm8 = CpuModel{ - .name = "arm8", - .llvm_name = "arm8", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const arm810 = CpuModel{ - .name = "arm810", - .llvm_name = "arm810", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const arm9 = CpuModel{ - .name = "arm9", - .llvm_name = "arm9", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm920 = CpuModel{ - .name = "arm920", - .llvm_name = "arm920", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm920t = CpuModel{ - .name = "arm920t", - .llvm_name = "arm920t", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm922t = CpuModel{ - .name = "arm922t", - .llvm_name = "arm922t", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm926ej_s = CpuModel{ - .name = "arm926ej_s", - .llvm_name = "arm926ej-s", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm940t = CpuModel{ - .name = "arm940t", - .llvm_name = "arm940t", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const arm946e_s = CpuModel{ - .name = "arm946e_s", - .llvm_name = "arm946e-s", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm966e_s = CpuModel{ - .name = "arm966e_s", - .llvm_name = "arm966e-s", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm968e_s = CpuModel{ - .name = "arm968e_s", - .llvm_name = "arm968e-s", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm9e = CpuModel{ - .name = "arm9e", - .llvm_name = "arm9e", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const arm9tdmi = CpuModel{ - .name = "arm9tdmi", - .llvm_name = "arm9tdmi", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const baseline = CpuModel{ - .name = "baseline", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .v7a, - }), - }; - pub const cortex_a12 = CpuModel{ - .name = "cortex_a12", - .llvm_name = "cortex-a12", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .mp, - .ret_addr_stack, - .trustzone, - .v7a, - .vfp4, - .virtualization, - .vmlx_forwarding, - }), - }; - pub const cortex_a15 = CpuModel{ - .name = "cortex_a15", - .llvm_name = "cortex-a15", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .mp, - .muxed_units, - .ret_addr_stack, - .splat_vfp_neon, - .trustzone, - .v7a, - .vfp4, - .virtualization, - .vldn_align, - }), - }; - pub const cortex_a17 = CpuModel{ - .name = "cortex_a17", - .llvm_name = "cortex-a17", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .mp, - .ret_addr_stack, - .trustzone, - .v7a, - .vfp4, - .virtualization, - .vmlx_forwarding, - }), - }; - pub const cortex_a32 = CpuModel{ - .name = "cortex_a32", - .llvm_name = "cortex-a32", - .features = featureSet(&[_]Feature{ - .v8a, - }), - }; - pub const cortex_a35 = CpuModel{ - .name = "cortex_a35", - .llvm_name = "cortex-a35", - .features = featureSet(&[_]Feature{ - .v8a, - }), - }; - pub const cortex_a5 = CpuModel{ - .name = "cortex_a5", - .llvm_name = "cortex-a5", - .features = featureSet(&[_]Feature{ - .mp, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .trustzone, - .v7a, - .vfp4, - .vmlx_forwarding, - }), - }; - pub const cortex_a53 = CpuModel{ - .name = "cortex_a53", - .llvm_name = "cortex-a53", - .features = featureSet(&[_]Feature{ - .fpao, - .v8a, - }), - }; - pub const cortex_a55 = CpuModel{ - .name = "cortex_a55", - .llvm_name = "cortex-a55", - .features = featureSet(&[_]Feature{ - .dotprod, - .v8_2a, - }), - }; - pub const cortex_a57 = CpuModel{ - .name = "cortex_a57", - .llvm_name = "cortex-a57", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .cheap_predicable_cpsr, - .fix_cortex_a57_aes_1742098, - .fpao, - .v8a, - }), - }; - pub const cortex_a7 = CpuModel{ - .name = "cortex_a7", - .llvm_name = "cortex-a7", - .features = featureSet(&[_]Feature{ - .mp, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .trustzone, - .v7a, - .vfp4, - .virtualization, - .vmlx_forwarding, - .vmlx_hazards, - }), - }; - pub const cortex_a710 = CpuModel{ - .name = "cortex_a710", - .llvm_name = "cortex-a710", - .features = featureSet(&[_]Feature{ - .bf16, - .fp16fml, - .i8mm, - .v9a, - }), - }; - pub const cortex_a72 = CpuModel{ - .name = "cortex_a72", - .llvm_name = "cortex-a72", - .features = featureSet(&[_]Feature{ - .fix_cortex_a57_aes_1742098, - .v8a, - }), - }; - pub const cortex_a73 = CpuModel{ - .name = "cortex_a73", - .llvm_name = "cortex-a73", - .features = featureSet(&[_]Feature{ - .v8a, - }), - }; - pub const cortex_a75 = CpuModel{ - .name = "cortex_a75", - .llvm_name = "cortex-a75", - .features = featureSet(&[_]Feature{ - .dotprod, - .v8_2a, - }), - }; - pub const cortex_a76 = CpuModel{ - .name = "cortex_a76", - .llvm_name = "cortex-a76", - .features = featureSet(&[_]Feature{ - .a76, - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a76ae = CpuModel{ - .name = "cortex_a76ae", - .llvm_name = "cortex-a76ae", - .features = featureSet(&[_]Feature{ - .a76, - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a77 = CpuModel{ - .name = "cortex_a77", - .llvm_name = "cortex-a77", - .features = featureSet(&[_]Feature{ - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a78 = CpuModel{ - .name = "cortex_a78", - .llvm_name = "cortex-a78", - .features = featureSet(&[_]Feature{ - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a78c = CpuModel{ - .name = "cortex_a78c", - .llvm_name = "cortex-a78c", - .features = featureSet(&[_]Feature{ - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_a8 = CpuModel{ - .name = "cortex_a8", - .llvm_name = "cortex-a8", - .features = featureSet(&[_]Feature{ - .nonpipelined_vfp, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .trustzone, - .v7a, - .vmlx_forwarding, - .vmlx_hazards, - }), - }; - pub const cortex_a9 = CpuModel{ - .name = "cortex_a9", - .llvm_name = "cortex-a9", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .expand_fp_mlx, - .fp16, - .mp, - .muxed_units, - .neon_fpmovs, - .prefer_vmovsr, - .ret_addr_stack, - .trustzone, - .v7a, - .vldn_align, - .vmlx_forwarding, - .vmlx_hazards, - }), - }; - pub const cortex_m0 = CpuModel{ - .name = "cortex_m0", - .llvm_name = "cortex-m0", - .features = featureSet(&[_]Feature{ - .no_branch_predictor, - .v6m, - }), - }; - pub const cortex_m0plus = CpuModel{ - .name = "cortex_m0plus", - .llvm_name = "cortex-m0plus", - .features = featureSet(&[_]Feature{ - .no_branch_predictor, - .v6m, - }), - }; - pub const cortex_m1 = CpuModel{ - .name = "cortex_m1", - .llvm_name = "cortex-m1", - .features = featureSet(&[_]Feature{ - .no_branch_predictor, - .v6m, - }), - }; - pub const cortex_m23 = CpuModel{ - .name = "cortex_m23", - .llvm_name = "cortex-m23", - .features = featureSet(&[_]Feature{ - .no_branch_predictor, - .no_movt, - .v8m, - }), - }; - pub const cortex_m3 = CpuModel{ - .name = "cortex_m3", - .llvm_name = "cortex-m3", - .features = featureSet(&[_]Feature{ - .loop_align, - .m3, - .no_branch_predictor, - .use_misched, - .v7m, - }), - }; - pub const cortex_m33 = CpuModel{ - .name = "cortex_m33", - .llvm_name = "cortex-m33", - .features = featureSet(&[_]Feature{ - .dsp, - .fix_cmse_cve_2021_35465, - .fp_armv8d16sp, - .loop_align, - .no_branch_predictor, - .slowfpvfmx, - .slowfpvmlx, - .use_misched, - .v8m_main, - }), - }; - pub const cortex_m35p = CpuModel{ - .name = "cortex_m35p", - .llvm_name = "cortex-m35p", - .features = featureSet(&[_]Feature{ - .dsp, - .fix_cmse_cve_2021_35465, - .fp_armv8d16sp, - .loop_align, - .no_branch_predictor, - .slowfpvfmx, - .slowfpvmlx, - .use_misched, - .v8m_main, - }), - }; - pub const cortex_m4 = CpuModel{ - .name = "cortex_m4", - .llvm_name = "cortex-m4", - .features = featureSet(&[_]Feature{ - .loop_align, - .no_branch_predictor, - .slowfpvfmx, - .slowfpvmlx, - .use_misched, - .v7em, - .vfp4d16sp, - }), - }; - pub const cortex_m55 = CpuModel{ - .name = "cortex_m55", - .llvm_name = "cortex-m55", - .features = featureSet(&[_]Feature{ - .fix_cmse_cve_2021_35465, - .fp_armv8d16, - .loop_align, - .mve_fp, - .no_branch_predictor, - .slowfpvmlx, - .use_misched, - .v8_1m_main, - }), - }; - pub const cortex_m7 = CpuModel{ - .name = "cortex_m7", - .llvm_name = "cortex-m7", - .features = featureSet(&[_]Feature{ - .fp_armv8d16, - .use_mipipeliner, - .use_misched, - .v7em, - }), - }; - pub const cortex_m85 = CpuModel{ - .name = "cortex_m85", - .llvm_name = "cortex-m85", - .features = featureSet(&[_]Feature{ - .fp_armv8d16, - .mve_fp, - .pacbti, - .use_misched, - .v8_1m_main, - }), - }; - pub const cortex_r4 = CpuModel{ - .name = "cortex_r4", - .llvm_name = "cortex-r4", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .r4, - .ret_addr_stack, - .v7r, - }), - }; - pub const cortex_r4f = CpuModel{ - .name = "cortex_r4f", - .llvm_name = "cortex-r4f", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .r4, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .v7r, - .vfp3d16, - }), - }; - pub const cortex_r5 = CpuModel{ - .name = "cortex_r5", - .llvm_name = "cortex-r5", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .hwdiv_arm, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .v7r, - .vfp3d16, - }), - }; - pub const cortex_r52 = CpuModel{ - .name = "cortex_r52", - .llvm_name = "cortex-r52", - .features = featureSet(&[_]Feature{ - .fpao, - .use_misched, - .v8r, - }), - }; - pub const cortex_r7 = CpuModel{ - .name = "cortex_r7", - .llvm_name = "cortex-r7", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .fp16, - .hwdiv_arm, - .mp, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .v7r, - .vfp3d16, - }), - }; - pub const cortex_r8 = CpuModel{ - .name = "cortex_r8", - .llvm_name = "cortex-r8", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .fp16, - .hwdiv_arm, - .mp, - .ret_addr_stack, - .slow_fp_brcc, - .slowfpvfmx, - .slowfpvmlx, - .v7r, - .vfp3d16, - }), - }; - pub const cortex_x1 = CpuModel{ - .name = "cortex_x1", - .llvm_name = "cortex-x1", - .features = featureSet(&[_]Feature{ - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cortex_x1c = CpuModel{ - .name = "cortex_x1c", - .llvm_name = "cortex-x1c", - .features = featureSet(&[_]Feature{ - .dotprod, - .fullfp16, - .v8_2a, - }), - }; - pub const cyclone = CpuModel{ - .name = "cyclone", - .llvm_name = "cyclone", - .features = featureSet(&[_]Feature{ - .avoid_movs_shop, - .avoid_partial_cpsr, - .disable_postra_scheduler, - .neonfp, - .ret_addr_stack, - .slowfpvfmx, - .slowfpvmlx, - .swift, - .use_misched, - .v8a, - .zcz, - }), - }; - pub const ep9312 = CpuModel{ - .name = "ep9312", - .llvm_name = "ep9312", - .features = featureSet(&[_]Feature{ - .v4t, - }), - }; - pub const exynos_m1 = CpuModel{ - .name = "exynos_m1", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .exynos, - .v8a, - }), - }; - pub const exynos_m2 = CpuModel{ - .name = "exynos_m2", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .exynos, - .v8a, - }), - }; - pub const exynos_m3 = CpuModel{ - .name = "exynos_m3", - .llvm_name = "exynos-m3", - .features = featureSet(&[_]Feature{ - .exynos, - .v8a, - }), - }; - pub const exynos_m4 = CpuModel{ - .name = "exynos_m4", - .llvm_name = "exynos-m4", - .features = featureSet(&[_]Feature{ - .dotprod, - .exynos, - .fullfp16, - .v8_2a, - }), - }; - pub const exynos_m5 = CpuModel{ - .name = "exynos_m5", - .llvm_name = "exynos-m5", - .features = featureSet(&[_]Feature{ - .dotprod, - .exynos, - .fullfp16, - .v8_2a, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const iwmmxt = CpuModel{ - .name = "iwmmxt", - .llvm_name = "iwmmxt", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; - pub const krait = CpuModel{ - .name = "krait", - .llvm_name = "krait", - .features = featureSet(&[_]Feature{ - .avoid_partial_cpsr, - .hwdiv, - .hwdiv_arm, - .muxed_units, - .ret_addr_stack, - .v7a, - .vfp4, - .vldn_align, - .vmlx_forwarding, - }), - }; - pub const kryo = CpuModel{ - .name = "kryo", - .llvm_name = "kryo", - .features = featureSet(&[_]Feature{ - .v8a, - }), - }; - pub const mpcore = CpuModel{ - .name = "mpcore", - .llvm_name = "mpcore", - .features = featureSet(&[_]Feature{ - .slowfpvmlx, - .v6k, - .vfp2, - }), - }; - pub const mpcorenovfp = CpuModel{ - .name = "mpcorenovfp", - .llvm_name = "mpcorenovfp", - .features = featureSet(&[_]Feature{ - .v6k, - }), - }; - pub const neoverse_n1 = CpuModel{ - .name = "neoverse_n1", - .llvm_name = "neoverse-n1", - .features = featureSet(&[_]Feature{ - .dotprod, - .v8_2a, - }), - }; - pub const neoverse_n2 = CpuModel{ - .name = "neoverse_n2", - .llvm_name = "neoverse-n2", - .features = featureSet(&[_]Feature{ - .bf16, - .i8mm, - .v8_5a, - }), - }; - pub const neoverse_v1 = CpuModel{ - .name = "neoverse_v1", - .llvm_name = "neoverse-v1", - .features = featureSet(&[_]Feature{ - .bf16, - .fullfp16, - .i8mm, - .v8_4a, - }), - }; - pub const sc000 = CpuModel{ - .name = "sc000", - .llvm_name = "sc000", - .features = featureSet(&[_]Feature{ - .no_branch_predictor, - .v6m, - }), - }; - pub const sc300 = CpuModel{ - .name = "sc300", - .llvm_name = "sc300", - .features = featureSet(&[_]Feature{ - .m3, - .no_branch_predictor, - .use_misched, - .v7m, - }), - }; - pub const strongarm = CpuModel{ - .name = "strongarm", - .llvm_name = "strongarm", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const strongarm110 = CpuModel{ - .name = "strongarm110", - .llvm_name = "strongarm110", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const strongarm1100 = CpuModel{ - .name = "strongarm1100", - .llvm_name = "strongarm1100", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const strongarm1110 = CpuModel{ - .name = "strongarm1110", - .llvm_name = "strongarm1110", - .features = featureSet(&[_]Feature{ - .v4, - }), - }; - pub const swift = CpuModel{ - .name = "swift", - .llvm_name = "swift", - .features = featureSet(&[_]Feature{ - .avoid_movs_shop, - .avoid_partial_cpsr, - .disable_postra_scheduler, - .hwdiv, - .hwdiv_arm, - .mp, - .neonfp, - .prefer_ishst, - .prof_unpr, - .ret_addr_stack, - .slow_load_D_subreg, - .slow_odd_reg, - .slow_vdup32, - .slow_vgetlni32, - .slowfpvfmx, - .slowfpvmlx, - .swift, - .use_misched, - .v7a, - .vfp4, - .vmlx_hazards, - .wide_stride_vfp, - }), - }; - pub const xscale = CpuModel{ - .name = "xscale", - .llvm_name = "xscale", - .features = featureSet(&[_]Feature{ - .v5te, - }), - }; -}; diff --git a/lib/std/target/avr.zig b/lib/std/target/avr.zig deleted file mode 100644 index bda274d2e6434a040396e37ef031fac4be865d86..0000000000000000000000000000000000000000 --- a/lib/std/target/avr.zig +++ /dev/null @@ -1,2607 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - addsubiw, - avr0, - avr1, - avr2, - avr25, - avr3, - avr31, - avr35, - avr4, - avr5, - avr51, - avr6, - avrtiny, - @"break", - des, - eijmpcall, - elpm, - elpmx, - ijmpcall, - jmpcall, - lowbytefirst, - lpm, - lpmx, - memmappedregs, - movw, - mul, - rmw, - smallstack, - special, - spm, - spmx, - sram, - tinyencoding, - xmega, - xmega3, - xmegau, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.addsubiw)] = .{ - .llvm_name = "addsubiw", - .description = "Enable 16-bit register-immediate addition and subtraction instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.avr0)] = .{ - .llvm_name = "avr0", - .description = "The device is a part of the avr0 family", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.avr1)] = .{ - .llvm_name = "avr1", - .description = "The device is a part of the avr1 family", - .dependencies = featureSet(&[_]Feature{ - .avr0, - .lpm, - .memmappedregs, - }), - }; - result[@intFromEnum(Feature.avr2)] = .{ - .llvm_name = "avr2", - .description = "The device is a part of the avr2 family", - .dependencies = featureSet(&[_]Feature{ - .addsubiw, - .avr1, - .ijmpcall, - .sram, - }), - }; - result[@intFromEnum(Feature.avr25)] = .{ - .llvm_name = "avr25", - .description = "The device is a part of the avr25 family", - .dependencies = featureSet(&[_]Feature{ - .avr2, - .@"break", - .lpmx, - .movw, - .spm, - }), - }; - result[@intFromEnum(Feature.avr3)] = .{ - .llvm_name = "avr3", - .description = "The device is a part of the avr3 family", - .dependencies = featureSet(&[_]Feature{ - .avr2, - .jmpcall, - }), - }; - result[@intFromEnum(Feature.avr31)] = .{ - .llvm_name = "avr31", - .description = "The device is a part of the avr31 family", - .dependencies = featureSet(&[_]Feature{ - .avr3, - .elpm, - }), - }; - result[@intFromEnum(Feature.avr35)] = .{ - .llvm_name = "avr35", - .description = "The device is a part of the avr35 family", - .dependencies = featureSet(&[_]Feature{ - .avr3, - .@"break", - .lpmx, - .movw, - .spm, - }), - }; - result[@intFromEnum(Feature.avr4)] = .{ - .llvm_name = "avr4", - .description = "The device is a part of the avr4 family", - .dependencies = featureSet(&[_]Feature{ - .avr2, - .@"break", - .lpmx, - .movw, - .mul, - .spm, - }), - }; - result[@intFromEnum(Feature.avr5)] = .{ - .llvm_name = "avr5", - .description = "The device is a part of the avr5 family", - .dependencies = featureSet(&[_]Feature{ - .avr3, - .@"break", - .lpmx, - .movw, - .mul, - .spm, - }), - }; - result[@intFromEnum(Feature.avr51)] = .{ - .llvm_name = "avr51", - .description = "The device is a part of the avr51 family", - .dependencies = featureSet(&[_]Feature{ - .avr5, - .elpm, - .elpmx, - }), - }; - result[@intFromEnum(Feature.avr6)] = .{ - .llvm_name = "avr6", - .description = "The device is a part of the avr6 family", - .dependencies = featureSet(&[_]Feature{ - .avr51, - .eijmpcall, - }), - }; - result[@intFromEnum(Feature.avrtiny)] = .{ - .llvm_name = "avrtiny", - .description = "The device is a part of the avrtiny family", - .dependencies = featureSet(&[_]Feature{ - .avr0, - .@"break", - .smallstack, - .sram, - .tinyencoding, - }), - }; - result[@intFromEnum(Feature.@"break")] = .{ - .llvm_name = "break", - .description = "The device supports the `BREAK` debugging instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.des)] = .{ - .llvm_name = "des", - .description = "The device supports the `DES k` encryption instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.eijmpcall)] = .{ - .llvm_name = "eijmpcall", - .description = "The device supports the `EIJMP`/`EICALL` instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.elpm)] = .{ - .llvm_name = "elpm", - .description = "The device supports the ELPM instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.elpmx)] = .{ - .llvm_name = "elpmx", - .description = "The device supports the `ELPM Rd, Z[+]` instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ijmpcall)] = .{ - .llvm_name = "ijmpcall", - .description = "The device supports `IJMP`/`ICALL`instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.jmpcall)] = .{ - .llvm_name = "jmpcall", - .description = "The device supports the `JMP` and `CALL` instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lowbytefirst)] = .{ - .llvm_name = "lowbytefirst", - .description = "Do the low byte first when writing a 16-bit port or storing a 16-bit word", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lpm)] = .{ - .llvm_name = "lpm", - .description = "The device supports the `LPM` instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lpmx)] = .{ - .llvm_name = "lpmx", - .description = "The device supports the `LPM Rd, Z[+]` instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.memmappedregs)] = .{ - .llvm_name = "memmappedregs", - .description = "The device has CPU registers mapped in data address space", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.movw)] = .{ - .llvm_name = "movw", - .description = "The device supports the 16-bit MOVW instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mul)] = .{ - .llvm_name = "mul", - .description = "The device supports the multiplication instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rmw)] = .{ - .llvm_name = "rmw", - .description = "The device supports the read-write-modify instructions: XCH, LAS, LAC, LAT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.smallstack)] = .{ - .llvm_name = "smallstack", - .description = "The device has an 8-bit stack pointer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.special)] = .{ - .llvm_name = "special", - .description = "Enable use of the entire instruction set - used for debugging", - .dependencies = featureSet(&[_]Feature{ - .addsubiw, - .@"break", - .des, - .eijmpcall, - .elpm, - .elpmx, - .ijmpcall, - .jmpcall, - .lpm, - .lpmx, - .memmappedregs, - .movw, - .mul, - .rmw, - .spm, - .spmx, - .sram, - }), - }; - result[@intFromEnum(Feature.spm)] = .{ - .llvm_name = "spm", - .description = "The device supports the `SPM` instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.spmx)] = .{ - .llvm_name = "spmx", - .description = "The device supports the `SPM Z+` instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sram)] = .{ - .llvm_name = "sram", - .description = "The device has random access memory", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tinyencoding)] = .{ - .llvm_name = "tinyencoding", - .description = "The device has Tiny core specific instruction encodings", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xmega)] = .{ - .llvm_name = "xmega", - .description = "The device is a part of the xmega family", - .dependencies = featureSet(&[_]Feature{ - .addsubiw, - .avr0, - .@"break", - .des, - .eijmpcall, - .elpm, - .elpmx, - .ijmpcall, - .jmpcall, - .lowbytefirst, - .lpm, - .lpmx, - .movw, - .mul, - .spm, - .spmx, - .sram, - }), - }; - result[@intFromEnum(Feature.xmega3)] = .{ - .llvm_name = "xmega3", - .description = "The device is a part of the xmega3 family", - .dependencies = featureSet(&[_]Feature{ - .addsubiw, - .avr0, - .@"break", - .ijmpcall, - .jmpcall, - .lowbytefirst, - .lpm, - .lpmx, - .movw, - .mul, - .sram, - }), - }; - result[@intFromEnum(Feature.xmegau)] = .{ - .llvm_name = "xmegau", - .description = "The device is a part of the xmegau family", - .dependencies = featureSet(&[_]Feature{ - .rmw, - .xmega, - }), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const at43usb320 = CpuModel{ - .name = "at43usb320", - .llvm_name = "at43usb320", - .features = featureSet(&[_]Feature{ - .avr31, - }), - }; - pub const at43usb355 = CpuModel{ - .name = "at43usb355", - .llvm_name = "at43usb355", - .features = featureSet(&[_]Feature{ - .avr3, - }), - }; - pub const at76c711 = CpuModel{ - .name = "at76c711", - .llvm_name = "at76c711", - .features = featureSet(&[_]Feature{ - .avr3, - }), - }; - pub const at86rf401 = CpuModel{ - .name = "at86rf401", - .llvm_name = "at86rf401", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .movw, - }), - }; - pub const at90c8534 = CpuModel{ - .name = "at90c8534", - .llvm_name = "at90c8534", - .features = featureSet(&[_]Feature{ - .avr2, - }), - }; - pub const at90can128 = CpuModel{ - .name = "at90can128", - .llvm_name = "at90can128", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const at90can32 = CpuModel{ - .name = "at90can32", - .llvm_name = "at90can32", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90can64 = CpuModel{ - .name = "at90can64", - .llvm_name = "at90can64", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90pwm1 = CpuModel{ - .name = "at90pwm1", - .llvm_name = "at90pwm1", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90pwm161 = CpuModel{ - .name = "at90pwm161", - .llvm_name = "at90pwm161", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90pwm2 = CpuModel{ - .name = "at90pwm2", - .llvm_name = "at90pwm2", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90pwm216 = CpuModel{ - .name = "at90pwm216", - .llvm_name = "at90pwm216", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90pwm2b = CpuModel{ - .name = "at90pwm2b", - .llvm_name = "at90pwm2b", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90pwm3 = CpuModel{ - .name = "at90pwm3", - .llvm_name = "at90pwm3", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90pwm316 = CpuModel{ - .name = "at90pwm316", - .llvm_name = "at90pwm316", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90pwm3b = CpuModel{ - .name = "at90pwm3b", - .llvm_name = "at90pwm3b", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90pwm81 = CpuModel{ - .name = "at90pwm81", - .llvm_name = "at90pwm81", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const at90s1200 = CpuModel{ - .name = "at90s1200", - .llvm_name = "at90s1200", - .features = featureSet(&[_]Feature{ - .avr0, - .smallstack, - }), - }; - pub const at90s2313 = CpuModel{ - .name = "at90s2313", - .llvm_name = "at90s2313", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s2323 = CpuModel{ - .name = "at90s2323", - .llvm_name = "at90s2323", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s2333 = CpuModel{ - .name = "at90s2333", - .llvm_name = "at90s2333", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s2343 = CpuModel{ - .name = "at90s2343", - .llvm_name = "at90s2343", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s4414 = CpuModel{ - .name = "at90s4414", - .llvm_name = "at90s4414", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s4433 = CpuModel{ - .name = "at90s4433", - .llvm_name = "at90s4433", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s4434 = CpuModel{ - .name = "at90s4434", - .llvm_name = "at90s4434", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const at90s8515 = CpuModel{ - .name = "at90s8515", - .llvm_name = "at90s8515", - .features = featureSet(&[_]Feature{ - .avr2, - }), - }; - pub const at90s8535 = CpuModel{ - .name = "at90s8535", - .llvm_name = "at90s8535", - .features = featureSet(&[_]Feature{ - .avr2, - }), - }; - pub const at90scr100 = CpuModel{ - .name = "at90scr100", - .llvm_name = "at90scr100", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90usb1286 = CpuModel{ - .name = "at90usb1286", - .llvm_name = "at90usb1286", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const at90usb1287 = CpuModel{ - .name = "at90usb1287", - .llvm_name = "at90usb1287", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const at90usb162 = CpuModel{ - .name = "at90usb162", - .llvm_name = "at90usb162", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const at90usb646 = CpuModel{ - .name = "at90usb646", - .llvm_name = "at90usb646", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90usb647 = CpuModel{ - .name = "at90usb647", - .llvm_name = "at90usb647", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const at90usb82 = CpuModel{ - .name = "at90usb82", - .llvm_name = "at90usb82", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const at94k = CpuModel{ - .name = "at94k", - .llvm_name = "at94k", - .features = featureSet(&[_]Feature{ - .avr3, - .lpmx, - .movw, - .mul, - }), - }; - pub const ata5272 = CpuModel{ - .name = "ata5272", - .llvm_name = "ata5272", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const ata5505 = CpuModel{ - .name = "ata5505", - .llvm_name = "ata5505", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const ata5702m322 = CpuModel{ - .name = "ata5702m322", - .llvm_name = "ata5702m322", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5782 = CpuModel{ - .name = "ata5782", - .llvm_name = "ata5782", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5790 = CpuModel{ - .name = "ata5790", - .llvm_name = "ata5790", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5790n = CpuModel{ - .name = "ata5790n", - .llvm_name = "ata5790n", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5791 = CpuModel{ - .name = "ata5791", - .llvm_name = "ata5791", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5795 = CpuModel{ - .name = "ata5795", - .llvm_name = "ata5795", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata5831 = CpuModel{ - .name = "ata5831", - .llvm_name = "ata5831", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata6285 = CpuModel{ - .name = "ata6285", - .llvm_name = "ata6285", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const ata6286 = CpuModel{ - .name = "ata6286", - .llvm_name = "ata6286", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const ata6289 = CpuModel{ - .name = "ata6289", - .llvm_name = "ata6289", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const ata6612c = CpuModel{ - .name = "ata6612c", - .llvm_name = "ata6612c", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const ata6613c = CpuModel{ - .name = "ata6613c", - .llvm_name = "ata6613c", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata6614q = CpuModel{ - .name = "ata6614q", - .llvm_name = "ata6614q", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata6616c = CpuModel{ - .name = "ata6616c", - .llvm_name = "ata6616c", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const ata6617c = CpuModel{ - .name = "ata6617c", - .llvm_name = "ata6617c", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const ata664251 = CpuModel{ - .name = "ata664251", - .llvm_name = "ata664251", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const ata8210 = CpuModel{ - .name = "ata8210", - .llvm_name = "ata8210", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const ata8510 = CpuModel{ - .name = "ata8510", - .llvm_name = "ata8510", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega103 = CpuModel{ - .name = "atmega103", - .llvm_name = "atmega103", - .features = featureSet(&[_]Feature{ - .avr31, - }), - }; - pub const atmega128 = CpuModel{ - .name = "atmega128", - .llvm_name = "atmega128", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega1280 = CpuModel{ - .name = "atmega1280", - .llvm_name = "atmega1280", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega1281 = CpuModel{ - .name = "atmega1281", - .llvm_name = "atmega1281", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega1284 = CpuModel{ - .name = "atmega1284", - .llvm_name = "atmega1284", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega1284p = CpuModel{ - .name = "atmega1284p", - .llvm_name = "atmega1284p", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega1284rfr2 = CpuModel{ - .name = "atmega1284rfr2", - .llvm_name = "atmega1284rfr2", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega128a = CpuModel{ - .name = "atmega128a", - .llvm_name = "atmega128a", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega128rfa1 = CpuModel{ - .name = "atmega128rfa1", - .llvm_name = "atmega128rfa1", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega128rfr2 = CpuModel{ - .name = "atmega128rfr2", - .llvm_name = "atmega128rfr2", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const atmega16 = CpuModel{ - .name = "atmega16", - .llvm_name = "atmega16", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega1608 = CpuModel{ - .name = "atmega1608", - .llvm_name = "atmega1608", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega1609 = CpuModel{ - .name = "atmega1609", - .llvm_name = "atmega1609", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega161 = CpuModel{ - .name = "atmega161", - .llvm_name = "atmega161", - .features = featureSet(&[_]Feature{ - .avr3, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega162 = CpuModel{ - .name = "atmega162", - .llvm_name = "atmega162", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega163 = CpuModel{ - .name = "atmega163", - .llvm_name = "atmega163", - .features = featureSet(&[_]Feature{ - .avr3, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega164a = CpuModel{ - .name = "atmega164a", - .llvm_name = "atmega164a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega164p = CpuModel{ - .name = "atmega164p", - .llvm_name = "atmega164p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega164pa = CpuModel{ - .name = "atmega164pa", - .llvm_name = "atmega164pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega165 = CpuModel{ - .name = "atmega165", - .llvm_name = "atmega165", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega165a = CpuModel{ - .name = "atmega165a", - .llvm_name = "atmega165a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega165p = CpuModel{ - .name = "atmega165p", - .llvm_name = "atmega165p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega165pa = CpuModel{ - .name = "atmega165pa", - .llvm_name = "atmega165pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega168 = CpuModel{ - .name = "atmega168", - .llvm_name = "atmega168", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega168a = CpuModel{ - .name = "atmega168a", - .llvm_name = "atmega168a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega168p = CpuModel{ - .name = "atmega168p", - .llvm_name = "atmega168p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega168pa = CpuModel{ - .name = "atmega168pa", - .llvm_name = "atmega168pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega168pb = CpuModel{ - .name = "atmega168pb", - .llvm_name = "atmega168pb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega169 = CpuModel{ - .name = "atmega169", - .llvm_name = "atmega169", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega169a = CpuModel{ - .name = "atmega169a", - .llvm_name = "atmega169a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega169p = CpuModel{ - .name = "atmega169p", - .llvm_name = "atmega169p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega169pa = CpuModel{ - .name = "atmega169pa", - .llvm_name = "atmega169pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16a = CpuModel{ - .name = "atmega16a", - .llvm_name = "atmega16a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16hva = CpuModel{ - .name = "atmega16hva", - .llvm_name = "atmega16hva", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16hva2 = CpuModel{ - .name = "atmega16hva2", - .llvm_name = "atmega16hva2", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16hvb = CpuModel{ - .name = "atmega16hvb", - .llvm_name = "atmega16hvb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16hvbrevb = CpuModel{ - .name = "atmega16hvbrevb", - .llvm_name = "atmega16hvbrevb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16m1 = CpuModel{ - .name = "atmega16m1", - .llvm_name = "atmega16m1", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega16u2 = CpuModel{ - .name = "atmega16u2", - .llvm_name = "atmega16u2", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const atmega16u4 = CpuModel{ - .name = "atmega16u4", - .llvm_name = "atmega16u4", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega2560 = CpuModel{ - .name = "atmega2560", - .llvm_name = "atmega2560", - .features = featureSet(&[_]Feature{ - .avr6, - }), - }; - pub const atmega2561 = CpuModel{ - .name = "atmega2561", - .llvm_name = "atmega2561", - .features = featureSet(&[_]Feature{ - .avr6, - }), - }; - pub const atmega2564rfr2 = CpuModel{ - .name = "atmega2564rfr2", - .llvm_name = "atmega2564rfr2", - .features = featureSet(&[_]Feature{ - .avr6, - }), - }; - pub const atmega256rfr2 = CpuModel{ - .name = "atmega256rfr2", - .llvm_name = "atmega256rfr2", - .features = featureSet(&[_]Feature{ - .avr6, - }), - }; - pub const atmega32 = CpuModel{ - .name = "atmega32", - .llvm_name = "atmega32", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3208 = CpuModel{ - .name = "atmega3208", - .llvm_name = "atmega3208", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega3209 = CpuModel{ - .name = "atmega3209", - .llvm_name = "atmega3209", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega323 = CpuModel{ - .name = "atmega323", - .llvm_name = "atmega323", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega324a = CpuModel{ - .name = "atmega324a", - .llvm_name = "atmega324a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega324p = CpuModel{ - .name = "atmega324p", - .llvm_name = "atmega324p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega324pa = CpuModel{ - .name = "atmega324pa", - .llvm_name = "atmega324pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega324pb = CpuModel{ - .name = "atmega324pb", - .llvm_name = "atmega324pb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega325 = CpuModel{ - .name = "atmega325", - .llvm_name = "atmega325", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3250 = CpuModel{ - .name = "atmega3250", - .llvm_name = "atmega3250", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3250a = CpuModel{ - .name = "atmega3250a", - .llvm_name = "atmega3250a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3250p = CpuModel{ - .name = "atmega3250p", - .llvm_name = "atmega3250p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3250pa = CpuModel{ - .name = "atmega3250pa", - .llvm_name = "atmega3250pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega325a = CpuModel{ - .name = "atmega325a", - .llvm_name = "atmega325a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega325p = CpuModel{ - .name = "atmega325p", - .llvm_name = "atmega325p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega325pa = CpuModel{ - .name = "atmega325pa", - .llvm_name = "atmega325pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega328 = CpuModel{ - .name = "atmega328", - .llvm_name = "atmega328", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega328p = CpuModel{ - .name = "atmega328p", - .llvm_name = "atmega328p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega328pb = CpuModel{ - .name = "atmega328pb", - .llvm_name = "atmega328pb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega329 = CpuModel{ - .name = "atmega329", - .llvm_name = "atmega329", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3290 = CpuModel{ - .name = "atmega3290", - .llvm_name = "atmega3290", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3290a = CpuModel{ - .name = "atmega3290a", - .llvm_name = "atmega3290a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3290p = CpuModel{ - .name = "atmega3290p", - .llvm_name = "atmega3290p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega3290pa = CpuModel{ - .name = "atmega3290pa", - .llvm_name = "atmega3290pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega329a = CpuModel{ - .name = "atmega329a", - .llvm_name = "atmega329a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega329p = CpuModel{ - .name = "atmega329p", - .llvm_name = "atmega329p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega329pa = CpuModel{ - .name = "atmega329pa", - .llvm_name = "atmega329pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32a = CpuModel{ - .name = "atmega32a", - .llvm_name = "atmega32a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32c1 = CpuModel{ - .name = "atmega32c1", - .llvm_name = "atmega32c1", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32hvb = CpuModel{ - .name = "atmega32hvb", - .llvm_name = "atmega32hvb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32hvbrevb = CpuModel{ - .name = "atmega32hvbrevb", - .llvm_name = "atmega32hvbrevb", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32m1 = CpuModel{ - .name = "atmega32m1", - .llvm_name = "atmega32m1", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32u2 = CpuModel{ - .name = "atmega32u2", - .llvm_name = "atmega32u2", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const atmega32u4 = CpuModel{ - .name = "atmega32u4", - .llvm_name = "atmega32u4", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega32u6 = CpuModel{ - .name = "atmega32u6", - .llvm_name = "atmega32u6", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega406 = CpuModel{ - .name = "atmega406", - .llvm_name = "atmega406", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega48 = CpuModel{ - .name = "atmega48", - .llvm_name = "atmega48", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega4808 = CpuModel{ - .name = "atmega4808", - .llvm_name = "atmega4808", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega4809 = CpuModel{ - .name = "atmega4809", - .llvm_name = "atmega4809", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega48a = CpuModel{ - .name = "atmega48a", - .llvm_name = "atmega48a", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega48p = CpuModel{ - .name = "atmega48p", - .llvm_name = "atmega48p", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega48pa = CpuModel{ - .name = "atmega48pa", - .llvm_name = "atmega48pa", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega48pb = CpuModel{ - .name = "atmega48pb", - .llvm_name = "atmega48pb", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega64 = CpuModel{ - .name = "atmega64", - .llvm_name = "atmega64", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega640 = CpuModel{ - .name = "atmega640", - .llvm_name = "atmega640", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega644 = CpuModel{ - .name = "atmega644", - .llvm_name = "atmega644", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega644a = CpuModel{ - .name = "atmega644a", - .llvm_name = "atmega644a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega644p = CpuModel{ - .name = "atmega644p", - .llvm_name = "atmega644p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega644pa = CpuModel{ - .name = "atmega644pa", - .llvm_name = "atmega644pa", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega644rfr2 = CpuModel{ - .name = "atmega644rfr2", - .llvm_name = "atmega644rfr2", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega645 = CpuModel{ - .name = "atmega645", - .llvm_name = "atmega645", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6450 = CpuModel{ - .name = "atmega6450", - .llvm_name = "atmega6450", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6450a = CpuModel{ - .name = "atmega6450a", - .llvm_name = "atmega6450a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6450p = CpuModel{ - .name = "atmega6450p", - .llvm_name = "atmega6450p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega645a = CpuModel{ - .name = "atmega645a", - .llvm_name = "atmega645a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega645p = CpuModel{ - .name = "atmega645p", - .llvm_name = "atmega645p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega649 = CpuModel{ - .name = "atmega649", - .llvm_name = "atmega649", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6490 = CpuModel{ - .name = "atmega6490", - .llvm_name = "atmega6490", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6490a = CpuModel{ - .name = "atmega6490a", - .llvm_name = "atmega6490a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega6490p = CpuModel{ - .name = "atmega6490p", - .llvm_name = "atmega6490p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega649a = CpuModel{ - .name = "atmega649a", - .llvm_name = "atmega649a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega649p = CpuModel{ - .name = "atmega649p", - .llvm_name = "atmega649p", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64a = CpuModel{ - .name = "atmega64a", - .llvm_name = "atmega64a", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64c1 = CpuModel{ - .name = "atmega64c1", - .llvm_name = "atmega64c1", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64hve = CpuModel{ - .name = "atmega64hve", - .llvm_name = "atmega64hve", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64hve2 = CpuModel{ - .name = "atmega64hve2", - .llvm_name = "atmega64hve2", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64m1 = CpuModel{ - .name = "atmega64m1", - .llvm_name = "atmega64m1", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega64rfr2 = CpuModel{ - .name = "atmega64rfr2", - .llvm_name = "atmega64rfr2", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const atmega8 = CpuModel{ - .name = "atmega8", - .llvm_name = "atmega8", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega808 = CpuModel{ - .name = "atmega808", - .llvm_name = "atmega808", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega809 = CpuModel{ - .name = "atmega809", - .llvm_name = "atmega809", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const atmega8515 = CpuModel{ - .name = "atmega8515", - .llvm_name = "atmega8515", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega8535 = CpuModel{ - .name = "atmega8535", - .llvm_name = "atmega8535", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega88 = CpuModel{ - .name = "atmega88", - .llvm_name = "atmega88", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega88a = CpuModel{ - .name = "atmega88a", - .llvm_name = "atmega88a", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega88p = CpuModel{ - .name = "atmega88p", - .llvm_name = "atmega88p", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega88pa = CpuModel{ - .name = "atmega88pa", - .llvm_name = "atmega88pa", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega88pb = CpuModel{ - .name = "atmega88pb", - .llvm_name = "atmega88pb", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega8a = CpuModel{ - .name = "atmega8a", - .llvm_name = "atmega8a", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .movw, - .mul, - .spm, - }), - }; - pub const atmega8hva = CpuModel{ - .name = "atmega8hva", - .llvm_name = "atmega8hva", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const atmega8u2 = CpuModel{ - .name = "atmega8u2", - .llvm_name = "atmega8u2", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const attiny10 = CpuModel{ - .name = "attiny10", - .llvm_name = "attiny10", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny102 = CpuModel{ - .name = "attiny102", - .llvm_name = "attiny102", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny104 = CpuModel{ - .name = "attiny104", - .llvm_name = "attiny104", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny11 = CpuModel{ - .name = "attiny11", - .llvm_name = "attiny11", - .features = featureSet(&[_]Feature{ - .avr1, - .smallstack, - }), - }; - pub const attiny12 = CpuModel{ - .name = "attiny12", - .llvm_name = "attiny12", - .features = featureSet(&[_]Feature{ - .avr1, - .smallstack, - }), - }; - pub const attiny13 = CpuModel{ - .name = "attiny13", - .llvm_name = "attiny13", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny13a = CpuModel{ - .name = "attiny13a", - .llvm_name = "attiny13a", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny15 = CpuModel{ - .name = "attiny15", - .llvm_name = "attiny15", - .features = featureSet(&[_]Feature{ - .avr1, - .smallstack, - }), - }; - pub const attiny1604 = CpuModel{ - .name = "attiny1604", - .llvm_name = "attiny1604", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1606 = CpuModel{ - .name = "attiny1606", - .llvm_name = "attiny1606", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1607 = CpuModel{ - .name = "attiny1607", - .llvm_name = "attiny1607", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1614 = CpuModel{ - .name = "attiny1614", - .llvm_name = "attiny1614", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1616 = CpuModel{ - .name = "attiny1616", - .llvm_name = "attiny1616", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1617 = CpuModel{ - .name = "attiny1617", - .llvm_name = "attiny1617", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1624 = CpuModel{ - .name = "attiny1624", - .llvm_name = "attiny1624", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1626 = CpuModel{ - .name = "attiny1626", - .llvm_name = "attiny1626", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1627 = CpuModel{ - .name = "attiny1627", - .llvm_name = "attiny1627", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny1634 = CpuModel{ - .name = "attiny1634", - .llvm_name = "attiny1634", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const attiny167 = CpuModel{ - .name = "attiny167", - .llvm_name = "attiny167", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const attiny20 = CpuModel{ - .name = "attiny20", - .llvm_name = "attiny20", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny202 = CpuModel{ - .name = "attiny202", - .llvm_name = "attiny202", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny204 = CpuModel{ - .name = "attiny204", - .llvm_name = "attiny204", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny212 = CpuModel{ - .name = "attiny212", - .llvm_name = "attiny212", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny214 = CpuModel{ - .name = "attiny214", - .llvm_name = "attiny214", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny22 = CpuModel{ - .name = "attiny22", - .llvm_name = "attiny22", - .features = featureSet(&[_]Feature{ - .avr2, - .smallstack, - }), - }; - pub const attiny2313 = CpuModel{ - .name = "attiny2313", - .llvm_name = "attiny2313", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny2313a = CpuModel{ - .name = "attiny2313a", - .llvm_name = "attiny2313a", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny24 = CpuModel{ - .name = "attiny24", - .llvm_name = "attiny24", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny24a = CpuModel{ - .name = "attiny24a", - .llvm_name = "attiny24a", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny25 = CpuModel{ - .name = "attiny25", - .llvm_name = "attiny25", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny26 = CpuModel{ - .name = "attiny26", - .llvm_name = "attiny26", - .features = featureSet(&[_]Feature{ - .avr2, - .lpmx, - .smallstack, - }), - }; - pub const attiny261 = CpuModel{ - .name = "attiny261", - .llvm_name = "attiny261", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny261a = CpuModel{ - .name = "attiny261a", - .llvm_name = "attiny261a", - .features = featureSet(&[_]Feature{ - .avr25, - .smallstack, - }), - }; - pub const attiny28 = CpuModel{ - .name = "attiny28", - .llvm_name = "attiny28", - .features = featureSet(&[_]Feature{ - .avr1, - .smallstack, - }), - }; - pub const attiny3216 = CpuModel{ - .name = "attiny3216", - .llvm_name = "attiny3216", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny3217 = CpuModel{ - .name = "attiny3217", - .llvm_name = "attiny3217", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny4 = CpuModel{ - .name = "attiny4", - .llvm_name = "attiny4", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny40 = CpuModel{ - .name = "attiny40", - .llvm_name = "attiny40", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny402 = CpuModel{ - .name = "attiny402", - .llvm_name = "attiny402", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny404 = CpuModel{ - .name = "attiny404", - .llvm_name = "attiny404", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny406 = CpuModel{ - .name = "attiny406", - .llvm_name = "attiny406", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny412 = CpuModel{ - .name = "attiny412", - .llvm_name = "attiny412", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny414 = CpuModel{ - .name = "attiny414", - .llvm_name = "attiny414", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny416 = CpuModel{ - .name = "attiny416", - .llvm_name = "attiny416", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny417 = CpuModel{ - .name = "attiny417", - .llvm_name = "attiny417", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny4313 = CpuModel{ - .name = "attiny4313", - .llvm_name = "attiny4313", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny43u = CpuModel{ - .name = "attiny43u", - .llvm_name = "attiny43u", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny44 = CpuModel{ - .name = "attiny44", - .llvm_name = "attiny44", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny441 = CpuModel{ - .name = "attiny441", - .llvm_name = "attiny441", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny44a = CpuModel{ - .name = "attiny44a", - .llvm_name = "attiny44a", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny45 = CpuModel{ - .name = "attiny45", - .llvm_name = "attiny45", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny461 = CpuModel{ - .name = "attiny461", - .llvm_name = "attiny461", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny461a = CpuModel{ - .name = "attiny461a", - .llvm_name = "attiny461a", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny48 = CpuModel{ - .name = "attiny48", - .llvm_name = "attiny48", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny5 = CpuModel{ - .name = "attiny5", - .llvm_name = "attiny5", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const attiny804 = CpuModel{ - .name = "attiny804", - .llvm_name = "attiny804", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny806 = CpuModel{ - .name = "attiny806", - .llvm_name = "attiny806", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny807 = CpuModel{ - .name = "attiny807", - .llvm_name = "attiny807", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny814 = CpuModel{ - .name = "attiny814", - .llvm_name = "attiny814", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny816 = CpuModel{ - .name = "attiny816", - .llvm_name = "attiny816", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny817 = CpuModel{ - .name = "attiny817", - .llvm_name = "attiny817", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const attiny828 = CpuModel{ - .name = "attiny828", - .llvm_name = "attiny828", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny84 = CpuModel{ - .name = "attiny84", - .llvm_name = "attiny84", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny841 = CpuModel{ - .name = "attiny841", - .llvm_name = "attiny841", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny84a = CpuModel{ - .name = "attiny84a", - .llvm_name = "attiny84a", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny85 = CpuModel{ - .name = "attiny85", - .llvm_name = "attiny85", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny861 = CpuModel{ - .name = "attiny861", - .llvm_name = "attiny861", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny861a = CpuModel{ - .name = "attiny861a", - .llvm_name = "attiny861a", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny87 = CpuModel{ - .name = "attiny87", - .llvm_name = "attiny87", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny88 = CpuModel{ - .name = "attiny88", - .llvm_name = "attiny88", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const attiny9 = CpuModel{ - .name = "attiny9", - .llvm_name = "attiny9", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const atxmega128a1 = CpuModel{ - .name = "atxmega128a1", - .llvm_name = "atxmega128a1", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega128a1u = CpuModel{ - .name = "atxmega128a1u", - .llvm_name = "atxmega128a1u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128a3 = CpuModel{ - .name = "atxmega128a3", - .llvm_name = "atxmega128a3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega128a3u = CpuModel{ - .name = "atxmega128a3u", - .llvm_name = "atxmega128a3u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128a4u = CpuModel{ - .name = "atxmega128a4u", - .llvm_name = "atxmega128a4u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128b1 = CpuModel{ - .name = "atxmega128b1", - .llvm_name = "atxmega128b1", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128b3 = CpuModel{ - .name = "atxmega128b3", - .llvm_name = "atxmega128b3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128c3 = CpuModel{ - .name = "atxmega128c3", - .llvm_name = "atxmega128c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega128d3 = CpuModel{ - .name = "atxmega128d3", - .llvm_name = "atxmega128d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega128d4 = CpuModel{ - .name = "atxmega128d4", - .llvm_name = "atxmega128d4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega16a4 = CpuModel{ - .name = "atxmega16a4", - .llvm_name = "atxmega16a4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega16a4u = CpuModel{ - .name = "atxmega16a4u", - .llvm_name = "atxmega16a4u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega16c4 = CpuModel{ - .name = "atxmega16c4", - .llvm_name = "atxmega16c4", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega16d4 = CpuModel{ - .name = "atxmega16d4", - .llvm_name = "atxmega16d4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega16e5 = CpuModel{ - .name = "atxmega16e5", - .llvm_name = "atxmega16e5", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega192a3 = CpuModel{ - .name = "atxmega192a3", - .llvm_name = "atxmega192a3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega192a3u = CpuModel{ - .name = "atxmega192a3u", - .llvm_name = "atxmega192a3u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega192c3 = CpuModel{ - .name = "atxmega192c3", - .llvm_name = "atxmega192c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega192d3 = CpuModel{ - .name = "atxmega192d3", - .llvm_name = "atxmega192d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega256a3 = CpuModel{ - .name = "atxmega256a3", - .llvm_name = "atxmega256a3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega256a3b = CpuModel{ - .name = "atxmega256a3b", - .llvm_name = "atxmega256a3b", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega256a3bu = CpuModel{ - .name = "atxmega256a3bu", - .llvm_name = "atxmega256a3bu", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega256a3u = CpuModel{ - .name = "atxmega256a3u", - .llvm_name = "atxmega256a3u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega256c3 = CpuModel{ - .name = "atxmega256c3", - .llvm_name = "atxmega256c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega256d3 = CpuModel{ - .name = "atxmega256d3", - .llvm_name = "atxmega256d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega32a4 = CpuModel{ - .name = "atxmega32a4", - .llvm_name = "atxmega32a4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega32a4u = CpuModel{ - .name = "atxmega32a4u", - .llvm_name = "atxmega32a4u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega32c3 = CpuModel{ - .name = "atxmega32c3", - .llvm_name = "atxmega32c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega32c4 = CpuModel{ - .name = "atxmega32c4", - .llvm_name = "atxmega32c4", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega32d3 = CpuModel{ - .name = "atxmega32d3", - .llvm_name = "atxmega32d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega32d4 = CpuModel{ - .name = "atxmega32d4", - .llvm_name = "atxmega32d4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega32e5 = CpuModel{ - .name = "atxmega32e5", - .llvm_name = "atxmega32e5", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega384c3 = CpuModel{ - .name = "atxmega384c3", - .llvm_name = "atxmega384c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega384d3 = CpuModel{ - .name = "atxmega384d3", - .llvm_name = "atxmega384d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega64a1 = CpuModel{ - .name = "atxmega64a1", - .llvm_name = "atxmega64a1", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega64a1u = CpuModel{ - .name = "atxmega64a1u", - .llvm_name = "atxmega64a1u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64a3 = CpuModel{ - .name = "atxmega64a3", - .llvm_name = "atxmega64a3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega64a3u = CpuModel{ - .name = "atxmega64a3u", - .llvm_name = "atxmega64a3u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64a4u = CpuModel{ - .name = "atxmega64a4u", - .llvm_name = "atxmega64a4u", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64b1 = CpuModel{ - .name = "atxmega64b1", - .llvm_name = "atxmega64b1", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64b3 = CpuModel{ - .name = "atxmega64b3", - .llvm_name = "atxmega64b3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64c3 = CpuModel{ - .name = "atxmega64c3", - .llvm_name = "atxmega64c3", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const atxmega64d3 = CpuModel{ - .name = "atxmega64d3", - .llvm_name = "atxmega64d3", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega64d4 = CpuModel{ - .name = "atxmega64d4", - .llvm_name = "atxmega64d4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const atxmega8e5 = CpuModel{ - .name = "atxmega8e5", - .llvm_name = "atxmega8e5", - .features = featureSet(&[_]Feature{ - .xmegau, - }), - }; - pub const avr1 = CpuModel{ - .name = "avr1", - .llvm_name = "avr1", - .features = featureSet(&[_]Feature{ - .avr1, - }), - }; - pub const avr2 = CpuModel{ - .name = "avr2", - .llvm_name = "avr2", - .features = featureSet(&[_]Feature{ - .avr2, - }), - }; - pub const avr25 = CpuModel{ - .name = "avr25", - .llvm_name = "avr25", - .features = featureSet(&[_]Feature{ - .avr25, - }), - }; - pub const avr3 = CpuModel{ - .name = "avr3", - .llvm_name = "avr3", - .features = featureSet(&[_]Feature{ - .avr3, - }), - }; - pub const avr31 = CpuModel{ - .name = "avr31", - .llvm_name = "avr31", - .features = featureSet(&[_]Feature{ - .avr31, - }), - }; - pub const avr35 = CpuModel{ - .name = "avr35", - .llvm_name = "avr35", - .features = featureSet(&[_]Feature{ - .avr35, - }), - }; - pub const avr4 = CpuModel{ - .name = "avr4", - .llvm_name = "avr4", - .features = featureSet(&[_]Feature{ - .avr4, - }), - }; - pub const avr5 = CpuModel{ - .name = "avr5", - .llvm_name = "avr5", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; - pub const avr51 = CpuModel{ - .name = "avr51", - .llvm_name = "avr51", - .features = featureSet(&[_]Feature{ - .avr51, - }), - }; - pub const avr6 = CpuModel{ - .name = "avr6", - .llvm_name = "avr6", - .features = featureSet(&[_]Feature{ - .avr6, - }), - }; - pub const avrtiny = CpuModel{ - .name = "avrtiny", - .llvm_name = "avrtiny", - .features = featureSet(&[_]Feature{ - .avrtiny, - }), - }; - pub const avrxmega1 = CpuModel{ - .name = "avrxmega1", - .llvm_name = "avrxmega1", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const avrxmega2 = CpuModel{ - .name = "avrxmega2", - .llvm_name = "avrxmega2", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const avrxmega3 = CpuModel{ - .name = "avrxmega3", - .llvm_name = "avrxmega3", - .features = featureSet(&[_]Feature{ - .xmega3, - }), - }; - pub const avrxmega4 = CpuModel{ - .name = "avrxmega4", - .llvm_name = "avrxmega4", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const avrxmega5 = CpuModel{ - .name = "avrxmega5", - .llvm_name = "avrxmega5", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const avrxmega6 = CpuModel{ - .name = "avrxmega6", - .llvm_name = "avrxmega6", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const avrxmega7 = CpuModel{ - .name = "avrxmega7", - .llvm_name = "avrxmega7", - .features = featureSet(&[_]Feature{ - .xmega, - }), - }; - pub const m3000 = CpuModel{ - .name = "m3000", - .llvm_name = "m3000", - .features = featureSet(&[_]Feature{ - .avr5, - }), - }; -}; diff --git a/lib/std/target/bpf.zig b/lib/std/target/bpf.zig deleted file mode 100644 index 40dc2d1c7e90229adde8e4769b3d41dea0767523..0000000000000000000000000000000000000000 --- a/lib/std/target/bpf.zig +++ /dev/null @@ -1,73 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - alu32, - dummy, - dwarfris, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.alu32)] = .{ - .llvm_name = "alu32", - .description = "Enable ALU32 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dummy)] = .{ - .llvm_name = "dummy", - .description = "unused feature", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dwarfris)] = .{ - .llvm_name = "dwarfris", - .description = "Disable MCAsmInfo DwarfUsesRelocationsAcrossSections", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const probe = CpuModel{ - .name = "probe", - .llvm_name = "probe", - .features = featureSet(&[_]Feature{}), - }; - pub const v1 = CpuModel{ - .name = "v1", - .llvm_name = "v1", - .features = featureSet(&[_]Feature{}), - }; - pub const v2 = CpuModel{ - .name = "v2", - .llvm_name = "v2", - .features = featureSet(&[_]Feature{}), - }; - pub const v3 = CpuModel{ - .name = "v3", - .llvm_name = "v3", - .features = featureSet(&[_]Feature{ - .alu32, - }), - }; -}; diff --git a/lib/std/target/csky.zig b/lib/std/target/csky.zig deleted file mode 100644 index 331e8057bfbdccf1b8da5efd91c97159781eb261..0000000000000000000000000000000000000000 --- a/lib/std/target/csky.zig +++ /dev/null @@ -1,3214 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"10e60", - @"2e3", - @"3e3r1", - @"3e3r2", - @"3e3r3", - @"3e7", - @"7e10", - btst16, - cache, - ccrt, - ck801, - ck802, - ck803, - ck803s, - ck804, - ck805, - ck807, - ck810, - ck810v, - ck860, - ck860v, - constpool, - doloop, - dsp1e2, - dsp_silan, - dspe60, - dspv2, - e1, - e2, - edsp, - elrw, - fdivdu, - float1e2, - float1e3, - float3e4, - float7e60, - floate1, - fpuv2_df, - fpuv2_sf, - fpuv3_df, - fpuv3_hf, - fpuv3_hi, - fpuv3_sf, - hard_float, - hard_float_abi, - hard_tp, - high_registers, - hwdiv, - istack, - java, - mp, - mp1e2, - multiple_stld, - nvic, - pushpop, - smart, - soft_tp, - stack_size, - trust, - vdsp2e3, - vdsp2e60f, - vdspv1, - vdspv2, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"10e60")] = .{ - .llvm_name = "10e60", - .description = "Support CSKY 10e60 instructions", - .dependencies = featureSet(&[_]Feature{ - .@"7e10", - }), - }; - result[@intFromEnum(Feature.@"2e3")] = .{ - .llvm_name = "2e3", - .description = "Support CSKY 2e3 instructions", - .dependencies = featureSet(&[_]Feature{ - .e2, - }), - }; - result[@intFromEnum(Feature.@"3e3r1")] = .{ - .llvm_name = "3e3r1", - .description = "Support CSKY 3e3r1 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"3e3r2")] = .{ - .llvm_name = "3e3r2", - .description = "Support CSKY 3e3r2 instructions", - .dependencies = featureSet(&[_]Feature{ - .@"3e3r1", - .doloop, - }), - }; - result[@intFromEnum(Feature.@"3e3r3")] = .{ - .llvm_name = "3e3r3", - .description = "Support CSKY 3e3r3 instructions", - .dependencies = featureSet(&[_]Feature{ - .doloop, - }), - }; - result[@intFromEnum(Feature.@"3e7")] = .{ - .llvm_name = "3e7", - .description = "Support CSKY 3e7 instructions", - .dependencies = featureSet(&[_]Feature{ - .@"2e3", - }), - }; - result[@intFromEnum(Feature.@"7e10")] = .{ - .llvm_name = "7e10", - .description = "Support CSKY 7e10 instructions", - .dependencies = featureSet(&[_]Feature{ - .@"3e7", - }), - }; - result[@intFromEnum(Feature.btst16)] = .{ - .llvm_name = "btst16", - .description = "Use the 16-bit btsti instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cache)] = .{ - .llvm_name = "cache", - .description = "Enable cache", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ccrt)] = .{ - .llvm_name = "ccrt", - .description = "Use CSKY compiler runtime", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck801)] = .{ - .llvm_name = "ck801", - .description = "CSKY ck801 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck802)] = .{ - .llvm_name = "ck802", - .description = "CSKY ck802 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck803)] = .{ - .llvm_name = "ck803", - .description = "CSKY ck803 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck803s)] = .{ - .llvm_name = "ck803s", - .description = "CSKY ck803s processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck804)] = .{ - .llvm_name = "ck804", - .description = "CSKY ck804 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck805)] = .{ - .llvm_name = "ck805", - .description = "CSKY ck805 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck807)] = .{ - .llvm_name = "ck807", - .description = "CSKY ck807 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck810)] = .{ - .llvm_name = "ck810", - .description = "CSKY ck810 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck810v)] = .{ - .llvm_name = "ck810v", - .description = "CSKY ck810v processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck860)] = .{ - .llvm_name = "ck860", - .description = "CSKY ck860 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ck860v)] = .{ - .llvm_name = "ck860v", - .description = "CSKY ck860v processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.constpool)] = .{ - .llvm_name = "constpool", - .description = "Dump the constant pool by compiler", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.doloop)] = .{ - .llvm_name = "doloop", - .description = "Enable doloop instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dsp1e2)] = .{ - .llvm_name = "dsp1e2", - .description = "Support CSKY dsp1e2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dsp_silan)] = .{ - .llvm_name = "dsp_silan", - .description = "Enable DSP Silan instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dspe60)] = .{ - .llvm_name = "dspe60", - .description = "Support CSKY dspe60 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dspv2)] = .{ - .llvm_name = "dspv2", - .description = "Enable DSP V2.0 instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.e1)] = .{ - .llvm_name = "e1", - .description = "Support CSKY e1 instructions", - .dependencies = featureSet(&[_]Feature{ - .elrw, - }), - }; - result[@intFromEnum(Feature.e2)] = .{ - .llvm_name = "e2", - .description = "Support CSKY e2 instructions", - .dependencies = featureSet(&[_]Feature{ - .e1, - }), - }; - result[@intFromEnum(Feature.edsp)] = .{ - .llvm_name = "edsp", - .description = "Enable DSP instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.elrw)] = .{ - .llvm_name = "elrw", - .description = "Use the extend LRW instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fdivdu)] = .{ - .llvm_name = "fdivdu", - .description = "Enable float divide instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.float1e2)] = .{ - .llvm_name = "float1e2", - .description = "Support CSKY float1e2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.float1e3)] = .{ - .llvm_name = "float1e3", - .description = "Support CSKY float1e3 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.float3e4)] = .{ - .llvm_name = "float3e4", - .description = "Support CSKY float3e4 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.float7e60)] = .{ - .llvm_name = "float7e60", - .description = "Support CSKY float7e60 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.floate1)] = .{ - .llvm_name = "floate1", - .description = "Support CSKY floate1 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv2_df)] = .{ - .llvm_name = "fpuv2_df", - .description = "Enable FPUv2 double float instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv2_sf)] = .{ - .llvm_name = "fpuv2_sf", - .description = "Enable FPUv2 single float instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv3_df)] = .{ - .llvm_name = "fpuv3_df", - .description = "Enable FPUv3 double float instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv3_hf)] = .{ - .llvm_name = "fpuv3_hf", - .description = "Enable FPUv3 half precision operate instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv3_hi)] = .{ - .llvm_name = "fpuv3_hi", - .description = "Enable FPUv3 half word converting instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpuv3_sf)] = .{ - .llvm_name = "fpuv3_sf", - .description = "Enable FPUv3 single float instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hard_float)] = .{ - .llvm_name = "hard-float", - .description = "Use hard floating point features", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hard_float_abi)] = .{ - .llvm_name = "hard-float-abi", - .description = "Use hard floating point ABI to pass args", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hard_tp)] = .{ - .llvm_name = "hard-tp", - .description = "Enable TLS Pointer register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.high_registers)] = .{ - .llvm_name = "high-registers", - .description = "Enable r16-r31 registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hwdiv)] = .{ - .llvm_name = "hwdiv", - .description = "Enable divide instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.istack)] = .{ - .llvm_name = "istack", - .description = "Enable interrput attribute", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.java)] = .{ - .llvm_name = "java", - .description = "Enable java instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mp)] = .{ - .llvm_name = "mp", - .description = "Support CSKY mp instructions", - .dependencies = featureSet(&[_]Feature{ - .@"2e3", - }), - }; - result[@intFromEnum(Feature.mp1e2)] = .{ - .llvm_name = "mp1e2", - .description = "Support CSKY mp1e2 instructions", - .dependencies = featureSet(&[_]Feature{ - .@"3e7", - }), - }; - result[@intFromEnum(Feature.multiple_stld)] = .{ - .llvm_name = "multiple_stld", - .description = "Enable multiple load/store instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nvic)] = .{ - .llvm_name = "nvic", - .description = "Enable NVIC", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pushpop)] = .{ - .llvm_name = "pushpop", - .description = "Enable push/pop instrutions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.smart)] = .{ - .llvm_name = "smart", - .description = "Let CPU work in Smart Mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_tp)] = .{ - .llvm_name = "soft-tp", - .description = "Disable TLS Pointer register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.stack_size)] = .{ - .llvm_name = "stack-size", - .description = "Output stack size information", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.trust)] = .{ - .llvm_name = "trust", - .description = "Enable trust instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vdsp2e3)] = .{ - .llvm_name = "vdsp2e3", - .description = "Support CSKY vdsp2e3 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vdsp2e60f)] = .{ - .llvm_name = "vdsp2e60f", - .description = "Support CSKY vdsp2e60f instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vdspv1)] = .{ - .llvm_name = "vdspv1", - .description = "Enable 128bit vdsp-v1 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vdspv2)] = .{ - .llvm_name = "vdspv2", - .description = "Enable vdsp-v2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const c807 = CpuModel{ - .name = "c807", - .llvm_name = "c807", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const c807f = CpuModel{ - .name = "c807f", - .llvm_name = "c807f", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .float1e3, - .float3e4, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const c810 = CpuModel{ - .name = "c810", - .llvm_name = "c810", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const c810t = CpuModel{ - .name = "c810t", - .llvm_name = "c810t", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const c810tv = CpuModel{ - .name = "c810tv", - .llvm_name = "c810tv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const c810v = CpuModel{ - .name = "c810v", - .llvm_name = "c810v", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const c860 = CpuModel{ - .name = "c860", - .llvm_name = "c860", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .dspe60, - .float7e60, - .fpuv3_df, - .fpuv3_hf, - .fpuv3_hi, - .fpuv3_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const c860v = CpuModel{ - .name = "c860v", - .llvm_name = "c860v", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .ck860v, - .dspe60, - .float7e60, - .fpuv3_df, - .fpuv3_hf, - .fpuv3_hi, - .fpuv3_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdsp2e60f, - .vdspv2, - }), - }; - pub const ck801 = CpuModel{ - .name = "ck801", - .llvm_name = "ck801", - .features = featureSet(&[_]Feature{ - .btst16, - .ck801, - .e1, - .trust, - }), - }; - pub const ck801t = CpuModel{ - .name = "ck801t", - .llvm_name = "ck801t", - .features = featureSet(&[_]Feature{ - .btst16, - .ck801, - .e1, - .trust, - }), - }; - pub const ck802 = CpuModel{ - .name = "ck802", - .llvm_name = "ck802", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const ck802j = CpuModel{ - .name = "ck802j", - .llvm_name = "ck802j", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .java, - .nvic, - .trust, - }), - }; - pub const ck802t = CpuModel{ - .name = "ck802t", - .llvm_name = "ck802t", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const ck803 = CpuModel{ - .name = "ck803", - .llvm_name = "ck803", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803e = CpuModel{ - .name = "ck803e", - .llvm_name = "ck803e", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ef = CpuModel{ - .name = "ck803ef", - .llvm_name = "ck803ef", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efh = CpuModel{ - .name = "ck803efh", - .llvm_name = "ck803efh", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhr1 = CpuModel{ - .name = "ck803efhr1", - .llvm_name = "ck803efhr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhr2 = CpuModel{ - .name = "ck803efhr2", - .llvm_name = "ck803efhr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhr3 = CpuModel{ - .name = "ck803efhr3", - .llvm_name = "ck803efhr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efht = CpuModel{ - .name = "ck803efht", - .llvm_name = "ck803efht", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhtr1 = CpuModel{ - .name = "ck803efhtr1", - .llvm_name = "ck803efhtr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhtr2 = CpuModel{ - .name = "ck803efhtr2", - .llvm_name = "ck803efhtr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efhtr3 = CpuModel{ - .name = "ck803efhtr3", - .llvm_name = "ck803efhtr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efr1 = CpuModel{ - .name = "ck803efr1", - .llvm_name = "ck803efr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efr2 = CpuModel{ - .name = "ck803efr2", - .llvm_name = "ck803efr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803efr3 = CpuModel{ - .name = "ck803efr3", - .llvm_name = "ck803efr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eft = CpuModel{ - .name = "ck803eft", - .llvm_name = "ck803eft", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eftr1 = CpuModel{ - .name = "ck803eftr1", - .llvm_name = "ck803eftr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eftr2 = CpuModel{ - .name = "ck803eftr2", - .llvm_name = "ck803eftr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eftr3 = CpuModel{ - .name = "ck803eftr3", - .llvm_name = "ck803eftr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eh = CpuModel{ - .name = "ck803eh", - .llvm_name = "ck803eh", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehr1 = CpuModel{ - .name = "ck803ehr1", - .llvm_name = "ck803ehr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehr2 = CpuModel{ - .name = "ck803ehr2", - .llvm_name = "ck803ehr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehr3 = CpuModel{ - .name = "ck803ehr3", - .llvm_name = "ck803ehr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803eht = CpuModel{ - .name = "ck803eht", - .llvm_name = "ck803eht", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehtr1 = CpuModel{ - .name = "ck803ehtr1", - .llvm_name = "ck803ehtr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehtr2 = CpuModel{ - .name = "ck803ehtr2", - .llvm_name = "ck803ehtr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ehtr3 = CpuModel{ - .name = "ck803ehtr3", - .llvm_name = "ck803ehtr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803er1 = CpuModel{ - .name = "ck803er1", - .llvm_name = "ck803er1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803er2 = CpuModel{ - .name = "ck803er2", - .llvm_name = "ck803er2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803er3 = CpuModel{ - .name = "ck803er3", - .llvm_name = "ck803er3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803et = CpuModel{ - .name = "ck803et", - .llvm_name = "ck803et", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803etr1 = CpuModel{ - .name = "ck803etr1", - .llvm_name = "ck803etr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803etr2 = CpuModel{ - .name = "ck803etr2", - .llvm_name = "ck803etr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803etr3 = CpuModel{ - .name = "ck803etr3", - .llvm_name = "ck803etr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dsp1e2, - .dspe60, - .dspv2, - .edsp, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803f = CpuModel{ - .name = "ck803f", - .llvm_name = "ck803f", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fh = CpuModel{ - .name = "ck803fh", - .llvm_name = "ck803fh", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fhr1 = CpuModel{ - .name = "ck803fhr1", - .llvm_name = "ck803fhr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fhr2 = CpuModel{ - .name = "ck803fhr2", - .llvm_name = "ck803fhr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fhr3 = CpuModel{ - .name = "ck803fhr3", - .llvm_name = "ck803fhr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fr1 = CpuModel{ - .name = "ck803fr1", - .llvm_name = "ck803fr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fr2 = CpuModel{ - .name = "ck803fr2", - .llvm_name = "ck803fr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803fr3 = CpuModel{ - .name = "ck803fr3", - .llvm_name = "ck803fr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ft = CpuModel{ - .name = "ck803ft", - .llvm_name = "ck803ft", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ftr1 = CpuModel{ - .name = "ck803ftr1", - .llvm_name = "ck803ftr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ftr2 = CpuModel{ - .name = "ck803ftr2", - .llvm_name = "ck803ftr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ftr3 = CpuModel{ - .name = "ck803ftr3", - .llvm_name = "ck803ftr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803h = CpuModel{ - .name = "ck803h", - .llvm_name = "ck803h", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803hr1 = CpuModel{ - .name = "ck803hr1", - .llvm_name = "ck803hr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803hr2 = CpuModel{ - .name = "ck803hr2", - .llvm_name = "ck803hr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803hr3 = CpuModel{ - .name = "ck803hr3", - .llvm_name = "ck803hr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803ht = CpuModel{ - .name = "ck803ht", - .llvm_name = "ck803ht", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803htr1 = CpuModel{ - .name = "ck803htr1", - .llvm_name = "ck803htr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803htr2 = CpuModel{ - .name = "ck803htr2", - .llvm_name = "ck803htr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803htr3 = CpuModel{ - .name = "ck803htr3", - .llvm_name = "ck803htr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803r1 = CpuModel{ - .name = "ck803r1", - .llvm_name = "ck803r1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803r2 = CpuModel{ - .name = "ck803r2", - .llvm_name = "ck803r2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803r3 = CpuModel{ - .name = "ck803r3", - .llvm_name = "ck803r3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803s = CpuModel{ - .name = "ck803s", - .llvm_name = "ck803s", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803se = CpuModel{ - .name = "ck803se", - .llvm_name = "ck803se", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sef = CpuModel{ - .name = "ck803sef", - .llvm_name = "ck803sef", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sefn = CpuModel{ - .name = "ck803sefn", - .llvm_name = "ck803sefn", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dsp_silan, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sefnt = CpuModel{ - .name = "ck803sefnt", - .llvm_name = "ck803sefnt", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dsp_silan, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803seft = CpuModel{ - .name = "ck803seft", - .llvm_name = "ck803seft", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dspe60, - .edsp, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sen = CpuModel{ - .name = "ck803sen", - .llvm_name = "ck803sen", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp1e2, - .dsp_silan, - .dspe60, - .edsp, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sf = CpuModel{ - .name = "ck803sf", - .llvm_name = "ck803sf", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sfn = CpuModel{ - .name = "ck803sfn", - .llvm_name = "ck803sfn", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp_silan, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803sn = CpuModel{ - .name = "ck803sn", - .llvm_name = "ck803sn", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp_silan, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803snt = CpuModel{ - .name = "ck803snt", - .llvm_name = "ck803snt", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .dsp_silan, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803st = CpuModel{ - .name = "ck803st", - .llvm_name = "ck803st", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .btst16, - .ck803, - .ck803s, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803t = CpuModel{ - .name = "ck803t", - .llvm_name = "ck803t", - .features = featureSet(&[_]Feature{ - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803tr1 = CpuModel{ - .name = "ck803tr1", - .llvm_name = "ck803tr1", - .features = featureSet(&[_]Feature{ - .@"3e3r1", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803tr2 = CpuModel{ - .name = "ck803tr2", - .llvm_name = "ck803tr2", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck803tr3 = CpuModel{ - .name = "ck803tr3", - .llvm_name = "ck803tr3", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .dspv2, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804 = CpuModel{ - .name = "ck804", - .llvm_name = "ck804", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804e = CpuModel{ - .name = "ck804e", - .llvm_name = "ck804e", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804ef = CpuModel{ - .name = "ck804ef", - .llvm_name = "ck804ef", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804efh = CpuModel{ - .name = "ck804efh", - .llvm_name = "ck804efh", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804efht = CpuModel{ - .name = "ck804efht", - .llvm_name = "ck804efht", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804eft = CpuModel{ - .name = "ck804eft", - .llvm_name = "ck804eft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804eh = CpuModel{ - .name = "ck804eh", - .llvm_name = "ck804eh", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804eht = CpuModel{ - .name = "ck804eht", - .llvm_name = "ck804eht", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804et = CpuModel{ - .name = "ck804et", - .llvm_name = "ck804et", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804f = CpuModel{ - .name = "ck804f", - .llvm_name = "ck804f", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804fh = CpuModel{ - .name = "ck804fh", - .llvm_name = "ck804fh", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804ft = CpuModel{ - .name = "ck804ft", - .llvm_name = "ck804ft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804h = CpuModel{ - .name = "ck804h", - .llvm_name = "ck804h", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804ht = CpuModel{ - .name = "ck804ht", - .llvm_name = "ck804ht", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck804t = CpuModel{ - .name = "ck804t", - .llvm_name = "ck804t", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const ck805 = CpuModel{ - .name = "ck805", - .llvm_name = "ck805", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805e = CpuModel{ - .name = "ck805e", - .llvm_name = "ck805e", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805ef = CpuModel{ - .name = "ck805ef", - .llvm_name = "ck805ef", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805eft = CpuModel{ - .name = "ck805eft", - .llvm_name = "ck805eft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805et = CpuModel{ - .name = "ck805et", - .llvm_name = "ck805et", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805f = CpuModel{ - .name = "ck805f", - .llvm_name = "ck805f", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805ft = CpuModel{ - .name = "ck805ft", - .llvm_name = "ck805ft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck805t = CpuModel{ - .name = "ck805t", - .llvm_name = "ck805t", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const ck807 = CpuModel{ - .name = "ck807", - .llvm_name = "ck807", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck807e = CpuModel{ - .name = "ck807e", - .llvm_name = "ck807e", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck807ef = CpuModel{ - .name = "ck807ef", - .llvm_name = "ck807ef", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .float1e3, - .float3e4, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck807f = CpuModel{ - .name = "ck807f", - .llvm_name = "ck807f", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .float1e3, - .float3e4, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810 = CpuModel{ - .name = "ck810", - .llvm_name = "ck810", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810e = CpuModel{ - .name = "ck810e", - .llvm_name = "ck810e", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810ef = CpuModel{ - .name = "ck810ef", - .llvm_name = "ck810ef", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810eft = CpuModel{ - .name = "ck810eft", - .llvm_name = "ck810eft", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810eftv = CpuModel{ - .name = "ck810eftv", - .llvm_name = "ck810eftv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810efv = CpuModel{ - .name = "ck810efv", - .llvm_name = "ck810efv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810et = CpuModel{ - .name = "ck810et", - .llvm_name = "ck810et", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810etv = CpuModel{ - .name = "ck810etv", - .llvm_name = "ck810etv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810ev = CpuModel{ - .name = "ck810ev", - .llvm_name = "ck810ev", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810f = CpuModel{ - .name = "ck810f", - .llvm_name = "ck810f", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810ft = CpuModel{ - .name = "ck810ft", - .llvm_name = "ck810ft", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810ftv = CpuModel{ - .name = "ck810ftv", - .llvm_name = "ck810ftv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810fv = CpuModel{ - .name = "ck810fv", - .llvm_name = "ck810fv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810t = CpuModel{ - .name = "ck810t", - .llvm_name = "ck810t", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck810tv = CpuModel{ - .name = "ck810tv", - .llvm_name = "ck810tv", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck810v = CpuModel{ - .name = "ck810v", - .llvm_name = "ck810v", - .features = featureSet(&[_]Feature{ - .@"7e10", - .cache, - .ck810, - .ck810v, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdspv1, - }), - }; - pub const ck860 = CpuModel{ - .name = "ck860", - .llvm_name = "ck860", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .dspe60, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck860f = CpuModel{ - .name = "ck860f", - .llvm_name = "ck860f", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .dspe60, - .float7e60, - .fpuv3_df, - .fpuv3_hf, - .fpuv3_hi, - .fpuv3_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const ck860fv = CpuModel{ - .name = "ck860fv", - .llvm_name = "ck860fv", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .ck860v, - .dspe60, - .float7e60, - .fpuv3_df, - .fpuv3_hf, - .fpuv3_hi, - .fpuv3_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdsp2e60f, - .vdspv2, - }), - }; - pub const ck860v = CpuModel{ - .name = "ck860v", - .llvm_name = "ck860v", - .features = featureSet(&[_]Feature{ - .@"10e60", - .@"3e3r2", - .@"3e3r3", - .btst16, - .cache, - .ck860, - .ck860v, - .dspe60, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - .vdsp2e60f, - .vdspv2, - }), - }; - pub const e801 = CpuModel{ - .name = "e801", - .llvm_name = "e801", - .features = featureSet(&[_]Feature{ - .btst16, - .ck801, - .e1, - .trust, - }), - }; - pub const e802 = CpuModel{ - .name = "e802", - .llvm_name = "e802", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const e802t = CpuModel{ - .name = "e802t", - .llvm_name = "e802t", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const e803 = CpuModel{ - .name = "e803", - .llvm_name = "e803", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e803t = CpuModel{ - .name = "e803t", - .llvm_name = "e803t", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804d = CpuModel{ - .name = "e804d", - .llvm_name = "e804d", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804df = CpuModel{ - .name = "e804df", - .llvm_name = "e804df", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804dft = CpuModel{ - .name = "e804dft", - .llvm_name = "e804dft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804dt = CpuModel{ - .name = "e804dt", - .llvm_name = "e804dt", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .dspv2, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804f = CpuModel{ - .name = "e804f", - .llvm_name = "e804f", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const e804ft = CpuModel{ - .name = "e804ft", - .llvm_name = "e804ft", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck804, - .float1e3, - .floate1, - .fpuv2_sf, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .btst16, - }), - }; - pub const @"i805" = CpuModel{ - .name = "i805", - .llvm_name = "i805", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const i805f = CpuModel{ - .name = "i805f", - .llvm_name = "i805f", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .ck805, - .float1e3, - .floate1, - .fpuv2_sf, - .high_registers, - .hwdiv, - .mp, - .nvic, - .trust, - .vdsp2e3, - .vdspv2, - }), - }; - pub const r807 = CpuModel{ - .name = "r807", - .llvm_name = "r807", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const r807f = CpuModel{ - .name = "r807f", - .llvm_name = "r807f", - .features = featureSet(&[_]Feature{ - .cache, - .ck807, - .dsp1e2, - .dspe60, - .edsp, - .fdivdu, - .float1e2, - .float1e3, - .float3e4, - .floate1, - .fpuv2_df, - .fpuv2_sf, - .hard_tp, - .high_registers, - .hwdiv, - .mp, - .mp1e2, - .nvic, - .trust, - }), - }; - pub const s802 = CpuModel{ - .name = "s802", - .llvm_name = "s802", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const s802t = CpuModel{ - .name = "s802t", - .llvm_name = "s802t", - .features = featureSet(&[_]Feature{ - .btst16, - .ck802, - .e2, - .nvic, - .trust, - }), - }; - pub const s803 = CpuModel{ - .name = "s803", - .llvm_name = "s803", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; - pub const s803t = CpuModel{ - .name = "s803t", - .llvm_name = "s803t", - .features = featureSet(&[_]Feature{ - .@"3e3r2", - .@"3e3r3", - .btst16, - .ck803, - .hwdiv, - .mp, - .nvic, - .trust, - }), - }; -}; diff --git a/lib/std/target/hexagon.zig b/lib/std/target/hexagon.zig deleted file mode 100644 index c84b2cb0c8b96d7f2b7d7be6aea19925a1a9df0e..0000000000000000000000000000000000000000 --- a/lib/std/target/hexagon.zig +++ /dev/null @@ -1,586 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - audio, - cabac, - compound, - duplex, - hvx, - hvx_ieee_fp, - hvx_length128b, - hvx_length64b, - hvx_qfloat, - hvxv60, - hvxv62, - hvxv65, - hvxv66, - hvxv67, - hvxv68, - hvxv69, - hvxv71, - hvxv73, - long_calls, - mem_noshuf, - memops, - noreturn_stack_elim, - nvj, - nvs, - packets, - prev65, - reserved_r19, - small_data, - tinycore, - unsafe_fp, - v5, - v55, - v60, - v62, - v65, - v66, - v67, - v68, - v69, - v71, - v73, - zreg, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.audio)] = .{ - .llvm_name = "audio", - .description = "Hexagon Audio extension instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cabac)] = .{ - .llvm_name = "cabac", - .description = "Emit the CABAC instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.compound)] = .{ - .llvm_name = "compound", - .description = "Use compound instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.duplex)] = .{ - .llvm_name = "duplex", - .description = "Enable generation of duplex instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hvx)] = .{ - .llvm_name = "hvx", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hvx_ieee_fp)] = .{ - .llvm_name = "hvx-ieee-fp", - .description = "Hexagon HVX IEEE floating point instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hvx_length128b)] = .{ - .llvm_name = "hvx-length128b", - .description = "Hexagon HVX 128B instructions", - .dependencies = featureSet(&[_]Feature{ - .hvx, - }), - }; - result[@intFromEnum(Feature.hvx_length64b)] = .{ - .llvm_name = "hvx-length64b", - .description = "Hexagon HVX 64B instructions", - .dependencies = featureSet(&[_]Feature{ - .hvx, - }), - }; - result[@intFromEnum(Feature.hvx_qfloat)] = .{ - .llvm_name = "hvx-qfloat", - .description = "Hexagon HVX QFloating point instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hvxv60)] = .{ - .llvm_name = "hvxv60", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvx, - }), - }; - result[@intFromEnum(Feature.hvxv62)] = .{ - .llvm_name = "hvxv62", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv60, - }), - }; - result[@intFromEnum(Feature.hvxv65)] = .{ - .llvm_name = "hvxv65", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv62, - }), - }; - result[@intFromEnum(Feature.hvxv66)] = .{ - .llvm_name = "hvxv66", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv65, - .zreg, - }), - }; - result[@intFromEnum(Feature.hvxv67)] = .{ - .llvm_name = "hvxv67", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv66, - }), - }; - result[@intFromEnum(Feature.hvxv68)] = .{ - .llvm_name = "hvxv68", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv67, - }), - }; - result[@intFromEnum(Feature.hvxv69)] = .{ - .llvm_name = "hvxv69", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv68, - }), - }; - result[@intFromEnum(Feature.hvxv71)] = .{ - .llvm_name = "hvxv71", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv69, - }), - }; - result[@intFromEnum(Feature.hvxv73)] = .{ - .llvm_name = "hvxv73", - .description = "Hexagon HVX instructions", - .dependencies = featureSet(&[_]Feature{ - .hvxv71, - }), - }; - result[@intFromEnum(Feature.long_calls)] = .{ - .llvm_name = "long-calls", - .description = "Use constant-extended calls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mem_noshuf)] = .{ - .llvm_name = "mem_noshuf", - .description = "Supports mem_noshuf feature", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.memops)] = .{ - .llvm_name = "memops", - .description = "Use memop instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.noreturn_stack_elim)] = .{ - .llvm_name = "noreturn-stack-elim", - .description = "Eliminate stack allocation in a noreturn function when possible", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nvj)] = .{ - .llvm_name = "nvj", - .description = "Support for new-value jumps", - .dependencies = featureSet(&[_]Feature{ - .packets, - }), - }; - result[@intFromEnum(Feature.nvs)] = .{ - .llvm_name = "nvs", - .description = "Support for new-value stores", - .dependencies = featureSet(&[_]Feature{ - .packets, - }), - }; - result[@intFromEnum(Feature.packets)] = .{ - .llvm_name = "packets", - .description = "Support for instruction packets", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prev65)] = .{ - .llvm_name = "prev65", - .description = "Support features deprecated in v65", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserved_r19)] = .{ - .llvm_name = "reserved-r19", - .description = "Reserve register R19", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.small_data)] = .{ - .llvm_name = "small-data", - .description = "Allow GP-relative addressing of global variables", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tinycore)] = .{ - .llvm_name = "tinycore", - .description = "Hexagon Tiny Core", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unsafe_fp)] = .{ - .llvm_name = "unsafe-fp", - .description = "Use unsafe FP math", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v5)] = .{ - .llvm_name = "v5", - .description = "Enable Hexagon V5 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v55)] = .{ - .llvm_name = "v55", - .description = "Enable Hexagon V55 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v60)] = .{ - .llvm_name = "v60", - .description = "Enable Hexagon V60 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v62)] = .{ - .llvm_name = "v62", - .description = "Enable Hexagon V62 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v65)] = .{ - .llvm_name = "v65", - .description = "Enable Hexagon V65 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v66)] = .{ - .llvm_name = "v66", - .description = "Enable Hexagon V66 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v67)] = .{ - .llvm_name = "v67", - .description = "Enable Hexagon V67 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v68)] = .{ - .llvm_name = "v68", - .description = "Enable Hexagon V68 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v69)] = .{ - .llvm_name = "v69", - .description = "Enable Hexagon V69 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v71)] = .{ - .llvm_name = "v71", - .description = "Enable Hexagon V71 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v73)] = .{ - .llvm_name = "v73", - .description = "Enable Hexagon V73 architecture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zreg)] = .{ - .llvm_name = "zreg", - .description = "Hexagon ZReg extension instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .memops, - .nvj, - .nvs, - .prev65, - .small_data, - .v5, - .v55, - .v60, - }), - }; - pub const hexagonv5 = CpuModel{ - .name = "hexagonv5", - .llvm_name = "hexagonv5", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .memops, - .nvj, - .nvs, - .prev65, - .small_data, - .v5, - }), - }; - pub const hexagonv55 = CpuModel{ - .name = "hexagonv55", - .llvm_name = "hexagonv55", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .memops, - .nvj, - .nvs, - .prev65, - .small_data, - .v5, - .v55, - }), - }; - pub const hexagonv60 = CpuModel{ - .name = "hexagonv60", - .llvm_name = "hexagonv60", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .memops, - .nvj, - .nvs, - .prev65, - .small_data, - .v5, - .v55, - .v60, - }), - }; - pub const hexagonv62 = CpuModel{ - .name = "hexagonv62", - .llvm_name = "hexagonv62", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .memops, - .nvj, - .nvs, - .prev65, - .small_data, - .v5, - .v55, - .v60, - .v62, - }), - }; - pub const hexagonv65 = CpuModel{ - .name = "hexagonv65", - .llvm_name = "hexagonv65", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - }), - }; - pub const hexagonv66 = CpuModel{ - .name = "hexagonv66", - .llvm_name = "hexagonv66", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - }), - }; - pub const hexagonv67 = CpuModel{ - .name = "hexagonv67", - .llvm_name = "hexagonv67", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - }), - }; - pub const hexagonv67t = CpuModel{ - .name = "hexagonv67t", - .llvm_name = "hexagonv67t", - .features = featureSet(&[_]Feature{ - .audio, - .compound, - .mem_noshuf, - .memops, - .nvs, - .small_data, - .tinycore, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - }), - }; - pub const hexagonv68 = CpuModel{ - .name = "hexagonv68", - .llvm_name = "hexagonv68", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - .v68, - }), - }; - pub const hexagonv69 = CpuModel{ - .name = "hexagonv69", - .llvm_name = "hexagonv69", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - .v68, - .v69, - }), - }; - pub const hexagonv71 = CpuModel{ - .name = "hexagonv71", - .llvm_name = "hexagonv71", - .features = featureSet(&[_]Feature{ - .cabac, - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - .v68, - .v69, - .v71, - }), - }; - pub const hexagonv71t = CpuModel{ - .name = "hexagonv71t", - .llvm_name = "hexagonv71t", - .features = featureSet(&[_]Feature{ - .audio, - .compound, - .mem_noshuf, - .memops, - .nvs, - .small_data, - .tinycore, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - .v68, - .v69, - .v71, - }), - }; - pub const hexagonv73 = CpuModel{ - .name = "hexagonv73", - .llvm_name = "hexagonv73", - .features = featureSet(&[_]Feature{ - .compound, - .duplex, - .mem_noshuf, - .memops, - .nvj, - .nvs, - .small_data, - .v5, - .v55, - .v60, - .v62, - .v65, - .v66, - .v67, - .v68, - .v69, - .v71, - .v73, - }), - }; -}; diff --git a/lib/std/target/loongarch.zig b/lib/std/target/loongarch.zig deleted file mode 100644 index 65dc33d78487dc6c7e31a1d389e319b693b51de8..0000000000000000000000000000000000000000 --- a/lib/std/target/loongarch.zig +++ /dev/null @@ -1,146 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"32bit", - @"64bit", - d, - f, - la_global_with_abs, - la_global_with_pcrel, - la_local_with_abs, - lasx, - lbt, - lsx, - lvz, - ual, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"32bit")] = .{ - .llvm_name = "32bit", - .description = "LA32 Basic Integer and Privilege Instruction Set", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"64bit")] = .{ - .llvm_name = "64bit", - .description = "LA64 Basic Integer and Privilege Instruction Set", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.d)] = .{ - .llvm_name = "d", - .description = "'D' (Double-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.f)] = .{ - .llvm_name = "f", - .description = "'F' (Single-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.la_global_with_abs)] = .{ - .llvm_name = "la-global-with-abs", - .description = "Expand la.global as la.abs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.la_global_with_pcrel)] = .{ - .llvm_name = "la-global-with-pcrel", - .description = "Expand la.global as la.pcrel", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.la_local_with_abs)] = .{ - .llvm_name = "la-local-with-abs", - .description = "Expand la.local as la.abs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lasx)] = .{ - .llvm_name = "lasx", - .description = "'LASX' (Loongson Advanced SIMD Extension)", - .dependencies = featureSet(&[_]Feature{ - .lsx, - }), - }; - result[@intFromEnum(Feature.lbt)] = .{ - .llvm_name = "lbt", - .description = "'LBT' (Loongson Binary Translation Extension)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lsx)] = .{ - .llvm_name = "lsx", - .description = "'LSX' (Loongson SIMD Extension)", - .dependencies = featureSet(&[_]Feature{ - .d, - }), - }; - result[@intFromEnum(Feature.lvz)] = .{ - .llvm_name = "lvz", - .description = "'LVZ' (Loongson Virtualization Extension)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ual)] = .{ - .llvm_name = "ual", - .description = "Allow memory accesses to be unaligned", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const generic_la32 = CpuModel{ - .name = "generic_la32", - .llvm_name = "generic-la32", - .features = featureSet(&[_]Feature{ - .@"32bit", - }), - }; - pub const generic_la64 = CpuModel{ - .name = "generic_la64", - .llvm_name = "generic-la64", - .features = featureSet(&[_]Feature{ - .@"64bit", - .ual, - }), - }; - pub const la464 = CpuModel{ - .name = "la464", - .llvm_name = "la464", - .features = featureSet(&[_]Feature{ - .@"64bit", - .lasx, - .lbt, - .lvz, - .ual, - }), - }; - pub const loongarch64 = CpuModel{ - .name = "loongarch64", - .llvm_name = "loongarch64", - .features = featureSet(&[_]Feature{ - .@"64bit", - .d, - .ual, - }), - }; -}; diff --git a/lib/std/target/m68k.zig b/lib/std/target/m68k.zig deleted file mode 100644 index 054b3974d1fc08eb06ccc2d4933b2e6d14b16d70..0000000000000000000000000000000000000000 --- a/lib/std/target/m68k.zig +++ /dev/null @@ -1,228 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - isa_68000, - isa_68010, - isa_68020, - isa_68030, - isa_68040, - isa_68060, - isa_68881, - isa_68882, - reserve_a0, - reserve_a1, - reserve_a2, - reserve_a3, - reserve_a4, - reserve_a5, - reserve_a6, - reserve_d0, - reserve_d1, - reserve_d2, - reserve_d3, - reserve_d4, - reserve_d5, - reserve_d6, - reserve_d7, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.isa_68000)] = .{ - .llvm_name = "isa-68000", - .description = "Is M68000 ISA supported", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.isa_68010)] = .{ - .llvm_name = "isa-68010", - .description = "Is M68010 ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68000, - }), - }; - result[@intFromEnum(Feature.isa_68020)] = .{ - .llvm_name = "isa-68020", - .description = "Is M68020 ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68010, - }), - }; - result[@intFromEnum(Feature.isa_68030)] = .{ - .llvm_name = "isa-68030", - .description = "Is M68030 ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68020, - }), - }; - result[@intFromEnum(Feature.isa_68040)] = .{ - .llvm_name = "isa-68040", - .description = "Is M68040 ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68030, - .isa_68882, - }), - }; - result[@intFromEnum(Feature.isa_68060)] = .{ - .llvm_name = "isa-68060", - .description = "Is M68060 ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68040, - }), - }; - result[@intFromEnum(Feature.isa_68881)] = .{ - .llvm_name = "isa-68881", - .description = "Is M68881 (FPU) ISA supported", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.isa_68882)] = .{ - .llvm_name = "isa-68882", - .description = "Is M68882 (FPU) ISA supported", - .dependencies = featureSet(&[_]Feature{ - .isa_68881, - }), - }; - result[@intFromEnum(Feature.reserve_a0)] = .{ - .llvm_name = "reserve-a0", - .description = "Reserve A0 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a1)] = .{ - .llvm_name = "reserve-a1", - .description = "Reserve A1 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a2)] = .{ - .llvm_name = "reserve-a2", - .description = "Reserve A2 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a3)] = .{ - .llvm_name = "reserve-a3", - .description = "Reserve A3 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a4)] = .{ - .llvm_name = "reserve-a4", - .description = "Reserve A4 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a5)] = .{ - .llvm_name = "reserve-a5", - .description = "Reserve A5 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_a6)] = .{ - .llvm_name = "reserve-a6", - .description = "Reserve A6 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d0)] = .{ - .llvm_name = "reserve-d0", - .description = "Reserve D0 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d1)] = .{ - .llvm_name = "reserve-d1", - .description = "Reserve D1 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d2)] = .{ - .llvm_name = "reserve-d2", - .description = "Reserve D2 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d3)] = .{ - .llvm_name = "reserve-d3", - .description = "Reserve D3 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d4)] = .{ - .llvm_name = "reserve-d4", - .description = "Reserve D4 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d5)] = .{ - .llvm_name = "reserve-d5", - .description = "Reserve D5 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d6)] = .{ - .llvm_name = "reserve-d6", - .description = "Reserve D6 register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_d7)] = .{ - .llvm_name = "reserve-d7", - .description = "Reserve D7 register", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .isa_68000, - }), - }; - pub const M68000 = CpuModel{ - .name = "M68000", - .llvm_name = "M68000", - .features = featureSet(&[_]Feature{ - .isa_68000, - }), - }; - pub const M68010 = CpuModel{ - .name = "M68010", - .llvm_name = "M68010", - .features = featureSet(&[_]Feature{ - .isa_68010, - }), - }; - pub const M68020 = CpuModel{ - .name = "M68020", - .llvm_name = "M68020", - .features = featureSet(&[_]Feature{ - .isa_68020, - }), - }; - pub const M68030 = CpuModel{ - .name = "M68030", - .llvm_name = "M68030", - .features = featureSet(&[_]Feature{ - .isa_68030, - }), - }; - pub const M68040 = CpuModel{ - .name = "M68040", - .llvm_name = "M68040", - .features = featureSet(&[_]Feature{ - .isa_68040, - }), - }; - pub const M68060 = CpuModel{ - .name = "M68060", - .llvm_name = "M68060", - .features = featureSet(&[_]Feature{ - .isa_68060, - }), - }; -}; diff --git a/lib/std/target/mips.zig b/lib/std/target/mips.zig deleted file mode 100644 index 8f3c0994d1dc08dc4edab589b94a000d979f8076..0000000000000000000000000000000000000000 --- a/lib/std/target/mips.zig +++ /dev/null @@ -1,531 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - abs2008, - cnmips, - cnmipsp, - crc, - dsp, - dspr2, - dspr3, - eva, - fp64, - fpxx, - ginv, - gp64, - long_calls, - micromips, - mips1, - mips16, - mips2, - mips3, - mips32, - mips32r2, - mips32r3, - mips32r5, - mips32r6, - mips3_32, - mips3_32r2, - mips3d, - mips4, - mips4_32, - mips4_32r2, - mips5, - mips5_32r2, - mips64, - mips64r2, - mips64r3, - mips64r5, - mips64r6, - msa, - mt, - nan2008, - noabicalls, - nomadd4, - nooddspreg, - p5600, - ptr64, - single_float, - soft_float, - sym32, - use_indirect_jump_hazard, - use_tcc_in_div, - vfpu, - virt, - xgot, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.abs2008)] = .{ - .llvm_name = "abs2008", - .description = "Disable IEEE 754-2008 abs.fmt mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cnmips)] = .{ - .llvm_name = "cnmips", - .description = "Octeon cnMIPS Support", - .dependencies = featureSet(&[_]Feature{ - .mips64r2, - }), - }; - result[@intFromEnum(Feature.cnmipsp)] = .{ - .llvm_name = "cnmipsp", - .description = "Octeon+ cnMIPS Support", - .dependencies = featureSet(&[_]Feature{ - .cnmips, - }), - }; - result[@intFromEnum(Feature.crc)] = .{ - .llvm_name = "crc", - .description = "Mips R6 CRC ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dsp)] = .{ - .llvm_name = "dsp", - .description = "Mips DSP ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dspr2)] = .{ - .llvm_name = "dspr2", - .description = "Mips DSP-R2 ASE", - .dependencies = featureSet(&[_]Feature{ - .dsp, - }), - }; - result[@intFromEnum(Feature.dspr3)] = .{ - .llvm_name = "dspr3", - .description = "Mips DSP-R3 ASE", - .dependencies = featureSet(&[_]Feature{ - .dspr2, - }), - }; - result[@intFromEnum(Feature.eva)] = .{ - .llvm_name = "eva", - .description = "Mips EVA ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp64)] = .{ - .llvm_name = "fp64", - .description = "Support 64-bit FP registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fpxx)] = .{ - .llvm_name = "fpxx", - .description = "Support for FPXX", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ginv)] = .{ - .llvm_name = "ginv", - .description = "Mips Global Invalidate ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gp64)] = .{ - .llvm_name = "gp64", - .description = "General Purpose Registers are 64-bit wide", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.long_calls)] = .{ - .llvm_name = "long-calls", - .description = "Disable use of the jal instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.micromips)] = .{ - .llvm_name = "micromips", - .description = "microMips mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips1)] = .{ - .llvm_name = "mips1", - .description = "Mips I ISA Support [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips16)] = .{ - .llvm_name = "mips16", - .description = "Mips16 mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips2)] = .{ - .llvm_name = "mips2", - .description = "Mips II ISA Support [highly experimental]", - .dependencies = featureSet(&[_]Feature{ - .mips1, - }), - }; - result[@intFromEnum(Feature.mips3)] = .{ - .llvm_name = "mips3", - .description = "MIPS III ISA Support [highly experimental]", - .dependencies = featureSet(&[_]Feature{ - .fp64, - .gp64, - .mips2, - .mips3_32, - .mips3_32r2, - }), - }; - result[@intFromEnum(Feature.mips32)] = .{ - .llvm_name = "mips32", - .description = "Mips32 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips2, - .mips3_32, - .mips4_32, - }), - }; - result[@intFromEnum(Feature.mips32r2)] = .{ - .llvm_name = "mips32r2", - .description = "Mips32r2 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32, - .mips3_32r2, - .mips4_32r2, - .mips5_32r2, - }), - }; - result[@intFromEnum(Feature.mips32r3)] = .{ - .llvm_name = "mips32r3", - .description = "Mips32r3 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32r2, - }), - }; - result[@intFromEnum(Feature.mips32r5)] = .{ - .llvm_name = "mips32r5", - .description = "Mips32r5 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32r3, - }), - }; - result[@intFromEnum(Feature.mips32r6)] = .{ - .llvm_name = "mips32r6", - .description = "Mips32r6 ISA Support [experimental]", - .dependencies = featureSet(&[_]Feature{ - .abs2008, - .fp64, - .mips32r5, - .nan2008, - }), - }; - result[@intFromEnum(Feature.mips3_32)] = .{ - .llvm_name = "mips3_32", - .description = "Subset of MIPS-III that is also in MIPS32 [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips3_32r2)] = .{ - .llvm_name = "mips3_32r2", - .description = "Subset of MIPS-III that is also in MIPS32r2 [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips3d)] = .{ - .llvm_name = "mips3d", - .description = "Mips 3D ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips4)] = .{ - .llvm_name = "mips4", - .description = "MIPS IV ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips3, - .mips4_32, - .mips4_32r2, - }), - }; - result[@intFromEnum(Feature.mips4_32)] = .{ - .llvm_name = "mips4_32", - .description = "Subset of MIPS-IV that is also in MIPS32 [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips4_32r2)] = .{ - .llvm_name = "mips4_32r2", - .description = "Subset of MIPS-IV that is also in MIPS32r2 [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips5)] = .{ - .llvm_name = "mips5", - .description = "MIPS V ISA Support [highly experimental]", - .dependencies = featureSet(&[_]Feature{ - .mips4, - .mips5_32r2, - }), - }; - result[@intFromEnum(Feature.mips5_32r2)] = .{ - .llvm_name = "mips5_32r2", - .description = "Subset of MIPS-V that is also in MIPS32r2 [highly experimental]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mips64)] = .{ - .llvm_name = "mips64", - .description = "Mips64 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32, - .mips5, - }), - }; - result[@intFromEnum(Feature.mips64r2)] = .{ - .llvm_name = "mips64r2", - .description = "Mips64r2 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32r2, - .mips64, - }), - }; - result[@intFromEnum(Feature.mips64r3)] = .{ - .llvm_name = "mips64r3", - .description = "Mips64r3 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32r3, - .mips64r2, - }), - }; - result[@intFromEnum(Feature.mips64r5)] = .{ - .llvm_name = "mips64r5", - .description = "Mips64r5 ISA Support", - .dependencies = featureSet(&[_]Feature{ - .mips32r5, - .mips64r3, - }), - }; - result[@intFromEnum(Feature.mips64r6)] = .{ - .llvm_name = "mips64r6", - .description = "Mips64r6 ISA Support [experimental]", - .dependencies = featureSet(&[_]Feature{ - .mips32r6, - .mips64r5, - }), - }; - result[@intFromEnum(Feature.msa)] = .{ - .llvm_name = "msa", - .description = "Mips MSA ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mt)] = .{ - .llvm_name = "mt", - .description = "Mips MT ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nan2008)] = .{ - .llvm_name = "nan2008", - .description = "IEEE 754-2008 NaN encoding", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.noabicalls)] = .{ - .llvm_name = "noabicalls", - .description = "Disable SVR4-style position-independent code", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nomadd4)] = .{ - .llvm_name = "nomadd4", - .description = "Disable 4-operand madd.fmt and related instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nooddspreg)] = .{ - .llvm_name = "nooddspreg", - .description = "Disable odd numbered single-precision registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.p5600)] = .{ - .llvm_name = "p5600", - .description = "The P5600 Processor", - .dependencies = featureSet(&[_]Feature{ - .mips32r5, - }), - }; - result[@intFromEnum(Feature.ptr64)] = .{ - .llvm_name = "ptr64", - .description = "Pointers are 64-bit wide", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.single_float)] = .{ - .llvm_name = "single-float", - .description = "Only supports single precision float", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_float)] = .{ - .llvm_name = "soft-float", - .description = "Does not support floating point instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sym32)] = .{ - .llvm_name = "sym32", - .description = "Symbols are 32 bit on Mips64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_indirect_jump_hazard)] = .{ - .llvm_name = "use-indirect-jump-hazard", - .description = "Use indirect jump guards to prevent certain speculation based attacks", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_tcc_in_div)] = .{ - .llvm_name = "use-tcc-in-div", - .description = "Force the assembler to use trapping", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vfpu)] = .{ - .llvm_name = "vfpu", - .description = "Enable vector FPU instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.virt)] = .{ - .llvm_name = "virt", - .description = "Mips Virtualization ASE", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xgot)] = .{ - .llvm_name = "xgot", - .description = "Assume 32-bit GOT", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .mips32, - }), - }; - pub const mips1 = CpuModel{ - .name = "mips1", - .llvm_name = "mips1", - .features = featureSet(&[_]Feature{ - .mips1, - }), - }; - pub const mips2 = CpuModel{ - .name = "mips2", - .llvm_name = "mips2", - .features = featureSet(&[_]Feature{ - .mips2, - }), - }; - pub const mips3 = CpuModel{ - .name = "mips3", - .llvm_name = "mips3", - .features = featureSet(&[_]Feature{ - .mips3, - }), - }; - pub const mips32 = CpuModel{ - .name = "mips32", - .llvm_name = "mips32", - .features = featureSet(&[_]Feature{ - .mips32, - }), - }; - pub const mips32r2 = CpuModel{ - .name = "mips32r2", - .llvm_name = "mips32r2", - .features = featureSet(&[_]Feature{ - .mips32r2, - }), - }; - pub const mips32r3 = CpuModel{ - .name = "mips32r3", - .llvm_name = "mips32r3", - .features = featureSet(&[_]Feature{ - .mips32r3, - }), - }; - pub const mips32r5 = CpuModel{ - .name = "mips32r5", - .llvm_name = "mips32r5", - .features = featureSet(&[_]Feature{ - .mips32r5, - }), - }; - pub const mips32r6 = CpuModel{ - .name = "mips32r6", - .llvm_name = "mips32r6", - .features = featureSet(&[_]Feature{ - .mips32r6, - }), - }; - pub const mips4 = CpuModel{ - .name = "mips4", - .llvm_name = "mips4", - .features = featureSet(&[_]Feature{ - .mips4, - }), - }; - pub const mips5 = CpuModel{ - .name = "mips5", - .llvm_name = "mips5", - .features = featureSet(&[_]Feature{ - .mips5, - }), - }; - pub const mips64 = CpuModel{ - .name = "mips64", - .llvm_name = "mips64", - .features = featureSet(&[_]Feature{ - .mips64, - }), - }; - pub const mips64r2 = CpuModel{ - .name = "mips64r2", - .llvm_name = "mips64r2", - .features = featureSet(&[_]Feature{ - .mips64r2, - }), - }; - pub const mips64r3 = CpuModel{ - .name = "mips64r3", - .llvm_name = "mips64r3", - .features = featureSet(&[_]Feature{ - .mips64r3, - }), - }; - pub const mips64r5 = CpuModel{ - .name = "mips64r5", - .llvm_name = "mips64r5", - .features = featureSet(&[_]Feature{ - .mips64r5, - }), - }; - pub const mips64r6 = CpuModel{ - .name = "mips64r6", - .llvm_name = "mips64r6", - .features = featureSet(&[_]Feature{ - .mips64r6, - }), - }; - pub const octeon = CpuModel{ - .name = "octeon", - .llvm_name = "octeon", - .features = featureSet(&[_]Feature{ - .cnmips, - }), - }; - pub const @"octeon+" = CpuModel{ - .name = "octeon+", - .llvm_name = "octeon+", - .features = featureSet(&[_]Feature{ - .cnmipsp, - }), - }; - pub const p5600 = CpuModel{ - .name = "p5600", - .llvm_name = "p5600", - .features = featureSet(&[_]Feature{ - .p5600, - }), - }; -}; diff --git a/lib/std/target/msp430.zig b/lib/std/target/msp430.zig deleted file mode 100644 index 98ea32d17fbbe33f2facd7d76c6cde3488e08499..0000000000000000000000000000000000000000 --- a/lib/std/target/msp430.zig +++ /dev/null @@ -1,69 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - ext, - hwmult16, - hwmult32, - hwmultf5, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.ext)] = .{ - .llvm_name = "ext", - .description = "Enable MSP430-X extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hwmult16)] = .{ - .llvm_name = "hwmult16", - .description = "Enable 16-bit hardware multiplier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hwmult32)] = .{ - .llvm_name = "hwmult32", - .description = "Enable 32-bit hardware multiplier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hwmultf5)] = .{ - .llvm_name = "hwmultf5", - .description = "Enable F5 series hardware multiplier", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const msp430 = CpuModel{ - .name = "msp430", - .llvm_name = "msp430", - .features = featureSet(&[_]Feature{}), - }; - pub const msp430x = CpuModel{ - .name = "msp430x", - .llvm_name = "msp430x", - .features = featureSet(&[_]Feature{ - .ext, - }), - }; -}; diff --git a/lib/std/target/nvptx.zig b/lib/std/target/nvptx.zig deleted file mode 100644 index 99a281604b83aa6aed0b0251d060e611c86d39c3..0000000000000000000000000000000000000000 --- a/lib/std/target/nvptx.zig +++ /dev/null @@ -1,439 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - ptx32, - ptx40, - ptx41, - ptx42, - ptx43, - ptx50, - ptx60, - ptx61, - ptx63, - ptx64, - ptx65, - ptx70, - ptx71, - ptx72, - ptx73, - ptx74, - ptx75, - ptx76, - ptx77, - ptx78, - ptx80, - ptx81, - sm_20, - sm_21, - sm_30, - sm_32, - sm_35, - sm_37, - sm_50, - sm_52, - sm_53, - sm_60, - sm_61, - sm_62, - sm_70, - sm_72, - sm_75, - sm_80, - sm_86, - sm_87, - sm_89, - sm_90, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.ptx32)] = .{ - .llvm_name = "ptx32", - .description = "Use PTX version 32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx40)] = .{ - .llvm_name = "ptx40", - .description = "Use PTX version 40", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx41)] = .{ - .llvm_name = "ptx41", - .description = "Use PTX version 41", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx42)] = .{ - .llvm_name = "ptx42", - .description = "Use PTX version 42", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx43)] = .{ - .llvm_name = "ptx43", - .description = "Use PTX version 43", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx50)] = .{ - .llvm_name = "ptx50", - .description = "Use PTX version 50", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx60)] = .{ - .llvm_name = "ptx60", - .description = "Use PTX version 60", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx61)] = .{ - .llvm_name = "ptx61", - .description = "Use PTX version 61", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx63)] = .{ - .llvm_name = "ptx63", - .description = "Use PTX version 63", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx64)] = .{ - .llvm_name = "ptx64", - .description = "Use PTX version 64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx65)] = .{ - .llvm_name = "ptx65", - .description = "Use PTX version 65", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx70)] = .{ - .llvm_name = "ptx70", - .description = "Use PTX version 70", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx71)] = .{ - .llvm_name = "ptx71", - .description = "Use PTX version 71", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx72)] = .{ - .llvm_name = "ptx72", - .description = "Use PTX version 72", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx73)] = .{ - .llvm_name = "ptx73", - .description = "Use PTX version 73", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx74)] = .{ - .llvm_name = "ptx74", - .description = "Use PTX version 74", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx75)] = .{ - .llvm_name = "ptx75", - .description = "Use PTX version 75", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx76)] = .{ - .llvm_name = "ptx76", - .description = "Use PTX version 76", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx77)] = .{ - .llvm_name = "ptx77", - .description = "Use PTX version 77", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx78)] = .{ - .llvm_name = "ptx78", - .description = "Use PTX version 78", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx80)] = .{ - .llvm_name = "ptx80", - .description = "Use PTX version 80", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptx81)] = .{ - .llvm_name = "ptx81", - .description = "Use PTX version 81", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_20)] = .{ - .llvm_name = "sm_20", - .description = "Target SM 20", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_21)] = .{ - .llvm_name = "sm_21", - .description = "Target SM 21", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_30)] = .{ - .llvm_name = "sm_30", - .description = "Target SM 30", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_32)] = .{ - .llvm_name = "sm_32", - .description = "Target SM 32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_35)] = .{ - .llvm_name = "sm_35", - .description = "Target SM 35", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_37)] = .{ - .llvm_name = "sm_37", - .description = "Target SM 37", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_50)] = .{ - .llvm_name = "sm_50", - .description = "Target SM 50", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_52)] = .{ - .llvm_name = "sm_52", - .description = "Target SM 52", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_53)] = .{ - .llvm_name = "sm_53", - .description = "Target SM 53", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_60)] = .{ - .llvm_name = "sm_60", - .description = "Target SM 60", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_61)] = .{ - .llvm_name = "sm_61", - .description = "Target SM 61", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_62)] = .{ - .llvm_name = "sm_62", - .description = "Target SM 62", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_70)] = .{ - .llvm_name = "sm_70", - .description = "Target SM 70", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_72)] = .{ - .llvm_name = "sm_72", - .description = "Target SM 72", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_75)] = .{ - .llvm_name = "sm_75", - .description = "Target SM 75", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_80)] = .{ - .llvm_name = "sm_80", - .description = "Target SM 80", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_86)] = .{ - .llvm_name = "sm_86", - .description = "Target SM 86", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_87)] = .{ - .llvm_name = "sm_87", - .description = "Target SM 87", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_89)] = .{ - .llvm_name = "sm_89", - .description = "Target SM 89", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm_90)] = .{ - .llvm_name = "sm_90", - .description = "Target SM 90", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const sm_20 = CpuModel{ - .name = "sm_20", - .llvm_name = "sm_20", - .features = featureSet(&[_]Feature{ - .ptx32, - .sm_20, - }), - }; - pub const sm_21 = CpuModel{ - .name = "sm_21", - .llvm_name = "sm_21", - .features = featureSet(&[_]Feature{ - .ptx32, - .sm_21, - }), - }; - pub const sm_30 = CpuModel{ - .name = "sm_30", - .llvm_name = "sm_30", - .features = featureSet(&[_]Feature{ - .sm_30, - }), - }; - pub const sm_32 = CpuModel{ - .name = "sm_32", - .llvm_name = "sm_32", - .features = featureSet(&[_]Feature{ - .ptx40, - .sm_32, - }), - }; - pub const sm_35 = CpuModel{ - .name = "sm_35", - .llvm_name = "sm_35", - .features = featureSet(&[_]Feature{ - .ptx32, - .sm_35, - }), - }; - pub const sm_37 = CpuModel{ - .name = "sm_37", - .llvm_name = "sm_37", - .features = featureSet(&[_]Feature{ - .ptx41, - .sm_37, - }), - }; - pub const sm_50 = CpuModel{ - .name = "sm_50", - .llvm_name = "sm_50", - .features = featureSet(&[_]Feature{ - .ptx40, - .sm_50, - }), - }; - pub const sm_52 = CpuModel{ - .name = "sm_52", - .llvm_name = "sm_52", - .features = featureSet(&[_]Feature{ - .ptx41, - .sm_52, - }), - }; - pub const sm_53 = CpuModel{ - .name = "sm_53", - .llvm_name = "sm_53", - .features = featureSet(&[_]Feature{ - .ptx42, - .sm_53, - }), - }; - pub const sm_60 = CpuModel{ - .name = "sm_60", - .llvm_name = "sm_60", - .features = featureSet(&[_]Feature{ - .ptx50, - .sm_60, - }), - }; - pub const sm_61 = CpuModel{ - .name = "sm_61", - .llvm_name = "sm_61", - .features = featureSet(&[_]Feature{ - .ptx50, - .sm_61, - }), - }; - pub const sm_62 = CpuModel{ - .name = "sm_62", - .llvm_name = "sm_62", - .features = featureSet(&[_]Feature{ - .ptx50, - .sm_62, - }), - }; - pub const sm_70 = CpuModel{ - .name = "sm_70", - .llvm_name = "sm_70", - .features = featureSet(&[_]Feature{ - .ptx60, - .sm_70, - }), - }; - pub const sm_72 = CpuModel{ - .name = "sm_72", - .llvm_name = "sm_72", - .features = featureSet(&[_]Feature{ - .ptx61, - .sm_72, - }), - }; - pub const sm_75 = CpuModel{ - .name = "sm_75", - .llvm_name = "sm_75", - .features = featureSet(&[_]Feature{ - .ptx63, - .sm_75, - }), - }; - pub const sm_80 = CpuModel{ - .name = "sm_80", - .llvm_name = "sm_80", - .features = featureSet(&[_]Feature{ - .ptx70, - .sm_80, - }), - }; - pub const sm_86 = CpuModel{ - .name = "sm_86", - .llvm_name = "sm_86", - .features = featureSet(&[_]Feature{ - .ptx71, - .sm_86, - }), - }; - pub const sm_87 = CpuModel{ - .name = "sm_87", - .llvm_name = "sm_87", - .features = featureSet(&[_]Feature{ - .ptx74, - .sm_87, - }), - }; - pub const sm_89 = CpuModel{ - .name = "sm_89", - .llvm_name = "sm_89", - .features = featureSet(&[_]Feature{ - .ptx78, - .sm_89, - }), - }; - pub const sm_90 = CpuModel{ - .name = "sm_90", - .llvm_name = "sm_90", - .features = featureSet(&[_]Feature{ - .ptx78, - .sm_90, - }), - }; -}; diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig deleted file mode 100644 index c350c166ba892dab0f460d58c7308b6b35a243a7..0000000000000000000000000000000000000000 --- a/lib/std/target/powerpc.zig +++ /dev/null @@ -1,1192 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"64bit", - @"64bitregs", - aix, - allow_unaligned_fp_access, - altivec, - booke, - bpermd, - cmpb, - crbits, - crypto, - direct_move, - e500, - efpu2, - extdiv, - fast_MFLR, - fcpsgn, - float128, - fpcvt, - fprnd, - fpu, - fre, - fres, - frsqrte, - frsqrtes, - fsqrt, - fuse_add_logical, - fuse_addi_load, - fuse_addis_load, - fuse_arith_add, - fuse_back2back, - fuse_cmp, - fuse_logical, - fuse_logical_add, - fuse_sha3, - fuse_store, - fuse_wideimm, - fuse_zeromove, - fusion, - hard_float, - htm, - icbt, - invariant_function_descriptors, - isa_future_instructions, - isa_v206_instructions, - isa_v207_instructions, - isa_v30_instructions, - isa_v31_instructions, - isel, - ldbrx, - lfiwax, - longcall, - mfocrf, - mma, - modern_aix_as, - msync, - paired_vector_memops, - partword_atomics, - pcrelative_memops, - popcntd, - power10_vector, - power8_altivec, - power8_vector, - power9_altivec, - power9_vector, - ppc4xx, - ppc6xx, - ppc_postra_sched, - ppc_prera_sched, - predictable_select_expensive, - prefix_instrs, - privileged, - quadword_atomics, - recipprec, - rop_protect, - secure_plt, - slow_popcntd, - spe, - stfiwx, - two_const_nr, - vectors_use_two_units, - vsx, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"64bit")] = .{ - .llvm_name = "64bit", - .description = "Enable 64-bit instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"64bitregs")] = .{ - .llvm_name = "64bitregs", - .description = "Enable 64-bit registers usage for ppc32 [beta]", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aix)] = .{ - .llvm_name = "aix", - .description = "AIX OS", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.allow_unaligned_fp_access)] = .{ - .llvm_name = "allow-unaligned-fp-access", - .description = "CPU does not trap on unaligned FP access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.altivec)] = .{ - .llvm_name = "altivec", - .description = "Enable Altivec instructions", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.booke)] = .{ - .llvm_name = "booke", - .description = "Enable Book E instructions", - .dependencies = featureSet(&[_]Feature{ - .icbt, - }), - }; - result[@intFromEnum(Feature.bpermd)] = .{ - .llvm_name = "bpermd", - .description = "Enable the bpermd instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cmpb)] = .{ - .llvm_name = "cmpb", - .description = "Enable the cmpb instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crbits)] = .{ - .llvm_name = "crbits", - .description = "Use condition-register bits individually", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crypto)] = .{ - .llvm_name = "crypto", - .description = "Enable POWER8 Crypto instructions", - .dependencies = featureSet(&[_]Feature{ - .power8_altivec, - }), - }; - result[@intFromEnum(Feature.direct_move)] = .{ - .llvm_name = "direct-move", - .description = "Enable Power8 direct move instructions", - .dependencies = featureSet(&[_]Feature{ - .vsx, - }), - }; - result[@intFromEnum(Feature.e500)] = .{ - .llvm_name = "e500", - .description = "Enable E500/E500mc instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.efpu2)] = .{ - .llvm_name = "efpu2", - .description = "Enable Embedded Floating-Point APU 2 instructions", - .dependencies = featureSet(&[_]Feature{ - .spe, - }), - }; - result[@intFromEnum(Feature.extdiv)] = .{ - .llvm_name = "extdiv", - .description = "Enable extended divide instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_MFLR)] = .{ - .llvm_name = "fast-MFLR", - .description = "MFLR is a fast instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fcpsgn)] = .{ - .llvm_name = "fcpsgn", - .description = "Enable the fcpsgn instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.float128)] = .{ - .llvm_name = "float128", - .description = "Enable the __float128 data type for IEEE-754R Binary128.", - .dependencies = featureSet(&[_]Feature{ - .vsx, - }), - }; - result[@intFromEnum(Feature.fpcvt)] = .{ - .llvm_name = "fpcvt", - .description = "Enable fc[ft]* (unsigned and single-precision) and lfiwzx instructions", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.fprnd)] = .{ - .llvm_name = "fprnd", - .description = "Enable the fri[mnpz] instructions", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.fpu)] = .{ - .llvm_name = "fpu", - .description = "Enable classic FPU instructions", - .dependencies = featureSet(&[_]Feature{ - .hard_float, - }), - }; - result[@intFromEnum(Feature.fre)] = .{ - .llvm_name = "fre", - .description = "Enable the fre instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.fres)] = .{ - .llvm_name = "fres", - .description = "Enable the fres instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.frsqrte)] = .{ - .llvm_name = "frsqrte", - .description = "Enable the frsqrte instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.frsqrtes)] = .{ - .llvm_name = "frsqrtes", - .description = "Enable the frsqrtes instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.fsqrt)] = .{ - .llvm_name = "fsqrt", - .description = "Enable the fsqrt instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.fuse_add_logical)] = .{ - .llvm_name = "fuse-add-logical", - .description = "Target supports Add with Logical Operations fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_addi_load)] = .{ - .llvm_name = "fuse-addi-load", - .description = "Power8 Addi-Load fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_addis_load)] = .{ - .llvm_name = "fuse-addis-load", - .description = "Power8 Addis-Load fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_arith_add)] = .{ - .llvm_name = "fuse-arith-add", - .description = "Target supports Arithmetic Operations with Add fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_back2back)] = .{ - .llvm_name = "fuse-back2back", - .description = "Target supports general back to back fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_cmp)] = .{ - .llvm_name = "fuse-cmp", - .description = "Target supports Comparison Operations fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_logical)] = .{ - .llvm_name = "fuse-logical", - .description = "Target supports Logical Operations fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_logical_add)] = .{ - .llvm_name = "fuse-logical-add", - .description = "Target supports Logical with Add Operations fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_sha3)] = .{ - .llvm_name = "fuse-sha3", - .description = "Target supports SHA3 assist fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_store)] = .{ - .llvm_name = "fuse-store", - .description = "Target supports store clustering", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_wideimm)] = .{ - .llvm_name = "fuse-wideimm", - .description = "Target supports Wide-Immediate fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fuse_zeromove)] = .{ - .llvm_name = "fuse-zeromove", - .description = "Target supports move to SPR with branch fusion", - .dependencies = featureSet(&[_]Feature{ - .fusion, - }), - }; - result[@intFromEnum(Feature.fusion)] = .{ - .llvm_name = "fusion", - .description = "Target supports instruction fusion", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hard_float)] = .{ - .llvm_name = "hard-float", - .description = "Enable floating-point instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.htm)] = .{ - .llvm_name = "htm", - .description = "Enable Hardware Transactional Memory instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.icbt)] = .{ - .llvm_name = "icbt", - .description = "Enable icbt instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.invariant_function_descriptors)] = .{ - .llvm_name = "invariant-function-descriptors", - .description = "Assume function descriptors are invariant", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.isa_future_instructions)] = .{ - .llvm_name = "isa-future-instructions", - .description = "Enable instructions for Future ISA.", - .dependencies = featureSet(&[_]Feature{ - .isa_v31_instructions, - }), - }; - result[@intFromEnum(Feature.isa_v206_instructions)] = .{ - .llvm_name = "isa-v206-instructions", - .description = "Enable instructions in ISA 2.06.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.isa_v207_instructions)] = .{ - .llvm_name = "isa-v207-instructions", - .description = "Enable instructions in ISA 2.07.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.isa_v30_instructions)] = .{ - .llvm_name = "isa-v30-instructions", - .description = "Enable instructions in ISA 3.0.", - .dependencies = featureSet(&[_]Feature{ - .isa_v207_instructions, - }), - }; - result[@intFromEnum(Feature.isa_v31_instructions)] = .{ - .llvm_name = "isa-v31-instructions", - .description = "Enable instructions in ISA 3.1.", - .dependencies = featureSet(&[_]Feature{ - .isa_v30_instructions, - }), - }; - result[@intFromEnum(Feature.isel)] = .{ - .llvm_name = "isel", - .description = "Enable the isel instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ldbrx)] = .{ - .llvm_name = "ldbrx", - .description = "Enable the ldbrx instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lfiwax)] = .{ - .llvm_name = "lfiwax", - .description = "Enable the lfiwax instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.longcall)] = .{ - .llvm_name = "longcall", - .description = "Always use indirect calls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mfocrf)] = .{ - .llvm_name = "mfocrf", - .description = "Enable the MFOCRF instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mma)] = .{ - .llvm_name = "mma", - .description = "Enable MMA instructions", - .dependencies = featureSet(&[_]Feature{ - .paired_vector_memops, - .power8_vector, - .power9_altivec, - }), - }; - result[@intFromEnum(Feature.modern_aix_as)] = .{ - .llvm_name = "modern-aix-as", - .description = "AIX system assembler is modern enough to support new mnes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.msync)] = .{ - .llvm_name = "msync", - .description = "Has only the msync instruction instead of sync", - .dependencies = featureSet(&[_]Feature{ - .booke, - }), - }; - result[@intFromEnum(Feature.paired_vector_memops)] = .{ - .llvm_name = "paired-vector-memops", - .description = "32Byte load and store instructions", - .dependencies = featureSet(&[_]Feature{ - .isa_v30_instructions, - }), - }; - result[@intFromEnum(Feature.partword_atomics)] = .{ - .llvm_name = "partword-atomics", - .description = "Enable l[bh]arx and st[bh]cx.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pcrelative_memops)] = .{ - .llvm_name = "pcrelative-memops", - .description = "Enable PC relative Memory Ops", - .dependencies = featureSet(&[_]Feature{ - .prefix_instrs, - }), - }; - result[@intFromEnum(Feature.popcntd)] = .{ - .llvm_name = "popcntd", - .description = "Enable the popcnt[dw] instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.power10_vector)] = .{ - .llvm_name = "power10-vector", - .description = "Enable POWER10 vector instructions", - .dependencies = featureSet(&[_]Feature{ - .isa_v31_instructions, - .power9_vector, - }), - }; - result[@intFromEnum(Feature.power8_altivec)] = .{ - .llvm_name = "power8-altivec", - .description = "Enable POWER8 Altivec instructions", - .dependencies = featureSet(&[_]Feature{ - .altivec, - }), - }; - result[@intFromEnum(Feature.power8_vector)] = .{ - .llvm_name = "power8-vector", - .description = "Enable POWER8 vector instructions", - .dependencies = featureSet(&[_]Feature{ - .power8_altivec, - .vsx, - }), - }; - result[@intFromEnum(Feature.power9_altivec)] = .{ - .llvm_name = "power9-altivec", - .description = "Enable POWER9 Altivec instructions", - .dependencies = featureSet(&[_]Feature{ - .isa_v30_instructions, - .power8_altivec, - }), - }; - result[@intFromEnum(Feature.power9_vector)] = .{ - .llvm_name = "power9-vector", - .description = "Enable POWER9 vector instructions", - .dependencies = featureSet(&[_]Feature{ - .power8_vector, - .power9_altivec, - }), - }; - result[@intFromEnum(Feature.ppc4xx)] = .{ - .llvm_name = "ppc4xx", - .description = "Enable PPC 4xx instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ppc6xx)] = .{ - .llvm_name = "ppc6xx", - .description = "Enable PPC 6xx instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ppc_postra_sched)] = .{ - .llvm_name = "ppc-postra-sched", - .description = "Use PowerPC post-RA scheduling strategy", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ppc_prera_sched)] = .{ - .llvm_name = "ppc-prera-sched", - .description = "Use PowerPC pre-RA scheduling strategy", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.predictable_select_expensive)] = .{ - .llvm_name = "predictable-select-expensive", - .description = "Prefer likely predicted branches over selects", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefix_instrs)] = .{ - .llvm_name = "prefix-instrs", - .description = "Enable prefixed instructions", - .dependencies = featureSet(&[_]Feature{ - .power8_vector, - .power9_altivec, - }), - }; - result[@intFromEnum(Feature.privileged)] = .{ - .llvm_name = "privileged", - .description = "Add privileged instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.quadword_atomics)] = .{ - .llvm_name = "quadword-atomics", - .description = "Enable lqarx and stqcx.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.recipprec)] = .{ - .llvm_name = "recipprec", - .description = "Assume higher precision reciprocal estimates", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rop_protect)] = .{ - .llvm_name = "rop-protect", - .description = "Add ROP protect", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.secure_plt)] = .{ - .llvm_name = "secure-plt", - .description = "Enable secure plt mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_popcntd)] = .{ - .llvm_name = "slow-popcntd", - .description = "Has slow popcnt[dw] instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.spe)] = .{ - .llvm_name = "spe", - .description = "Enable SPE instructions", - .dependencies = featureSet(&[_]Feature{ - .hard_float, - }), - }; - result[@intFromEnum(Feature.stfiwx)] = .{ - .llvm_name = "stfiwx", - .description = "Enable the stfiwx instruction", - .dependencies = featureSet(&[_]Feature{ - .fpu, - }), - }; - result[@intFromEnum(Feature.two_const_nr)] = .{ - .llvm_name = "two-const-nr", - .description = "Requires two constant Newton-Raphson computation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vectors_use_two_units)] = .{ - .llvm_name = "vectors-use-two-units", - .description = "Vectors use two units", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vsx)] = .{ - .llvm_name = "vsx", - .description = "Enable VSX instructions", - .dependencies = featureSet(&[_]Feature{ - .altivec, - }), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const @"440" = CpuModel{ - .name = "440", - .llvm_name = "440", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - .isel, - .msync, - }), - }; - pub const @"450" = CpuModel{ - .name = "450", - .llvm_name = "450", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - .isel, - .msync, - }), - }; - pub const @"601" = CpuModel{ - .name = "601", - .llvm_name = "601", - .features = featureSet(&[_]Feature{ - .fpu, - }), - }; - pub const @"602" = CpuModel{ - .name = "602", - .llvm_name = "602", - .features = featureSet(&[_]Feature{ - .fpu, - }), - }; - pub const @"603" = CpuModel{ - .name = "603", - .llvm_name = "603", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"603e" = CpuModel{ - .name = "603e", - .llvm_name = "603e", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"603ev" = CpuModel{ - .name = "603ev", - .llvm_name = "603ev", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"604" = CpuModel{ - .name = "604", - .llvm_name = "604", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"604e" = CpuModel{ - .name = "604e", - .llvm_name = "604e", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"620" = CpuModel{ - .name = "620", - .llvm_name = "620", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"7400" = CpuModel{ - .name = "7400", - .llvm_name = "7400", - .features = featureSet(&[_]Feature{ - .altivec, - .fres, - .frsqrte, - }), - }; - pub const @"7450" = CpuModel{ - .name = "7450", - .llvm_name = "7450", - .features = featureSet(&[_]Feature{ - .altivec, - .fres, - .frsqrte, - }), - }; - pub const @"750" = CpuModel{ - .name = "750", - .llvm_name = "750", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const @"970" = CpuModel{ - .name = "970", - .llvm_name = "970", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fres, - .frsqrte, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const a2 = CpuModel{ - .name = "a2", - .llvm_name = "a2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .booke, - .cmpb, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .isa_v206_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .recipprec, - .slow_popcntd, - .stfiwx, - }), - }; - pub const e500 = CpuModel{ - .name = "e500", - .llvm_name = "e500", - .features = featureSet(&[_]Feature{ - .isel, - .msync, - .spe, - }), - }; - pub const e500mc = CpuModel{ - .name = "e500mc", - .llvm_name = "e500mc", - .features = featureSet(&[_]Feature{ - .booke, - .isel, - .stfiwx, - }), - }; - pub const e5500 = CpuModel{ - .name = "e5500", - .llvm_name = "e5500", - .features = featureSet(&[_]Feature{ - .@"64bit", - .booke, - .isel, - .mfocrf, - .stfiwx, - }), - }; - pub const future = CpuModel{ - .name = "future", - .llvm_name = "future", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .crbits, - .crypto, - .direct_move, - .extdiv, - .fast_MFLR, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .fuse_add_logical, - .fuse_arith_add, - .fuse_logical, - .fuse_logical_add, - .fuse_sha3, - .fuse_store, - .htm, - .icbt, - .isa_future_instructions, - .isa_v206_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .mma, - .partword_atomics, - .pcrelative_memops, - .popcntd, - .power10_vector, - .ppc_postra_sched, - .ppc_prera_sched, - .predictable_select_expensive, - .quadword_atomics, - .recipprec, - .stfiwx, - .two_const_nr, - }), - }; - pub const g3 = CpuModel{ - .name = "g3", - .llvm_name = "g3", - .features = featureSet(&[_]Feature{ - .fres, - .frsqrte, - }), - }; - pub const g4 = CpuModel{ - .name = "g4", - .llvm_name = "g4", - .features = featureSet(&[_]Feature{ - .altivec, - .fres, - .frsqrte, - }), - }; - pub const @"g4+" = CpuModel{ - .name = "g4+", - .llvm_name = "g4+", - .features = featureSet(&[_]Feature{ - .altivec, - .fres, - .frsqrte, - }), - }; - pub const g5 = CpuModel{ - .name = "g5", - .llvm_name = "g5", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fres, - .frsqrte, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .hard_float, - }), - }; - pub const ppc = CpuModel{ - .name = "ppc", - .llvm_name = "ppc", - .features = featureSet(&[_]Feature{ - .hard_float, - }), - }; - pub const ppc64 = CpuModel{ - .name = "ppc64", - .llvm_name = "ppc64", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fres, - .frsqrte, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const ppc64le = CpuModel{ - .name = "ppc64le", - .llvm_name = "ppc64le", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .crbits, - .crypto, - .direct_move, - .extdiv, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .fuse_addi_load, - .fuse_addis_load, - .htm, - .icbt, - .isa_v206_instructions, - .isa_v207_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .partword_atomics, - .popcntd, - .power8_vector, - .predictable_select_expensive, - .quadword_atomics, - .recipprec, - .stfiwx, - .two_const_nr, - }), - }; - pub const pwr10 = CpuModel{ - .name = "pwr10", - .llvm_name = "pwr10", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .crbits, - .crypto, - .direct_move, - .extdiv, - .fast_MFLR, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .fuse_add_logical, - .fuse_arith_add, - .fuse_logical, - .fuse_logical_add, - .fuse_sha3, - .fuse_store, - .htm, - .icbt, - .isa_v206_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .mma, - .partword_atomics, - .pcrelative_memops, - .popcntd, - .power10_vector, - .ppc_postra_sched, - .ppc_prera_sched, - .predictable_select_expensive, - .quadword_atomics, - .recipprec, - .stfiwx, - .two_const_nr, - }), - }; - pub const pwr3 = CpuModel{ - .name = "pwr3", - .llvm_name = "pwr3", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fres, - .frsqrte, - .mfocrf, - .stfiwx, - }), - }; - pub const pwr4 = CpuModel{ - .name = "pwr4", - .llvm_name = "pwr4", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fres, - .frsqrte, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const pwr5 = CpuModel{ - .name = "pwr5", - .llvm_name = "pwr5", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const pwr5x = CpuModel{ - .name = "pwr5x", - .llvm_name = "pwr5x", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .mfocrf, - .stfiwx, - }), - }; - pub const pwr6 = CpuModel{ - .name = "pwr6", - .llvm_name = "pwr6", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .cmpb, - .fcpsgn, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .lfiwax, - .mfocrf, - .recipprec, - .stfiwx, - }), - }; - pub const pwr6x = CpuModel{ - .name = "pwr6x", - .llvm_name = "pwr6x", - .features = featureSet(&[_]Feature{ - .@"64bit", - .altivec, - .cmpb, - .fcpsgn, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .lfiwax, - .mfocrf, - .recipprec, - .stfiwx, - }), - }; - pub const pwr7 = CpuModel{ - .name = "pwr7", - .llvm_name = "pwr7", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .extdiv, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .isa_v206_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .popcntd, - .recipprec, - .stfiwx, - .two_const_nr, - .vsx, - }), - }; - pub const pwr8 = CpuModel{ - .name = "pwr8", - .llvm_name = "pwr8", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .crbits, - .crypto, - .direct_move, - .extdiv, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .fuse_addi_load, - .fuse_addis_load, - .htm, - .icbt, - .isa_v206_instructions, - .isa_v207_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .partword_atomics, - .popcntd, - .power8_vector, - .predictable_select_expensive, - .quadword_atomics, - .recipprec, - .stfiwx, - .two_const_nr, - }), - }; - pub const pwr9 = CpuModel{ - .name = "pwr9", - .llvm_name = "pwr9", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_unaligned_fp_access, - .bpermd, - .cmpb, - .crbits, - .crypto, - .direct_move, - .extdiv, - .fcpsgn, - .fpcvt, - .fprnd, - .fre, - .fres, - .frsqrte, - .frsqrtes, - .fsqrt, - .htm, - .icbt, - .isa_v206_instructions, - .isel, - .ldbrx, - .lfiwax, - .mfocrf, - .partword_atomics, - .popcntd, - .power9_vector, - .ppc_postra_sched, - .ppc_prera_sched, - .predictable_select_expensive, - .quadword_atomics, - .recipprec, - .stfiwx, - .two_const_nr, - .vectors_use_two_units, - }), - }; -}; diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig deleted file mode 100644 index 66c02ae6d093d0057d5f8d7a012017015301ccf7..0000000000000000000000000000000000000000 --- a/lib/std/target/riscv.zig +++ /dev/null @@ -1,1341 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"32bit", - @"64bit", - a, - c, - d, - dlen_factor_2, - e, - experimental_smaia, - experimental_ssaia, - experimental_zacas, - experimental_zfa, - experimental_zfbfmin, - experimental_zicond, - experimental_zihintntl, - experimental_ztso, - experimental_zvbb, - experimental_zvbc, - experimental_zvfbfmin, - experimental_zvfbfwma, - experimental_zvkg, - experimental_zvkn, - experimental_zvknc, - experimental_zvkned, - experimental_zvkng, - experimental_zvknha, - experimental_zvknhb, - experimental_zvks, - experimental_zvksc, - experimental_zvksed, - experimental_zvksg, - experimental_zvksh, - experimental_zvkt, - f, - forced_atomics, - h, - lui_addi_fusion, - m, - no_default_unroll, - no_optimized_zero_stride_load, - no_rvc_hints, - relax, - reserve_x1, - reserve_x10, - reserve_x11, - reserve_x12, - reserve_x13, - reserve_x14, - reserve_x15, - reserve_x16, - reserve_x17, - reserve_x18, - reserve_x19, - reserve_x2, - reserve_x20, - reserve_x21, - reserve_x22, - reserve_x23, - reserve_x24, - reserve_x25, - reserve_x26, - reserve_x27, - reserve_x28, - reserve_x29, - reserve_x3, - reserve_x30, - reserve_x31, - reserve_x4, - reserve_x5, - reserve_x6, - reserve_x7, - reserve_x8, - reserve_x9, - save_restore, - seq_cst_trailing_fence, - short_forward_branch_opt, - svinval, - svnapot, - svpbmt, - tagged_globals, - unaligned_scalar_mem, - unaligned_vector_mem, - v, - xcvbitmanip, - xcvmac, - xsfcie, - xsfvcp, - xtheadba, - xtheadbb, - xtheadbs, - xtheadcmo, - xtheadcondmov, - xtheadfmemidx, - xtheadmac, - xtheadmemidx, - xtheadmempair, - xtheadsync, - xtheadvdot, - xventanacondops, - zawrs, - zba, - zbb, - zbc, - zbkb, - zbkc, - zbkx, - zbs, - zca, - zcb, - zcd, - zce, - zcf, - zcmp, - zcmt, - zdinx, - zfh, - zfhmin, - zfinx, - zhinx, - zhinxmin, - zicbom, - zicbop, - zicboz, - zicntr, - zicsr, - zifencei, - zihintpause, - zihpm, - zk, - zkn, - zknd, - zkne, - zknh, - zkr, - zks, - zksed, - zksh, - zkt, - zmmul, - zve32f, - zve32x, - zve64d, - zve64f, - zve64x, - zvfh, - zvl1024b, - zvl128b, - zvl16384b, - zvl2048b, - zvl256b, - zvl32768b, - zvl32b, - zvl4096b, - zvl512b, - zvl64b, - zvl65536b, - zvl8192b, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"32bit")] = .{ - .llvm_name = "32bit", - .description = "Implements RV32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"64bit")] = .{ - .llvm_name = "64bit", - .description = "Implements RV64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.a)] = .{ - .llvm_name = "a", - .description = "'A' (Atomic Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.c)] = .{ - .llvm_name = "c", - .description = "'C' (Compressed Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.d)] = .{ - .llvm_name = "d", - .description = "'D' (Double-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.dlen_factor_2)] = .{ - .llvm_name = "dlen-factor-2", - .description = "Vector unit DLEN(data path width) is half of VLEN", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.e)] = .{ - .llvm_name = "e", - .description = "Implements RV{32,64}E (provides 16 rather than 32 GPRs)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_smaia)] = .{ - .llvm_name = "experimental-smaia", - .description = "'Smaia' (Smaia encompasses all added CSRs and all modifications to interrupt response behavior that the AIA specifies for a hart, over all privilege levels.)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_ssaia)] = .{ - .llvm_name = "experimental-ssaia", - .description = "'Ssaia' (Ssaia is essentially the same as Smaia except excluding the machine-level CSRs and behavior not directly visible to supervisor level.)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zacas)] = .{ - .llvm_name = "experimental-zacas", - .description = "'Zacas' (Atomic Compare-And-Swap Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zfa)] = .{ - .llvm_name = "experimental-zfa", - .description = "'Zfa' (Additional Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.experimental_zfbfmin)] = .{ - .llvm_name = "experimental-zfbfmin", - .description = "'Zfbfmin' (Scalar BF16 Converts)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.experimental_zicond)] = .{ - .llvm_name = "experimental-zicond", - .description = "'Zicond' (Integer Conditional Operations)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zihintntl)] = .{ - .llvm_name = "experimental-zihintntl", - .description = "'Zihintntl' (Non-Temporal Locality Hints)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_ztso)] = .{ - .llvm_name = "experimental-ztso", - .description = "'Ztso' (Memory Model - Total Store Order)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvbb)] = .{ - .llvm_name = "experimental-zvbb", - .description = "'Zvbb' (Vector Bit-manipulation used in Cryptography)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvbc)] = .{ - .llvm_name = "experimental-zvbc", - .description = "'Zvbc' (Vector Carryless Multiplication)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvfbfmin)] = .{ - .llvm_name = "experimental-zvfbfmin", - .description = "'Zvbfmin' (Vector BF16 Converts)", - .dependencies = featureSet(&[_]Feature{ - .zve32f, - }), - }; - result[@intFromEnum(Feature.experimental_zvfbfwma)] = .{ - .llvm_name = "experimental-zvfbfwma", - .description = "'Zvfbfwma' (Vector BF16 widening mul-add)", - .dependencies = featureSet(&[_]Feature{ - .zve32f, - }), - }; - result[@intFromEnum(Feature.experimental_zvkg)] = .{ - .llvm_name = "experimental-zvkg", - .description = "'Zvkg' (Vector GCM instructions for Cryptography)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvkn)] = .{ - .llvm_name = "experimental-zvkn", - .description = "This extension is shorthand for the following set of other extensions: Zvkned, Zvknhb, Zvbb, Zvbc, and Zvkt.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvknc)] = .{ - .llvm_name = "experimental-zvknc", - .description = "This extension is shorthand for the following set of other extensions: Zvkn and Zvbc.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvkned)] = .{ - .llvm_name = "experimental-zvkned", - .description = "'Zvkned' (Vector AES Encryption & Decryption (Single Round))", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvkng)] = .{ - .llvm_name = "experimental-zvkng", - .description = "This extension is shorthand for the following set of other extensions: Zvkn and Zvkg.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvknha)] = .{ - .llvm_name = "experimental-zvknha", - .description = "'Zvknha' (Vector SHA-2 (SHA-256 only))", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvknhb)] = .{ - .llvm_name = "experimental-zvknhb", - .description = "'Zvknhb' (Vector SHA-2 (SHA-256 and SHA-512))", - .dependencies = featureSet(&[_]Feature{ - .experimental_zvknha, - }), - }; - result[@intFromEnum(Feature.experimental_zvks)] = .{ - .llvm_name = "experimental-zvks", - .description = "This extension is shorthand for the following set of other extensions: Zvksed, Zvksh, Zvbb, Zvbc, and Zvkt.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvksc)] = .{ - .llvm_name = "experimental-zvksc", - .description = "This extension is shorthand for the following set of other extensions: Zvks and Zvbc.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvksed)] = .{ - .llvm_name = "experimental-zvksed", - .description = "'Zvksed' (SM4 Block Cipher Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvksg)] = .{ - .llvm_name = "experimental-zvksg", - .description = "This extension is shorthand for the following set of other extensions: Zvks and Zvkg.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvksh)] = .{ - .llvm_name = "experimental-zvksh", - .description = "'Zvksh' (SM3 Hash Function Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.experimental_zvkt)] = .{ - .llvm_name = "experimental-zvkt", - .description = "'Zvkt' (Vector Data-Independent Execution Latency)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.f)] = .{ - .llvm_name = "f", - .description = "'F' (Single-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .zicsr, - }), - }; - result[@intFromEnum(Feature.forced_atomics)] = .{ - .llvm_name = "forced-atomics", - .description = "Assume that lock-free native-width atomics are available", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.h)] = .{ - .llvm_name = "h", - .description = "'H' (Hypervisor)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lui_addi_fusion)] = .{ - .llvm_name = "lui-addi-fusion", - .description = "Enable LUI+ADDI macrofusion", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.m)] = .{ - .llvm_name = "m", - .description = "'M' (Integer Multiplication and Division)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_default_unroll)] = .{ - .llvm_name = "no-default-unroll", - .description = "Disable default unroll preference.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_optimized_zero_stride_load)] = .{ - .llvm_name = "no-optimized-zero-stride-load", - .description = "Hasn't optimized (perform fewer memory operations)zero-stride vector load", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_rvc_hints)] = .{ - .llvm_name = "no-rvc-hints", - .description = "Disable RVC Hint Instructions.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.relax)] = .{ - .llvm_name = "relax", - .description = "Enable Linker relaxation.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x1)] = .{ - .llvm_name = "reserve-x1", - .description = "Reserve X1", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x10)] = .{ - .llvm_name = "reserve-x10", - .description = "Reserve X10", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x11)] = .{ - .llvm_name = "reserve-x11", - .description = "Reserve X11", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x12)] = .{ - .llvm_name = "reserve-x12", - .description = "Reserve X12", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x13)] = .{ - .llvm_name = "reserve-x13", - .description = "Reserve X13", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x14)] = .{ - .llvm_name = "reserve-x14", - .description = "Reserve X14", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x15)] = .{ - .llvm_name = "reserve-x15", - .description = "Reserve X15", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x16)] = .{ - .llvm_name = "reserve-x16", - .description = "Reserve X16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x17)] = .{ - .llvm_name = "reserve-x17", - .description = "Reserve X17", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x18)] = .{ - .llvm_name = "reserve-x18", - .description = "Reserve X18", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x19)] = .{ - .llvm_name = "reserve-x19", - .description = "Reserve X19", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x2)] = .{ - .llvm_name = "reserve-x2", - .description = "Reserve X2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x20)] = .{ - .llvm_name = "reserve-x20", - .description = "Reserve X20", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x21)] = .{ - .llvm_name = "reserve-x21", - .description = "Reserve X21", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x22)] = .{ - .llvm_name = "reserve-x22", - .description = "Reserve X22", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x23)] = .{ - .llvm_name = "reserve-x23", - .description = "Reserve X23", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x24)] = .{ - .llvm_name = "reserve-x24", - .description = "Reserve X24", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x25)] = .{ - .llvm_name = "reserve-x25", - .description = "Reserve X25", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x26)] = .{ - .llvm_name = "reserve-x26", - .description = "Reserve X26", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x27)] = .{ - .llvm_name = "reserve-x27", - .description = "Reserve X27", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x28)] = .{ - .llvm_name = "reserve-x28", - .description = "Reserve X28", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x29)] = .{ - .llvm_name = "reserve-x29", - .description = "Reserve X29", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x3)] = .{ - .llvm_name = "reserve-x3", - .description = "Reserve X3", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x30)] = .{ - .llvm_name = "reserve-x30", - .description = "Reserve X30", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x31)] = .{ - .llvm_name = "reserve-x31", - .description = "Reserve X31", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x4)] = .{ - .llvm_name = "reserve-x4", - .description = "Reserve X4", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x5)] = .{ - .llvm_name = "reserve-x5", - .description = "Reserve X5", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x6)] = .{ - .llvm_name = "reserve-x6", - .description = "Reserve X6", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x7)] = .{ - .llvm_name = "reserve-x7", - .description = "Reserve X7", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x8)] = .{ - .llvm_name = "reserve-x8", - .description = "Reserve X8", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reserve_x9)] = .{ - .llvm_name = "reserve-x9", - .description = "Reserve X9", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.save_restore)] = .{ - .llvm_name = "save-restore", - .description = "Enable save/restore.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.seq_cst_trailing_fence)] = .{ - .llvm_name = "seq-cst-trailing-fence", - .description = "Enable trailing fence for seq-cst store.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.short_forward_branch_opt)] = .{ - .llvm_name = "short-forward-branch-opt", - .description = "Enable short forward branch optimization", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.svinval)] = .{ - .llvm_name = "svinval", - .description = "'Svinval' (Fine-Grained Address-Translation Cache Invalidation)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.svnapot)] = .{ - .llvm_name = "svnapot", - .description = "'Svnapot' (NAPOT Translation Contiguity)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.svpbmt)] = .{ - .llvm_name = "svpbmt", - .description = "'Svpbmt' (Page-Based Memory Types)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tagged_globals)] = .{ - .llvm_name = "tagged-globals", - .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_scalar_mem)] = .{ - .llvm_name = "unaligned-scalar-mem", - .description = "Has reasonably performant unaligned scalar loads and stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.unaligned_vector_mem)] = .{ - .llvm_name = "unaligned-vector-mem", - .description = "Has reasonably performant unaligned vector loads and stores", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v)] = .{ - .llvm_name = "v", - .description = "'V' (Vector Extension for Application Processors)", - .dependencies = featureSet(&[_]Feature{ - .zve64d, - .zvl128b, - }), - }; - result[@intFromEnum(Feature.xcvbitmanip)] = .{ - .llvm_name = "xcvbitmanip", - .description = "'XCVbitmanip' (CORE-V Bit Manipulation)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xcvmac)] = .{ - .llvm_name = "xcvmac", - .description = "'XCVmac' (CORE-V Multiply-Accumulate)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xsfcie)] = .{ - .llvm_name = "xsfcie", - .description = "'XSfcie' (SiFive Custom Instruction Extension SCIE.)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xsfvcp)] = .{ - .llvm_name = "xsfvcp", - .description = "'XSfvcp' (SiFive Custom Vector Coprocessor Interface Instructions)", - .dependencies = featureSet(&[_]Feature{ - .zve32x, - }), - }; - result[@intFromEnum(Feature.xtheadba)] = .{ - .llvm_name = "xtheadba", - .description = "'xtheadba' (T-Head address calculation instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadbb)] = .{ - .llvm_name = "xtheadbb", - .description = "'xtheadbb' (T-Head basic bit-manipulation instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadbs)] = .{ - .llvm_name = "xtheadbs", - .description = "'xtheadbs' (T-Head single-bit instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadcmo)] = .{ - .llvm_name = "xtheadcmo", - .description = "'xtheadcmo' (T-Head cache management instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadcondmov)] = .{ - .llvm_name = "xtheadcondmov", - .description = "'xtheadcondmov' (T-Head conditional move instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadfmemidx)] = .{ - .llvm_name = "xtheadfmemidx", - .description = "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.xtheadmac)] = .{ - .llvm_name = "xtheadmac", - .description = "'xtheadmac' (T-Head Multiply-Accumulate Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadmemidx)] = .{ - .llvm_name = "xtheadmemidx", - .description = "'xtheadmemidx' (T-Head Indexed Memory Operations)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadmempair)] = .{ - .llvm_name = "xtheadmempair", - .description = "'xtheadmempair' (T-Head two-GPR Memory Operations)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadsync)] = .{ - .llvm_name = "xtheadsync", - .description = "'xtheadsync' (T-Head multicore synchronization instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xtheadvdot)] = .{ - .llvm_name = "xtheadvdot", - .description = "'xtheadvdot' (T-Head Vector Extensions for Dot)", - .dependencies = featureSet(&[_]Feature{ - .v, - }), - }; - result[@intFromEnum(Feature.xventanacondops)] = .{ - .llvm_name = "xventanacondops", - .description = "'XVentanaCondOps' (Ventana Conditional Ops)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zawrs)] = .{ - .llvm_name = "zawrs", - .description = "'Zawrs' (Wait on Reservation Set)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zba)] = .{ - .llvm_name = "zba", - .description = "'Zba' (Address Generation Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbb)] = .{ - .llvm_name = "zbb", - .description = "'Zbb' (Basic Bit-Manipulation)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbc)] = .{ - .llvm_name = "zbc", - .description = "'Zbc' (Carry-Less Multiplication)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbkb)] = .{ - .llvm_name = "zbkb", - .description = "'Zbkb' (Bitmanip instructions for Cryptography)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbkc)] = .{ - .llvm_name = "zbkc", - .description = "'Zbkc' (Carry-less multiply instructions for Cryptography)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbkx)] = .{ - .llvm_name = "zbkx", - .description = "'Zbkx' (Crossbar permutation instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zbs)] = .{ - .llvm_name = "zbs", - .description = "'Zbs' (Single-Bit Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zca)] = .{ - .llvm_name = "zca", - .description = "'Zca' (part of the C extension, excluding compressed floating point loads/stores)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zcb)] = .{ - .llvm_name = "zcb", - .description = "'Zcb' (Compressed basic bit manipulation instructions)", - .dependencies = featureSet(&[_]Feature{ - .zca, - }), - }; - result[@intFromEnum(Feature.zcd)] = .{ - .llvm_name = "zcd", - .description = "'Zcd' (Compressed Double-Precision Floating-Point Instructions)", - .dependencies = featureSet(&[_]Feature{ - .zca, - }), - }; - result[@intFromEnum(Feature.zce)] = .{ - .llvm_name = "zce", - .description = "'Zce' (Compressed extensions for microcontrollers)", - .dependencies = featureSet(&[_]Feature{ - .zcb, - .zcmp, - .zcmt, - }), - }; - result[@intFromEnum(Feature.zcf)] = .{ - .llvm_name = "zcf", - .description = "'Zcf' (Compressed Single-Precision Floating-Point Instructions)", - .dependencies = featureSet(&[_]Feature{ - .zca, - }), - }; - result[@intFromEnum(Feature.zcmp)] = .{ - .llvm_name = "zcmp", - .description = "'Zcmp' (sequenced instuctions for code-size reduction)", - .dependencies = featureSet(&[_]Feature{ - .zca, - }), - }; - result[@intFromEnum(Feature.zcmt)] = .{ - .llvm_name = "zcmt", - .description = "'Zcmt' (table jump instuctions for code-size reduction)", - .dependencies = featureSet(&[_]Feature{ - .zca, - .zicsr, - }), - }; - result[@intFromEnum(Feature.zdinx)] = .{ - .llvm_name = "zdinx", - .description = "'Zdinx' (Double in Integer)", - .dependencies = featureSet(&[_]Feature{ - .zfinx, - }), - }; - result[@intFromEnum(Feature.zfh)] = .{ - .llvm_name = "zfh", - .description = "'Zfh' (Half-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.zfhmin)] = .{ - .llvm_name = "zfhmin", - .description = "'Zfhmin' (Half-Precision Floating-Point Minimal)", - .dependencies = featureSet(&[_]Feature{ - .f, - }), - }; - result[@intFromEnum(Feature.zfinx)] = .{ - .llvm_name = "zfinx", - .description = "'Zfinx' (Float in Integer)", - .dependencies = featureSet(&[_]Feature{ - .zicsr, - }), - }; - result[@intFromEnum(Feature.zhinx)] = .{ - .llvm_name = "zhinx", - .description = "'Zhinx' (Half Float in Integer)", - .dependencies = featureSet(&[_]Feature{ - .zfinx, - }), - }; - result[@intFromEnum(Feature.zhinxmin)] = .{ - .llvm_name = "zhinxmin", - .description = "'Zhinxmin' (Half Float in Integer Minimal)", - .dependencies = featureSet(&[_]Feature{ - .zfinx, - }), - }; - result[@intFromEnum(Feature.zicbom)] = .{ - .llvm_name = "zicbom", - .description = "'Zicbom' (Cache-Block Management Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zicbop)] = .{ - .llvm_name = "zicbop", - .description = "'Zicbop' (Cache-Block Prefetch Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zicboz)] = .{ - .llvm_name = "zicboz", - .description = "'Zicboz' (Cache-Block Zero Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zicntr)] = .{ - .llvm_name = "zicntr", - .description = "'Zicntr' (Base Counters and Timers)", - .dependencies = featureSet(&[_]Feature{ - .zicsr, - }), - }; - result[@intFromEnum(Feature.zicsr)] = .{ - .llvm_name = "zicsr", - .description = "'zicsr' (CSRs)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zifencei)] = .{ - .llvm_name = "zifencei", - .description = "'Zifencei' (fence.i)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zihintpause)] = .{ - .llvm_name = "zihintpause", - .description = "'Zihintpause' (Pause Hint)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zihpm)] = .{ - .llvm_name = "zihpm", - .description = "'Zihpm' (Hardware Performance Counters)", - .dependencies = featureSet(&[_]Feature{ - .zicsr, - }), - }; - result[@intFromEnum(Feature.zk)] = .{ - .llvm_name = "zk", - .description = "'Zk' (Standard scalar cryptography extension)", - .dependencies = featureSet(&[_]Feature{ - .zkn, - .zkr, - .zkt, - }), - }; - result[@intFromEnum(Feature.zkn)] = .{ - .llvm_name = "zkn", - .description = "'Zkn' (NIST Algorithm Suite)", - .dependencies = featureSet(&[_]Feature{ - .zbkb, - .zbkc, - .zbkx, - .zknd, - .zkne, - .zknh, - }), - }; - result[@intFromEnum(Feature.zknd)] = .{ - .llvm_name = "zknd", - .description = "'Zknd' (NIST Suite: AES Decryption)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zkne)] = .{ - .llvm_name = "zkne", - .description = "'Zkne' (NIST Suite: AES Encryption)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zknh)] = .{ - .llvm_name = "zknh", - .description = "'Zknh' (NIST Suite: Hash Function Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zkr)] = .{ - .llvm_name = "zkr", - .description = "'Zkr' (Entropy Source Extension)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zks)] = .{ - .llvm_name = "zks", - .description = "'Zks' (ShangMi Algorithm Suite)", - .dependencies = featureSet(&[_]Feature{ - .zbkb, - .zbkc, - .zbkx, - .zksed, - .zksh, - }), - }; - result[@intFromEnum(Feature.zksed)] = .{ - .llvm_name = "zksed", - .description = "'Zksed' (ShangMi Suite: SM4 Block Cipher Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zksh)] = .{ - .llvm_name = "zksh", - .description = "'Zksh' (ShangMi Suite: SM3 Hash Function Instructions)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zkt)] = .{ - .llvm_name = "zkt", - .description = "'Zkt' (Data Independent Execution Latency)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zmmul)] = .{ - .llvm_name = "zmmul", - .description = "'Zmmul' (Integer Multiplication)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zve32f)] = .{ - .llvm_name = "zve32f", - .description = "'Zve32f' (Vector Extensions for Embedded Processors with maximal 32 EEW and F extension)", - .dependencies = featureSet(&[_]Feature{ - .f, - .zve32x, - }), - }; - result[@intFromEnum(Feature.zve32x)] = .{ - .llvm_name = "zve32x", - .description = "'Zve32x' (Vector Extensions for Embedded Processors with maximal 32 EEW)", - .dependencies = featureSet(&[_]Feature{ - .zicsr, - .zvl32b, - }), - }; - result[@intFromEnum(Feature.zve64d)] = .{ - .llvm_name = "zve64d", - .description = "'Zve64d' (Vector Extensions for Embedded Processors with maximal 64 EEW, F and D extension)", - .dependencies = featureSet(&[_]Feature{ - .d, - .zve64f, - }), - }; - result[@intFromEnum(Feature.zve64f)] = .{ - .llvm_name = "zve64f", - .description = "'Zve64f' (Vector Extensions for Embedded Processors with maximal 64 EEW and F extension)", - .dependencies = featureSet(&[_]Feature{ - .zve32f, - .zve64x, - }), - }; - result[@intFromEnum(Feature.zve64x)] = .{ - .llvm_name = "zve64x", - .description = "'Zve64x' (Vector Extensions for Embedded Processors with maximal 64 EEW)", - .dependencies = featureSet(&[_]Feature{ - .zve32x, - .zvl64b, - }), - }; - result[@intFromEnum(Feature.zvfh)] = .{ - .llvm_name = "zvfh", - .description = "'Zvfh' (Vector Half-Precision Floating-Point)", - .dependencies = featureSet(&[_]Feature{ - .zfhmin, - .zve32f, - }), - }; - result[@intFromEnum(Feature.zvl1024b)] = .{ - .llvm_name = "zvl1024b", - .description = "'Zvl' (Minimum Vector Length) 1024", - .dependencies = featureSet(&[_]Feature{ - .zvl512b, - }), - }; - result[@intFromEnum(Feature.zvl128b)] = .{ - .llvm_name = "zvl128b", - .description = "'Zvl' (Minimum Vector Length) 128", - .dependencies = featureSet(&[_]Feature{ - .zvl64b, - }), - }; - result[@intFromEnum(Feature.zvl16384b)] = .{ - .llvm_name = "zvl16384b", - .description = "'Zvl' (Minimum Vector Length) 16384", - .dependencies = featureSet(&[_]Feature{ - .zvl8192b, - }), - }; - result[@intFromEnum(Feature.zvl2048b)] = .{ - .llvm_name = "zvl2048b", - .description = "'Zvl' (Minimum Vector Length) 2048", - .dependencies = featureSet(&[_]Feature{ - .zvl1024b, - }), - }; - result[@intFromEnum(Feature.zvl256b)] = .{ - .llvm_name = "zvl256b", - .description = "'Zvl' (Minimum Vector Length) 256", - .dependencies = featureSet(&[_]Feature{ - .zvl128b, - }), - }; - result[@intFromEnum(Feature.zvl32768b)] = .{ - .llvm_name = "zvl32768b", - .description = "'Zvl' (Minimum Vector Length) 32768", - .dependencies = featureSet(&[_]Feature{ - .zvl16384b, - }), - }; - result[@intFromEnum(Feature.zvl32b)] = .{ - .llvm_name = "zvl32b", - .description = "'Zvl' (Minimum Vector Length) 32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.zvl4096b)] = .{ - .llvm_name = "zvl4096b", - .description = "'Zvl' (Minimum Vector Length) 4096", - .dependencies = featureSet(&[_]Feature{ - .zvl2048b, - }), - }; - result[@intFromEnum(Feature.zvl512b)] = .{ - .llvm_name = "zvl512b", - .description = "'Zvl' (Minimum Vector Length) 512", - .dependencies = featureSet(&[_]Feature{ - .zvl256b, - }), - }; - result[@intFromEnum(Feature.zvl64b)] = .{ - .llvm_name = "zvl64b", - .description = "'Zvl' (Minimum Vector Length) 64", - .dependencies = featureSet(&[_]Feature{ - .zvl32b, - }), - }; - result[@intFromEnum(Feature.zvl65536b)] = .{ - .llvm_name = "zvl65536b", - .description = "'Zvl' (Minimum Vector Length) 65536", - .dependencies = featureSet(&[_]Feature{ - .zvl32768b, - }), - }; - result[@intFromEnum(Feature.zvl8192b)] = .{ - .llvm_name = "zvl8192b", - .description = "'Zvl' (Minimum Vector Length) 8192", - .dependencies = featureSet(&[_]Feature{ - .zvl4096b, - }), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const baseline_rv32 = CpuModel{ - .name = "baseline_rv32", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .d, - .m, - }), - }; - pub const baseline_rv64 = CpuModel{ - .name = "baseline_rv64", - .llvm_name = null, - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .d, - .m, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const generic_rv32 = CpuModel{ - .name = "generic_rv32", - .llvm_name = "generic-rv32", - .features = featureSet(&[_]Feature{ - .@"32bit", - }), - }; - pub const generic_rv64 = CpuModel{ - .name = "generic_rv64", - .llvm_name = "generic-rv64", - .features = featureSet(&[_]Feature{ - .@"64bit", - }), - }; - pub const rocket = CpuModel{ - .name = "rocket", - .llvm_name = "rocket", - .features = featureSet(&[_]Feature{}), - }; - pub const rocket_rv32 = CpuModel{ - .name = "rocket_rv32", - .llvm_name = "rocket-rv32", - .features = featureSet(&[_]Feature{ - .@"32bit", - .zicsr, - .zifencei, - }), - }; - pub const rocket_rv64 = CpuModel{ - .name = "rocket_rv64", - .llvm_name = "rocket-rv64", - .features = featureSet(&[_]Feature{ - .@"64bit", - .zicsr, - .zifencei, - }), - }; - pub const sifive_7_series = CpuModel{ - .name = "sifive_7_series", - .llvm_name = "sifive-7-series", - .features = featureSet(&[_]Feature{ - .no_default_unroll, - .short_forward_branch_opt, - }), - }; - pub const sifive_e20 = CpuModel{ - .name = "sifive_e20", - .llvm_name = "sifive-e20", - .features = featureSet(&[_]Feature{ - .@"32bit", - .c, - .m, - .zicsr, - .zifencei, - }), - }; - pub const sifive_e21 = CpuModel{ - .name = "sifive_e21", - .llvm_name = "sifive-e21", - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .m, - .zicsr, - .zifencei, - }), - }; - pub const sifive_e24 = CpuModel{ - .name = "sifive_e24", - .llvm_name = "sifive-e24", - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .f, - .m, - .zifencei, - }), - }; - pub const sifive_e31 = CpuModel{ - .name = "sifive_e31", - .llvm_name = "sifive-e31", - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .m, - .zicsr, - .zifencei, - }), - }; - pub const sifive_e34 = CpuModel{ - .name = "sifive_e34", - .llvm_name = "sifive-e34", - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .f, - .m, - .zifencei, - }), - }; - pub const sifive_e76 = CpuModel{ - .name = "sifive_e76", - .llvm_name = "sifive-e76", - .features = featureSet(&[_]Feature{ - .@"32bit", - .a, - .c, - .f, - .m, - .no_default_unroll, - .short_forward_branch_opt, - .zifencei, - }), - }; - pub const sifive_s21 = CpuModel{ - .name = "sifive_s21", - .llvm_name = "sifive-s21", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .m, - .zicsr, - .zifencei, - }), - }; - pub const sifive_s51 = CpuModel{ - .name = "sifive_s51", - .llvm_name = "sifive-s51", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .m, - .zicsr, - .zifencei, - }), - }; - pub const sifive_s54 = CpuModel{ - .name = "sifive_s54", - .llvm_name = "sifive-s54", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .d, - .m, - .zifencei, - }), - }; - pub const sifive_s76 = CpuModel{ - .name = "sifive_s76", - .llvm_name = "sifive-s76", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .d, - .m, - .no_default_unroll, - .short_forward_branch_opt, - .xsfcie, - .zifencei, - .zihintpause, - }), - }; - pub const sifive_u54 = CpuModel{ - .name = "sifive_u54", - .llvm_name = "sifive-u54", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .d, - .m, - .zifencei, - }), - }; - pub const sifive_u74 = CpuModel{ - .name = "sifive_u74", - .llvm_name = "sifive-u74", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .d, - .m, - .no_default_unroll, - .short_forward_branch_opt, - .zifencei, - }), - }; - pub const sifive_x280 = CpuModel{ - .name = "sifive_x280", - .llvm_name = "sifive-x280", - .features = featureSet(&[_]Feature{ - .@"64bit", - .a, - .c, - .dlen_factor_2, - .m, - .no_default_unroll, - .short_forward_branch_opt, - .v, - .zba, - .zbb, - .zfh, - .zifencei, - .zvfh, - .zvl512b, - }), - }; - pub const syntacore_scr1_base = CpuModel{ - .name = "syntacore_scr1_base", - .llvm_name = "syntacore-scr1-base", - .features = featureSet(&[_]Feature{ - .@"32bit", - .c, - .no_default_unroll, - .zicsr, - .zifencei, - }), - }; - pub const syntacore_scr1_max = CpuModel{ - .name = "syntacore_scr1_max", - .llvm_name = "syntacore-scr1-max", - .features = featureSet(&[_]Feature{ - .@"32bit", - .c, - .m, - .no_default_unroll, - .zicsr, - .zifencei, - }), - }; -}; diff --git a/lib/std/target/s390x.zig b/lib/std/target/s390x.zig deleted file mode 100644 index b64284725833d45e4f02fe96570411e65f4ca4d4..0000000000000000000000000000000000000000 --- a/lib/std/target/s390x.zig +++ /dev/null @@ -1,667 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - bear_enhancement, - deflate_conversion, - dfp_packed_conversion, - dfp_zoned_conversion, - distinct_ops, - enhanced_dat_2, - enhanced_sort, - execution_hint, - fast_serialization, - fp_extension, - guarded_storage, - high_word, - insert_reference_bits_multiple, - interlocked_access1, - load_and_trap, - load_and_zero_rightmost_byte, - load_store_on_cond, - load_store_on_cond_2, - message_security_assist_extension3, - message_security_assist_extension4, - message_security_assist_extension5, - message_security_assist_extension7, - message_security_assist_extension8, - message_security_assist_extension9, - miscellaneous_extensions, - miscellaneous_extensions_2, - miscellaneous_extensions_3, - nnp_assist, - population_count, - processor_activity_instrumentation, - processor_assist, - reset_dat_protection, - reset_reference_bits_multiple, - soft_float, - transactional_execution, - vector, - vector_enhancements_1, - vector_enhancements_2, - vector_packed_decimal, - vector_packed_decimal_enhancement, - vector_packed_decimal_enhancement_2, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.bear_enhancement)] = .{ - .llvm_name = "bear-enhancement", - .description = "Assume that the BEAR-enhancement facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.deflate_conversion)] = .{ - .llvm_name = "deflate-conversion", - .description = "Assume that the deflate-conversion facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dfp_packed_conversion)] = .{ - .llvm_name = "dfp-packed-conversion", - .description = "Assume that the DFP packed-conversion facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.dfp_zoned_conversion)] = .{ - .llvm_name = "dfp-zoned-conversion", - .description = "Assume that the DFP zoned-conversion facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.distinct_ops)] = .{ - .llvm_name = "distinct-ops", - .description = "Assume that the distinct-operands facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.enhanced_dat_2)] = .{ - .llvm_name = "enhanced-dat-2", - .description = "Assume that the enhanced-DAT facility 2 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.enhanced_sort)] = .{ - .llvm_name = "enhanced-sort", - .description = "Assume that the enhanced-sort facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.execution_hint)] = .{ - .llvm_name = "execution-hint", - .description = "Assume that the execution-hint facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_serialization)] = .{ - .llvm_name = "fast-serialization", - .description = "Assume that the fast-serialization facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fp_extension)] = .{ - .llvm_name = "fp-extension", - .description = "Assume that the floating-point extension facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.guarded_storage)] = .{ - .llvm_name = "guarded-storage", - .description = "Assume that the guarded-storage facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.high_word)] = .{ - .llvm_name = "high-word", - .description = "Assume that the high-word facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.insert_reference_bits_multiple)] = .{ - .llvm_name = "insert-reference-bits-multiple", - .description = "Assume that the insert-reference-bits-multiple facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.interlocked_access1)] = .{ - .llvm_name = "interlocked-access1", - .description = "Assume that interlocked-access facility 1 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.load_and_trap)] = .{ - .llvm_name = "load-and-trap", - .description = "Assume that the load-and-trap facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.load_and_zero_rightmost_byte)] = .{ - .llvm_name = "load-and-zero-rightmost-byte", - .description = "Assume that the load-and-zero-rightmost-byte facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.load_store_on_cond)] = .{ - .llvm_name = "load-store-on-cond", - .description = "Assume that the load/store-on-condition facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.load_store_on_cond_2)] = .{ - .llvm_name = "load-store-on-cond-2", - .description = "Assume that the load/store-on-condition facility 2 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension3)] = .{ - .llvm_name = "message-security-assist-extension3", - .description = "Assume that the message-security-assist extension facility 3 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension4)] = .{ - .llvm_name = "message-security-assist-extension4", - .description = "Assume that the message-security-assist extension facility 4 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension5)] = .{ - .llvm_name = "message-security-assist-extension5", - .description = "Assume that the message-security-assist extension facility 5 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension7)] = .{ - .llvm_name = "message-security-assist-extension7", - .description = "Assume that the message-security-assist extension facility 7 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension8)] = .{ - .llvm_name = "message-security-assist-extension8", - .description = "Assume that the message-security-assist extension facility 8 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.message_security_assist_extension9)] = .{ - .llvm_name = "message-security-assist-extension9", - .description = "Assume that the message-security-assist extension facility 9 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.miscellaneous_extensions)] = .{ - .llvm_name = "miscellaneous-extensions", - .description = "Assume that the miscellaneous-extensions facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.miscellaneous_extensions_2)] = .{ - .llvm_name = "miscellaneous-extensions-2", - .description = "Assume that the miscellaneous-extensions facility 2 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.miscellaneous_extensions_3)] = .{ - .llvm_name = "miscellaneous-extensions-3", - .description = "Assume that the miscellaneous-extensions facility 3 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nnp_assist)] = .{ - .llvm_name = "nnp-assist", - .description = "Assume that the NNP-assist facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.population_count)] = .{ - .llvm_name = "population-count", - .description = "Assume that the population-count facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.processor_activity_instrumentation)] = .{ - .llvm_name = "processor-activity-instrumentation", - .description = "Assume that the processor-activity-instrumentation facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.processor_assist)] = .{ - .llvm_name = "processor-assist", - .description = "Assume that the processor-assist facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reset_dat_protection)] = .{ - .llvm_name = "reset-dat-protection", - .description = "Assume that the reset-DAT-protection facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reset_reference_bits_multiple)] = .{ - .llvm_name = "reset-reference-bits-multiple", - .description = "Assume that the reset-reference-bits-multiple facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_float)] = .{ - .llvm_name = "soft-float", - .description = "Use software emulation for floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.transactional_execution)] = .{ - .llvm_name = "transactional-execution", - .description = "Assume that the transactional-execution facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector)] = .{ - .llvm_name = "vector", - .description = "Assume that the vectory facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector_enhancements_1)] = .{ - .llvm_name = "vector-enhancements-1", - .description = "Assume that the vector enhancements facility 1 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector_enhancements_2)] = .{ - .llvm_name = "vector-enhancements-2", - .description = "Assume that the vector enhancements facility 2 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector_packed_decimal)] = .{ - .llvm_name = "vector-packed-decimal", - .description = "Assume that the vector packed decimal facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector_packed_decimal_enhancement)] = .{ - .llvm_name = "vector-packed-decimal-enhancement", - .description = "Assume that the vector packed decimal enhancement facility is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vector_packed_decimal_enhancement_2)] = .{ - .llvm_name = "vector-packed-decimal-enhancement-2", - .description = "Assume that the vector packed decimal enhancement facility 2 is installed", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const arch10 = CpuModel{ - .name = "arch10", - .llvm_name = "arch10", - .features = featureSet(&[_]Feature{ - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_and_trap, - .load_store_on_cond, - .message_security_assist_extension3, - .message_security_assist_extension4, - .miscellaneous_extensions, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - }), - }; - pub const arch11 = CpuModel{ - .name = "arch11", - .llvm_name = "arch11", - .features = featureSet(&[_]Feature{ - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .miscellaneous_extensions, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - }), - }; - pub const arch12 = CpuModel{ - .name = "arch12", - .llvm_name = "arch12", - .features = featureSet(&[_]Feature{ - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_packed_decimal, - }), - }; - pub const arch13 = CpuModel{ - .name = "arch13", - .llvm_name = "arch13", - .features = featureSet(&[_]Feature{ - .deflate_conversion, - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .enhanced_sort, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .message_security_assist_extension9, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .miscellaneous_extensions_3, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_enhancements_2, - .vector_packed_decimal, - .vector_packed_decimal_enhancement, - }), - }; - pub const arch14 = CpuModel{ - .name = "arch14", - .llvm_name = "arch14", - .features = featureSet(&[_]Feature{ - .bear_enhancement, - .deflate_conversion, - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .enhanced_sort, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .message_security_assist_extension9, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .miscellaneous_extensions_3, - .nnp_assist, - .population_count, - .processor_activity_instrumentation, - .processor_assist, - .reset_dat_protection, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_enhancements_2, - .vector_packed_decimal, - .vector_packed_decimal_enhancement, - .vector_packed_decimal_enhancement_2, - }), - }; - pub const arch8 = CpuModel{ - .name = "arch8", - .llvm_name = "arch8", - .features = featureSet(&[_]Feature{}), - }; - pub const arch9 = CpuModel{ - .name = "arch9", - .llvm_name = "arch9", - .features = featureSet(&[_]Feature{ - .distinct_ops, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_store_on_cond, - .message_security_assist_extension3, - .message_security_assist_extension4, - .population_count, - .reset_reference_bits_multiple, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const z10 = CpuModel{ - .name = "z10", - .llvm_name = "z10", - .features = featureSet(&[_]Feature{}), - }; - pub const z13 = CpuModel{ - .name = "z13", - .llvm_name = "z13", - .features = featureSet(&[_]Feature{ - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .miscellaneous_extensions, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - }), - }; - pub const z14 = CpuModel{ - .name = "z14", - .llvm_name = "z14", - .features = featureSet(&[_]Feature{ - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_packed_decimal, - }), - }; - pub const z15 = CpuModel{ - .name = "z15", - .llvm_name = "z15", - .features = featureSet(&[_]Feature{ - .deflate_conversion, - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .enhanced_sort, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .message_security_assist_extension9, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .miscellaneous_extensions_3, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_enhancements_2, - .vector_packed_decimal, - .vector_packed_decimal_enhancement, - }), - }; - pub const z16 = CpuModel{ - .name = "z16", - .llvm_name = "z16", - .features = featureSet(&[_]Feature{ - .bear_enhancement, - .deflate_conversion, - .dfp_packed_conversion, - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .enhanced_sort, - .execution_hint, - .fast_serialization, - .fp_extension, - .guarded_storage, - .high_word, - .insert_reference_bits_multiple, - .interlocked_access1, - .load_and_trap, - .load_and_zero_rightmost_byte, - .load_store_on_cond, - .load_store_on_cond_2, - .message_security_assist_extension3, - .message_security_assist_extension4, - .message_security_assist_extension5, - .message_security_assist_extension7, - .message_security_assist_extension8, - .message_security_assist_extension9, - .miscellaneous_extensions, - .miscellaneous_extensions_2, - .miscellaneous_extensions_3, - .nnp_assist, - .population_count, - .processor_activity_instrumentation, - .processor_assist, - .reset_dat_protection, - .reset_reference_bits_multiple, - .transactional_execution, - .vector, - .vector_enhancements_1, - .vector_enhancements_2, - .vector_packed_decimal, - .vector_packed_decimal_enhancement, - .vector_packed_decimal_enhancement_2, - }), - }; - pub const z196 = CpuModel{ - .name = "z196", - .llvm_name = "z196", - .features = featureSet(&[_]Feature{ - .distinct_ops, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_store_on_cond, - .message_security_assist_extension3, - .message_security_assist_extension4, - .population_count, - .reset_reference_bits_multiple, - }), - }; - pub const zEC12 = CpuModel{ - .name = "zEC12", - .llvm_name = "zEC12", - .features = featureSet(&[_]Feature{ - .dfp_zoned_conversion, - .distinct_ops, - .enhanced_dat_2, - .execution_hint, - .fast_serialization, - .fp_extension, - .high_word, - .interlocked_access1, - .load_and_trap, - .load_store_on_cond, - .message_security_assist_extension3, - .message_security_assist_extension4, - .miscellaneous_extensions, - .population_count, - .processor_assist, - .reset_reference_bits_multiple, - .transactional_execution, - }), - }; -}; diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig deleted file mode 100644 index 87bd95697c2081d3c34dfb47ba57b76c1f678628..0000000000000000000000000000000000000000 --- a/lib/std/target/sparc.zig +++ /dev/null @@ -1,455 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - deprecated_v8, - detectroundchange, - fixallfdivsqrt, - hard_quad_float, - hasleoncasa, - hasumacsmac, - insertnopload, - leon, - leoncyclecounter, - leonpwrpsr, - no_fmuls, - no_fsmuld, - popc, - soft_float, - soft_mul_div, - v9, - vis, - vis2, - vis3, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.deprecated_v8)] = .{ - .llvm_name = "deprecated-v8", - .description = "Enable deprecated V8 instructions in V9 mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.detectroundchange)] = .{ - .llvm_name = "detectroundchange", - .description = "LEON3 erratum detection: Detects any rounding mode change request: use only the round-to-nearest rounding mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fixallfdivsqrt)] = .{ - .llvm_name = "fixallfdivsqrt", - .description = "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hard_quad_float)] = .{ - .llvm_name = "hard-quad-float", - .description = "Enable quad-word floating point instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hasleoncasa)] = .{ - .llvm_name = "hasleoncasa", - .description = "Enable CASA instruction for LEON3 and LEON4 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hasumacsmac)] = .{ - .llvm_name = "hasumacsmac", - .description = "Enable UMAC and SMAC for LEON3 and LEON4 processors", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.insertnopload)] = .{ - .llvm_name = "insertnopload", - .description = "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.leon)] = .{ - .llvm_name = "leon", - .description = "Enable LEON extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.leoncyclecounter)] = .{ - .llvm_name = "leoncyclecounter", - .description = "Use the Leon cycle counter register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.leonpwrpsr)] = .{ - .llvm_name = "leonpwrpsr", - .description = "Enable the PWRPSR instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_fmuls)] = .{ - .llvm_name = "no-fmuls", - .description = "Disable the fmuls instruction.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_fsmuld)] = .{ - .llvm_name = "no-fsmuld", - .description = "Disable the fsmuld instruction.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.popc)] = .{ - .llvm_name = "popc", - .description = "Use the popc (population count) instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_float)] = .{ - .llvm_name = "soft-float", - .description = "Use software emulation for floating point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.soft_mul_div)] = .{ - .llvm_name = "soft-mul-div", - .description = "Use software emulation for integer multiply and divide", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v9)] = .{ - .llvm_name = "v9", - .description = "Enable SPARC-V9 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vis)] = .{ - .llvm_name = "vis", - .description = "Enable UltraSPARC Visual Instruction Set extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vis2)] = .{ - .llvm_name = "vis2", - .description = "Enable Visual Instruction Set extensions II", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vis3)] = .{ - .llvm_name = "vis3", - .description = "Enable Visual Instruction Set extensions III", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const at697e = CpuModel{ - .name = "at697e", - .llvm_name = "at697e", - .features = featureSet(&[_]Feature{ - .insertnopload, - .leon, - }), - }; - pub const at697f = CpuModel{ - .name = "at697f", - .llvm_name = "at697f", - .features = featureSet(&[_]Feature{ - .insertnopload, - .leon, - }), - }; - pub const f934 = CpuModel{ - .name = "f934", - .llvm_name = "f934", - .features = featureSet(&[_]Feature{}), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; - pub const gr712rc = CpuModel{ - .name = "gr712rc", - .llvm_name = "gr712rc", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const gr740 = CpuModel{ - .name = "gr740", - .llvm_name = "gr740", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .hasumacsmac, - .leon, - .leoncyclecounter, - .leonpwrpsr, - }), - }; - pub const hypersparc = CpuModel{ - .name = "hypersparc", - .llvm_name = "hypersparc", - .features = featureSet(&[_]Feature{}), - }; - pub const leon2 = CpuModel{ - .name = "leon2", - .llvm_name = "leon2", - .features = featureSet(&[_]Feature{ - .leon, - }), - }; - pub const leon3 = CpuModel{ - .name = "leon3", - .llvm_name = "leon3", - .features = featureSet(&[_]Feature{ - .hasumacsmac, - .leon, - }), - }; - pub const leon4 = CpuModel{ - .name = "leon4", - .llvm_name = "leon4", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .hasumacsmac, - .leon, - }), - }; - pub const ma2080 = CpuModel{ - .name = "ma2080", - .llvm_name = "ma2080", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2085 = CpuModel{ - .name = "ma2085", - .llvm_name = "ma2085", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2100 = CpuModel{ - .name = "ma2100", - .llvm_name = "ma2100", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2150 = CpuModel{ - .name = "ma2150", - .llvm_name = "ma2150", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2155 = CpuModel{ - .name = "ma2155", - .llvm_name = "ma2155", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2450 = CpuModel{ - .name = "ma2450", - .llvm_name = "ma2450", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2455 = CpuModel{ - .name = "ma2455", - .llvm_name = "ma2455", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2480 = CpuModel{ - .name = "ma2480", - .llvm_name = "ma2480", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2485 = CpuModel{ - .name = "ma2485", - .llvm_name = "ma2485", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2x5x = CpuModel{ - .name = "ma2x5x", - .llvm_name = "ma2x5x", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const ma2x8x = CpuModel{ - .name = "ma2x8x", - .llvm_name = "ma2x8x", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const myriad2 = CpuModel{ - .name = "myriad2", - .llvm_name = "myriad2", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const myriad2_1 = CpuModel{ - .name = "myriad2_1", - .llvm_name = "myriad2.1", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const myriad2_2 = CpuModel{ - .name = "myriad2_2", - .llvm_name = "myriad2.2", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const myriad2_3 = CpuModel{ - .name = "myriad2_3", - .llvm_name = "myriad2.3", - .features = featureSet(&[_]Feature{ - .hasleoncasa, - .leon, - }), - }; - pub const niagara = CpuModel{ - .name = "niagara", - .llvm_name = "niagara", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .v9, - .vis, - .vis2, - }), - }; - pub const niagara2 = CpuModel{ - .name = "niagara2", - .llvm_name = "niagara2", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .popc, - .v9, - .vis, - .vis2, - }), - }; - pub const niagara3 = CpuModel{ - .name = "niagara3", - .llvm_name = "niagara3", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .popc, - .v9, - .vis, - .vis2, - }), - }; - pub const niagara4 = CpuModel{ - .name = "niagara4", - .llvm_name = "niagara4", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .popc, - .v9, - .vis, - .vis2, - .vis3, - }), - }; - pub const sparclet = CpuModel{ - .name = "sparclet", - .llvm_name = "sparclet", - .features = featureSet(&[_]Feature{}), - }; - pub const sparclite = CpuModel{ - .name = "sparclite", - .llvm_name = "sparclite", - .features = featureSet(&[_]Feature{}), - }; - pub const sparclite86x = CpuModel{ - .name = "sparclite86x", - .llvm_name = "sparclite86x", - .features = featureSet(&[_]Feature{}), - }; - pub const supersparc = CpuModel{ - .name = "supersparc", - .llvm_name = "supersparc", - .features = featureSet(&[_]Feature{}), - }; - pub const tsc701 = CpuModel{ - .name = "tsc701", - .llvm_name = "tsc701", - .features = featureSet(&[_]Feature{}), - }; - pub const ultrasparc = CpuModel{ - .name = "ultrasparc", - .llvm_name = "ultrasparc", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .v9, - .vis, - }), - }; - pub const ultrasparc3 = CpuModel{ - .name = "ultrasparc3", - .llvm_name = "ultrasparc3", - .features = featureSet(&[_]Feature{ - .deprecated_v8, - .v9, - .vis, - .vis2, - }), - }; - pub const ut699 = CpuModel{ - .name = "ut699", - .llvm_name = "ut699", - .features = featureSet(&[_]Feature{ - .fixallfdivsqrt, - .insertnopload, - .leon, - .no_fmuls, - .no_fsmuld, - }), - }; - pub const v7 = CpuModel{ - .name = "v7", - .llvm_name = "v7", - .features = featureSet(&[_]Feature{ - .no_fsmuld, - .soft_mul_div, - }), - }; - pub const v8 = CpuModel{ - .name = "v8", - .llvm_name = "v8", - .features = featureSet(&[_]Feature{}), - }; - pub const v9 = CpuModel{ - .name = "v9", - .llvm_name = "v9", - .features = featureSet(&[_]Feature{ - .v9, - }), - }; -}; diff --git a/lib/std/target/spirv.zig b/lib/std/target/spirv.zig deleted file mode 100644 index 9d79aff2212cf6b687898b08897cf0185f28fa7b..0000000000000000000000000000000000000000 --- a/lib/std/target/spirv.zig +++ /dev/null @@ -1,2091 +0,0 @@ -//! This file is auto-generated by tools/update_spirv_features.zig. -//! TODO: Dependencies of capabilities on extensions. -//! TODO: Dependencies of extensions on extensions. -//! TODO: Dependencies of extensions on versions. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - v1_1, - v1_2, - v1_3, - v1_4, - v1_5, - SPV_AMD_shader_fragment_mask, - SPV_AMD_gpu_shader_int16, - SPV_AMD_gpu_shader_half_float, - SPV_AMD_texture_gather_bias_lod, - SPV_AMD_shader_ballot, - SPV_AMD_gcn_shader, - SPV_AMD_shader_image_load_store_lod, - SPV_AMD_shader_explicit_vertex_parameter, - SPV_AMD_shader_trinary_minmax, - SPV_AMD_gpu_shader_half_float_fetch, - SPV_GOOGLE_hlsl_functionality1, - SPV_GOOGLE_user_type, - SPV_GOOGLE_decorate_string, - SPV_EXT_demote_to_helper_invocation, - SPV_EXT_descriptor_indexing, - SPV_EXT_fragment_fully_covered, - SPV_EXT_shader_stencil_export, - SPV_EXT_physical_storage_buffer, - SPV_EXT_shader_atomic_float_add, - SPV_EXT_shader_atomic_float_min_max, - SPV_EXT_shader_image_int64, - SPV_EXT_fragment_shader_interlock, - SPV_EXT_fragment_invocation_density, - SPV_EXT_shader_viewport_index_layer, - SPV_INTEL_loop_fuse, - SPV_INTEL_fpga_dsp_control, - SPV_INTEL_fpga_reg, - SPV_INTEL_fpga_memory_accesses, - SPV_INTEL_fpga_loop_controls, - SPV_INTEL_io_pipes, - SPV_INTEL_unstructured_loop_controls, - SPV_INTEL_blocking_pipes, - SPV_INTEL_device_side_avc_motion_estimation, - SPV_INTEL_fpga_memory_attributes, - SPV_INTEL_fp_fast_math_mode, - SPV_INTEL_media_block_io, - SPV_INTEL_shader_integer_functions2, - SPV_INTEL_subgroups, - SPV_INTEL_fpga_cluster_attributes, - SPV_INTEL_kernel_attributes, - SPV_INTEL_arbitrary_precision_integers, - SPV_KHR_8bit_storage, - SPV_KHR_shader_clock, - SPV_KHR_device_group, - SPV_KHR_16bit_storage, - SPV_KHR_variable_pointers, - SPV_KHR_no_integer_wrap_decoration, - SPV_KHR_subgroup_vote, - SPV_KHR_multiview, - SPV_KHR_shader_ballot, - SPV_KHR_vulkan_memory_model, - SPV_KHR_physical_storage_buffer, - SPV_KHR_workgroup_memory_explicit_layout, - SPV_KHR_fragment_shading_rate, - SPV_KHR_shader_atomic_counter_ops, - SPV_KHR_shader_draw_parameters, - SPV_KHR_storage_buffer_storage_class, - SPV_KHR_linkonce_odr, - SPV_KHR_terminate_invocation, - SPV_KHR_non_semantic_info, - SPV_KHR_post_depth_coverage, - SPV_KHR_expect_assume, - SPV_KHR_ray_tracing, - SPV_KHR_ray_query, - SPV_KHR_float_controls, - SPV_NV_viewport_array2, - SPV_NV_shader_subgroup_partitioned, - SPV_NVX_multiview_per_view_attributes, - SPV_NV_ray_tracing, - SPV_NV_shader_image_footprint, - SPV_NV_shading_rate, - SPV_NV_stereo_view_rendering, - SPV_NV_compute_shader_derivatives, - SPV_NV_shader_sm_builtins, - SPV_NV_mesh_shader, - SPV_NV_geometry_shader_passthrough, - SPV_NV_fragment_shader_barycentric, - SPV_NV_cooperative_matrix, - SPV_NV_sample_mask_override_coverage, - Matrix, - Shader, - Geometry, - Tessellation, - Addresses, - Linkage, - Kernel, - Vector16, - Float16Buffer, - Float16, - Float64, - Int64, - Int64Atomics, - ImageBasic, - ImageReadWrite, - ImageMipmap, - Pipes, - Groups, - DeviceEnqueue, - LiteralSampler, - AtomicStorage, - Int16, - TessellationPointSize, - GeometryPointSize, - ImageGatherExtended, - StorageImageMultisample, - UniformBufferArrayDynamicIndexing, - SampledImageArrayDynamicIndexing, - StorageBufferArrayDynamicIndexing, - StorageImageArrayDynamicIndexing, - ClipDistance, - CullDistance, - ImageCubeArray, - SampleRateShading, - ImageRect, - SampledRect, - GenericPointer, - Int8, - InputAttachment, - SparseResidency, - MinLod, - Sampled1D, - Image1D, - SampledCubeArray, - SampledBuffer, - ImageBuffer, - ImageMSArray, - StorageImageExtendedFormats, - ImageQuery, - DerivativeControl, - InterpolationFunction, - TransformFeedback, - GeometryStreams, - StorageImageReadWithoutFormat, - StorageImageWriteWithoutFormat, - MultiViewport, - SubgroupDispatch, - NamedBarrier, - PipeStorage, - GroupNonUniform, - GroupNonUniformVote, - GroupNonUniformArithmetic, - GroupNonUniformBallot, - GroupNonUniformShuffle, - GroupNonUniformShuffleRelative, - GroupNonUniformClustered, - GroupNonUniformQuad, - ShaderLayer, - ShaderViewportIndex, - FragmentShadingRateKHR, - SubgroupBallotKHR, - DrawParameters, - WorkgroupMemoryExplicitLayoutKHR, - WorkgroupMemoryExplicitLayout8BitAccessKHR, - WorkgroupMemoryExplicitLayout16BitAccessKHR, - SubgroupVoteKHR, - StorageBuffer16BitAccess, - StorageUniformBufferBlock16, - UniformAndStorageBuffer16BitAccess, - StorageUniform16, - StoragePushConstant16, - StorageInputOutput16, - DeviceGroup, - MultiView, - VariablePointersStorageBuffer, - VariablePointers, - AtomicStorageOps, - SampleMaskPostDepthCoverage, - StorageBuffer8BitAccess, - UniformAndStorageBuffer8BitAccess, - StoragePushConstant8, - DenormPreserve, - DenormFlushToZero, - SignedZeroInfNanPreserve, - RoundingModeRTE, - RoundingModeRTZ, - RayQueryProvisionalKHR, - RayQueryKHR, - RayTraversalPrimitiveCullingKHR, - RayTracingKHR, - Float16ImageAMD, - ImageGatherBiasLodAMD, - FragmentMaskAMD, - StencilExportEXT, - ImageReadWriteLodAMD, - Int64ImageEXT, - ShaderClockKHR, - SampleMaskOverrideCoverageNV, - GeometryShaderPassthroughNV, - ShaderViewportIndexLayerEXT, - ShaderViewportIndexLayerNV, - ShaderViewportMaskNV, - ShaderStereoViewNV, - PerViewAttributesNV, - FragmentFullyCoveredEXT, - MeshShadingNV, - ImageFootprintNV, - FragmentBarycentricNV, - ComputeDerivativeGroupQuadsNV, - FragmentDensityEXT, - ShadingRateNV, - GroupNonUniformPartitionedNV, - ShaderNonUniform, - ShaderNonUniformEXT, - RuntimeDescriptorArray, - RuntimeDescriptorArrayEXT, - InputAttachmentArrayDynamicIndexing, - InputAttachmentArrayDynamicIndexingEXT, - UniformTexelBufferArrayDynamicIndexing, - UniformTexelBufferArrayDynamicIndexingEXT, - StorageTexelBufferArrayDynamicIndexing, - StorageTexelBufferArrayDynamicIndexingEXT, - UniformBufferArrayNonUniformIndexing, - UniformBufferArrayNonUniformIndexingEXT, - SampledImageArrayNonUniformIndexing, - SampledImageArrayNonUniformIndexingEXT, - StorageBufferArrayNonUniformIndexing, - StorageBufferArrayNonUniformIndexingEXT, - StorageImageArrayNonUniformIndexing, - StorageImageArrayNonUniformIndexingEXT, - InputAttachmentArrayNonUniformIndexing, - InputAttachmentArrayNonUniformIndexingEXT, - UniformTexelBufferArrayNonUniformIndexing, - UniformTexelBufferArrayNonUniformIndexingEXT, - StorageTexelBufferArrayNonUniformIndexing, - StorageTexelBufferArrayNonUniformIndexingEXT, - RayTracingNV, - VulkanMemoryModel, - VulkanMemoryModelKHR, - VulkanMemoryModelDeviceScope, - VulkanMemoryModelDeviceScopeKHR, - PhysicalStorageBufferAddresses, - PhysicalStorageBufferAddressesEXT, - ComputeDerivativeGroupLinearNV, - RayTracingProvisionalKHR, - CooperativeMatrixNV, - FragmentShaderSampleInterlockEXT, - FragmentShaderShadingRateInterlockEXT, - ShaderSMBuiltinsNV, - FragmentShaderPixelInterlockEXT, - DemoteToHelperInvocationEXT, - SubgroupShuffleINTEL, - SubgroupBufferBlockIOINTEL, - SubgroupImageBlockIOINTEL, - SubgroupImageMediaBlockIOINTEL, - RoundToInfinityINTEL, - FloatingPointModeINTEL, - IntegerFunctions2INTEL, - FunctionPointersINTEL, - IndirectReferencesINTEL, - AsmINTEL, - AtomicFloat32MinMaxEXT, - AtomicFloat64MinMaxEXT, - AtomicFloat16MinMaxEXT, - VectorComputeINTEL, - VectorAnyINTEL, - ExpectAssumeKHR, - SubgroupAvcMotionEstimationINTEL, - SubgroupAvcMotionEstimationIntraINTEL, - SubgroupAvcMotionEstimationChromaINTEL, - VariableLengthArrayINTEL, - FunctionFloatControlINTEL, - FPGAMemoryAttributesINTEL, - FPFastMathModeINTEL, - ArbitraryPrecisionIntegersINTEL, - UnstructuredLoopControlsINTEL, - FPGALoopControlsINTEL, - KernelAttributesINTEL, - FPGAKernelAttributesINTEL, - FPGAMemoryAccessesINTEL, - FPGAClusterAttributesINTEL, - LoopFuseINTEL, - FPGABufferLocationINTEL, - USMStorageClassesINTEL, - IOPipesINTEL, - BlockingPipesINTEL, - FPGARegINTEL, - AtomicFloat32AddEXT, - AtomicFloat64AddEXT, - LongConstantCompositeINTEL, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - @setEvalBranchQuota(2000); - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.v1_1)] = .{ - .llvm_name = null, - .description = "SPIR-V version 1.1", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.v1_2)] = .{ - .llvm_name = null, - .description = "SPIR-V version 1.2", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - }), - }; - result[@intFromEnum(Feature.v1_3)] = .{ - .llvm_name = null, - .description = "SPIR-V version 1.3", - .dependencies = featureSet(&[_]Feature{ - .v1_2, - }), - }; - result[@intFromEnum(Feature.v1_4)] = .{ - .llvm_name = null, - .description = "SPIR-V version 1.4", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.v1_5)] = .{ - .llvm_name = null, - .description = "SPIR-V version 1.5", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_fragment_mask)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_fragment_mask", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_int16)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_int16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_texture_gather_bias_lod)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_texture_gather_bias_lod", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_ballot)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_ballot", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gcn_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gcn_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_image_load_store_lod)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_image_load_store_lod", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_explicit_vertex_parameter)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_explicit_vertex_parameter", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_trinary_minmax)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_trinary_minmax", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float_fetch)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float_fetch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_hlsl_functionality1)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_hlsl_functionality1", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_user_type)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_user_type", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_decorate_string)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_decorate_string", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_demote_to_helper_invocation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_demote_to_helper_invocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_descriptor_indexing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_descriptor_indexing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_fully_covered)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_fully_covered", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_stencil_export)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_stencil_export", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_physical_storage_buffer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_physical_storage_buffer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_add)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_atomic_float_add", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_atomic_float_min_max", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_image_int64)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_image_int64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_shader_interlock)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_shader_interlock", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_invocation_density)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_invocation_density", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_viewport_index_layer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_viewport_index_layer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_loop_fuse)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_loop_fuse", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_dsp_control)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_dsp_control", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_reg)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_reg", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_accesses)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_memory_accesses", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_loop_controls)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_loop_controls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_io_pipes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_io_pipes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_unstructured_loop_controls)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_unstructured_loop_controls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_blocking_pipes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_blocking_pipes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_device_side_avc_motion_estimation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_device_side_avc_motion_estimation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_memory_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fp_fast_math_mode)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fp_fast_math_mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_media_block_io)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_media_block_io", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_shader_integer_functions2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_shader_integer_functions2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_subgroups)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_subgroups", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_cluster_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_cluster_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_kernel_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_kernel_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_integers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_integers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_8bit_storage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_clock)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_clock", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_device_group)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_device_group", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_16bit_storage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_16bit_storage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_variable_pointers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_variable_pointers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_no_integer_wrap_decoration)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_no_integer_wrap_decoration", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_subgroup_vote)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_subgroup_vote", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_multiview)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_multiview", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_ballot)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_ballot", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_vulkan_memory_model)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_vulkan_memory_model", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_physical_storage_buffer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_physical_storage_buffer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_workgroup_memory_explicit_layout", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_fragment_shading_rate)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_fragment_shading_rate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_atomic_counter_ops", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_draw_parameters)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_draw_parameters", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_storage_buffer_storage_class)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_storage_buffer_storage_class", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_linkonce_odr)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_linkonce_odr", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_terminate_invocation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_terminate_invocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_non_semantic_info)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_non_semantic_info", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_post_depth_coverage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_post_depth_coverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_expect_assume)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_expect_assume", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_tracing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_tracing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_query", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_float_controls)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_float_controls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_viewport_array2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_viewport_array2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_subgroup_partitioned)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_subgroup_partitioned", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NVX_multiview_per_view_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NVX_multiview_per_view_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_ray_tracing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_ray_tracing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_image_footprint)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_image_footprint", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shading_rate)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shading_rate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_stereo_view_rendering)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_stereo_view_rendering", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_compute_shader_derivatives)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_compute_shader_derivatives", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_sm_builtins)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_sm_builtins", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_mesh_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_mesh_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_geometry_shader_passthrough)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_fragment_shader_barycentric)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_cooperative_matrix)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_cooperative_matrix", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_sample_mask_override_coverage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Matrix)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Matrix", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Shader)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Shader", - .dependencies = featureSet(&[_]Feature{ - .Matrix, - }), - }; - result[@intFromEnum(Feature.Geometry)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Geometry", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Tessellation)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Tessellation", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Addresses)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Addresses", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Linkage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Linkage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Kernel)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Kernel", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Vector16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Vector16", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.Float16Buffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16Buffer", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.Float16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Float64)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Int64)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Int64Atomics)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64Atomics", - .dependencies = featureSet(&[_]Feature{ - .Int64, - }), - }; - result[@intFromEnum(Feature.ImageBasic)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageBasic", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.ImageReadWrite)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageReadWrite", - .dependencies = featureSet(&[_]Feature{ - .ImageBasic, - }), - }; - result[@intFromEnum(Feature.ImageMipmap)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageMipmap", - .dependencies = featureSet(&[_]Feature{ - .ImageBasic, - }), - }; - result[@intFromEnum(Feature.Pipes)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Pipes", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.Groups)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Groups", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.DeviceEnqueue)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DeviceEnqueue", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.LiteralSampler)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LiteralSampler", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.AtomicStorage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicStorage", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Int16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TessellationPointSize)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TessellationPointSize", - .dependencies = featureSet(&[_]Feature{ - .Tessellation, - }), - }; - result[@intFromEnum(Feature.GeometryPointSize)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryPointSize", - .dependencies = featureSet(&[_]Feature{ - .Geometry, - }), - }; - result[@intFromEnum(Feature.ImageGatherExtended)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageGatherExtended", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageMultisample)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageMultisample", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.UniformBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SampledImageArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledImageArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ClipDistance)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ClipDistance", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.CullDistance)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CullDistance", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageCubeArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageCubeArray", - .dependencies = featureSet(&[_]Feature{ - .SampledCubeArray, - }), - }; - result[@intFromEnum(Feature.SampleRateShading)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleRateShading", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageRect)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageRect", - .dependencies = featureSet(&[_]Feature{ - .SampledRect, - }), - }; - result[@intFromEnum(Feature.SampledRect)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledRect", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.GenericPointer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GenericPointer", - .dependencies = featureSet(&[_]Feature{ - .Addresses, - }), - }; - result[@intFromEnum(Feature.Int8)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int8", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.InputAttachment)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachment", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SparseResidency)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SparseResidency", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.MinLod)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MinLod", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Sampled1D)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Sampled1D", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Image1D)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Image1D", - .dependencies = featureSet(&[_]Feature{ - .Sampled1D, - }), - }; - result[@intFromEnum(Feature.SampledCubeArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledCubeArray", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SampledBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledBuffer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ImageBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageBuffer", - .dependencies = featureSet(&[_]Feature{ - .SampledBuffer, - }), - }; - result[@intFromEnum(Feature.ImageMSArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageMSArray", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageExtendedFormats)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageExtendedFormats", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageQuery)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageQuery", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.DerivativeControl)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DerivativeControl", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.InterpolationFunction)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InterpolationFunction", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.TransformFeedback)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TransformFeedback", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.GeometryStreams)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryStreams", - .dependencies = featureSet(&[_]Feature{ - .Geometry, - }), - }; - result[@intFromEnum(Feature.StorageImageReadWithoutFormat)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageReadWithoutFormat", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageWriteWithoutFormat)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageWriteWithoutFormat", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.MultiViewport)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MultiViewport", - .dependencies = featureSet(&[_]Feature{ - .Geometry, - }), - }; - result[@intFromEnum(Feature.SubgroupDispatch)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupDispatch", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .DeviceEnqueue, - }), - }; - result[@intFromEnum(Feature.NamedBarrier)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability NamedBarrier", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .Kernel, - }), - }; - result[@intFromEnum(Feature.PipeStorage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PipeStorage", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .Pipes, - }), - }; - result[@intFromEnum(Feature.GroupNonUniform)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniform", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformVote)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformVote", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformArithmetic)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformArithmetic", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformBallot)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformBallot", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformShuffle)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformShuffle", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformShuffleRelative)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformShuffleRelative", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformClustered)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformClustered", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformQuad)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformQuad", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.ShaderLayer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderLayer", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.ShaderViewportIndex)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportIndex", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.FragmentShadingRateKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShadingRateKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SubgroupBallotKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupBallotKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.DrawParameters)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DrawParameters", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayoutKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayoutKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout8BitAccessKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout8BitAccessKHR", - .dependencies = featureSet(&[_]Feature{ - .WorkgroupMemoryExplicitLayoutKHR, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout16BitAccessKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout16BitAccessKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SubgroupVoteKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupVoteKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.StorageBuffer16BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBuffer16BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.StorageUniformBufferBlock16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageUniformBufferBlock16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.UniformAndStorageBuffer16BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformAndStorageBuffer16BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .StorageBuffer16BitAccess, - .StorageUniformBufferBlock16, - }), - }; - result[@intFromEnum(Feature.StorageUniform16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageUniform16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .StorageBuffer16BitAccess, - .StorageUniformBufferBlock16, - }), - }; - result[@intFromEnum(Feature.StoragePushConstant16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StoragePushConstant16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.StorageInputOutput16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageInputOutput16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.DeviceGroup)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DeviceGroup", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.MultiView)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MultiView", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.VariablePointersStorageBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariablePointersStorageBuffer", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.VariablePointers)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariablePointers", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .VariablePointersStorageBuffer, - }), - }; - result[@intFromEnum(Feature.AtomicStorageOps)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicStorageOps", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SampleMaskPostDepthCoverage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleMaskPostDepthCoverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.StorageBuffer8BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBuffer8BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.UniformAndStorageBuffer8BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformAndStorageBuffer8BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .StorageBuffer8BitAccess, - }), - }; - result[@intFromEnum(Feature.StoragePushConstant8)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StoragePushConstant8", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.DenormPreserve)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DenormPreserve", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.DenormFlushToZero)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DenormFlushToZero", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.SignedZeroInfNanPreserve)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SignedZeroInfNanPreserve", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RoundingModeRTE)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundingModeRTE", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RoundingModeRTZ)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundingModeRTZ", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RayQueryProvisionalKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayQueryProvisionalKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayQueryKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayQueryKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayTraversalPrimitiveCullingKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTraversalPrimitiveCullingKHR", - .dependencies = featureSet(&[_]Feature{ - .RayQueryKHR, - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.RayTracingKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Float16ImageAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16ImageAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageGatherBiasLodAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageGatherBiasLodAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentMaskAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentMaskAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StencilExportEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StencilExportEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageReadWriteLodAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageReadWriteLodAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Int64ImageEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64ImageEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ShaderClockKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderClockKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SampleMaskOverrideCoverageNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleMaskOverrideCoverageNV", - .dependencies = featureSet(&[_]Feature{ - .SampleRateShading, - }), - }; - result[@intFromEnum(Feature.GeometryShaderPassthroughNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryShaderPassthroughNV", - .dependencies = featureSet(&[_]Feature{ - .Geometry, - }), - }; - result[@intFromEnum(Feature.ShaderViewportIndexLayerEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportIndexLayerEXT", - .dependencies = featureSet(&[_]Feature{ - .MultiViewport, - }), - }; - result[@intFromEnum(Feature.ShaderViewportIndexLayerNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportIndexLayerNV", - .dependencies = featureSet(&[_]Feature{ - .MultiViewport, - }), - }; - result[@intFromEnum(Feature.ShaderViewportMaskNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportMaskNV", - .dependencies = featureSet(&[_]Feature{ - .ShaderViewportIndexLayerNV, - }), - }; - result[@intFromEnum(Feature.ShaderStereoViewNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderStereoViewNV", - .dependencies = featureSet(&[_]Feature{ - .ShaderViewportMaskNV, - }), - }; - result[@intFromEnum(Feature.PerViewAttributesNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PerViewAttributesNV", - .dependencies = featureSet(&[_]Feature{ - .MultiView, - }), - }; - result[@intFromEnum(Feature.FragmentFullyCoveredEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentFullyCoveredEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.MeshShadingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MeshShadingNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageFootprintNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageFootprintNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FragmentBarycentricNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentBarycentricNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ComputeDerivativeGroupQuadsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ComputeDerivativeGroupQuadsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FragmentDensityEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentDensityEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ShadingRateNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShadingRateNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformPartitionedNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformPartitionedNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ShaderNonUniform)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderNonUniform", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.ShaderNonUniformEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderNonUniformEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.RuntimeDescriptorArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RuntimeDescriptorArray", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.RuntimeDescriptorArrayEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RuntimeDescriptorArrayEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - }), - }; - result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexingEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.RayTracingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModel)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModel", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModelKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModelKHR", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModelDeviceScope)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScope", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModelDeviceScopeKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScopeKHR", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.PhysicalStorageBufferAddresses)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PhysicalStorageBufferAddresses", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.PhysicalStorageBufferAddressesEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PhysicalStorageBufferAddressesEXT", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.ComputeDerivativeGroupLinearNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ComputeDerivativeGroupLinearNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTracingProvisionalKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingProvisionalKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.CooperativeMatrixNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderSampleInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderSampleInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderShadingRateInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderShadingRateInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ShaderSMBuiltinsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderSMBuiltinsNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderPixelInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderPixelInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.DemoteToHelperInvocationEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DemoteToHelperInvocationEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SubgroupShuffleINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupShuffleINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupBufferBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupBufferBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupImageBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupImageBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupImageMediaBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupImageMediaBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RoundToInfinityINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundToInfinityINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FloatingPointModeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FloatingPointModeINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IntegerFunctions2INTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IntegerFunctions2INTEL", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FunctionPointersINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FunctionPointersINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IndirectReferencesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IndirectReferencesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AsmINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AsmINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat32MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat32MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat64MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat64MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat16MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat16MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.VectorComputeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VectorComputeINTEL", - .dependencies = featureSet(&[_]Feature{ - .VectorAnyINTEL, - }), - }; - result[@intFromEnum(Feature.VectorAnyINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VectorAnyINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ExpectAssumeKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ExpectAssumeKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationIntraINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationIntraINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationChromaINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationChromaINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.VariableLengthArrayINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariableLengthArrayINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FunctionFloatControlINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FunctionFloatControlINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAMemoryAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAMemoryAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPFastMathModeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPFastMathModeINTEL", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.ArbitraryPrecisionIntegersINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ArbitraryPrecisionIntegersINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.UnstructuredLoopControlsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UnstructuredLoopControlsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGALoopControlsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGALoopControlsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.KernelAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability KernelAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAKernelAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAKernelAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAMemoryAccessesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAMemoryAccessesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAClusterAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAClusterAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.LoopFuseINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LoopFuseINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGABufferLocationINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGABufferLocationINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.USMStorageClassesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability USMStorageClassesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IOPipesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IOPipesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.BlockingPipesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability BlockingPipesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGARegINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGARegINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat32AddEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat32AddEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.AtomicFloat64AddEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat64AddEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.LongConstantCompositeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LongConstantCompositeINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; -}; diff --git a/lib/std/target/ve.zig b/lib/std/target/ve.zig deleted file mode 100644 index 09ee056ef9035466500ed83d8055aba1de13c076..0000000000000000000000000000000000000000 --- a/lib/std/target/ve.zig +++ /dev/null @@ -1,39 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - vpu, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.vpu)] = .{ - .llvm_name = "vpu", - .description = "Enable the VPU", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; -}; diff --git a/lib/std/target/wasm.zig b/lib/std/target/wasm.zig deleted file mode 100644 index a06d37cf7dd910bac908bf5dc063335a536b5a65..0000000000000000000000000000000000000000 --- a/lib/std/target/wasm.zig +++ /dev/null @@ -1,126 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - atomics, - bulk_memory, - exception_handling, - extended_const, - multivalue, - mutable_globals, - nontrapping_fptoint, - reference_types, - relaxed_simd, - sign_ext, - simd128, - tail_call, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.atomics)] = .{ - .llvm_name = "atomics", - .description = "Enable Atomics", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.bulk_memory)] = .{ - .llvm_name = "bulk-memory", - .description = "Enable bulk memory operations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.exception_handling)] = .{ - .llvm_name = "exception-handling", - .description = "Enable Wasm exception handling", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.extended_const)] = .{ - .llvm_name = "extended-const", - .description = "Enable extended const expressions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.multivalue)] = .{ - .llvm_name = "multivalue", - .description = "Enable multivalue blocks, instructions, and functions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mutable_globals)] = .{ - .llvm_name = "mutable-globals", - .description = "Enable mutable globals", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nontrapping_fptoint)] = .{ - .llvm_name = "nontrapping-fptoint", - .description = "Enable non-trapping float-to-int conversion operators", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.reference_types)] = .{ - .llvm_name = "reference-types", - .description = "Enable reference types", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.relaxed_simd)] = .{ - .llvm_name = "relaxed-simd", - .description = "Enable relaxed-simd instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sign_ext)] = .{ - .llvm_name = "sign-ext", - .description = "Enable sign extension operators", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.simd128)] = .{ - .llvm_name = "simd128", - .description = "Enable 128-bit SIMD", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tail_call)] = .{ - .llvm_name = "tail-call", - .description = "Enable tail call instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const bleeding_edge = CpuModel{ - .name = "bleeding_edge", - .llvm_name = "bleeding-edge", - .features = featureSet(&[_]Feature{ - .atomics, - .bulk_memory, - .mutable_globals, - .nontrapping_fptoint, - .sign_ext, - .simd128, - .tail_call, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .mutable_globals, - .sign_ext, - }), - }; - pub const mvp = CpuModel{ - .name = "mvp", - .llvm_name = "mvp", - .features = featureSet(&[_]Feature{}), - }; -}; diff --git a/lib/std/target/x86.zig b/lib/std/target/x86.zig deleted file mode 100644 index 43ec04f41cdddc81b52281c91e2dba12695851a3..0000000000000000000000000000000000000000 --- a/lib/std/target/x86.zig +++ /dev/null @@ -1,4179 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - @"16bit_mode", - @"32bit_mode", - @"3dnow", - @"3dnowa", - @"64bit", - adx, - aes, - allow_light_256_bit, - amx_bf16, - amx_complex, - amx_fp16, - amx_int8, - amx_tile, - avx, - avx2, - avx512bf16, - avx512bitalg, - avx512bw, - avx512cd, - avx512dq, - avx512er, - avx512f, - avx512fp16, - avx512ifma, - avx512pf, - avx512vbmi, - avx512vbmi2, - avx512vl, - avx512vnni, - avx512vp2intersect, - avx512vpopcntdq, - avxifma, - avxneconvert, - avxvnni, - avxvnniint16, - avxvnniint8, - bmi, - bmi2, - branchfusion, - cldemote, - clflushopt, - clwb, - clzero, - cmov, - cmpccxadd, - crc32, - cx16, - cx8, - enqcmd, - ermsb, - f16c, - false_deps_getmant, - false_deps_lzcnt_tzcnt, - false_deps_mulc, - false_deps_mullq, - false_deps_perm, - false_deps_popcnt, - false_deps_range, - fast_11bytenop, - fast_15bytenop, - fast_7bytenop, - fast_bextr, - fast_gather, - fast_hops, - fast_lzcnt, - fast_movbe, - fast_scalar_fsqrt, - fast_scalar_shift_masks, - fast_shld_rotate, - fast_variable_crosslane_shuffle, - fast_variable_perlane_shuffle, - fast_vector_fsqrt, - fast_vector_shift_masks, - faster_shift_than_shuffle, - fma, - fma4, - fsgsbase, - fsrm, - fxsr, - gfni, - harden_sls_ijmp, - harden_sls_ret, - hreset, - idivl_to_divb, - idivq_to_divl, - invpcid, - kl, - lea_sp, - lea_uses_ag, - lvi_cfi, - lvi_load_hardening, - lwp, - lzcnt, - macrofusion, - mmx, - movbe, - movdir64b, - movdiri, - mwaitx, - no_bypass_delay, - no_bypass_delay_blend, - no_bypass_delay_mov, - no_bypass_delay_shuffle, - nopl, - pad_short_functions, - pclmul, - pconfig, - pku, - popcnt, - prefer_128_bit, - prefer_256_bit, - prefer_mask_registers, - prefer_movmsk_over_vtest, - prefetchi, - prefetchwt1, - prfchw, - ptwrite, - raoint, - rdpid, - rdpru, - rdrnd, - rdseed, - retpoline, - retpoline_external_thunk, - retpoline_indirect_branches, - retpoline_indirect_calls, - rtm, - sahf, - sbb_dep_breaking, - serialize, - seses, - sgx, - sha, - sha512, - shstk, - slow_3ops_lea, - slow_incdec, - slow_lea, - slow_pmaddwd, - slow_pmulld, - slow_shld, - slow_two_mem_ops, - slow_unaligned_mem_16, - slow_unaligned_mem_32, - sm3, - sm4, - soft_float, - sse, - sse2, - sse3, - sse4_1, - sse4_2, - sse4a, - sse_unaligned_mem, - ssse3, - tagged_globals, - tbm, - tsxldtrk, - tuning_fast_imm_vector_shift, - uintr, - use_glm_div_sqrt_costs, - use_slm_arith_costs, - vaes, - vpclmulqdq, - vzeroupper, - waitpkg, - wbnoinvd, - widekl, - x87, - xop, - xsave, - xsavec, - xsaveopt, - xsaves, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.@"16bit_mode")] = .{ - .llvm_name = "16bit-mode", - .description = "16-bit mode (i8086)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"32bit_mode")] = .{ - .llvm_name = "32bit-mode", - .description = "32-bit mode (80386)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.@"3dnow")] = .{ - .llvm_name = "3dnow", - .description = "Enable 3DNow! instructions", - .dependencies = featureSet(&[_]Feature{ - .mmx, - }), - }; - result[@intFromEnum(Feature.@"3dnowa")] = .{ - .llvm_name = "3dnowa", - .description = "Enable 3DNow! Athlon instructions", - .dependencies = featureSet(&[_]Feature{ - .@"3dnow", - }), - }; - result[@intFromEnum(Feature.@"64bit")] = .{ - .llvm_name = "64bit", - .description = "Support 64-bit instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.adx)] = .{ - .llvm_name = "adx", - .description = "Support ADX instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.aes)] = .{ - .llvm_name = "aes", - .description = "Enable AES instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.allow_light_256_bit)] = .{ - .llvm_name = "allow-light-256-bit", - .description = "Enable generation of 256-bit load/stores even if we prefer 128-bit", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.amx_bf16)] = .{ - .llvm_name = "amx-bf16", - .description = "Support AMX-BF16 instructions", - .dependencies = featureSet(&[_]Feature{ - .amx_tile, - }), - }; - result[@intFromEnum(Feature.amx_complex)] = .{ - .llvm_name = "amx-complex", - .description = "Support AMX-COMPLEX instructions", - .dependencies = featureSet(&[_]Feature{ - .amx_tile, - }), - }; - result[@intFromEnum(Feature.amx_fp16)] = .{ - .llvm_name = "amx-fp16", - .description = "Support AMX amx-fp16 instructions", - .dependencies = featureSet(&[_]Feature{ - .amx_tile, - }), - }; - result[@intFromEnum(Feature.amx_int8)] = .{ - .llvm_name = "amx-int8", - .description = "Support AMX-INT8 instructions", - .dependencies = featureSet(&[_]Feature{ - .amx_tile, - }), - }; - result[@intFromEnum(Feature.amx_tile)] = .{ - .llvm_name = "amx-tile", - .description = "Support AMX-TILE instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.avx)] = .{ - .llvm_name = "avx", - .description = "Enable AVX instructions", - .dependencies = featureSet(&[_]Feature{ - .sse4_2, - }), - }; - result[@intFromEnum(Feature.avx2)] = .{ - .llvm_name = "avx2", - .description = "Enable AVX2 instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.avx512bf16)] = .{ - .llvm_name = "avx512bf16", - .description = "Support bfloat16 floating point", - .dependencies = featureSet(&[_]Feature{ - .avx512bw, - }), - }; - result[@intFromEnum(Feature.avx512bitalg)] = .{ - .llvm_name = "avx512bitalg", - .description = "Enable AVX-512 Bit Algorithms", - .dependencies = featureSet(&[_]Feature{ - .avx512bw, - }), - }; - result[@intFromEnum(Feature.avx512bw)] = .{ - .llvm_name = "avx512bw", - .description = "Enable AVX-512 Byte and Word Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512cd)] = .{ - .llvm_name = "avx512cd", - .description = "Enable AVX-512 Conflict Detection Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512dq)] = .{ - .llvm_name = "avx512dq", - .description = "Enable AVX-512 Doubleword and Quadword Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512er)] = .{ - .llvm_name = "avx512er", - .description = "Enable AVX-512 Exponential and Reciprocal Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512f)] = .{ - .llvm_name = "avx512f", - .description = "Enable AVX-512 instructions", - .dependencies = featureSet(&[_]Feature{ - .avx2, - .f16c, - .fma, - }), - }; - result[@intFromEnum(Feature.avx512fp16)] = .{ - .llvm_name = "avx512fp16", - .description = "Support 16-bit floating point", - .dependencies = featureSet(&[_]Feature{ - .avx512bw, - .avx512dq, - .avx512vl, - }), - }; - result[@intFromEnum(Feature.avx512ifma)] = .{ - .llvm_name = "avx512ifma", - .description = "Enable AVX-512 Integer Fused Multiple-Add", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512pf)] = .{ - .llvm_name = "avx512pf", - .description = "Enable AVX-512 PreFetch Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512vbmi)] = .{ - .llvm_name = "avx512vbmi", - .description = "Enable AVX-512 Vector Byte Manipulation Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512bw, - }), - }; - result[@intFromEnum(Feature.avx512vbmi2)] = .{ - .llvm_name = "avx512vbmi2", - .description = "Enable AVX-512 further Vector Byte Manipulation Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512bw, - }), - }; - result[@intFromEnum(Feature.avx512vl)] = .{ - .llvm_name = "avx512vl", - .description = "Enable AVX-512 Vector Length eXtensions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512vnni)] = .{ - .llvm_name = "avx512vnni", - .description = "Enable AVX-512 Vector Neural Network Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512vp2intersect)] = .{ - .llvm_name = "avx512vp2intersect", - .description = "Enable AVX-512 vp2intersect", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avx512vpopcntdq)] = .{ - .llvm_name = "avx512vpopcntdq", - .description = "Enable AVX-512 Population Count Instructions", - .dependencies = featureSet(&[_]Feature{ - .avx512f, - }), - }; - result[@intFromEnum(Feature.avxifma)] = .{ - .llvm_name = "avxifma", - .description = "Enable AVX-IFMA", - .dependencies = featureSet(&[_]Feature{ - .avx2, - }), - }; - result[@intFromEnum(Feature.avxneconvert)] = .{ - .llvm_name = "avxneconvert", - .description = "Support AVX-NE-CONVERT instructions", - .dependencies = featureSet(&[_]Feature{ - .avx2, - }), - }; - result[@intFromEnum(Feature.avxvnni)] = .{ - .llvm_name = "avxvnni", - .description = "Support AVX_VNNI encoding", - .dependencies = featureSet(&[_]Feature{ - .avx2, - }), - }; - result[@intFromEnum(Feature.avxvnniint16)] = .{ - .llvm_name = "avxvnniint16", - .description = "Enable AVX-VNNI-INT16", - .dependencies = featureSet(&[_]Feature{ - .avx2, - }), - }; - result[@intFromEnum(Feature.avxvnniint8)] = .{ - .llvm_name = "avxvnniint8", - .description = "Enable AVX-VNNI-INT8", - .dependencies = featureSet(&[_]Feature{ - .avx2, - }), - }; - result[@intFromEnum(Feature.bmi)] = .{ - .llvm_name = "bmi", - .description = "Support BMI instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.bmi2)] = .{ - .llvm_name = "bmi2", - .description = "Support BMI2 instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.branchfusion)] = .{ - .llvm_name = "branchfusion", - .description = "CMP/TEST can be fused with conditional branches", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cldemote)] = .{ - .llvm_name = "cldemote", - .description = "Enable Cache Line Demote", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.clflushopt)] = .{ - .llvm_name = "clflushopt", - .description = "Flush A Cache Line Optimized", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.clwb)] = .{ - .llvm_name = "clwb", - .description = "Cache Line Write Back", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.clzero)] = .{ - .llvm_name = "clzero", - .description = "Enable Cache Line Zero", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cmov)] = .{ - .llvm_name = "cmov", - .description = "Enable conditional move instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cmpccxadd)] = .{ - .llvm_name = "cmpccxadd", - .description = "Support CMPCCXADD instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.crc32)] = .{ - .llvm_name = "crc32", - .description = "Enable SSE 4.2 CRC32 instruction (used when SSE4.2 is supported but function is GPR only)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.cx16)] = .{ - .llvm_name = "cx16", - .description = "64-bit with cmpxchg16b (this is true for most x86-64 chips, but not the first AMD chips)", - .dependencies = featureSet(&[_]Feature{ - .cx8, - }), - }; - result[@intFromEnum(Feature.cx8)] = .{ - .llvm_name = "cx8", - .description = "Support CMPXCHG8B instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.enqcmd)] = .{ - .llvm_name = "enqcmd", - .description = "Has ENQCMD instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ermsb)] = .{ - .llvm_name = "ermsb", - .description = "REP MOVS/STOS are fast", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.f16c)] = .{ - .llvm_name = "f16c", - .description = "Support 16-bit floating point conversion instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.false_deps_getmant)] = .{ - .llvm_name = "false-deps-getmant", - .description = "VGETMANTSS/SD/SH and VGETMANDPS/PD(memory version) has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_lzcnt_tzcnt)] = .{ - .llvm_name = "false-deps-lzcnt-tzcnt", - .description = "LZCNT/TZCNT have a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_mulc)] = .{ - .llvm_name = "false-deps-mulc", - .description = "VF[C]MULCPH/SH has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_mullq)] = .{ - .llvm_name = "false-deps-mullq", - .description = "VPMULLQ has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_perm)] = .{ - .llvm_name = "false-deps-perm", - .description = "VPERMD/Q/PS/PD has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_popcnt)] = .{ - .llvm_name = "false-deps-popcnt", - .description = "POPCNT has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.false_deps_range)] = .{ - .llvm_name = "false-deps-range", - .description = "VRANGEPD/PS/SD/SS has a false dependency on dest register", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_11bytenop)] = .{ - .llvm_name = "fast-11bytenop", - .description = "Target can quickly decode up to 11 byte NOPs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_15bytenop)] = .{ - .llvm_name = "fast-15bytenop", - .description = "Target can quickly decode up to 15 byte NOPs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_7bytenop)] = .{ - .llvm_name = "fast-7bytenop", - .description = "Target can quickly decode up to 7 byte NOPs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_bextr)] = .{ - .llvm_name = "fast-bextr", - .description = "Indicates that the BEXTR instruction is implemented as a single uop with good throughput", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_gather)] = .{ - .llvm_name = "fast-gather", - .description = "Indicates if gather is reasonably fast (this is true for Skylake client and all AVX-512 CPUs)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_hops)] = .{ - .llvm_name = "fast-hops", - .description = "Prefer horizontal vector math instructions (haddp, phsub, etc.) over normal vector instructions with shuffles", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_lzcnt)] = .{ - .llvm_name = "fast-lzcnt", - .description = "LZCNT instructions are as fast as most simple integer ops", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_movbe)] = .{ - .llvm_name = "fast-movbe", - .description = "Prefer a movbe over a single-use load + bswap / single-use bswap + store", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_scalar_fsqrt)] = .{ - .llvm_name = "fast-scalar-fsqrt", - .description = "Scalar SQRT is fast (disable Newton-Raphson)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_scalar_shift_masks)] = .{ - .llvm_name = "fast-scalar-shift-masks", - .description = "Prefer a left/right scalar logical shift pair over a shift+and pair", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_shld_rotate)] = .{ - .llvm_name = "fast-shld-rotate", - .description = "SHLD can be used as a faster rotate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_variable_crosslane_shuffle)] = .{ - .llvm_name = "fast-variable-crosslane-shuffle", - .description = "Cross-lane shuffles with variable masks are fast", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_variable_perlane_shuffle)] = .{ - .llvm_name = "fast-variable-perlane-shuffle", - .description = "Per-lane shuffles with variable masks are fast", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_vector_fsqrt)] = .{ - .llvm_name = "fast-vector-fsqrt", - .description = "Vector SQRT is fast (disable Newton-Raphson)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fast_vector_shift_masks)] = .{ - .llvm_name = "fast-vector-shift-masks", - .description = "Prefer a left/right vector logical shift pair over a shift+and pair", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.faster_shift_than_shuffle)] = .{ - .llvm_name = "faster-shift-than-shuffle", - .description = "Shifts are faster (or as fast) as shuffle", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fma)] = .{ - .llvm_name = "fma", - .description = "Enable three-operand fused multiple-add", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.fma4)] = .{ - .llvm_name = "fma4", - .description = "Enable four-operand fused multiple-add", - .dependencies = featureSet(&[_]Feature{ - .avx, - .sse4a, - }), - }; - result[@intFromEnum(Feature.fsgsbase)] = .{ - .llvm_name = "fsgsbase", - .description = "Support FS/GS Base instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fsrm)] = .{ - .llvm_name = "fsrm", - .description = "REP MOVSB of short lengths is faster", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.fxsr)] = .{ - .llvm_name = "fxsr", - .description = "Support fxsave/fxrestore instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.gfni)] = .{ - .llvm_name = "gfni", - .description = "Enable Galois Field Arithmetic Instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.harden_sls_ijmp)] = .{ - .llvm_name = "harden-sls-ijmp", - .description = "Harden against straight line speculation across indirect JMP instructions.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.harden_sls_ret)] = .{ - .llvm_name = "harden-sls-ret", - .description = "Harden against straight line speculation across RET instructions.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.hreset)] = .{ - .llvm_name = "hreset", - .description = "Has hreset instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.idivl_to_divb)] = .{ - .llvm_name = "idivl-to-divb", - .description = "Use 8-bit divide for positive values less than 256", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.idivq_to_divl)] = .{ - .llvm_name = "idivq-to-divl", - .description = "Use 32-bit divide for positive values less than 2^32", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.invpcid)] = .{ - .llvm_name = "invpcid", - .description = "Invalidate Process-Context Identifier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.kl)] = .{ - .llvm_name = "kl", - .description = "Support Key Locker kl Instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.lea_sp)] = .{ - .llvm_name = "lea-sp", - .description = "Use LEA for adjusting the stack pointer (this is an optimization for Intel Atom processors)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lea_uses_ag)] = .{ - .llvm_name = "lea-uses-ag", - .description = "LEA instruction needs inputs at AG stage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lvi_cfi)] = .{ - .llvm_name = "lvi-cfi", - .description = "Prevent indirect calls/branches from using a memory operand, and precede all indirect calls/branches from a register with an LFENCE instruction to serialize control flow. Also decompose RET instructions into a POP+LFENCE+JMP sequence.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lvi_load_hardening)] = .{ - .llvm_name = "lvi-load-hardening", - .description = "Insert LFENCE instructions to prevent data speculatively injected into loads from being used maliciously.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lwp)] = .{ - .llvm_name = "lwp", - .description = "Enable LWP instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.lzcnt)] = .{ - .llvm_name = "lzcnt", - .description = "Support LZCNT instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.macrofusion)] = .{ - .llvm_name = "macrofusion", - .description = "Various instructions can be fused with conditional branches", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mmx)] = .{ - .llvm_name = "mmx", - .description = "Enable MMX instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.movbe)] = .{ - .llvm_name = "movbe", - .description = "Support MOVBE instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.movdir64b)] = .{ - .llvm_name = "movdir64b", - .description = "Support movdir64b instruction (direct store 64 bytes)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.movdiri)] = .{ - .llvm_name = "movdiri", - .description = "Support movdiri instruction (direct store integer)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.mwaitx)] = .{ - .llvm_name = "mwaitx", - .description = "Enable MONITORX/MWAITX timer functionality", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bypass_delay)] = .{ - .llvm_name = "no-bypass-delay", - .description = "Has no bypass delay when using the 'wrong' domain", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bypass_delay_blend)] = .{ - .llvm_name = "no-bypass-delay-blend", - .description = "Has no bypass delay when using the 'wrong' blend type", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bypass_delay_mov)] = .{ - .llvm_name = "no-bypass-delay-mov", - .description = "Has no bypass delay when using the 'wrong' mov type", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.no_bypass_delay_shuffle)] = .{ - .llvm_name = "no-bypass-delay-shuffle", - .description = "Has no bypass delay when using the 'wrong' shuffle type", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.nopl)] = .{ - .llvm_name = "nopl", - .description = "Enable NOPL instruction (generally pentium pro+)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pad_short_functions)] = .{ - .llvm_name = "pad-short-functions", - .description = "Pad short functions (to prevent a stall when returning too early)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pclmul)] = .{ - .llvm_name = "pclmul", - .description = "Enable packed carry-less multiplication instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.pconfig)] = .{ - .llvm_name = "pconfig", - .description = "platform configuration instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.pku)] = .{ - .llvm_name = "pku", - .description = "Enable protection keys", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.popcnt)] = .{ - .llvm_name = "popcnt", - .description = "Support POPCNT instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_128_bit)] = .{ - .llvm_name = "prefer-128-bit", - .description = "Prefer 128-bit AVX instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_256_bit)] = .{ - .llvm_name = "prefer-256-bit", - .description = "Prefer 256-bit AVX instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_mask_registers)] = .{ - .llvm_name = "prefer-mask-registers", - .description = "Prefer AVX512 mask registers over PTEST/MOVMSK", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefer_movmsk_over_vtest)] = .{ - .llvm_name = "prefer-movmsk-over-vtest", - .description = "Prefer movmsk over vtest instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefetchi)] = .{ - .llvm_name = "prefetchi", - .description = "Prefetch instruction with T0 or T1 Hint", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prefetchwt1)] = .{ - .llvm_name = "prefetchwt1", - .description = "Prefetch with Intent to Write and T1 Hint", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.prfchw)] = .{ - .llvm_name = "prfchw", - .description = "Support PRFCHW instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ptwrite)] = .{ - .llvm_name = "ptwrite", - .description = "Support ptwrite instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.raoint)] = .{ - .llvm_name = "raoint", - .description = "Support RAO-INT instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rdpid)] = .{ - .llvm_name = "rdpid", - .description = "Support RDPID instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rdpru)] = .{ - .llvm_name = "rdpru", - .description = "Support RDPRU instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rdrnd)] = .{ - .llvm_name = "rdrnd", - .description = "Support RDRAND instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rdseed)] = .{ - .llvm_name = "rdseed", - .description = "Support RDSEED instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.retpoline)] = .{ - .llvm_name = "retpoline", - .description = "Remove speculation of indirect branches from the generated code, either by avoiding them entirely or lowering them with a speculation blocking construct", - .dependencies = featureSet(&[_]Feature{ - .retpoline_indirect_branches, - .retpoline_indirect_calls, - }), - }; - result[@intFromEnum(Feature.retpoline_external_thunk)] = .{ - .llvm_name = "retpoline-external-thunk", - .description = "When lowering an indirect call or branch using a `retpoline`, rely on the specified user provided thunk rather than emitting one ourselves. Only has effect when combined with some other retpoline feature", - .dependencies = featureSet(&[_]Feature{ - .retpoline_indirect_calls, - }), - }; - result[@intFromEnum(Feature.retpoline_indirect_branches)] = .{ - .llvm_name = "retpoline-indirect-branches", - .description = "Remove speculation of indirect branches from the generated code", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.retpoline_indirect_calls)] = .{ - .llvm_name = "retpoline-indirect-calls", - .description = "Remove speculation of indirect calls from the generated code", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.rtm)] = .{ - .llvm_name = "rtm", - .description = "Support RTM instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sahf)] = .{ - .llvm_name = "sahf", - .description = "Support LAHF and SAHF instructions in 64-bit mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sbb_dep_breaking)] = .{ - .llvm_name = "sbb-dep-breaking", - .description = "SBB with same register has no source dependency", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.serialize)] = .{ - .llvm_name = "serialize", - .description = "Has serialize instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.seses)] = .{ - .llvm_name = "seses", - .description = "Prevent speculative execution side channel timing attacks by inserting a speculation barrier before memory reads, memory writes, and conditional branches. Implies LVI Control Flow integrity.", - .dependencies = featureSet(&[_]Feature{ - .lvi_cfi, - }), - }; - result[@intFromEnum(Feature.sgx)] = .{ - .llvm_name = "sgx", - .description = "Enable Software Guard Extensions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sha)] = .{ - .llvm_name = "sha", - .description = "Enable SHA instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.sha512)] = .{ - .llvm_name = "sha512", - .description = "Support SHA512 instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.shstk)] = .{ - .llvm_name = "shstk", - .description = "Support CET Shadow-Stack instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_3ops_lea)] = .{ - .llvm_name = "slow-3ops-lea", - .description = "LEA instruction with 3 ops or certain registers is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_incdec)] = .{ - .llvm_name = "slow-incdec", - .description = "INC and DEC instructions are slower than ADD and SUB", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_lea)] = .{ - .llvm_name = "slow-lea", - .description = "LEA instruction with certain arguments is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_pmaddwd)] = .{ - .llvm_name = "slow-pmaddwd", - .description = "PMADDWD is slower than PMULLD", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_pmulld)] = .{ - .llvm_name = "slow-pmulld", - .description = "PMULLD instruction is slow (compared to PMULLW/PMULHW and PMULUDQ)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_shld)] = .{ - .llvm_name = "slow-shld", - .description = "SHLD instruction is slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_two_mem_ops)] = .{ - .llvm_name = "slow-two-mem-ops", - .description = "Two memory operand instructions are slow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_unaligned_mem_16)] = .{ - .llvm_name = "slow-unaligned-mem-16", - .description = "Slow unaligned 16-byte memory access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.slow_unaligned_mem_32)] = .{ - .llvm_name = "slow-unaligned-mem-32", - .description = "Slow unaligned 32-byte memory access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sm3)] = .{ - .llvm_name = "sm3", - .description = "Support SM3 instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.sm4)] = .{ - .llvm_name = "sm4", - .description = "Support SM4 instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - }), - }; - result[@intFromEnum(Feature.soft_float)] = .{ - .llvm_name = "soft-float", - .description = "Use software floating point features", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sse)] = .{ - .llvm_name = "sse", - .description = "Enable SSE instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.sse2)] = .{ - .llvm_name = "sse2", - .description = "Enable SSE2 instructions", - .dependencies = featureSet(&[_]Feature{ - .sse, - }), - }; - result[@intFromEnum(Feature.sse3)] = .{ - .llvm_name = "sse3", - .description = "Enable SSE3 instructions", - .dependencies = featureSet(&[_]Feature{ - .sse2, - }), - }; - result[@intFromEnum(Feature.sse4_1)] = .{ - .llvm_name = "sse4.1", - .description = "Enable SSE 4.1 instructions", - .dependencies = featureSet(&[_]Feature{ - .ssse3, - }), - }; - result[@intFromEnum(Feature.sse4_2)] = .{ - .llvm_name = "sse4.2", - .description = "Enable SSE 4.2 instructions", - .dependencies = featureSet(&[_]Feature{ - .sse4_1, - }), - }; - result[@intFromEnum(Feature.sse4a)] = .{ - .llvm_name = "sse4a", - .description = "Support SSE 4a instructions", - .dependencies = featureSet(&[_]Feature{ - .sse3, - }), - }; - result[@intFromEnum(Feature.sse_unaligned_mem)] = .{ - .llvm_name = "sse-unaligned-mem", - .description = "Allow unaligned memory operands with SSE instructions (this may require setting a configuration bit in the processor)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ssse3)] = .{ - .llvm_name = "ssse3", - .description = "Enable SSSE3 instructions", - .dependencies = featureSet(&[_]Feature{ - .sse3, - }), - }; - result[@intFromEnum(Feature.tagged_globals)] = .{ - .llvm_name = "tagged-globals", - .description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits.", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tbm)] = .{ - .llvm_name = "tbm", - .description = "Enable TBM instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tsxldtrk)] = .{ - .llvm_name = "tsxldtrk", - .description = "Support TSXLDTRK instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.tuning_fast_imm_vector_shift)] = .{ - .llvm_name = "tuning-fast-imm-vector-shift", - .description = "Vector shifts are fast (2/cycle) as opposed to slow (1/cycle)", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.uintr)] = .{ - .llvm_name = "uintr", - .description = "Has UINTR Instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_glm_div_sqrt_costs)] = .{ - .llvm_name = "use-glm-div-sqrt-costs", - .description = "Use Goldmont specific floating point div/sqrt costs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.use_slm_arith_costs)] = .{ - .llvm_name = "use-slm-arith-costs", - .description = "Use Silvermont specific arithmetic costs", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.vaes)] = .{ - .llvm_name = "vaes", - .description = "Promote selected AES instructions to AVX512/AVX registers", - .dependencies = featureSet(&[_]Feature{ - .aes, - .avx, - }), - }; - result[@intFromEnum(Feature.vpclmulqdq)] = .{ - .llvm_name = "vpclmulqdq", - .description = "Enable vpclmulqdq instructions", - .dependencies = featureSet(&[_]Feature{ - .avx, - .pclmul, - }), - }; - result[@intFromEnum(Feature.vzeroupper)] = .{ - .llvm_name = "vzeroupper", - .description = "Should insert vzeroupper instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.waitpkg)] = .{ - .llvm_name = "waitpkg", - .description = "Wait and pause enhancements", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.wbnoinvd)] = .{ - .llvm_name = "wbnoinvd", - .description = "Write Back No Invalidate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.widekl)] = .{ - .llvm_name = "widekl", - .description = "Support Key Locker wide Instructions", - .dependencies = featureSet(&[_]Feature{ - .kl, - }), - }; - result[@intFromEnum(Feature.x87)] = .{ - .llvm_name = "x87", - .description = "Enable X87 float instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xop)] = .{ - .llvm_name = "xop", - .description = "Enable XOP instructions", - .dependencies = featureSet(&[_]Feature{ - .fma4, - }), - }; - result[@intFromEnum(Feature.xsave)] = .{ - .llvm_name = "xsave", - .description = "Support xsave instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.xsavec)] = .{ - .llvm_name = "xsavec", - .description = "Support xsavec instructions", - .dependencies = featureSet(&[_]Feature{ - .xsave, - }), - }; - result[@intFromEnum(Feature.xsaveopt)] = .{ - .llvm_name = "xsaveopt", - .description = "Support xsaveopt instructions", - .dependencies = featureSet(&[_]Feature{ - .xsave, - }), - }; - result[@intFromEnum(Feature.xsaves)] = .{ - .llvm_name = "xsaves", - .description = "Support xsaves instructions", - .dependencies = featureSet(&[_]Feature{ - .xsave, - }), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const alderlake = CpuModel{ - .name = "alderlake", - .llvm_name = "alderlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .f16c, - .false_deps_perm, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .gfni, - .hreset, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_movmsk_over_vtest, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .widekl, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const amdfam10 = CpuModel{ - .name = "amdfam10", - .llvm_name = "amdfam10", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx16, - .fast_scalar_shift_masks, - .fxsr, - .lzcnt, - .nopl, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .sse4a, - .vzeroupper, - .x87, - }), - }; - pub const athlon = CpuModel{ - .name = "athlon", - .llvm_name = "athlon", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cmov, - .cx8, - .nopl, - .slow_shld, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const athlon64 = CpuModel{ - .name = "athlon64", - .llvm_name = "athlon64", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx8, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const athlon64_sse3 = CpuModel{ - .name = "athlon64_sse3", - .llvm_name = "athlon64-sse3", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx16, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const athlon_4 = CpuModel{ - .name = "athlon_4", - .llvm_name = "athlon-4", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cmov, - .cx8, - .fxsr, - .nopl, - .slow_shld, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const athlon_fx = CpuModel{ - .name = "athlon_fx", - .llvm_name = "athlon-fx", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx8, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const athlon_mp = CpuModel{ - .name = "athlon_mp", - .llvm_name = "athlon-mp", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cmov, - .cx8, - .fxsr, - .nopl, - .slow_shld, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const athlon_tbird = CpuModel{ - .name = "athlon_tbird", - .llvm_name = "athlon-tbird", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cmov, - .cx8, - .nopl, - .slow_shld, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const athlon_xp = CpuModel{ - .name = "athlon_xp", - .llvm_name = "athlon-xp", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cmov, - .cx8, - .fxsr, - .nopl, - .slow_shld, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const atom = CpuModel{ - .name = "atom", - .llvm_name = "atom", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fxsr, - .idivl_to_divb, - .idivq_to_divl, - .lea_sp, - .lea_uses_ag, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pad_short_functions, - .sahf, - .slow_two_mem_ops, - .slow_unaligned_mem_16, - .ssse3, - .vzeroupper, - .x87, - }), - }; - pub const atom_sse4_2_movbe = CpuModel{ - .name = "atom_sse4_2_movbe", - .llvm_name = "atom_sse4_2_movbe", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .clflushopt, - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_7bytenop, - .fast_movbe, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .sha, - .slow_incdec, - .slow_lea, - .slow_pmulld, - .slow_two_mem_ops, - .sse4_2, - .use_slm_arith_costs, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const barcelona = CpuModel{ - .name = "barcelona", - .llvm_name = "barcelona", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx16, - .fast_scalar_shift_masks, - .fxsr, - .lzcnt, - .nopl, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .sse4a, - .vzeroupper, - .x87, - }), - }; - pub const bdver1 = CpuModel{ - .name = "bdver1", - .llvm_name = "bdver1", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .branchfusion, - .cmov, - .crc32, - .cx16, - .fast_11bytenop, - .fast_scalar_shift_masks, - .fxsr, - .lwp, - .lzcnt, - .mmx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .vzeroupper, - .x87, - .xop, - .xsave, - }), - }; - pub const bdver2 = CpuModel{ - .name = "bdver2", - .llvm_name = "bdver2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .bmi, - .branchfusion, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_11bytenop, - .fast_bextr, - .fast_movbe, - .fast_scalar_shift_masks, - .fma, - .fxsr, - .lwp, - .lzcnt, - .mmx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .tbm, - .vzeroupper, - .x87, - .xop, - .xsave, - }), - }; - pub const bdver3 = CpuModel{ - .name = "bdver3", - .llvm_name = "bdver3", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .bmi, - .branchfusion, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_11bytenop, - .fast_bextr, - .fast_movbe, - .fast_scalar_shift_masks, - .fma, - .fsgsbase, - .fxsr, - .lwp, - .lzcnt, - .mmx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .tbm, - .vzeroupper, - .x87, - .xop, - .xsaveopt, - }), - }; - pub const bdver4 = CpuModel{ - .name = "bdver4", - .llvm_name = "bdver4", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .avx2, - .bmi, - .bmi2, - .branchfusion, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_11bytenop, - .fast_bextr, - .fast_movbe, - .fast_scalar_shift_masks, - .fma, - .fsgsbase, - .fxsr, - .lwp, - .lzcnt, - .mmx, - .movbe, - .mwaitx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .tbm, - .vzeroupper, - .x87, - .xop, - .xsaveopt, - }), - }; - pub const bonnell = CpuModel{ - .name = "bonnell", - .llvm_name = "bonnell", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fxsr, - .idivl_to_divb, - .idivq_to_divl, - .lea_sp, - .lea_uses_ag, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pad_short_functions, - .sahf, - .slow_two_mem_ops, - .slow_unaligned_mem_16, - .ssse3, - .vzeroupper, - .x87, - }), - }; - pub const broadwell = CpuModel{ - .name = "broadwell", - .llvm_name = "broadwell", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .ermsb, - .f16c, - .false_deps_lzcnt_tzcnt, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fma, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .vzeroupper, - .x87, - .xsaveopt, - }), - }; - pub const btver1 = CpuModel{ - .name = "btver1", - .llvm_name = "btver1", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fast_15bytenop, - .fast_scalar_shift_masks, - .fast_vector_shift_masks, - .fxsr, - .lzcnt, - .mmx, - .nopl, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .sse4a, - .ssse3, - .vzeroupper, - .x87, - }), - }; - pub const btver2 = CpuModel{ - .name = "btver2", - .llvm_name = "btver2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .bmi, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_15bytenop, - .fast_bextr, - .fast_hops, - .fast_lzcnt, - .fast_movbe, - .fast_scalar_shift_masks, - .fast_vector_shift_masks, - .fxsr, - .lzcnt, - .mmx, - .movbe, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .sahf, - .sbb_dep_breaking, - .slow_shld, - .sse4a, - .x87, - .xsaveopt, - }), - }; - pub const c3 = CpuModel{ - .name = "c3", - .llvm_name = "c3", - .features = featureSet(&[_]Feature{ - .@"3dnow", - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const c3_2 = CpuModel{ - .name = "c3_2", - .llvm_name = "c3-2", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const cannonlake = CpuModel{ - .name = "cannonlake", - .llvm_name = "cannonlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vl, - .bmi, - .bmi2, - .clflushopt, - .cmov, - .crc32, - .cx16, - .ermsb, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .sha, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const cascadelake = CpuModel{ - .name = "cascadelake", - .llvm_name = "cascadelake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx512bw, - .avx512cd, - .avx512dq, - .avx512vl, - .avx512vnni, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .faster_shift_than_shuffle, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const cooperlake = CpuModel{ - .name = "cooperlake", - .llvm_name = "cooperlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx512bf16, - .avx512cd, - .avx512dq, - .avx512vl, - .avx512vnni, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .faster_shift_than_shuffle, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const core2 = CpuModel{ - .name = "core2", - .llvm_name = "core2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fxsr, - .macrofusion, - .mmx, - .nopl, - .sahf, - .slow_unaligned_mem_16, - .ssse3, - .vzeroupper, - .x87, - }), - }; - pub const corei7 = CpuModel{ - .name = "corei7", - .llvm_name = "corei7", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .fxsr, - .macrofusion, - .mmx, - .no_bypass_delay_mov, - .nopl, - .popcnt, - .sahf, - .sse4_2, - .vzeroupper, - .x87, - }), - }; - pub const emeraldrapids = CpuModel{ - .name = "emeraldrapids", - .llvm_name = "emeraldrapids", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .amx_bf16, - .amx_int8, - .avx512bf16, - .avx512bitalg, - .avx512cd, - .avx512fp16, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vnni, - .avx512vpopcntdq, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .enqcmd, - .ermsb, - .false_deps_getmant, - .false_deps_mulc, - .false_deps_mullq, - .false_deps_perm, - .false_deps_range, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .tsxldtrk, - .tuning_fast_imm_vector_shift, - .uintr, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cx8, - .fast_15bytenop, - .fast_scalar_fsqrt, - .idivq_to_divl, - .macrofusion, - .slow_3ops_lea, - .vzeroupper, - .x87, - }), - }; - pub const geode = CpuModel{ - .name = "geode", - .llvm_name = "geode", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const goldmont = CpuModel{ - .name = "goldmont", - .llvm_name = "goldmont", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .clflushopt, - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_movbe, - .fsgsbase, - .fxsr, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .sha, - .slow_incdec, - .slow_lea, - .slow_two_mem_ops, - .sse4_2, - .use_glm_div_sqrt_costs, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const goldmont_plus = CpuModel{ - .name = "goldmont_plus", - .llvm_name = "goldmont-plus", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .clflushopt, - .cmov, - .crc32, - .cx16, - .fast_movbe, - .fsgsbase, - .fxsr, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .slow_incdec, - .slow_lea, - .slow_two_mem_ops, - .sse4_2, - .use_glm_div_sqrt_costs, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const grandridge = CpuModel{ - .name = "grandridge", - .llvm_name = "grandridge", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .avxifma, - .avxneconvert, - .avxvnni, - .avxvnniint8, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .cmpccxadd, - .crc32, - .cx16, - .enqcmd, - .f16c, - .fast_movbe, - .fma, - .fsgsbase, - .fxsr, - .gfni, - .hreset, - .invpcid, - .lzcnt, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay, - .nopl, - .pconfig, - .pku, - .popcnt, - .prfchw, - .ptwrite, - .raoint, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .slow_incdec, - .slow_lea, - .slow_two_mem_ops, - .uintr, - .use_glm_div_sqrt_costs, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .widekl, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const graniterapids = CpuModel{ - .name = "graniterapids", - .llvm_name = "graniterapids", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .amx_bf16, - .amx_fp16, - .amx_int8, - .avx512bf16, - .avx512bitalg, - .avx512cd, - .avx512fp16, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vnni, - .avx512vpopcntdq, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .enqcmd, - .ermsb, - .false_deps_getmant, - .false_deps_mulc, - .false_deps_mullq, - .false_deps_perm, - .false_deps_range, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_256_bit, - .prefetchi, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .tsxldtrk, - .tuning_fast_imm_vector_shift, - .uintr, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const graniterapids_d = CpuModel{ - .name = "graniterapids_d", - .llvm_name = "graniterapids-d", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .amx_bf16, - .amx_complex, - .amx_fp16, - .amx_int8, - .avx512bf16, - .avx512bitalg, - .avx512cd, - .avx512fp16, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vnni, - .avx512vpopcntdq, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .enqcmd, - .ermsb, - .false_deps_getmant, - .false_deps_mulc, - .false_deps_mullq, - .false_deps_perm, - .false_deps_range, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_256_bit, - .prefetchi, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .tsxldtrk, - .tuning_fast_imm_vector_shift, - .uintr, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const haswell = CpuModel{ - .name = "haswell", - .llvm_name = "haswell", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .ermsb, - .f16c, - .false_deps_lzcnt_tzcnt, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fma, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .popcnt, - .rdrnd, - .sahf, - .slow_3ops_lea, - .vzeroupper, - .x87, - .xsaveopt, - }), - }; - pub const @"i386" = CpuModel{ - .name = "i386", - .llvm_name = "i386", - .features = featureSet(&[_]Feature{ - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const @"i486" = CpuModel{ - .name = "i486", - .llvm_name = "i486", - .features = featureSet(&[_]Feature{ - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const @"i586" = CpuModel{ - .name = "i586", - .llvm_name = "i586", - .features = featureSet(&[_]Feature{ - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const @"i686" = CpuModel{ - .name = "i686", - .llvm_name = "i686", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const icelake_client = CpuModel{ - .name = "icelake_client", - .llvm_name = "icelake-client", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx512bitalg, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vl, - .avx512vnni, - .avx512vpopcntdq, - .bmi, - .bmi2, - .clflushopt, - .cmov, - .crc32, - .cx16, - .ermsb, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const icelake_server = CpuModel{ - .name = "icelake_server", - .llvm_name = "icelake-server", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx512bitalg, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vl, - .avx512vnni, - .avx512vpopcntdq, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const ivybridge = CpuModel{ - .name = "ivybridge", - .llvm_name = "ivybridge", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .f16c, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .macrofusion, - .mmx, - .no_bypass_delay_mov, - .nopl, - .pclmul, - .popcnt, - .rdrnd, - .sahf, - .slow_3ops_lea, - .slow_unaligned_mem_32, - .vzeroupper, - .x87, - .xsaveopt, - }), - }; - pub const k6 = CpuModel{ - .name = "k6", - .llvm_name = "k6", - .features = featureSet(&[_]Feature{ - .cx8, - .mmx, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const k6_2 = CpuModel{ - .name = "k6_2", - .llvm_name = "k6-2", - .features = featureSet(&[_]Feature{ - .@"3dnow", - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const k6_3 = CpuModel{ - .name = "k6_3", - .llvm_name = "k6-3", - .features = featureSet(&[_]Feature{ - .@"3dnow", - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const k8 = CpuModel{ - .name = "k8", - .llvm_name = "k8", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx8, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const k8_sse3 = CpuModel{ - .name = "k8_sse3", - .llvm_name = "k8-sse3", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx16, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const knl = CpuModel{ - .name = "knl", - .llvm_name = "knl", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .avx512cd, - .avx512er, - .avx512pf, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .fast_gather, - .fast_movbe, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .lzcnt, - .mmx, - .movbe, - .nopl, - .pclmul, - .popcnt, - .prefer_mask_registers, - .prefetchwt1, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .slow_incdec, - .slow_pmaddwd, - .slow_two_mem_ops, - .x87, - .xsaveopt, - }), - }; - pub const knm = CpuModel{ - .name = "knm", - .llvm_name = "knm", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .avx512cd, - .avx512er, - .avx512pf, - .avx512vpopcntdq, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .fast_gather, - .fast_movbe, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .lzcnt, - .mmx, - .movbe, - .nopl, - .pclmul, - .popcnt, - .prefer_mask_registers, - .prefetchwt1, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .slow_incdec, - .slow_pmaddwd, - .slow_two_mem_ops, - .x87, - .xsaveopt, - }), - }; - pub const lakemont = CpuModel{ - .name = "lakemont", - .llvm_name = "lakemont", - .features = featureSet(&[_]Feature{ - .cx8, - .slow_unaligned_mem_16, - .soft_float, - .vzeroupper, - }), - }; - pub const meteorlake = CpuModel{ - .name = "meteorlake", - .llvm_name = "meteorlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .f16c, - .false_deps_perm, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .gfni, - .hreset, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_movmsk_over_vtest, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .widekl, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const nehalem = CpuModel{ - .name = "nehalem", - .llvm_name = "nehalem", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .fxsr, - .macrofusion, - .mmx, - .no_bypass_delay_mov, - .nopl, - .popcnt, - .sahf, - .sse4_2, - .vzeroupper, - .x87, - }), - }; - pub const nocona = CpuModel{ - .name = "nocona", - .llvm_name = "nocona", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const opteron = CpuModel{ - .name = "opteron", - .llvm_name = "opteron", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx8, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const opteron_sse3 = CpuModel{ - .name = "opteron_sse3", - .llvm_name = "opteron-sse3", - .features = featureSet(&[_]Feature{ - .@"3dnowa", - .@"64bit", - .cmov, - .cx16, - .fast_scalar_shift_masks, - .fxsr, - .nopl, - .sbb_dep_breaking, - .slow_shld, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const penryn = CpuModel{ - .name = "penryn", - .llvm_name = "penryn", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx16, - .fxsr, - .macrofusion, - .mmx, - .nopl, - .sahf, - .slow_unaligned_mem_16, - .sse4_1, - .vzeroupper, - .x87, - }), - }; - pub const pentium = CpuModel{ - .name = "pentium", - .llvm_name = "pentium", - .features = featureSet(&[_]Feature{ - .cx8, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const pentium2 = CpuModel{ - .name = "pentium2", - .llvm_name = "pentium2", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const pentium3 = CpuModel{ - .name = "pentium3", - .llvm_name = "pentium3", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const pentium3m = CpuModel{ - .name = "pentium3m", - .llvm_name = "pentium3m", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse, - .vzeroupper, - .x87, - }), - }; - pub const pentium4 = CpuModel{ - .name = "pentium4", - .llvm_name = "pentium4", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const pentium_m = CpuModel{ - .name = "pentium_m", - .llvm_name = "pentium-m", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const pentium_mmx = CpuModel{ - .name = "pentium_mmx", - .llvm_name = "pentium-mmx", - .features = featureSet(&[_]Feature{ - .cx8, - .mmx, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const pentiumpro = CpuModel{ - .name = "pentiumpro", - .llvm_name = "pentiumpro", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .nopl, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const prescott = CpuModel{ - .name = "prescott", - .llvm_name = "prescott", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const raptorlake = CpuModel{ - .name = "raptorlake", - .llvm_name = "raptorlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .f16c, - .false_deps_perm, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .gfni, - .hreset, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_movmsk_over_vtest, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .widekl, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const rocketlake = CpuModel{ - .name = "rocketlake", - .llvm_name = "rocketlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx512bitalg, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vl, - .avx512vnni, - .avx512vpopcntdq, - .bmi, - .bmi2, - .clflushopt, - .cmov, - .crc32, - .cx16, - .ermsb, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const sandybridge = CpuModel{ - .name = "sandybridge", - .llvm_name = "sandybridge", - .features = featureSet(&[_]Feature{ - .@"64bit", - .avx, - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fxsr, - .idivq_to_divl, - .macrofusion, - .mmx, - .no_bypass_delay_mov, - .nopl, - .pclmul, - .popcnt, - .sahf, - .slow_3ops_lea, - .slow_unaligned_mem_32, - .vzeroupper, - .x87, - .xsaveopt, - }), - }; - pub const sapphirerapids = CpuModel{ - .name = "sapphirerapids", - .llvm_name = "sapphirerapids", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .amx_bf16, - .amx_int8, - .avx512bf16, - .avx512bitalg, - .avx512cd, - .avx512fp16, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vnni, - .avx512vpopcntdq, - .avxvnni, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .enqcmd, - .ermsb, - .false_deps_getmant, - .false_deps_mulc, - .false_deps_mullq, - .false_deps_perm, - .false_deps_range, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pconfig, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .tsxldtrk, - .tuning_fast_imm_vector_shift, - .uintr, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const sierraforest = CpuModel{ - .name = "sierraforest", - .llvm_name = "sierraforest", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .avxifma, - .avxneconvert, - .avxvnni, - .avxvnniint8, - .bmi, - .bmi2, - .cldemote, - .clflushopt, - .clwb, - .cmov, - .cmpccxadd, - .crc32, - .cx16, - .enqcmd, - .f16c, - .fast_movbe, - .fma, - .fsgsbase, - .fxsr, - .gfni, - .hreset, - .invpcid, - .lzcnt, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay, - .nopl, - .pconfig, - .pku, - .popcnt, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .serialize, - .sha, - .shstk, - .slow_incdec, - .slow_lea, - .slow_two_mem_ops, - .uintr, - .use_glm_div_sqrt_costs, - .vaes, - .vpclmulqdq, - .vzeroupper, - .waitpkg, - .widekl, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const silvermont = CpuModel{ - .name = "silvermont", - .llvm_name = "silvermont", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_7bytenop, - .fast_movbe, - .fxsr, - .idivq_to_divl, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .sahf, - .slow_incdec, - .slow_lea, - .slow_pmulld, - .slow_two_mem_ops, - .sse4_2, - .use_slm_arith_costs, - .vzeroupper, - .x87, - }), - }; - pub const skx = CpuModel{ - .name = "skx", - .llvm_name = "skx", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx512bw, - .avx512cd, - .avx512dq, - .avx512vl, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .faster_shift_than_shuffle, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const skylake = CpuModel{ - .name = "skylake", - .llvm_name = "skylake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .clflushopt, - .cmov, - .crc32, - .cx16, - .ermsb, - .f16c, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const skylake_avx512 = CpuModel{ - .name = "skylake_avx512", - .llvm_name = "skylake-avx512", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx512bw, - .avx512cd, - .avx512dq, - .avx512vl, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .faster_shift_than_shuffle, - .fsgsbase, - .fxsr, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pclmul, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .slow_3ops_lea, - .tuning_fast_imm_vector_shift, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const slm = CpuModel{ - .name = "slm", - .llvm_name = "slm", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_7bytenop, - .fast_movbe, - .fxsr, - .idivq_to_divl, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .sahf, - .slow_incdec, - .slow_lea, - .slow_pmulld, - .slow_two_mem_ops, - .sse4_2, - .use_slm_arith_costs, - .vzeroupper, - .x87, - }), - }; - pub const tigerlake = CpuModel{ - .name = "tigerlake", - .llvm_name = "tigerlake", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx512bitalg, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vl, - .avx512vnni, - .avx512vp2intersect, - .avx512vpopcntdq, - .bmi, - .bmi2, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .ermsb, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .idivq_to_divl, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .movdir64b, - .movdiri, - .no_bypass_delay_blend, - .no_bypass_delay_mov, - .no_bypass_delay_shuffle, - .nopl, - .pku, - .popcnt, - .prefer_256_bit, - .prfchw, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .shstk, - .tuning_fast_imm_vector_shift, - .vaes, - .vpclmulqdq, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const tremont = CpuModel{ - .name = "tremont", - .llvm_name = "tremont", - .features = featureSet(&[_]Feature{ - .@"64bit", - .aes, - .clflushopt, - .clwb, - .cmov, - .crc32, - .cx16, - .fast_movbe, - .fsgsbase, - .fxsr, - .gfni, - .mmx, - .movbe, - .no_bypass_delay, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .ptwrite, - .rdpid, - .rdrnd, - .rdseed, - .sahf, - .sha, - .slow_incdec, - .slow_lea, - .slow_two_mem_ops, - .sse4_2, - .use_glm_div_sqrt_costs, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const westmere = CpuModel{ - .name = "westmere", - .llvm_name = "westmere", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .fxsr, - .macrofusion, - .mmx, - .no_bypass_delay_mov, - .nopl, - .pclmul, - .popcnt, - .sahf, - .sse4_2, - .vzeroupper, - .x87, - }), - }; - pub const winchip2 = CpuModel{ - .name = "winchip2", - .llvm_name = "winchip2", - .features = featureSet(&[_]Feature{ - .@"3dnow", - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const winchip_c6 = CpuModel{ - .name = "winchip_c6", - .llvm_name = "winchip-c6", - .features = featureSet(&[_]Feature{ - .mmx, - .slow_unaligned_mem_16, - .vzeroupper, - .x87, - }), - }; - pub const x86_64 = CpuModel{ - .name = "x86_64", - .llvm_name = "x86-64", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .cx8, - .fxsr, - .idivq_to_divl, - .macrofusion, - .mmx, - .nopl, - .slow_3ops_lea, - .slow_incdec, - .sse2, - .vzeroupper, - .x87, - }), - }; - pub const x86_64_v2 = CpuModel{ - .name = "x86_64_v2", - .llvm_name = "x86-64-v2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fxsr, - .idivq_to_divl, - .macrofusion, - .mmx, - .nopl, - .popcnt, - .sahf, - .slow_3ops_lea, - .slow_unaligned_mem_32, - .sse4_2, - .vzeroupper, - .x87, - }), - }; - pub const x86_64_v3 = CpuModel{ - .name = "x86_64_v3", - .llvm_name = "x86-64-v3", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .f16c, - .false_deps_lzcnt_tzcnt, - .false_deps_popcnt, - .fast_15bytenop, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fma, - .fxsr, - .idivq_to_divl, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .nopl, - .popcnt, - .sahf, - .slow_3ops_lea, - .vzeroupper, - .x87, - .xsave, - }), - }; - pub const x86_64_v4 = CpuModel{ - .name = "x86_64_v4", - .llvm_name = "x86-64-v4", - .features = featureSet(&[_]Feature{ - .@"64bit", - .allow_light_256_bit, - .avx512bw, - .avx512cd, - .avx512dq, - .avx512vl, - .bmi, - .bmi2, - .cmov, - .crc32, - .cx16, - .false_deps_popcnt, - .fast_15bytenop, - .fast_gather, - .fast_scalar_fsqrt, - .fast_shld_rotate, - .fast_variable_crosslane_shuffle, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fxsr, - .idivq_to_divl, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .nopl, - .popcnt, - .prefer_256_bit, - .sahf, - .slow_3ops_lea, - .vzeroupper, - .x87, - .xsave, - }), - }; - pub const yonah = CpuModel{ - .name = "yonah", - .llvm_name = "yonah", - .features = featureSet(&[_]Feature{ - .cmov, - .cx8, - .fxsr, - .mmx, - .nopl, - .slow_unaligned_mem_16, - .sse3, - .vzeroupper, - .x87, - }), - }; - pub const znver1 = CpuModel{ - .name = "znver1", - .llvm_name = "znver1", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .branchfusion, - .clflushopt, - .clzero, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_15bytenop, - .fast_bextr, - .fast_lzcnt, - .fast_movbe, - .fast_scalar_fsqrt, - .fast_scalar_shift_masks, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .lzcnt, - .mmx, - .movbe, - .mwaitx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdrnd, - .rdseed, - .sahf, - .sbb_dep_breaking, - .sha, - .slow_shld, - .sse4a, - .vzeroupper, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const znver2 = CpuModel{ - .name = "znver2", - .llvm_name = "znver2", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .aes, - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .branchfusion, - .clflushopt, - .clwb, - .clzero, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_15bytenop, - .fast_bextr, - .fast_lzcnt, - .fast_movbe, - .fast_scalar_fsqrt, - .fast_scalar_shift_masks, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fxsr, - .lzcnt, - .mmx, - .movbe, - .mwaitx, - .nopl, - .pclmul, - .popcnt, - .prfchw, - .rdpid, - .rdpru, - .rdrnd, - .rdseed, - .sahf, - .sbb_dep_breaking, - .sha, - .slow_shld, - .sse4a, - .vzeroupper, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const znver3 = CpuModel{ - .name = "znver3", - .llvm_name = "znver3", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx2, - .bmi, - .bmi2, - .branchfusion, - .clflushopt, - .clwb, - .clzero, - .cmov, - .crc32, - .cx16, - .f16c, - .fast_15bytenop, - .fast_bextr, - .fast_lzcnt, - .fast_movbe, - .fast_scalar_fsqrt, - .fast_scalar_shift_masks, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fma, - .fsgsbase, - .fsrm, - .fxsr, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .mwaitx, - .nopl, - .pku, - .popcnt, - .prfchw, - .rdpid, - .rdpru, - .rdrnd, - .rdseed, - .sahf, - .sbb_dep_breaking, - .sha, - .slow_shld, - .sse4a, - .vaes, - .vpclmulqdq, - .vzeroupper, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; - pub const znver4 = CpuModel{ - .name = "znver4", - .llvm_name = "znver4", - .features = featureSet(&[_]Feature{ - .@"64bit", - .adx, - .allow_light_256_bit, - .avx512bf16, - .avx512bitalg, - .avx512cd, - .avx512dq, - .avx512ifma, - .avx512vbmi, - .avx512vbmi2, - .avx512vl, - .avx512vnni, - .avx512vpopcntdq, - .bmi, - .bmi2, - .branchfusion, - .clflushopt, - .clwb, - .clzero, - .cmov, - .crc32, - .cx16, - .fast_15bytenop, - .fast_bextr, - .fast_lzcnt, - .fast_movbe, - .fast_scalar_fsqrt, - .fast_scalar_shift_masks, - .fast_variable_perlane_shuffle, - .fast_vector_fsqrt, - .fsgsbase, - .fsrm, - .fxsr, - .gfni, - .invpcid, - .lzcnt, - .macrofusion, - .mmx, - .movbe, - .mwaitx, - .nopl, - .pku, - .popcnt, - .prfchw, - .rdpid, - .rdpru, - .rdrnd, - .rdseed, - .sahf, - .sbb_dep_breaking, - .sha, - .shstk, - .slow_shld, - .sse4a, - .vaes, - .vpclmulqdq, - .vzeroupper, - .wbnoinvd, - .x87, - .xsavec, - .xsaveopt, - .xsaves, - }), - }; -}; diff --git a/lib/std/target/xtensa.zig b/lib/std/target/xtensa.zig deleted file mode 100644 index 22851c4554cf86cb9c22a61fc290fe3884faf4e3..0000000000000000000000000000000000000000 --- a/lib/std/target/xtensa.zig +++ /dev/null @@ -1,39 +0,0 @@ -//! This file is auto-generated by tools/update_cpu_features.zig. - -const std = @import("../std.zig"); -const CpuFeature = std.Target.Cpu.Feature; -const CpuModel = std.Target.Cpu.Model; - -pub const Feature = enum { - density, -}; - -pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet; -pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas; -pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny; -pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll; - -pub const all_features = blk: { - const len = @typeInfo(Feature).Enum.fields.len; - std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - var result: [len]CpuFeature = undefined; - result[@intFromEnum(Feature.density)] = .{ - .llvm_name = "density", - .description = "Enable Density instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - const ti = @typeInfo(Feature); - for (&result, 0..) |*elem, i| { - elem.index = i; - elem.name = ti.Enum.fields[i].name; - } - break :blk result; -}; - -pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; -}; diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 2d2aaf17ba40d0c673af65ef917c51bbea19fbd4..84feb2cf0a4bb617109dd910f3eb001872964d38 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"); @@ -16,7 +13,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"); @@ -114,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) { @@ -203,6 +201,124 @@ 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 = @typeInfo(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")); + } +}; + +/// 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/CrossTarget.zig b/lib/std/zig/CrossTarget.zig deleted file mode 100644 index ea496051b4ca73a12507d80c0c2f5232b78efe70..0000000000000000000000000000000000000000 --- a/lib/std/zig/CrossTarget.zig +++ /dev/null @@ -1,895 +0,0 @@ -//! 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; - -/// `null` means native. -cpu_arch: ?Target.Cpu.Arch = null, - -cpu_model: CpuModel = CpuModel.determined_by_cpu_arch, - -/// Sparse set of CPU features to add to the set from `cpu_model`. -cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, - -/// Sparse set of CPU features to remove from the set from `cpu_model`. -cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, - -/// `null` means native. -os_tag: ?Target.Os.Tag = null, - -/// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native) -/// then `null` for this field means native. -os_version_min: ?OsVersion = null, - -/// When cross compiling, `null` means default (latest known OS version). -/// When `os_tag` is native, `null` means equal to the native OS version. -os_version_max: ?OsVersion = null, - -/// `null` means default when cross compiling, or native when os_tag is native. -/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. -glibc_version: ?SemanticVersion = null, - -/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. -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{}, - -/// `null` means default for the cpu/arch/os combo. -ofmt: ?Target.ObjectFormat = null, - -pub const CpuModel = union(enum) { - /// Always native - native, - - /// Always baseline - baseline, - - /// If CPU Architecture is native, then the CPU model will be native. Otherwise, - /// it will be baseline. - determined_by_cpu_arch, - - explicit: *const Target.Cpu.Model, -}; - -pub const OsVersion = union(enum) { - none: void, - semver: SemanticVersion, - windows: Target.Os.WindowsVersion, -}; - -pub const SemanticVersion = std.SemanticVersion; - -pub const DynamicLinker = Target.DynamicLinker; - -pub fn fromTarget(target: Target) CrossTarget { - var result: CrossTarget = .{ - .cpu_arch = target.cpu.arch, - .cpu_model = .{ .explicit = target.cpu.model }, - .os_tag = target.os.tag, - .os_version_min = undefined, - .os_version_max = undefined, - .abi = target.abi, - .glibc_version = if (target.isGnuLibC()) - target.os.version_range.linux.glibc - else - null, - }; - result.updateOsVersionRange(target.os); - - const all_features = target.cpu.arch.allFeaturesList(); - var cpu_model_set = target.cpu.model.features; - cpu_model_set.populateDependencies(all_features); - { - // The "add" set is the full set with the CPU Model set removed. - const add_set = &result.cpu_features_add; - add_set.* = target.cpu.features; - add_set.removeFeatureSet(cpu_model_set); - } - { - // The "sub" set is the features that are on in CPU Model set and off in the full set. - const sub_set = &result.cpu_features_sub; - sub_set.* = cpu_model_set; - sub_set.removeFeatureSet(target.cpu.features); - } - return result; -} - -fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void { - switch (os.tag) { - .freestanding, - .ananas, - .cloudabi, - .fuchsia, - .kfreebsd, - .lv2, - .solaris, - .illumos, - .zos, - .haiku, - .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, - => { - self.os_version_min = .{ .none = {} }; - self.os_version_max = .{ .none = {} }; - }, - - .freebsd, - .macos, - .ios, - .tvos, - .watchos, - .netbsd, - .openbsd, - .dragonfly, - => { - self.os_version_min = .{ .semver = os.version_range.semver.min }; - self.os_version_max = .{ .semver = os.version_range.semver.max }; - }, - - .linux => { - self.os_version_min = .{ .semver = os.version_range.linux.range.min }; - self.os_version_max = .{ .semver = os.version_range.linux.range.max }; - }, - - .windows => { - self.os_version_min = .{ .windows = os.version_range.windows.min }; - self.os_version_max = .{ .windows = os.version_range.windows.max }; - }, - } -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn toTarget(self: CrossTarget) 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 - /// The fields are, respectively: - /// * CPU Architecture - /// * Operating System (and optional version range) - /// * C ABI (optional, with optional glibc version) - /// The string "native" can be used for CPU architecture as well as Operating System. - /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted. - arch_os_abi: []const u8 = "native", - - /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" - /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features - /// to remove from the set. - /// The following special strings are recognized for CPU Model name: - /// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set - /// of features that is expected to be supported on most available hardware. - /// * "native" - The native CPU model is to be detected when compiling. - /// If this field is not provided (`null`), then the value will depend on the - /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". - cpu_features: ?[]const u8 = null, - - /// Absolute path to dynamic linker, to override the default, which is either a natively - /// detected path, or a standard path. - dynamic_linker: ?[]const u8 = null, - - object_format: ?[]const u8 = null, - - /// If this is provided, the function will populate some information about parsing failures, - /// so that user-friendly error messages can be delivered. - diagnostics: ?*Diagnostics = null, - - pub const Diagnostics = struct { - /// If the architecture was determined, this will be populated. - arch: ?Target.Cpu.Arch = null, - - /// If the OS name was determined, this will be populated. - os_name: ?[]const u8 = null, - - /// If the OS tag was determined, this will be populated. - os_tag: ?Target.Os.Tag = null, - - /// If the ABI was determined, this will be populated. - abi: ?Target.Abi = null, - - /// If the CPU name was determined, this will be populated. - cpu_name: ?[]const u8 = null, - - /// If error.UnknownCpuFeature is returned, this will be populated. - unknown_feature_name: ?[]const u8 = null, - }; -}; - -pub fn parse(args: ParseOptions) !CrossTarget { - var dummy_diags: ParseOptions.Diagnostics = undefined; - const diags = args.diagnostics orelse &dummy_diags; - - var result: CrossTarget = .{ - .dynamic_linker = DynamicLinker.init(args.dynamic_linker), - }; - - var it = mem.splitScalar(u8, args.arch_os_abi, '-'); - const arch_name = it.first(); - const arch_is_native = mem.eql(u8, arch_name, "native"); - if (!arch_is_native) { - result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse - return error.UnknownArchitecture; - } - const arch = result.getCpuArch(); - diags.arch = arch; - - if (it.next()) |os_text| { - try parseOs(&result, diags, os_text); - } else if (!arch_is_native) { - return error.MissingOperatingSystem; - } - - const opt_abi_text = it.next(); - if (opt_abi_text) |abi_text| { - var abi_it = mem.splitScalar(u8, abi_text, '.'); - const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse - return error.UnknownApplicationBinaryInterface; - result.abi = abi; - diags.abi = abi; - - const abi_ver_text = abi_it.rest(); - if (abi_it.next() != null) { - if (result.isGnuLibC()) { - result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) { - error.Overflow => return error.InvalidAbiVersion, - error.InvalidVersion => return error.InvalidAbiVersion, - }; - } else { - return error.InvalidAbiVersion; - } - } - } - - if (it.next() != null) return error.UnexpectedExtraField; - - if (args.cpu_features) |cpu_features| { - const all_features = arch.allFeaturesList(); - var index: usize = 0; - while (index < cpu_features.len and - cpu_features[index] != '+' and - cpu_features[index] != '-') - { - index += 1; - } - const cpu_name = cpu_features[0..index]; - diags.cpu_name = cpu_name; - - const add_set = &result.cpu_features_add; - const sub_set = &result.cpu_features_sub; - if (mem.eql(u8, cpu_name, "native")) { - result.cpu_model = .native; - } else if (mem.eql(u8, cpu_name, "baseline")) { - result.cpu_model = .baseline; - } else { - result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) }; - } - - while (index < cpu_features.len) { - const op = cpu_features[index]; - const set = switch (op) { - '+' => add_set, - '-' => sub_set, - else => unreachable, - }; - index += 1; - const start = index; - while (index < cpu_features.len and - cpu_features[index] != '+' and - cpu_features[index] != '-') - { - index += 1; - } - const feature_name = cpu_features[start..index]; - for (all_features, 0..) |feature, feat_index_usize| { - const feat_index = @as(Target.Cpu.Feature.Set.Index, @intCast(feat_index_usize)); - if (mem.eql(u8, feature_name, feature.name)) { - set.addFeature(feat_index); - break; - } - } else { - diags.unknown_feature_name = feature_name; - return error.UnknownCpuFeature; - } - } - } - - if (args.object_format) |ofmt_name| { - result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse - return error.UnknownObjectFormat; - } - - return result; -} - -/// 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 -/// 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, '-'); - const arch_name = it.first(); - const arch_is_native = mem.eql(u8, arch_name, "native"); - if (arch_is_native) { - return builtin.cpu.arch; - } else { - return std.meta.stringToEnum(Target.Cpu.Arch, arch_name); - } -} - -/// Similar to `SemanticVersion.parse`, but with following changes: -/// * Leading zeroes are allowed. -/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. -pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion { - const parseVersionComponentFn = (struct { - fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize { - return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) { - error.InvalidCharacter => return error.InvalidVersion, - error.Overflow => return error.Overflow, - }; - } - }).parseVersionComponentInner; - var version_components = mem.splitScalar(u8, ver, '.'); - const major = version_components.first(); - const minor = version_components.next() orelse return error.InvalidVersion; - const patch = version_components.next() orelse "0"; - if (version_components.next() != null) return error.InvalidVersion; - return .{ - .major = try parseVersionComponentFn(major), - .minor = try parseVersionComponentFn(minor), - .patch = try parseVersionComponentFn(patch), - }; -} - -test parseVersion { - try std.testing.expectError(error.InvalidVersion, parseVersion("1")); - try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2")); - try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3")); - try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getCpu(self: CrossTarget) 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`. - 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.NativeTargetInfo.detect`. - 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: CrossTarget) Target.Cpu.Arch { - return self.cpu_arch orelse builtin.cpu.arch; -} - -pub fn getCpuModel(self: CrossTarget) *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 { - return self.getCpu().features; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getOs(self: CrossTarget) 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`. - 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: CrossTarget) 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 { - if (self.os_version_min) |version_min| return version_min; - var tmp: CrossTarget = undefined; - tmp.updateOsVersionRange(self.getOs()); - return tmp.os_version_min.?; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn getOsVersionMax(self: CrossTarget) OsVersion { - if (self.os_version_max) |version_max| return version_max; - var tmp: CrossTarget = 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 { - 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`. - return builtin.abi; - } - - return Target.Abi.default(self.getCpuArch(), self.getOs()); -} - -pub fn isFreeBSD(self: CrossTarget) bool { - return self.getOsTag() == .freebsd; -} - -pub fn isDarwin(self: CrossTarget) bool { - return self.getOsTag().isDarwin(); -} - -pub fn isNetBSD(self: CrossTarget) bool { - return self.getOsTag() == .netbsd; -} - -pub fn isOpenBSD(self: CrossTarget) bool { - return self.getOsTag() == .openbsd; -} - -pub fn isUefi(self: CrossTarget) bool { - return self.getOsTag() == .uefi; -} - -pub fn isDragonFlyBSD(self: CrossTarget) bool { - return self.getOsTag() == .dragonfly; -} - -pub fn isLinux(self: CrossTarget) bool { - return self.getOsTag() == .linux; -} - -pub fn isWindows(self: CrossTarget) bool { - return self.getOsTag() == .windows; -} - -pub fn exeFileExt(self: CrossTarget) [:0]const u8 { - return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); -} - -pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 { - return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi()); -} - -pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 { - return self.getOsTag().dynamicLibSuffix(); -} - -pub fn libPrefix(self: CrossTarget) [:0]const u8 { - return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi()); -} - -pub fn isNativeCpu(self: CrossTarget) 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 { - 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 { - return self.os_tag == null and self.abi == null; -} - -pub fn isNative(self: CrossTarget) bool { - return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); -} - -/// Formats a version with the patch component omitted if it is zero, -/// unlike SemanticVersion.format which formats all its version components regardless. -fn formatVersion(version: SemanticVersion, writer: anytype) !void { - if (version.patch == 0) { - try writer.print("{d}.{d}", .{ version.major, version.minor }); - } else { - try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch }); - } -} - -pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}![]u8 { - if (self.isNative()) { - return allocator.dupe(u8, "native"); - } - - const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native"; - const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; - - var result = std.ArrayList(u8).init(allocator); - defer result.deinit(); - - try result.writer().print("{s}-{s}", .{ arch_name, os_name }); - - // 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()) { - .none => {}, - .semver => |v| { - try result.writer().writeAll("."); - try formatVersion(v, result.writer()); - }, - .windows => |v| try result.writer().print("{s}", .{v}), - } - } - if (self.os_version_max) |max| { - switch (max) { - .none => {}, - .semver => |v| { - try result.writer().writeAll("..."); - try formatVersion(v, result.writer()); - }, - .windows => |v| try result.writer().print("..{s}", .{v}), - } - } - - if (self.glibc_version) |v| { - try result.writer().print("-{s}.", .{@tagName(self.getAbi())}); - try formatVersion(v, result.writer()); - } else if (self.abi) |abi| { - try result.writer().print("-{s}", .{@tagName(abi)}); - } - - return result.toOwnedSlice(); -} - -pub fn allocDescription(self: CrossTarget, 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 { - return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); -} - -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()); -} - -pub fn setGnuLibCVersion(self: *CrossTarget, 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 { - return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); -} - -pub fn updateCpuFeatures(self: CrossTarget, 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 { - var it = mem.splitScalar(u8, text, '.'); - const os_name = it.first(); - diags.os_name = os_name; - const os_is_native = mem.eql(u8, os_name, "native"); - if (!os_is_native) { - result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse - return error.UnknownOperatingSystem; - } - const tag = result.getOsTag(); - diags.os_tag = tag; - - const version_text = it.rest(); - if (it.next() == null) return; - - switch (tag) { - .freestanding, - .ananas, - .cloudabi, - .fuchsia, - .kfreebsd, - .lv2, - .solaris, - .illumos, - .zos, - .haiku, - .minix, - .rtems, - .nacl, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .wasi, - .emscripten, - .uefi, - .opencl, - .glsl450, - .vulkan, - .plan9, - .driverkit, - .shadermodel, - .liteos, - .other, - => return error.InvalidOperatingSystemVersion, - - .freebsd, - .macos, - .ios, - .tvos, - .watchos, - .netbsd, - .openbsd, - .linux, - .dragonfly, - => { - var range_it = mem.splitSequence(u8, version_text, "..."); - - const min_text = range_it.next().?; - const min_ver = parseVersion(min_text) catch |err| switch (err) { - error.Overflow => return error.InvalidOperatingSystemVersion, - error.InvalidVersion => return error.InvalidOperatingSystemVersion, - }; - result.os_version_min = .{ .semver = min_ver }; - - const max_text = range_it.next() orelse return; - const max_ver = parseVersion(max_text) catch |err| switch (err) { - error.Overflow => return error.InvalidOperatingSystemVersion, - error.InvalidVersion => return error.InvalidOperatingSystemVersion, - }; - result.os_version_max = .{ .semver = max_ver }; - }, - - .windows => { - var range_it = mem.splitSequence(u8, version_text, "..."); - - const min_text = range_it.first(); - const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse - return error.InvalidOperatingSystemVersion; - result.os_version_min = .{ .windows = min_ver }; - - const max_text = range_it.next() orelse return; - const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse - return error.InvalidOperatingSystemVersion; - result.os_version_max = .{ .windows = max_ver }; - }, - } -} - -test "CrossTarget.parse" { - if (builtin.target.isGnuLibC()) { - var cross_target = try CrossTarget.parse(.{}); - cross_target.setGnuLibCVersion(2, 1, 1); - - const text = try cross_target.zigTriple(std.testing.allocator); - defer std.testing.allocator.free(text); - - var buf: [256]u8 = undefined; - const triple = std.fmt.bufPrint( - buf[0..], - "native-native-{s}.2.1.1", - .{@tagName(builtin.abi)}, - ) catch unreachable; - - try std.testing.expectEqualSlices(u8, triple, text); - } - { - const cross_target = try CrossTarget.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); - } - { - const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "native" }); - - try std.testing.expect(cross_target.cpu_arch == null); - try std.testing.expect(cross_target.isNative()); - - const text = try cross_target.zigTriple(std.testing.allocator); - defer std.testing.allocator.free(text); - try std.testing.expectEqualSlices(u8, "native", text); - } - { - const cross_target = try CrossTarget.parse(.{ - .arch_os_abi = "x86_64-linux-gnu", - .cpu_features = "x86_64-sse-sse2-avx-cx8", - }); - const target = cross_target.toTarget(); - - try std.testing.expect(target.os.tag == .linux); - try std.testing.expect(target.abi == .gnu); - try std.testing.expect(target.cpu.arch == .x86_64); - try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); - try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); - try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); - try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); - try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); - - try std.testing.expect(Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov })); - try std.testing.expect(!Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx })); - 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); - defer std.testing.allocator.free(text); - try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); - } - { - const cross_target = try CrossTarget.parse(.{ - .arch_os_abi = "arm-linux-musleabihf", - .cpu_features = "generic+v8a", - }); - const target = cross_target.toTarget(); - - try std.testing.expect(target.os.tag == .linux); - try std.testing.expect(target.abi == .musleabihf); - try std.testing.expect(target.cpu.arch == .arm); - 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); - defer std.testing.allocator.free(text); - try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); - } - { - const cross_target = try CrossTarget.parse(.{ - .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", - .cpu_features = "generic+v8a", - }); - const target = cross_target.toTarget(); - - try std.testing.expect(target.cpu.arch == .aarch64); - try std.testing.expect(target.os.tag == .linux); - try std.testing.expect(target.os.version_range.linux.range.min.major == 3); - try std.testing.expect(target.os.version_range.linux.range.min.minor == 10); - try std.testing.expect(target.os.version_range.linux.range.min.patch == 0); - try std.testing.expect(target.os.version_range.linux.range.max.major == 4); - try std.testing.expect(target.os.version_range.linux.range.max.minor == 4); - try std.testing.expect(target.os.version_range.linux.range.max.patch == 1); - try std.testing.expect(target.os.version_range.linux.glibc.major == 2); - try std.testing.expect(target.os.version_range.linux.glibc.minor == 27); - 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); - 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/system.zig b/lib/std/zig/system.zig index 3ec92c8274e04ab512d99308249c5328da564797..c2a9fa4f9fe37d4f5c91f728641f15842b65ee03 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -1,13 +1,1144 @@ 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 { + 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 => { + 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 (os.tag) { + .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 (os.tag) { + .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| { + 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.cpu_arch orelse builtin.cpu.arch; + + 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 => {}, + } + 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 + // 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 833d698d4285695767efefb8a4d59dc23492e379..715c172c39bcc972b4391070a45da81ecee30f3d 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 080f18bf0a21028a804740c30398725daa63c202..0000000000000000000000000000000000000000 --- 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 CrossTarget = std.zig.CrossTarget; -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 `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) { - 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 (cross_target.os_version_min) |min| switch (min) { - .none => {}, - .semver => |semver| switch (cross_target.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) { - .none => {}, - .semver => |semver| switch (cross_target.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()); - 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 = switch (cross_target.cpu_model) { - .native => detectNativeCpuAndFeatures(cpu_arch, os, cross_target), - .baseline => Target.Cpu.baseline(cpu_arch), - .determined_by_cpu_arch => if (cross_target.cpu_arch == null) - detectNativeCpuAndFeatures(cpu_arch, os, cross_target) - 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); - // 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 (!std.Target.x86.featureSetHasAny(cross_target.cpu_features_add, .{ - .@"16bit_mode", .@"32bit_mode", - })) { - switch (result.target.abi) { - .code16 => result.target.cpu.features.addFeature( - @intFromEnum(std.Target.x86.Feature.@"16bit_mode"), - ), - else => result.target.cpu.features.addFeature( - @intFromEnum(std.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(std.Target.arm.Feature.thumb_mode), - ); - }, - else => {}, - } - cross_target.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, - cross_target: CrossTarget, -) 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; - // 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); - } - if (cross_target.abi) |abi| { - if (abi.isMusl()) { - // musl implies static linking. - return defaultAbiAndDynamicLinker(cpu, os, cross_target); - } - } - // 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 = cross_target.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, cross_target); - }, - - 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, cross_target); - 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, cross_target) 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, cross_target); - }, - }; -} - -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 = CrossTarget.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 CrossTarget.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, - cross_target: CrossTarget, -) 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 = cross_target.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), - }, - .dynamic_linker = cross_target.dynamic_linker, - }; - var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC - const look_for_ld = cross_target.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 - cross_target.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 - cross_target.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, cross_target: CrossTarget) !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), - }; - return NativeTargetInfo{ - .target = target, - .dynamic_linker = if (cross_target.dynamic_linker.get() == null) - target.standardDynamicLinkerPath() - else - cross_target.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, cross_target: CrossTarget) ?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); - }, - 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 target is capable of executing natively 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/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig index 2c0b22e96cba05e474256771f1762a37dfc7e234..c4feb7a35b26fffa709c9c2f30e3ea7e4c15a390 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 f2f89f8317b66c9cee6b4ab2b96128d57356cce1..d2d31b4079817b3c549870c9a4738bc0c2519362 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 b99f5cf65faa00dea81edf3f1ef225a168a0c4af..edcfcebf29d3a39531d74586a6dd6cdeb5d9e85d 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/Builtin.zig b/src/Builtin.zig new file mode 100644 index 0000000000000000000000000000000000000000..3211dd3a690bd80bf10733d8f89b6a1221c16157 --- /dev/null +++ b/src/Builtin.zig @@ -0,0 +1,314 @@ +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); + 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; + + @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; + \\ + ); + } + } +} + +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, + } + + log.debug("parsing and generating '{s}'", .{mod.root_src_path}); + + file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig); + 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; +} + +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); + defer af.deinit(); + 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 = .{ + .size = file.source.len, + .inode = 0, // dummy value + .mtime = 0, // dummy value + }; +} + +const builtin = @import("builtin"); +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"); +const log = std.log.scoped(.builtin); diff --git a/src/Compilation.zig b/src/Compilation.zig index 296b300f8d8c555151d270d6e6e8b017ec40543c..6c7f1d0d83cb326db6fd0d8c7854fc928570e090 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -28,31 +28,79 @@ 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 BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; 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"); +const LlvmObject = @import("codegen/llvm.zig").Object; + +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, +/// 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, +/// 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. +root_mod: *Package.Module, + +/// User-specified settings that have all the defaults resolved into concrete values. +config: Config, + +/// 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) +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, +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), +version: ?std.SemanticVersion, +libc_installation: ?*const LibCInstallation, +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. +/// 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) = 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 = .{}, +link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, lld_errors: std.ArrayListUnmanaged(LldError) = .{}, work_queue: std.fifo.LinearFifo(Job, .Dynamic), @@ -87,9 +135,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, -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. @@ -105,33 +150,25 @@ 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, -unwind_tables: bool, -test_evented_io: bool, debug_compiler_runtime_libs: bool, debug_compile_errors: bool, job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, +job_queued_update_builtin_zig: bool, alloc_failure_occurred: bool = false, 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, +global_cc_argv: []const []const u8, 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, @@ -163,19 +200,13 @@ 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. /// 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, - /// How many lines of reference trace should be included per compile error. /// Null means only show snippet on first error. reference_trace: ?u32 = null, @@ -195,7 +226,31 @@ emit_llvm_bc: ?EmitLoc, work_queue_wait_group: WaitGroup = .{}, astgen_wait_group: WaitGroup = .{}, -pub const default_stack_protector_buffer_size = 4; +llvm_opt_bisect_limit: c_int, + +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: []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 try arena.dupeZ(u8, basename); + } + } +}; + +pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; pub const SemaError = Module.SemaError; pub const CRTFile = struct { @@ -209,8 +264,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 }, @@ -227,16 +282,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 = &.{}, }; @@ -289,7 +348,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, }; @@ -659,6 +718,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, @@ -743,6 +804,41 @@ 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); + hh.addListOfBytes(mod.cc_argv); + } + + 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); } @@ -752,7 +848,21 @@ 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 addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void { + hh.add(x != null); + addDebugFormat(hh, x orelse return); + } + + 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 => {}, + .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. // TODO this logic can likely be improved by utilizing clang_options_data.zig. @@ -771,8 +881,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 `. @@ -781,9 +889,62 @@ 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; + +pub const CacheMode = enum { incremental, whole }; + +const CacheUse = union(CacheMode) { + incremental: *Incremental, + whole: *Whole, + + 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 `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, + /// 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; + } + } + + fn moveLock(whole: *Whole) Cache.Lock { + const result = whole.lock.?; + whole.lock = null; + return result; + } + }; + + 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 { path: []const u8, @@ -795,16 +956,27 @@ 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, - target: Target, - root_name: []const u8, - main_mod: ?*Package.Module, - output_mode: std.builtin.OutputMode, thread_pool: *ThreadPool, - dynamic_linker: ?[]const u8 = null, + 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 = null, + /// This is provided so that the API user has a chance to tweak the + /// per-module settings of the standard library. + /// 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. emit_bin: ?EmitLoc, @@ -820,8 +992,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 /// operation, allowing Zig to skip linking when the hash would be unchanged. @@ -830,14 +1000,11 @@ 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{}, @@ -850,41 +1017,16 @@ pub const InitOptions = struct { /// * getpid /// * 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, + 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. - 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, @@ -895,22 +1037,19 @@ 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, 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: ?BuildId = null, + build_id: ?std.zig.BuildId = null, disable_c_depfile: bool = false, linker_z_nodelete: bool = false, linker_z_notext: bool = false, @@ -924,12 +1063,11 @@ 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, - major_subsystem_version: ?u32 = null, - minor_subsystem_version: ?u32 = null, + linker_sort_section: ?link.File.Elf.SortSection = null, + major_subsystem_version: ?u16 = null, + minor_subsystem_version: ?u16 = null, clang_passthrough_mode: bool = false, verbose_cc: bool = false, verbose_link: bool = false, @@ -940,8 +1078,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 @@ -949,28 +1085,21 @@ 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, - entry: ?[]const u8 = null, + hash_style: link.File.Elf.HashStyle = .both, + entry: Entry = .default, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, - stack_size_override: ?u64 = null, - image_base_override: ?u64 = null, - self_exe_path: ?[]const u8 = null, + stack_size: ?u64 = null, + image_base: ?u64 = null, version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation = null, - machine_code_model: std.builtin.CodeModel = .default, + 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, - 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 @@ -991,449 +1120,223 @@ 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, - /// (SPIR-V) whether to generate a structured control flow graph or not - want_structured_cfg: ?bool = null, + error_limit: ?Compilation.Module.ErrorInt = null, + global_cc_argv: []const []const u8 = &.{}, + + pub const Entry = link.File.OpenOptions.Entry; }; 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(); + var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{}; + defer seen_table.deinit(gpa); + try seen_table.put(gpa, root_mod, {}); - 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]); + 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); + } + }; + + 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; } - }.lessThan); - for (module_indices) |module_index| { - const module = mod_table.values()[module_index]; - if ((try seen_table.getOrPut(module)).found_existing) continue; + cache_helpers.addModule(hash, mod); - // 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) { +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, - .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.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 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; + const use_llvm = options.config.use_llvm; - // 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; + // 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; - // 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; - } - } - - // 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) - 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 link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; const build_id = options.build_id orelse .none; - // 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); - } - - 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 dll_export_fns = options.dll_export_fns orelse (is_dyn_lib or options.rdynamic); + const link_libc = options.config.link_libc; 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, - ); + // 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 => {}, + } + } + 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, + }, + }; + }; 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; - } - } - 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; - }; - 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 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) { - .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); + 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 @@ -1455,197 +1358,27 @@ 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.addOptional(options.dwarf_format); + cache.hash.add(options.config.link_libcpp); + cache.hash.add(options.config.link_libunwind); + cache.hash.add(output_mode); + 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); 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: { - // 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. - 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); - } - }, - .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(valgrind); - hash.add(single_threaded); - hash.add(use_llvm); - hash.add(use_lib_llvm); - hash.add(dll_export_fns); - hash.add(options.is_test); - hash.add(options.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); - 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 - // 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 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); - } - + 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 // to redundantly happen for each AstGen operation. const zir_sub_dir = "z"; @@ -1664,277 +1397,183 @@ 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 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.getBuiltinDependency(), + }); - const module = try arena.create(Module); - errdefer module.deinit(); - module.* = .{ + const zcu = try arena.create(Module); + zcu.* = .{ .gpa = gpa, .comp = comp, .main_mod = main_mod, - .root_mod = root_mod, - .zig_cache_artifact_directory = zig_cache_artifact_directory, + .root_mod = options.root_mod, + .std_mod = std_mod, .global_zir_cache = global_zir_cache, .local_zir_cache = local_zir_cache, .emit_h = emit_h, .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa), .error_limit = error_limit, + .llvm_object = null, }; - try module.init(); - - break :blk module; + try zcu.init(); + break :blk zcu; } else blk: { if (options.emit_h != null) return error.NoZigModuleForCHeader; break :blk null; }; - errdefer if (module) |zm| zm.deinit(); + errdefer if (opt_zcu) |zcu| zcu.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, - }; - - // 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 emit_bin = options.emit_bin orelse break :blk null; - - if (emit_bin.directory) |directory| { - break :blk link.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 (module) |zm| { - break :blk link.Emit{ - .directory = zm.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 link.Emit{ - .directory = link_artifact_directory, - .sub_path = emit_bin.basename, - }; - }; - - const implib_emit: ?link.Emit = blk: { - const emit_implib = options.emit_implib orelse break :blk null; - - if (emit_implib.directory) |directory| { - break :blk link.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 link.Emit{ - .directory = bin_file_emit.?.directory, - .sub_path = emit_implib.basename, - }; - }; - - const docs_emit: ?link.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 = module.?.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) = .{}; + var 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 bin_file = try link.File.openPath(gpa, .{ - .emit = bin_file_emit, - .implib_emit = implib_emit, - .docs_emit = docs_emit, + comp.* = .{ + .gpa = gpa, + .arena = arena, + .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, + .zig_lib_directory = options.zig_lib_directory, + .local_cache_directory = options.local_cache_directory, + .global_cache_directory = options.global_cache_directory, + .emit_asm = options.emit_asm, + .emit_llvm_ir = options.emit_llvm_ir, + .emit_llvm_bc = options.emit_llvm_bc, + .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), + .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), + .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), + .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), + .c_source_files = options.c_source_files, + .rc_source_files = options.rc_source_files, + .cache_parent = cache, + .self_exe_path = options.self_exe_path, + .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, + .thread_pool = options.thread_pool, + .clang_passthrough_mode = options.clang_passthrough_mode, + .clang_preprocessor_mode = options.clang_preprocessor_mode, + .verbose_cc = options.verbose_cc, + .verbose_air = options.verbose_air, + .verbose_intern_pool = options.verbose_intern_pool, + .verbose_generic_instances = options.verbose_generic_instances, + .verbose_llvm_ir = options.verbose_llvm_ir, + .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, + .reference_trace = options.reference_trace, + .formatted_panics = formatted_panics, + .time_report = options.time_report, + .stack_report = options.stack_report, + .test_filter = options.test_filter, + .test_name_prefix = options.test_name_prefix, + .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, + .debug_compile_errors = options.debug_compile_errors, + .libcxx_abi_version = options.libcxx_abi_version, .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, - .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, + .system_libs = system_libs, + .version = options.version, + .libc_installation = libc_dirs.libc_installation, + .include_compiler_rt = include_compiler_rt, .objects = options.link_objects, - .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, - .system_libs = system_libs, + .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, + .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, + .global_cc_argv = options.global_cc_argv, + }; + + // 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, + .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, .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, + .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, - .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, + .each_lib_rpath = each_lib_rpath, .build_id = build_id, - .cache_mode = cache_mode, - .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, - .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, @@ -1943,76 +1582,125 @@ pub fn create(gpa: Allocator, options: InitOptions) !*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, - .want_structured_cfg = options.want_structured_cfg, - }); - errdefer bin_file.destroy(); - comp.* = .{ - .gpa = gpa, - .arena = arena_allocator, - .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, - .emit_asm = options.emit_asm, - .emit_llvm_ir = options.emit_llvm_ir, - .emit_llvm_bc = options.emit_llvm_bc, - .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), - .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), - .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), - .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_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, - .self_exe_path = options.self_exe_path, - .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, - .verbose_cc = options.verbose_cc, - .verbose_air = options.verbose_air, - .verbose_intern_pool = options.verbose_intern_pool, - .verbose_generic_instances = options.verbose_generic_instances, - .verbose_llvm_ir = options.verbose_llvm_ir, - .verbose_llvm_bc = options.verbose_llvm_bc, - .verbose_cimport = options.verbose_cimport, - .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, - .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, - .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, + .entry_addr = null, // CLI does not expose this option (yet?) }; + + switch (options.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(options.config.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, 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 + // 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, comp, emit, lf_open_opts); + } + + if (options.emit_implib) |emit_implib| { + comp.implib_emit = .{ + .directory = emit_implib.directory orelse artifact_directory, + .sub_path = emit_implib.basename, + }; + } + + if (options.emit_docs) |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), + .tmp_artifact_directory = null, + .lock = null, + }; + comp.cache_use = .{ .whole = whole }; + }, + } + + // 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); + } + break :comp comp; }; errdefer comp.destroy(); - const target = comp.getTarget(); + const target = comp.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, 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); @@ -2052,9 +1740,12 @@ 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 = switch (comp.cache_use) { + .whole => |whole| whole.bin_sub_path != null, + .incremental => comp.bin_file != 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, @@ -2095,27 +1786,30 @@ 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| { + // worst-case we need all components + try comp.work_queue.ensureUnusedCapacity(comp.wasi_emulated_libs.len + 2); + + 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(wasi_exec_model) }, + .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) }, .{ .wasi_libc_crt_file = .libc_a }, }); } + if (comp.wantBuildMinGWFromSource()) { if (!target_util.canBuildLibC(target)) return error.LibCUnavailable; @@ -2132,7 +1826,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, @@ -2141,7 +1835,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 }); @@ -2150,31 +1844,31 @@ 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.bin_file.options.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", }; - try comp.bin_file.options.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); + try comp.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; - } 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. @@ -2182,8 +1876,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 = {} }); } @@ -2192,88 +1886,87 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { return comp; } -pub fn destroy(self: *Compilation) void { - const optional_module = self.bin_file.options.module; - self.bin_file.destroy(); - if (optional_module) |module| module.deinit(); - - const gpa = self.gpa; - 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 = 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(); - if (self.owned_link_dir) |*dir| dir.close(); - - // This destroys `self`. - var arena_instance = self.arena; - arena_instance.deinit(); + comp.cache_parent.manifest_dir.close(); } pub fn clearMiscFailures(comp: *Compilation) void { @@ -2286,38 +1979,41 @@ 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 { - 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.bin_file.options.module) |module| { - const builtin_mod = module.main_mod.deps.get("builtin").?; - module.zig_cache_artifact_directory = builtin_mod.root.root_dir; - } -} - -fn cleanupTmpArtifactDirectory( +/// Only legal to call when cache mode is incremental and a link file is present. +pub fn hotCodeSwap( 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(); + 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 { + switch (comp.cache_use) { + .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. @@ -2325,96 +2021,100 @@ 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; 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.bin_file.options.cache_mode == .whole) { - // We are about to obtain this lock, so here we give other processes a chance first. - comp.bin_file.releaseLock(); + switch (comp.cache_use) { + .whole => |whole| { + 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(); - comp.whole_cache_manifest = &man; - try comp.addNonIncrementalStuffToCacheManifest(&man); + man = comp.cache_parent.obtain(); + whole.cache_manifest = &man; + try addNonIncrementalStuffToCacheManifest(comp, arena, &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.bin_file.options.root_name}); - const digest = man.final(); - - comp.wholeCacheModeSetBinFilePath(&digest); + const is_hit = man.hit() catch |err| { + 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 ""; + 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; + 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.bin_file.options.root_name}); + comp.wholeCacheModeSetBinFilePath(whole, &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(whole.lock == null); + whole.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(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(); + 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.bin_file.options.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 (whole.implib_sub_path) |sub_path| { + comp.implib_emit = .{ + .directory = tmp_artifact_directory, + .sub_path = std.fs.path.basename(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 (whole.bin_sub_path) |sub_path| { + const emit: Emit = .{ + .directory = tmp_artifact_directory, + .sub_path = std.fs.path.basename(sub_path), + }; + comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts); + } + }, + .incremental => {}, } // For compiling C objects, we rely on the cache hash system to avoid duplicating work. @@ -2433,13 +2133,13 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void } } - if (comp.bin_file.options.module) |module| { - module.compile_log_text.shrinkAndFree(module.gpa, 0); + if (comp.module) |module| { + module.compile_log_text.shrinkAndFree(gpa, 0); module.generation += 1; // 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 @@ -2448,22 +2148,21 @@ 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); } - 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); } // 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. @@ -2473,34 +2172,34 @@ 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 }); } - 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 }); } } 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, + 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); + module.intern_pool.dumpGenericInstances(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. @@ -2516,106 +2215,188 @@ 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(); - if (comp.whole_cache_manifest != null) { - const digest = man.final(); + switch (comp.cache_use) { + .whole => |whole| { + const digest = man.final(); - // Rename the temporary directory into place. - var directory = tmp_artifact_directory.?; - tmp_artifact_directory = null; + // 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| gpa.free(p); + whole.tmp_artifact_directory = null; + } else unreachable; - directory.handle.close(); - defer restorePrevZigCacheArtifactDirectory(comp, &directory); + 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 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; - } + // 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; + }; - try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); - comp.wholeCacheModeSetBinFilePath(&digest); + 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); - // Has to be after the `wholeCacheModeSetBinFilePath` above. - if (need_writable_dance) { - try comp.bin_file.makeWritable(); - } + // 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.?, + }; - // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest(). - if (comp.bin_file.options.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(); + // Has to be after the `wholeCacheModeSetBinFilePath` above. + if (need_writable_dance) { + try lf.makeWritable(); + } + } - const dir_path = try comp.local_cache_directory.join(comp.gpa, &.{o_sub_path}); - defer comp.gpa.free(dir_path); + try flush(comp, arena, main_progress_node); + if (comp.totalErrorCount() != 0) return; - 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; + if (comp.bin_file) |lf| { + lf.destroy(); + comp.bin_file = null; + } - // 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); + assert(whole.lock == null); + whole.lock = man.toOwnedLock(); + }, + .incremental => { + 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)}); +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(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, }; + } - assert(comp.bin_file.lock == null); - comp.bin_file.lock = man.toOwnedLock(); - } else { - try comp.flush(main_progress_node); + if (comp.module) |zcu| { + try link.File.C.flushEmitH(zcu); - if (comp.totalErrorCount() == 0) { - try maybeGenerateAutodocs(comp, main_progress_node); + 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); } } - // 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.bin_file.options.module) |module| { - for (module.import_table.values()) |file| { - file.unloadTree(comp.gpa); - file.unloadSource(comp.gpa); - } - } + if (comp.totalErrorCount() == 0) { + try maybeGenerateAutodocs(comp, prog_node); + } +} + +/// 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 { + var seen_eaccess = false; + while (true) { + 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 + 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 => 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; } } 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 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(); @@ -2629,46 +2410,31 @@ 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.options.module) |module| { - try link.File.C.flushEmitH(module); - } -} - /// 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.options.emit = .{ - .directory = comp.local_cache_directory, - .sub_path = sub_path, - }; } - 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.bin_file.options.implib_emit = .{ + comp.implib_emit = .{ .directory = comp.local_cache_directory, .sub_path = sub_path, }; } - 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.bin_file.options.docs_emit = .{ + comp.docs_emit = .{ .directory = comp.local_cache_directory, .sub_path = sub_path, }; @@ -2689,51 +2455,33 @@ 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; - const target = comp.getTarget(); - - 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.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); - { - 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); - 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.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.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); - man.hash.addOptional(comp.bin_file.options.want_structured_cfg); + } else { + cache_helpers.addModule(&man.hash, comp.root_mod); } - 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); @@ -2759,88 +2507,99 @@ 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.addListOfBytes(comp.clang_argv); + man.hash.addListOfBytes(comp.global_cc_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); - 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.options.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); - 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.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.libc_installation != null); - if (comp.bin_file.options.libc_installation) |libc_installation| { + 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; + 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); 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); - try link.hashAddSystemLibs(man, comp.bin_file.options.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.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); + 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.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); + man.hash.addOptional(opts.initial_memory); + man.hash.addOptional(opts.max_memory); + man.hash.addOptional(opts.global_base); // Mach-O specific stuff - man.hash.addListOfBytes(comp.bin_file.options.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); + 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(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); + 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 { - if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or + if (comp.config.output_mode != .Obj or comp.module != null or comp.c_object_table.count() == 0) { return; @@ -2877,6 +2636,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. @@ -2982,12 +2785,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 { @@ -3006,10 +2811,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.bin_file.options.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), @@ -3033,7 +2838,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; @@ -3041,7 +2846,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(); @@ -3057,23 +2862,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.bin_file.options.module) |module| { + if (comp.module) |module| { total += module.failed_exports.count(); total += module.failed_embed_files.count(); @@ -3116,16 +2921,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); - // Misc linker errors - total += self.bin_file.miscErrors().len; + total += comp.link_errors.items.len; // Compile log errors only count if there are no other errors. if (total == 0) { - if (self.bin_file.options.module) |module| { + if (comp.module) |module| { total += @intFromBool(module.compile_log_decls.count() != 0); } } @@ -3134,24 +2938,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(.{ @@ -3165,19 +2969,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.bin_file.options.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.*); @@ -3249,14 +3053,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, @@ -3270,7 +3074,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { })); } - for (self.bin_file.miscErrors()) |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), @@ -3283,7 +3087,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { } } - if (self.bin_file.options.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(); @@ -3309,9 +3113,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.bin_file.options.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); } @@ -3344,7 +3148,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; @@ -3354,7 +3158,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; @@ -3595,13 +3399,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.bin_file.options.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, }); } } @@ -3637,15 +3453,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; }; @@ -3679,7 +3495,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) { @@ -3717,14 +3533,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) { @@ -3783,13 +3599,13 @@ 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, }; 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. @@ -3801,9 +3617,10 @@ 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| { + 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, @@ -3818,7 +3635,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, @@ -3875,10 +3692,13 @@ 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(); - 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( @@ -3997,7 +3817,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 => { @@ -4065,19 +3885,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), }); }; } @@ -4100,7 +3918,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, .{}); @@ -4118,21 +3936,24 @@ 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(comp.bin_file.options.link_libcpp); + 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 // 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); } @@ -4152,7 +3973,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); } }; @@ -4160,19 +3981,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. @@ -4209,15 +4030,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; @@ -4265,10 +4086,13 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { 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(); @@ -4297,7 +4121,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { }; } - 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) { @@ -4423,7 +4247,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; @@ -4462,7 +4286,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; @@ -4482,7 +4306,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) { @@ -4505,7 +4329,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); @@ -4529,10 +4353,10 @@ 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 - comp.bin_file.options.output_mode == .Obj and comp.bin_file.options.objects.len == 0; + const direct_o = comp.c_source_files.len == 1 and comp.module == null and + 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]; @@ -4582,12 +4406,12 @@ 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); - 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"; @@ -4625,7 +4449,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); @@ -4720,10 +4544,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| { @@ -4973,7 +4802,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); @@ -5019,10 +4848,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| { @@ -5094,10 +4926,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 => {}, } } @@ -5151,11 +4986,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. @@ -5165,8 +5001,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 @@ -5187,19 +5024,19 @@ pub fn addCCArgs( try argv.append("-fno-caret-diagnostics"); } - if (comp.bin_file.options.function_sections) { + if (comp.function_sections) { try argv.append("-ffunction-sections"); } - if (comp.bin_file.options.data_sections) { + if (comp.data_sections) { try argv.append("-fdata-sections"); } - if (comp.bin_file.options.no_builtin) { + if (comp.no_builtin) { 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", }); @@ -5220,7 +5057,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"); } @@ -5235,7 +5072,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", }); @@ -5244,7 +5081,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, @@ -5269,7 +5106,7 @@ pub fn addCCArgs( "-nostdinc", "-fno-spell-checking", }); - if (comp.bin_file.options.lto) { + if (comp.config.lto) { try argv.append("-flto"); } @@ -5281,7 +5118,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 }); } @@ -5324,9 +5161,8 @@ 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)})); + if (mod.code_model != .default) { + try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)})); } switch (target.os.tag) { @@ -5375,7 +5211,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 @@ -5386,27 +5222,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", @@ -5417,7 +5253,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"); @@ -5447,11 +5283,11 @@ 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"); } - if (comp.unwind_tables) { + if (mod.unwind_tables) { try argv.append("-funwind-tables"); } else { try argv.append("-fno-unwind-tables"); @@ -5536,22 +5372,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.config.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| { @@ -5574,7 +5409,16 @@ pub fn addCCArgs( try argv.append("-ffreestanding"); } - try argv.appendSlice(comp.clang_argv); + 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(comp.global_cc_argv); + try argv.appendSlice(mod.cc_argv); } fn failCObj( @@ -5621,68 +5465,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; @@ -6064,7 +5846,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 { @@ -6285,21 +6067,21 @@ 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; } 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, }; - return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and - comp.bin_file.options.libc_installation == null and - comp.bin_file.options.target.ofmt != .c; + const ofmt = comp.root_mod.resolved_target.result.ofmt; + return comp.config.link_libc and is_exe_or_dyn_lib and + comp.libc_installation == null and ofmt != .c; } fn wantBuildGLibCFromSource(comp: Compilation) bool { @@ -6321,13 +6103,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 { @@ -6377,7 +6159,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() }); @@ -6430,7 +6212,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, @@ -6448,7 +6230,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, @@ -6456,222 +6238,8 @@ 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("};\n"); - - try buffer.writer().print( - \\pub const target = std.Target{{ - \\ .cpu = cpu, - \\ .os = os, - \\ .abi = abi, - \\ .ofmt = object_format, - \\}}; - \\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); + const target = comp.root_mod.resolved_target.result; + return target_util.zigBackend(target, comp.config.use_llvm); } pub fn updateSubCompilation( @@ -6718,60 +6286,83 @@ fn buildOutputFromZig( const tracy_trace = trace(@src()); defer tracy_trace.end(); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(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, - .fully_qualified_name = "root", - }; - 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, .{ - .root_name = root_name, - .target = target, - .output_mode = output_mode, - }); - defer comp.gpa.free(bin_basename); + const unwind_tables = comp.link_eh_frame_hdr; + const strip = comp.compilerRtStrip(); + const optimize_mode = comp.compilerRtOptMode(); - const emit_bin = Compilation.EmitLoc{ - .directory = null, // Put it in the cache directory. - .basename = bin_basename, - }; - const sub_compilation = try Compilation.create(comp.gpa, .{ - .global_cache_directory = comp.global_cache_directory, - .local_cache_directory = comp.global_cache_directory, - .zig_lib_directory = comp.zig_lib_directory, - .cache_mode = .whole, - .target = target, - .root_name = root_name, - .main_mod = &main_mod, + const config = try Config.resolve(.{ .output_mode = output_mode, - .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.libc_installation, - .emit_bin = emit_bin, - .optimize_mode = comp.compilerRtOptMode(), .link_mode = .Static, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .have_zcu = true, + .emit_bin = true, + .root_optimize_mode = optimize_mode, + .root_strip = strip, + .link_libc = comp.config.link_libc, + .any_unwind_tables = unwind_tables, + }); + + 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, + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .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 = optimize_mode, + .structured_cfg = comp.root_mod.structured_cfg, + }, + .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(); + const bin_basename = try std.zig.binNameAlloc(arena, .{ + .root_name = root_name, + .target = target, + .output_mode = output_mode, + }); + + 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, + .self_exe_path = comp.self_exe_path, + .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 = .{ + .directory = null, // Put it in the cache directory. + .basename = bin_basename, + }, .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, + .verbose_link = comp.verbose_link, .verbose_air = comp.verbose_air, .verbose_intern_pool = comp.verbose_intern_pool, .verbose_generic_instances = comp.verbose_intern_pool, @@ -6781,20 +6372,13 @@ 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(); try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); 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, - }), - .lock = sub_compilation.bin_file.toOwnedLock(), - }; + out.* = try sub_compilation.toCrtFile(); } pub fn build_crt_file( @@ -6803,56 +6387,89 @@ 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, + /// 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(); - const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(comp.gpa, .{ + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + 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); - 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, - .cache_mode = .whole, - .target = target, - .root_name = root_name, - .main_mod = null, + const config = try Config.resolve(.{ .output_mode = output_mode, - .thread_pool = comp.thread_pool, - .libc_installation = comp.bin_file.options.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, + .resolved_target = comp.root_mod.resolved_target, + .is_test = false, + .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, .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, + }); + 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 = "", + }, + .fully_qualified_name = "root", + .inherited = .{ + .resolved_target = comp.root_mod.resolved_target, + .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 = &.{}, + .parent = null, + .builtin_mod = null, + }); + + for (c_source_files) |*item| { + item.owner = root_mod; + } + + 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, .self_exe_path = comp.self_exe_path, + .cache_mode = .whole, + .config = config, + .root_mod = root_mod, + .root_name = root_name, + .thread_pool = comp.thread_pool, + .libc_installation = comp.libc_installation, + .emit_bin = .{ + .directory = null, // Put it in the cache directory. + .basename = basename, + }, + .emit_h = null, .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, @@ -6862,21 +6479,22 @@ 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(); 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, try sub_compilation.toCrtFile()); +} - 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, +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 { @@ -6884,21 +6502,24 @@ 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 // 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); - if (!gop.found_existing and comp.getTarget().os.tag == .windows) { + const gop = try comp.system_libs.getOrPut(comp.gpa, lib_name); + if (!gop.found_existing) { gop.value_ptr.* = .{ .needed = true, .weak = false, .path = null, }; - try comp.work_queue.writeItem(.{ - .windows_import_lib = comp.bin_file.options.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, + }); + } } } @@ -6906,10 +6527,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, } @@ -6918,5 +6540,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/Compilation/Config.zig b/src/Compilation/Config.zig new file mode 100644 index 0000000000000000000000000000000000000000..78273f66e42ea8d8b9a4df21a96d8ba7651a7686 --- /dev/null +++ b/src/Compilation/Config.zig @@ -0,0 +1,512 @@ +//! 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, +link_mode: std.builtin.LinkMode, +link_libc: bool, +link_libcpp: bool, +link_libunwind: 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 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, +/// 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, +debug_format: DebugFormat, +root_strip: bool, +root_error_tracing: bool, +dll_export_fns: bool, +rdynamic: bool, + +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, + is_test: bool, + have_zcu: bool, + 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, + any_non_single_threaded: bool = false, + any_sanitize_thread: bool = false, + any_unwind_tables: bool = false, + 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, + 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, + /// 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, + debug_format: ?DebugFormat = null, + dll_export_fns: ?bool = null, + rdynamic: ?bool = null, +}; + +pub const ResolveError = error{ + WasiExecModelRequiresWasi, + SharedMemoryIsWasmOnly, + ObjectFilesCannotShareMemory, + SharedMemoryRequiresAtomicsAndBulkMemory, + ThreadsRequireSharedMemory, + EmittingLlvmModuleRequiresLlvmBackend, + LlvmLacksTargetSupport, + ZigLacksTargetSupport, + EmittingBinaryRequiresLlvmLibrary, + LldIncompatibleObjectFormat, + LtoRequiresLld, + SanitizeThreadRequiresLibCpp, + LibCppRequiresLibUnwind, + OsRequiresLibC, + LibCppRequiresLibC, + LibUnwindRequiresLibC, + TargetCannotDynamicLink, + LibCRequiresDynamicLinking, + SharedLibrariesRequireDynamicLinking, + ExportMemoryAndDynamicIncompatible, + DynamicLibraryPrecludesPie, + TargetRequiresPie, + SanitizeThreadRequiresPie, + BackendLacksErrorTracing, + LlvmLibraryUnavailable, + LldUnavailable, + ClangUnavailable, + DllExportFnsRequiresWindows, +}; + +pub fn resolve(options: Options) ResolveError!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; + }; + + // *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 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) + return error.EmittingLlvmModuleRequiresLlvmBackend; + if (!target_util.hasLlvmSupport(target, target.ofmt)) + return error.LlvmLacksTargetSupport; + + 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 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 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 and options.emit_bin) 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 (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. + 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_util.hasLldSupport(target.ofmt)) { + if (options.use_lld == true) return error.LldIncompatibleObjectFormat; + break :b false; + } + + if (!build_options.have_llvm) { + if (options.use_lld == true) return error.LldUnavailable; + 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.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. + // 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 (options.output_mode == .Obj); + 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; + }; + + 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, + }; + }; + + 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, + }; + }; + + 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; + + 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) { + .Obj, .Exe => false, + .Lib => link_mode == .Dynamic, + }; + }; + + 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, + .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, + .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, + .wasi_exec_model = wasi_exec_model, + .debug_format = debug_format, + .root_strip = root_strip, + .dll_export_fns = dll_export_fns, + .rdynamic = rdynamic, + }; +} + +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 6e5609f63c02d5909c80d44f0a022ce45aa24e33..9d3810f671e5cb5af16a7981e4cd0726a0ae78bd 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; @@ -35,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); @@ -51,14 +54,17 @@ 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, -/// 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 /// `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. @@ -153,8 +159,6 @@ stage1_flags: packed struct { reserved: u2 = 0, } = .{}, -job_queued_update_builtin_zig: bool = true, - compile_log_text: ArrayListUnmanaged(u8) = .{}, emit_h: ?*GlobalEmitH, @@ -622,7 +626,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.result.cpu.arch; + if (cpu_arch.isNvptx()) { for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) { '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_', else => {}, @@ -949,15 +954,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); @@ -1019,8 +1030,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 { @@ -2469,108 +2481,111 @@ 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; - for (mod.import_table.keys()) |key| { + if (zcu.llvm_object) |llvm_object| { + if (build_options.only_c) unreachable; + llvm_object.deinit(); + } + + 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.zig_cache_artifact_directory.handle.close(); - 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); } 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| { + 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 { @@ -2632,6 +2647,8 @@ comptime { } pub fn astGenFile(mod: *Module, file: *File) !void { + assert(!file.mod.isBuiltin()); + const tracy = trace(@src()); defer tracy.end(); @@ -3076,72 +3093,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, @@ -3228,6 +3179,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); @@ -3280,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, @@ -3311,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 @@ -3331,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.options.emit == 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)}); } @@ -3365,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)}, ), @@ -3381,27 +3330,32 @@ 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) { - 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; + }, + }; + } }, } } @@ -3477,6 +3431,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 @@ -3558,25 +3515,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 => {}, } } @@ -3588,6 +3549,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; @@ -3597,20 +3559,18 @@ 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.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; 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 }, @@ -3624,6 +3584,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]; } @@ -3719,7 +3680,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; @@ -3863,25 +3823,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, @@ -3889,7 +3848,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); @@ -3907,10 +3877,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, @@ -3924,10 +3894,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); @@ -4118,12 +4085,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 = .{ @@ -4312,14 +4283,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) { @@ -4331,6 +4302,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; @@ -4373,14 +4347,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 }); } } @@ -4466,7 +4435,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); } @@ -4628,7 +4599,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.any_error_tracing and !sema.fn_ret_ty.isError(mod)) { sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) { @@ -4721,25 +4692,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); } @@ -4875,12 +4827,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 { @@ -5288,43 +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; } } - mod.comp.bin_file.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); }, }; } @@ -5335,7 +5307,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.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); @@ -5467,39 +5439,39 @@ 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; - const no_bin_file = (comp.bin_file.options.emit == 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); - - 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.bin_file) |lf| { + 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; + }, + else => { + 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(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.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; + }, + }; + } } fn reportRetryableFileError( @@ -5592,10 +5564,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; @@ -5622,21 +5590,11 @@ pub const Feature = enum { safety_checked_instructions, }; -pub fn backendSupportsFeature(mod: Module, feature: Feature) bool { - 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, - }; +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 target_util.backendSupportsFeature(cpu_arch, ofmt, use_llvm, feature); } /// Shortcut for calling `intern_pool.get`. diff --git a/src/Package.zig b/src/Package.zig index ab06ca9852087cf08f2b533db4755f48d6ac92d2..da2e214154b44cf2864ad1fcb073ed42846e93dd 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; }; @@ -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 0c8d40bffa65fd406282769d18044e6024515a45..66d5a21eab7d7573dfe355dd90981fdb48ff41e5 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,17 +14,465 @@ 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, +/// (SPIR-V) whether to generate a structured control flow graph or not +structured_cfg: bool, + +/// 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.builtin_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), }; -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, + structured_cfg: ?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 { + 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; + + 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; + break :b options.global.root_strip; + }; + + 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; + break :b options.global.root_error_tracing; + }; + + 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 false; + } + 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: { + 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; + } + 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 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; + + 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 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, + .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 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); + 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, + .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; + }; + + if (opt_builtin_mod) |builtin_mod| { + 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, + .structured_cfg = undefined, + .builtin_file = null, + }; + 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()); + return result; } const Module = @This(); @@ -32,3 +480,9 @@ 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"); +const File = @import("../Module.zig").File; diff --git a/src/Sema.zig b/src/Sema.zig index e9af6d17404ca1cde042646168f91542fb04d048..0c464a0bc105fd8c5ac219f273d44b09e0fb820f 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, @@ -1324,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; }, @@ -1825,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. @@ -2040,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(); @@ -5733,7 +5739,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); @@ -5742,7 +5748,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); @@ -5754,14 +5760,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, .{ + .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)}); @@ -6267,7 +6298,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; @@ -6292,8 +6323,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, @@ -6301,8 +6332,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, @@ -6316,7 +6347,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); @@ -6513,8 +6544,7 @@ 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 (!mod.comp.bin_file.options.error_return_tracing) return .none; + if (!block.ownerModule().error_tracing) return .none; if (block.is_comptime) return .none; @@ -6698,7 +6728,7 @@ fn zirCall( input_is_error = false; } - if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_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); @@ -7451,7 +7481,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)]) { @@ -7489,7 +7519,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, @@ -8062,15 +8092,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; @@ -9058,7 +9086,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`). @@ -9075,8 +9103,8 @@ 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 (!comp.bin_file.options.link_libc) { + if (target.is_libc_lib_name(lib_name)) { + if (!comp.config.link_libc) { return sema.fail( block, src_loc, @@ -9086,22 +9114,25 @@ fn handleExternLibName( } break :blk; } - if (target_util.is_libcpp_lib_name(target, 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 (target.is_libcpp_lib_name(lib_name)) { + 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) { + if (!target.isWasm() and !block.ownerModule().pic) { return sema.fail( block, src_loc, @@ -18728,18 +18759,14 @@ 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.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; - 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; @@ -18764,9 +18791,8 @@ 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 (!mod.comp.bin_file.options.error_return_tracing) return; + if (!start_block.ownerModule().error_tracing) return; const tracy = trace(@src()); defer tracy.end(); @@ -20037,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 - mod.comp.bin_file.options.error_return_tracing and - mod.backendSupportsFeature(.error_return_trace)) + block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); } @@ -34520,7 +34545,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"); } @@ -36692,7 +36719,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/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 9ad7b0bbaa07884c4f1b9e99aecfe3086bd4f44b..ee5e58ae05e95530dd46698817dc8feb3660cf23 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.options.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.resolved_target.result; - 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, @@ -476,7 +475,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 +655,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 +1027,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 +1047,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 +1138,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 +1175,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 +1256,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 +1319,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 +1414,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 +1904,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 +1965,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 +1997,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 +2013,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 +2047,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 +2080,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 +2116,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 +2187,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 +2205,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 +2240,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 +2275,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 +2325,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 +2365,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 +2392,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 +2515,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 +2643,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 +2867,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 +3015,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 +3059,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 +3139,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 +3251,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 +3296,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 +3322,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 +3425,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 +3449,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 +3491,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 +3614,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 +3862,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 +3893,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 +3916,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 +3938,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 +4091,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 +4116,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 +4166,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 +4194,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 +4249,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 +4421,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 +4453,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 +4513,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 +4621,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 +4829,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 +4885,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 +4927,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 +4954,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 +4981,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 +5008,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 +5225,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 +5402,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 +5572,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 +5734,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 +5933,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 +6053,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 +6097,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 +6134,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 +6199,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; @@ -6333,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, @@ -6344,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; } @@ -6363,7 +6362,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 +6391,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/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 9ba722f393688ea5989998908a2bc09d7e0e8a13..3f629fd46f3ee1cf93f517d83831c62893693770 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 ef3ee3871b98b5843c68b004774626cad440f673..7227347e1b9ec4502774d65251627042e55bad5b 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, @@ -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.options.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.resolved_target.result; - 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, @@ -482,7 +481,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 +641,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 +1009,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 +1030,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 +1117,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 +1150,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 +1216,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 +1280,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 +1376,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 +1585,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 +1698,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 +1862,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 +2018,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 +2041,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 +2118,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 +2228,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 +2252,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 +2369,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 +2428,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 +2471,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 +2527,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 +2661,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 +2738,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 +2767,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 +2887,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 +2911,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 +3001,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 +3395,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 +3451,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 +3484,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 +3500,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 +3543,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 +3591,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 +3608,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 +3677,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 +3695,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 +3733,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 +3778,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 +3817,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 +3860,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 +3894,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 +3931,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 +3966,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 +4173,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 +4228,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 +4379,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 +4411,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 +4472,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 +4579,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 +4794,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 +4828,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 +4855,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 +4875,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 +4917,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 +4944,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 +5159,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 +5330,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 +5492,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 +5739,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 +5895,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 +6014,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 +6065,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 +6096,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 +6124,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 +6160,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; @@ -6282,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, @@ -6293,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; } @@ -6312,11 +6313,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/arm/Emit.zig b/src/arch/arm/Emit.zig index 45c3392918d5a62123a93b7fa09112654117859d..2ab3b60ee6f61e30f14080ce3130214289e5510d 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 c217288e63ebe7cc177a1871880988c102c158c1..7d3b0cd1a0acf095ce2b407248d398be493431e2 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.options.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.resolved_target.result; - 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, @@ -350,7 +349,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 +473,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 +804,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 +815,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 +892,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 +1068,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 +1331,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 +1505,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 +1531,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 +1632,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 +1709,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 +1811,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 +1842,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 +1886,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 +2124,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 +2507,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 +2552,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 +2580,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 +2616,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; @@ -2709,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, @@ -2720,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; } @@ -2739,11 +2738,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/Emit.zig b/src/arch/riscv64/Emit.zig index 9d82cc38cc5dd54d80e71a8c0a9beb4c73ef0279..f382f6f9ebf548f091121e7b8f20345af17d6683 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 79dd6ec8d8dca276247edcb7b28271c456429c0b..e7db3be8b0201f8628406b57957db6222d828db8 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.options.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.resolved_target.result; - 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, @@ -364,7 +363,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 +491,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 +761,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 +839,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 +873,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 +1010,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 +1205,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 +1297,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 +1429,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 +1661,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 +1757,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 +1818,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 +1902,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 +2044,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 +2108,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 +2340,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 +2445,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 +2570,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 +2703,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 +2717,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 +2731,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 +2752,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 +2792,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 +2812,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 +2859,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 +3400,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 +3520,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)) { @@ -3547,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; } @@ -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); @@ -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, @@ -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/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig index 4701035bc922d4a842d3f82030574dff60105d16..b2f2e6f79d081f0f8bc55f15de98fc2eb72b4fe0 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 a9028768f7146e8328f296543223fcb4aa42116f..da33ae521d494b9de6d9cfd37b5d2acc1389e3aa 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; @@ -1210,18 +1210,23 @@ pub fn generate( debug_output: codegen.DebugInfoOutput, ) codegen.CodeGenError!codegen.Result { _ = src_loc; - const mod = bin_file.options.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.resolved_target.result; var code_gen: CodeGen = .{ - .gpa = bin_file.allocator, + .gpa = gpa, .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, @@ -1237,7 +1242,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 +1353,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 +1422,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 +1521,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 +1547,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 +2077,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 +2098,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 +2141,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 +2161,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 +2188,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 +2300,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 +2354,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 +2433,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 +2461,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 +2504,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 +2541,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 +2560,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 +2587,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 +2624,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 +2638,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 +2657,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 +2793,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 +2878,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 +2984,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 +3035,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 +3074,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 +3137,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 +3149,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 +3177,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 +3230,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 +3399,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 +3441,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 +3477,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 +3598,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 +3716,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 +3725,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 +3752,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 +3823,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 +3839,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 +3857,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 +3869,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 +3888,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 +3919,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 +4018,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 +4198,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 +4233,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 +4261,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 +4285,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 +4315,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 +4347,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 +4370,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 +4438,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 +4452,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 +4480,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 +4503,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 +4520,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 +4548,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 +4605,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 +4635,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 +4688,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 +4712,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 +4735,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 +4750,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 +4787,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 +4817,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 +4845,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 +4878,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 +4967,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 +5036,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 +5081,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 +5127,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 +5206,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 +5275,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 +5405,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 +5504,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 +5540,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 +5582,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 +5606,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 +5711,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 +5737,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 +5758,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 +5767,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 +5807,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 +5868,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 +5908,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 +5980,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 +6045,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 +6108,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 +6278,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 +6322,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 +6356,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 +6409,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 +6476,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 +6522,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 +6540,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 +6589,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 +6660,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 +6675,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 +6698,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 +6811,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 +6841,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 +6888,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 +6924,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 +6972,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 +7039,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 +7160,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 +7213,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 +7369,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 +7454,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 +7527,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 +7554,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; @@ -7724,10 +7729,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(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); } @@ -7735,7 +7743,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 +7782,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 d1b7114b1255896e05e4d17a2aa800af9366554f..7e67a9828582c329533e596762998065c05247fa 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.options.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,10 @@ 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 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)); var buf: [5]u8 = undefined; @@ -422,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 0a4c9844dcca92e98c131472919dbfd8fc281acd..55e241cbd4c36b0ed2c61a59f61d837179f8b3d6 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 { @@ -131,7 +134,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); @@ -795,22 +798,22 @@ 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.options.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const comp = bin_file.comp; + const gpa = comp.gpa; + 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 = zcu.namespacePtr(fn_owner_decl.src_namespace); + const mod = namespace.file_scope.mod; - const gpa = bin_file.allocator; var function = Self{ .gpa = gpa, .air = air, .liveness = liveness, - .target = &bin_file.options.target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .func_index = func_index }, @@ -841,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( @@ -856,13 +859,13 @@ 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.? }, 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.", .{}, @@ -875,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(bin_file.options.target.stackAlignment()), + Alignment.fromNonzeroByteUnits(function.target.stackAlignment()), ), })); function.frame_allocs.set( @@ -906,25 +909,28 @@ 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, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -942,7 +948,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}, @@ -966,12 +972,16 @@ pub fn generateLazy( code: *std.ArrayList(u8), debug_output: DebugInfoOutput, ) CodeGenError!Result { - const gpa = bin_file.allocator; + const comp = bin_file.comp; + const gpa = comp.gpa; + // 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 = &bin_file.options.target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .lazy_sym = lazy_sym }, @@ -993,25 +1003,28 @@ 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, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -1029,7 +1042,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}, @@ -1060,7 +1073,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 +1090,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, ); @@ -1096,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, @@ -1106,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) { @@ -1683,7 +1701,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 +1903,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 +2185,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 +2436,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 +2456,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 +2489,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 +2902,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 +2993,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 +3120,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 +3149,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 +3190,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 +3224,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 +3450,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 +3533,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 +3609,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 +3749,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 +3810,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 +3889,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 +3953,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 +4187,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 +4237,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 +4289,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 +4564,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 +4610,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 +4644,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 +4696,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 +4743,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 +4803,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 +4851,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 +4885,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 +4939,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 +4962,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 +5021,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 +5089,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 +5125,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 +5150,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 +5264,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 +5314,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 +5359,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 +5403,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 +5457,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 +5616,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 +5734,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 +5797,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 +5889,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 +5980,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 +6002,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 +6124,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 +6300,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 +6332,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 +6356,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 +6398,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 +6538,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 +6783,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 +6882,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 +6923,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 +6980,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 +7077,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 +7118,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 +7156,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 +7181,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 +7469,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 +7488,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 +7576,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 +7623,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 +7993,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 +8059,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 +8301,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 +10033,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 +10453,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 +10578,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 +10611,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 +10647,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 +10766,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: { @@ -10901,7 +10919,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; @@ -10969,7 +10987,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 +11036,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 +11430,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 +11569,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 +11642,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 +11750,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 +11786,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 +11833,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 +12115,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 +12176,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 +12883,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 +13182,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 +13280,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 +13579,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)) }, @@ -13814,7 +13832,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 }, @@ -13922,7 +13940,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 +13998,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 +14021,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 +14100,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 +14171,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 +14267,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 +14671,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 +14799,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 +14854,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 +14896,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 +14998,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 +15350,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 +15407,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 +15580,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 +15631,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 +15798,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 +15851,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 +16060,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. @@ -16057,7 +16075,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}); @@ -16116,7 +16134,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 +16174,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); @@ -16413,14 +16431,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; } @@ -16468,7 +16488,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 +16496,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 +16525,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 +16570,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 +16589,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 +16604,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 +16661,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/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index b3a5316104fbcdecf6228d02c64d4d06d7a38b99..e8668e82f4a7bddab09e42842b328b72797800e5 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 0c309991f6b07bf35acd8b13d01af865aba5f3dd..cc5ae7712bb17b890c3d83fb486264b05e069817 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/codegen.zig b/src/codegen.zig index b464a9f36535512ddff67aec35047330149c70b7..1ac8626a79597b06facf47e88e984d35becd9b5b 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.resolved_target.result; + 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.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, } } @@ -107,13 +117,15 @@ pub fn generateLazySymbol( const tracy = trace(@src()); defer tracy.end(); - const target = bin_file.options.target; + const comp = bin_file.comp; + const zcu = comp.module.?; + const target = comp.root_mod.resolved_target.result; const endian = target.cpu.arch.endian(); + const gpa = comp.gpa; - const mod = bin_file.options.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 +133,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,20 +149,20 @@ 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); } 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(mod) }, + .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(zcu) }, ) }; } @@ -165,7 +177,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 +674,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) { @@ -757,7 +769,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 +777,27 @@ fn lowerAnonDeclRef( reloc_info: RelocInfo, ) CodeGenError!Result { _ = debug_output; - const target = bin_file.options.target; - const mod = bin_file.options.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 +814,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 +823,21 @@ fn lowerDeclRef( ) CodeGenError!Result { _ = src_loc; _ = debug_output; - const target = bin_file.options.target; - const mod = bin_file.options.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.resolved_target.result; 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 +910,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.options.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.resolved_target.result; - 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, @@ -928,29 +943,34 @@ 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(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 is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded; - const is_extern = decl.isExtern(mod); + 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); - 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); @@ -963,12 +983,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(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 }); } @@ -978,110 +998,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(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); 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(gpa, 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.options.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.options.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.resolved_target.result; 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 }); } @@ -1090,45 +1118,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), } } @@ -1146,7 +1174,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/codegen/llvm.zig b/src/codegen/llvm.zig index 70eab9489cc4acab8fe534850de012fde5ffa891..91c4faffcc276c2624cda653502fd5efc5333658 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"); @@ -821,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 @@ -849,27 +850,25 @@ 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); - 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, comp: *Compilation) !*Object { + if (build_options.only_c) unreachable; + 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(); @@ -877,10 +876,11 @@ 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: { + switch (comp.config.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); @@ -898,26 +898,29 @@ 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: { - var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; - if (options.module) |mod| m: { - const d = try mod.root_mod.root.joinStringZ(builder.gpa, ""); + 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; - const abs = std.fs.realpath(d, &buf) catch break :blk d; - builder.gpa.free(d); - break :blk try builder.gpa.dupeZ(u8, abs); + const realpath = std.fs.realpathAlloc(arena, d) catch break :blk d; + break :blk try arena.dupeZ(u8, realpath); } - const cwd = try std.process.getCwd(&buf); - break :blk try builder.gpa.dupeZ(u8, cwd); + const cwd = try std.process.getCwdAlloc(arena); + break :blk try arena.dupeZ(u8, cwd); }; - defer builder.gpa.free(compile_unit_dir_z); 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 @@ -926,19 +929,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, @@ -953,15 +956,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, + comp.function_sections, + comp.data_sections, 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(); @@ -970,15 +973,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); @@ -989,16 +992,17 @@ pub const Object = struct { } } - return .{ + const obj = try arena.create(Object); + 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 = .{}, @@ -1009,9 +1013,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,22 +1034,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, - 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; @@ -1182,12 +1172,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, + asm_path: ?[*: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(); @@ -1213,7 +1213,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 { @@ -1221,91 +1221,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.bin_file.options.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; @@ -1314,17 +1295,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, @@ -1359,7 +1342,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 = .{ @@ -1369,7 +1352,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"), @@ -1392,20 +1375,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.bin_file.options.error_return_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); @@ -1433,8 +1418,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); @@ -1450,12 +1435,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, "")); @@ -1465,12 +1450,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, "")); @@ -1483,11 +1468,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, "")); @@ -1495,14 +1480,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) { @@ -1511,7 +1496,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; @@ -1528,7 +1513,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| { @@ -1540,7 +1525,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 @@ -1558,11 +1543,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, "")); @@ -1573,11 +1558,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, "")); @@ -1592,11 +1577,11 @@ pub const Object = struct { var di_scope: ?if (build_options.have_llvm) *llvm.DIScope else noreturn = null; 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 - !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 @@ -1613,7 +1598,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()); @@ -1634,7 +1619,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 (owner_mod.single_threaded) .singlethread else .system, .di_scope = di_scope, .di_file = di_file, .base_line = dg.decl.src_line, @@ -1648,7 +1633,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; }, @@ -1657,7 +1642,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 { @@ -1695,6 +1680,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); @@ -1719,7 +1705,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 (mod.wantDllExports()) 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)) { @@ -1785,11 +1772,14 @@ 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 (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); + 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, @@ -1842,7 +1832,9 @@ 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); + 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, @@ -2821,7 +2813,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)); @@ -2899,7 +2891,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"); @@ -2934,22 +2926,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; @@ -2957,7 +2951,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); @@ -2967,7 +2961,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), @@ -2988,8 +2982,8 @@ pub const Object = struct { llvm_arg_i += 1; } - const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(mod) and - mod.comp.bin_file.options.error_return_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); @@ -3010,7 +3004,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); @@ -3023,14 +3017,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), @@ -3056,13 +3050,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"), @@ -3074,12 +3069,10 @@ 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.bin_file.options.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 @@ -3087,26 +3080,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, @@ -3176,7 +3170,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.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, &o.builder, @@ -3679,7 +3674,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)); @@ -4648,6 +4643,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 { @@ -4656,6 +4745,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); @@ -5144,7 +5240,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); @@ -5616,7 +5712,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, @@ -6549,11 +6645,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(); @@ -6564,18 +6662,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, @@ -6583,7 +6681,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 ); @@ -6678,11 +6776,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); @@ -8731,9 +8830,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); @@ -8823,7 +8923,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; @@ -9139,7 +9240,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; @@ -9490,24 +9592,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); @@ -9526,7 +9629,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); } @@ -9546,7 +9649,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, @@ -9558,100 +9661,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/codegen/spirv.zig b/src/codegen/spirv.zig index fb1f2bb827bd2cc3fad970a9e4009c15d6baf908..6b2587e3cb879d3d8c5f7ec98946aa2cdccb3e3c 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/glibc.zig b/src/glibc.zig index d719dab491f950f92c732141036687338fd8111a..00d76f32fb0d2cd0b5e15ca1592f51b23aa0d49a 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, @@ -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; } @@ -1061,40 +1067,70 @@ 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 map_file_path = try path.join(arena, &.{ bin_directory.path.?, all_map_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 c_source_files = [1]Compilation.CSourceFile{ .{ - .src_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, asm_file_basename }), + .src_path = try path.join(arena, &.{ bin_directory.path.?, asm_file_basename }), + .owner = root_mod, }, }; - 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, - .cache_mode = .whole, - .target = comp.getTarget(), - .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, + .self_exe_path = comp.self_exe_path, + .cache_mode = .incremental, + .config = config, + .root_mod = root_mod, + .root_name = lib.name, + .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/libc_installation.zig b/src/libc_installation.zig index 48b505d9359b519854dabc362c12e164f0778166..0901194dd83ac1d16f25c0e8ac7c63f7438690af 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, ) !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/libcxx.zig b/src/libcxx.zig index 19c1d25b8c7828ff1235f80c1ad2f10377e2557d..8e28c2174d4a5d92f1a79132c5dbe6301893a900 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, @@ -137,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| { @@ -154,7 +199,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; } @@ -223,49 +268,32 @@ 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 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, + .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(); @@ -273,12 +301,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.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.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 { @@ -296,7 +319,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, @@ -318,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| { @@ -332,7 +402,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; } @@ -365,7 +435,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 @@ -386,49 +455,32 @@ 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 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, + .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(); @@ -436,10 +488,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.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.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 2489eb21afd30792d55906234426d91a7762ad0b..14a7db088873c092c5dedf96a5175b6f8771b926 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) { @@ -33,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); @@ -49,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, }); } @@ -73,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, }); } { @@ -93,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, }); } @@ -116,10 +166,11 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void { "tsan", "sanitizer_common", common_src, }), .extra_flags = cflags.items, + .owner = root_mod, }); } - 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; @@ -140,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, }); } @@ -160,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, }); } @@ -188,63 +241,40 @@ 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 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, - .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, + .self_exe_path = comp.self_exe_path, + .cache_mode = .whole, + .config = config, + .root_mod = root_mod, + .root_name = root_name, + .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(); 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.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.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 f0330a4e5157ce8617265e7909817d34eccff793..5f0613c3619a6a4657e257d8a04844e5c5bb1654 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,49 @@ 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(), + .root_strip = comp.compilerRtStrip(), + .link_libc = true, + // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 + .lto = 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 = 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 = &.{}, + .parent = null, + .builtin_mod = null, + }); + + 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,10 +104,10 @@ 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.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) { @@ -80,49 +120,32 @@ 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, .{ + 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, .zig_lib_directory = comp.zig_lib_directory, + .config = 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.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(); @@ -130,13 +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 = 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, - }), - .lock = sub_compilation.bin_file.toOwnedLock(), - }; + comp.libunwind_static_lib = try sub_compilation.toCrtFile(); } const unwind_src_list = [_][]const u8{ diff --git a/src/link.zig b/src/link.zig index 12b9c58d9bb1e7f58ef1653f66a62234d0360860..5c296b49abb5f05c2f82d6cbc4b2e1835052367f 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; @@ -19,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 @@ -33,17 +33,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 }; - pub fn hashAddSystemLibs( man: *Cache.Manifest, hm: std.StringArrayHashMapUnmanaged(SystemLib), @@ -57,355 +46,172 @@ 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 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, - 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 - /// 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: 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, + zcu_object_sub_path: ?[]const u8 = null, + disable_lld_caching: bool, + gc_sections: bool, + print_gc_sections: bool, + build_id: std.zig.BuildId, + rpath_list: []const []const u8, + allow_shlib_undefined: bool, + stack_size: u64, /// 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 { + 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, + image_base: ?u64, + emit_relocs: 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, + compress_debug_sections: Elf.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, + each_lib_rpath: bool, + build_id: std.zig.BuildId, + disable_lld_caching: bool, + hash_style: Elf.HashStyle, + sort_section: ?Elf.SortSection, + major_subsystem_version: ?u16, + minor_subsystem_version: ?u16, + 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, + print_icf_sections: bool, + print_map: bool, + + /// 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, + + // 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, + frameworks: []const MachO.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, + + pub const Entry = union(enum) { + default, + disabled, + enabled, + named: []const u8, + }; + }; + /// 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; + /// `arena` is used for allocations with the same lifetime as the created File. + pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: OpenOptions, + ) !*File { + 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; + }, } + } - 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, - }; + pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: OpenOptions, + ) !*File { + 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; + }, } - 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; - } - - return file; } pub fn cast(base: *File, comptime T: type) ?*T { @@ -416,11 +222,13 @@ 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; 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| { @@ -431,9 +239,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) { @@ -448,10 +257,13 @@ pub const File = struct { } } } + 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, - .mode = determineMode(base.options), + .mode = determineMode(use_lld, output_mode, link_mode), }); }, .c, .spirv, .nvptx => {}, @@ -459,9 +271,14 @@ pub const File = struct { } pub fn makeExecutable(base: *File) !void { - switch (base.options.output_mode) { + 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, - .Lib => switch (base.options.link_mode) { + .Lib => switch (link_mode) { .Static => return, .Dynamic => {}, }, @@ -470,8 +287,7 @@ 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) { + 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; @@ -490,7 +306,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; @@ -555,16 +371,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); + }, } } @@ -577,16 +389,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); + }, } } @@ -594,59 +403,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); + }, } } @@ -666,56 +464,12 @@ 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 => { + .c => @fieldParentPtr(C, "base", base).deinit(), + + inline else => |tag| { 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); + @fieldParentPtr(tag.Type(), "base", base).deinit(); }, } } @@ -793,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 emit = base.options.emit orelse return; // -fno-emit-bin + 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; @@ -813,75 +570,43 @@ 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) { - return base.linkAsArchive(comp, prog_node); + 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(arena, 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(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 { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); - } + pub fn flushModule(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { 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(arena, prog_node); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).flushModule(arena, 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), - } - } - - 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 &.{}, + .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); + }, } } @@ -900,19 +625,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); + }, } } @@ -929,150 +649,91 @@ 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; - 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 => {}, - } - } - - /// 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( + pub fn deleteDeclExport( base: *File, - cache_directory: Compilation.Directory, - tmp_dir_sub_path: []const u8, - o_sub_path: []const u8, + decl_index: InternPool.DeclIndex, + name: InternPool.NullTerminatedString, ) !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; - } + if (build_options.only_c) @compileError("unreachable"); + switch (base.tag) { + .plan9, + .c, + .spirv, + .nvptx, + => {}, + + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).deleteDeclExport(decl_index, name); + }, } } - pub fn linkAsArchive(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { - const emit = base.options.emit orelse return; - + pub fn linkAsArchive(base: *File, arena: Allocator, prog_node: *std.Progress.Node) FlushError!void { const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); + const comp = base.comp; + const gpa = comp.gpa; - 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 = 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: { - try base.flushModule(comp, prog_node); + const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { + 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.intermediary_basename.? }); + break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? }); } 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 (comp.include_compiler_rt) comp.compiler_rt_obj.?.full_object_path else null; @@ -1084,17 +745,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 = 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); @@ -1107,7 +770,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. @@ -1137,11 +800,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; - var object_files = try std.ArrayList([*:0]const u8).initCapacity(base.allocator, num_object_files); + 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(gpa, 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| { @@ -1152,14 +815,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}); @@ -1170,12 +833,13 @@ 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; - 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)}); }; @@ -1199,6 +863,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 { @@ -1237,6 +930,73 @@ 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 fn isStatic(self: File) bool { + return self.comp.config.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 fn emitLlvmObject( + base: File, + arena: Allocator, + llvm_object: *LlvmObject, + prog_node: *std.Progress.Node, + ) !void { + 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"); pub const Coff = @import("link/Coff.zig"); pub const Plan9 = @import("link/Plan9.zig"); @@ -1247,19 +1007,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/C.zig b/src/link/C.zig index 85d13bf7ec4c1599cf6a15331ce989696f05cf81..68facb374b2730a4475d75a35ed4143309171c5e 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; @@ -83,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), @@ -91,28 +93,55 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { }; } -pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C { - assert(options.target.ofmt == .c); +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*C { + return createEmpty(arena, comp, emit, options); +} - if (options.use_llvm) return error.LLVMHasNoCBackend; - if (options.use_lld) return error.LLDHasNoCBackend; +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); + 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; - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + // These are caught by `Compilation.Config.resolve`. + assert(!use_lld); + assert(!use_llvm); + + 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(); - 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 = 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, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, }, }; @@ -120,7 +149,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 +170,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 +184,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 +252,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 +314,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) { @@ -347,12 +376,13 @@ 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) { - 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) { @@ -363,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(); @@ -371,8 +403,9 @@ 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 module = self.base.options.module.?; + const comp = self.base.comp; + const gpa = comp.gpa; + const module = self.base.comp.module.?; { var i: usize = 0; @@ -520,8 +553,8 @@ fn flushCTypes( pass: codegen.DeclGen.Pass, decl_ctypes: codegen.CType.Store, ) FlushDeclError!void { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; const decl_ctypes_len = decl_ctypes.count(); f.ctypes_map.clearRetainingCapacity(); @@ -601,7 +634,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; @@ -609,7 +642,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, @@ -643,7 +676,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; @@ -651,7 +684,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, @@ -683,7 +716,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 +735,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 5fbf02871adfbc511855fdd266e4868532c3c601..7d825ef4d14d7150bdcbaaabcae867bcdef4267a 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -3,11 +3,24 @@ //! 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 zcu_object_sub_path. llvm_object: ?*LlvmObject = null, base: link.File, -error_flags: link.File.ErrorFlags = .{}, +image_base: u64, +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: 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, ptr_width: PtrWidth, page_size: u32, @@ -48,9 +61,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,61 +236,217 @@ 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); - - if (options.use_llvm) { - return createEmpty(allocator, options); - } - - const self = try createEmpty(allocator, options); - errdefer self.base.destroy(); - - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ - .truncate = false, - .read = true, - .mode = link.determineMode(options), - }); - self.base.file = file; - - try self.populateMissingMetadata(); - - return self; -} - -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { - const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) { +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*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 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); + + // 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, - .options = options, - .allocator = gpa, + .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, }, .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, + }, + + // 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, + .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 or !comp.config.have_zcu)) { + // LLVM emits the object file (if any); LLD links it into the final product. + return self; + } + + // 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 = true, + .read = true, + .mode = link.File.determineMode(use_lld, output_mode, link_mode), + }); + + assert(self.llvm_object == null); + const gpa = 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 (options.use_llvm) { - self.llvm_object = try LlvmObject.create(gpa, options); + 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 open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Coff { + // 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 { - 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 +515,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 +546,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 +730,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 +758,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 +782,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 +836,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 @@ -807,7 +884,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. @@ -853,24 +930,24 @@ 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); }, } 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 +1051,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 +1138,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,8 +1168,8 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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) { @@ -1121,7 +1199,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 +1252,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 +1267,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,8 +1299,8 @@ fn updateLazySymbolAtom( atom_index: Atom.Index, section_index: u16, ) !void { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; var required_alignment: InternPool.Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1281,8 +1360,9 @@ fn updateLazySymbolAtom( } pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.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 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.* = .{}; const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { @@ -1305,7 +1385,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(), @@ -1317,9 +1398,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: { @@ -1343,7 +1424,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)); @@ -1401,7 +1482,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,7 +1493,8 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("freeDecl {*}", .{decl}); @@ -1421,7 +1503,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); } } @@ -1436,8 +1518,10 @@ pub fn updateExports( } const ip = &mod.intern_pool; + 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| { @@ -1447,16 +1531,16 @@ 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, }; 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 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")) { @@ -1474,9 +1558,7 @@ 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.allocator; + const gpa = comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -1570,11 +1652,11 @@ 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; - 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 +1684,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); @@ -1624,38 +1706,35 @@ 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 { - 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; +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.options.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| { - return try llvm_object.flushModule(comp, prog_node); + 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.allocator; - - const module = self.base.options.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 @@ -1756,12 +1835,12 @@ 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 comp.config.output_mode == .Exe) { log.debug("flushing. no_entry_point_found = true\n", .{}); - self.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.error_flags.no_entry_point_found = false; + comp.link_error_flags.no_entry_point_found = false; try self.writeHeader(); } @@ -1794,8 +1873,8 @@ pub fn lowerAnonDecl( explicit_alignment: InternPool.Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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), @@ -1868,7 +1947,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 +1974,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 +2085,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 +2233,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 +2256,8 @@ fn writeDataDirectoriesHeaders(self: *Coff) !void { } fn writeHeader(self: *Coff) !void { - const gpa = self.base.allocator; + 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(); const writer = buffer.writer(); @@ -2194,14 +2275,14 @@ 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.comp.config.link_mode == .Dynamic) { flags.DLL = 1; } 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, @@ -2221,8 +2302,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; @@ -2253,15 +2332,15 @@ 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, .minor_operating_system_version = 0, .major_image_version = 0, .minor_image_version = 0, - .major_subsystem_version = 6, - .minor_subsystem_version = 0, + .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, @@ -2273,7 +2352,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; }, @@ -2287,15 +2366,15 @@ 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, .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, @@ -2307,7 +2386,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; }, @@ -2421,24 +2500,25 @@ 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; + + // 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]; } -pub fn getImageBase(self: Coff) u64 { - const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { - .Exe => switch (self.base.options.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 @@ -2499,7 +2579,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 +2610,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 +2630,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/Coff/Atom.zig b/src/link/Coff/Atom.zig index 9e5557575541d742a3427d69723035258711c198..4aa97fa6aced07b8f3a59d85f2301123a0ea9ced 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/Coff/Relocation.zig b/src/link/Coff/Relocation.zig index 84cfcdc18a882b791f88f1e9a9d4644adbd56768..b25427fedaa8b5c7662267de1c5d9e6af2e4eea8 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 573a85e167f9a2e60dcdb4a4c24bd73433cf17e4..914be5a4435aef036285bc7213cc7e5df07a531f 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -17,26 +17,25 @@ 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(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); + const comp = self.base.comp; + const gpa = comp.gpa; - 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. - const module_obj_path: ?[]const u8 = if (self.base.options.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.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; @@ -45,27 +44,35 @@ 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_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 link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib; - const target = self.base.options.target; + 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 = 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"; 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); } @@ -78,14 +85,14 @@ 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.addOptional(self.base.options.image_base_override); - 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.addOptionalBytes(entry_name); + man.hash.add(self.base.stack_size); + man.hash.add(self.image_base); + man.hash.addListOfBytes(self.lib_dirs); + man.hash.add(comp.skip_linker_dependencies); + if (comp.config.link_libc) { + 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.?); @@ -93,19 +100,19 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } } - try link.hashAddSystemLibs(&man, self.base.options.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); + try link.hashAddSystemLibs(&man, comp.system_libs); + 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); + man.hash.add(self.nxcompat); + man.hash.add(self.dynamicbase); + 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.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.add(self.major_subsystem_version); + man.hash.add(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(); @@ -135,13 +142,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod }; } - if (self.base.options.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. 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; @@ -160,7 +167,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 - @@ -170,34 +177,31 @@ 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 (comp.config.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) { - switch (self.base.options.optimize_mode) { + if (comp.config.lto) { + 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})); - } - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base})); + 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})); if (target.cpu.arch == .x86) { try argv.append("-MACHINE:X86"); @@ -211,7 +215,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } - for (self.base.options.force_undefined_symbols.keys()) |symbol| { + for (comp.force_undefined_symbols.keys()) |symbol| { try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol})); } @@ -219,34 +223,32 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append("-DLL"); } - if (self.base.options.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.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.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})); - if (self.base.options.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})); } - if (self.base.options.link_libc) { - if (self.base.options.libc_installation) |libc_installation| { + if (comp.config.link_libc) { + if (comp.libc_installation) |libc_installation| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?})); if (target.abi == .msvc) { @@ -256,12 +258,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 { @@ -283,18 +285,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.options.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 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) { @@ -313,16 +315,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.base.options.major_subsystem_version) |major| { - if (self.base.options.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 => { @@ -419,21 +414,21 @@ 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 (!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.options.link_mode) { + const lib_str = switch (comp.config.link_mode) { .Dynamic => "", .Static => "lib", }; - const d_str = switch (self.base.options.optimize_mode) { + const d_str = switch (optimize_mode) { .Debug => "d", else => "", }; - switch (self.base.options.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})), } @@ -451,8 +446,8 @@ 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 (!is_lib and entry_name == null) { + if (comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); } else { @@ -467,18 +462,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); } @@ -489,20 +484,20 @@ 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(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); 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; } @@ -516,7 +511,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod return error.DllImportLibraryNotFound; } - if (self.base.options.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..]); } @@ -586,7 +581,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 ef803a45f18bb0dad6ebe6bd6e1296e6e38b9883..cabaed1addc73b8aea07562c690e0179b4a8b6f0 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) { @@ -1190,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, @@ -1200,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.resolved_target.result; + 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()); @@ -1407,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, @@ -1431,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, @@ -1741,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 @@ -1883,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, @@ -1895,7 +1900,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; @@ -1906,7 +1911,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, @@ -1929,9 +1936,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); @@ -1995,7 +2002,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), @@ -2003,7 +2012,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), @@ -2225,7 +2236,10 @@ 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 gpa = comp.gpa; + 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 @@ -2289,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, @@ -2297,9 +2311,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, @@ -2563,7 +2578,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; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d52a5fa423a50373e4a8d89dc68cd8030dc3bcb3..2f1d5703f9735f274cbf74724fb725d50f8410c4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,8 +1,34 @@ base: link.File, +image_base: u64, +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, +print_icf_sections: bool, +print_map: bool, +entry_name: ?[]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 zcu_object_sub_path. llvm_object: ?*LlvmObject = null, /// A list of all input files. @@ -171,9 +197,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) = .{}, @@ -199,59 +222,161 @@ 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 openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf { - assert(options.target.ofmt == .elf); +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Elf { + const target = comp.root_mod.resolved_target.result; + assert(target.ofmt == .elf); - const self = try createEmpty(allocator, options); + 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 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; + + // 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 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, + .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, + }, + .ptr_width = ptr_width, + .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; + break :b options.image_base orelse switch (ptr_width) { + .p32 => 0x10000, + .p64 => 0x1000000, + }; + }, + + .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, + .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); + } errdefer self.base.destroy(); - 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), - }); - } + 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; } - errdefer if (self.base.intermediary_basename) |path| allocator.free(path); - self.base.file = try options.emit.?.directory.handle.createFile(sub_path, .{ - .truncate = false, + const is_obj = output_mode == .Obj; + const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static); + + // 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 = true, .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); + const gpa = 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) { .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), @@ -266,7 +391,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option .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, @@ -275,71 +400,49 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option .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, }); } - if (options.module != null and !options.use_llvm) { - const index = @as(File.Index, @intCast(try self.files.addOne(allocator))); - self.files.set(index, .{ .zig_object = .{ - .index = index, - .path = try std.fmt.allocPrint(self.base.allocator, "{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(gpa: Allocator, options: link.Options) !*Elf { - const ptr_width: PtrWidth = switch (options.target.ptrBitWidth()) { - 0...32 => .p32, - 33...64 => .p64, - else => return error.UnsupportedELFArchitecture, - }; - const self = try gpa.create(Elf); - errdefer gpa.destroy(self); - - const page_size: u32 = switch (options.target.cpu.arch) { - .powerpc64le => 0x10000, - .sparc64 => 0x2000, - else => 0x1000, - }; - const is_dyn_lib = options.output_mode == .Lib and options.link_mode == .Dynamic; - const default_sym_version: elf.Elf64_Versym = if (is_dyn_lib or options.rdynamic) - elf.VER_NDX_GLOBAL - else - elf.VER_NDX_LOCAL; - - self.* = .{ - .base = .{ - .tag = .elf, - .options = options, - .allocator = gpa, - .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); - } - - return self; +pub fn open( + arena: Allocator, + comp: *Compilation, + 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); } 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 => {}, @@ -378,7 +481,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); @@ -494,17 +596,23 @@ 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 { - const gpa = self.base.allocator; +pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { + 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 { 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; @@ -519,9 +627,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, @@ -538,7 +646,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, @@ -602,8 +710,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, @@ -619,7 +727,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, @@ -650,7 +758,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.?, @@ -679,7 +787,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.?, @@ -918,56 +1026,47 @@ 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; +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; + 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; + 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.allocator; 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(self.base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const target = self.base.options.target; - 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: { + 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.zcu_object_sub_path) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); } else { break :blk path; } } else null; - const gc_sections = self.base.options.gc_sections orelse false; // --verbose-link - if (self.base.options.verbose_link) try self.dumpArgv(comp); + if (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; @@ -975,8 +1074,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. @@ -987,8 +1086,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(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 @@ -1000,24 +1099,24 @@ 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| { + for (self.base.rpath_list) |rpath| { _ = try rpath_table.put(rpath, {}); } - if (self.base.options.each_lib_rpath) { - var test_path = std.ArrayList(u8).init(self.base.allocator); + 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.base.options.system_libs.keys()) |link_lib| { + for (self.lib_dirs) |lib_dir_path| { + 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.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; @@ -1027,14 +1126,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } // TSAN - if (self.base.options.tsan) { + if (comp.config.any_sanitize_thread) { try positionals.append(.{ .path = 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 positionals.append(.{ .path = lib.full_object_path }); } @@ -1053,27 +1150,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.options.system_libs.values().len); - for (self.base.options.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.options.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.options.link_libunwind) { + if (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| { + comp.link_error_flags.missing_libc = false; + if (comp.config.link_libc) { + if (comp.libc_installation) |lc| { const flags = target_util.libcFullLinkFlags(target); try system_libs.ensureUnusedCapacity(flags.len); @@ -1085,7 +1182,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; } @@ -1116,13 +1213,13 @@ 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", }); try system_libs.append(.{ .path = path }); } else { - self.error_flags.missing_libc = true; + comp.link_error_flags.missing_libc = true; } } @@ -1160,7 +1257,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node }; } - if (self.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| { @@ -1170,7 +1267,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 (comp.link_errors.items.len > 0) return error.FlushFailure; // Dedup shared objects { @@ -1211,18 +1308,15 @@ 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.isDynLib()) break :entry "_start"; - break :entry null; - }; - self.entry_index = if (entry) |name| self.globalByName(name) else null; + if (self.entry_name) |name| { + self.entry_index = self.globalByName(name); + } } - 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); } } @@ -1290,26 +1384,26 @@ 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; + comp.link_error_flags.no_entry_point_found = true; } else { log.debug("flushing. no_entry_point_found = false", .{}); - self.error_flags.no_entry_point_found = false; + comp.link_error_flags.no_entry_point_found = false; try self.writeElfHeader(); } - if (self.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 { - const gpa = self.base.allocator; + 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 @@ -1331,7 +1425,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const }; } - if (self.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| { @@ -1443,16 +1537,16 @@ 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 (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 { - const gpa = self.base.allocator; + const gpa = self.base.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 @@ -1474,14 +1568,14 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) }; } - if (self.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.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 @@ -1515,28 +1609,29 @@ 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 (comp.link_errors.items.len > 0) return error.FlushFailure; } /// --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.options.target; - 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: { + const target = self.base.comp.root_mod.resolved_target.result; + 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.zcu_object_sub_path) |path| blk: { if (fs.path.dirname(full_out_path)) |dirname| { break :blk try fs.path.join(arena, &.{ dirname, path }); } else { 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 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; @@ -1547,21 +1642,21 @@ 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()) { - for (self.base.options.objects) |obj| { + if (self.base.isRelocatable()) { + for (comp.objects) |obj| { try argv.append(obj.path); } @@ -1573,36 +1668,35 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append(p); } } else { - if (!self.isStatic()) { - if (self.base.options.dynamic_linker) |path| { + if (!self.base.isStatic()) { + if (target.dynamic_linker.get()) |path| { try argv.append("-dynamic-linker"); try argv.append(path); } } - if (self.isDynLib()) { - if (self.base.options.soname) |name| { + if (self.base.isDynLib()) { + if (self.soname) |name| { try argv.append("-soname"); try argv.append(name); } } - if (self.base.options.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } - 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; @@ -1613,57 +1707,55 @@ 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})); - } + try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); - if (gc_sections) { + if (self.base.gc_sections) { 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 (comp.link_eh_frame_hdr) { try argv.append("--eh-frame-hdr"); } - if (self.base.options.rdynamic) { + if (comp.config.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"); } - if (self.isStatic()) { + if (self.base.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 (comp.config.pie and self.base.isExe()) { try argv.append("-pie"); } - if (self.base.options.strip) { + if (comp.config.debug_format == .strip) { try argv.append("-s"); } @@ -1672,20 +1764,20 @@ 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 (self.base.options.libc_installation) |libc_installation| { + if (comp.config.link_libc) { + if (self.base.comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); } } 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; @@ -1713,15 +1805,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); } @@ -1730,11 +1819,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 => {}, @@ -1756,20 +1845,20 @@ 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 (self.base.options.libc_installation != null) { - const needs_grouping = self.base.options.link_mode == .Static; + 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"); try argv.appendSlice(target_util.libcFullLinkFlags(target)); if (needs_grouping) try argv.append("--end-group"); @@ -1782,7 +1871,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", })); @@ -1842,7 +1931,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 +1951,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 +1977,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 +1999,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)); @@ -1920,8 +2009,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(); @@ -1938,8 +2025,8 @@ 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| { - if (!self.isStatic()) { + for (self.lib_dirs) |lib_dir| { + if (!self.base.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic)) break :success; } @@ -1955,7 +2042,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; } @@ -1995,8 +2082,9 @@ 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.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) { @@ -2010,7 +2098,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, @@ -2139,7 +2227,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; } } @@ -2147,7 +2235,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); @@ -2190,7 +2278,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 { @@ -2259,26 +2347,25 @@ 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(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); + const comp = self.base.comp; + const gpa = comp.gpa; - 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. - const module_obj_path: ?[]const u8 = if (self.base.options.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.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; @@ -2287,16 +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 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 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 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 output_mode = comp.config.output_mode; + const is_obj = output_mode == .Obj; + const is_lib = output_mode == .Lib; + 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 = 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; @@ -2314,11 +2400,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. @@ -2326,9 +2412,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); @@ -2341,52 +2427,51 @@ 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.add(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); - if (self.base.options.output_mode == .Exe) { - man.hash.add(stack_size); - man.hash.add(self.base.options.build_id); + 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); + 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); + 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) { - man.hash.add(self.base.options.libc_installation != null); - if (self.base.options.libc_installation) |libc_installation| { + if (comp.config.link_libc) { + man.hash.add(comp.libc_installation != null); + if (comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); } if (have_dynamic_linker) { - man.hash.addOptionalBytes(self.base.options.dynamic_linker); + man.hash.addOptionalBytes(target.dynamic_linker.get()); } } - man.hash.addOptionalBytes(self.base.options.soname); - man.hash.addOptional(self.base.options.version); - try link.hashAddSystemLibs(&man, self.base.options.system_libs); - man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys()); - man.hash.add(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.addOptionalBytes(self.soname); + man.hash.addOptional(comp.version); + 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); + man.hash.add(self.compress_debug_sections); + man.hash.add(comp.config.any_sanitize_thread); + 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(); @@ -2421,15 +2506,15 @@ 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 - (self.base.options.lto or target.isBpfFreestanding())) + if (output_mode == .Obj and + (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; @@ -2448,7 +2533,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 - @@ -2461,46 +2546,49 @@ 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 (comp.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, - })); + switch (comp.root_mod.optimize_mode) { + .Debug => {}, + .ReleaseSmall => try argv.append("-O2"), + .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), + } - if (self.base.options.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } - for (self.base.options.force_undefined_symbols.keys()) |sym| { + for (comp.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 } - 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| { @@ -2511,85 +2599,83 @@ 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| { + 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); } - if (gc_sections) { + if (self.base.gc_sections) { 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 (comp.link_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 (comp.config.rdynamic) { try argv.append("--export-dynamic"); } - if (self.base.options.strip) { + if (comp.config.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})); } @@ -2604,7 +2690,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 { @@ -2614,7 +2700,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 (comp.config.pie and output_mode == .Exe) { try argv.append("-pie"); } @@ -2631,29 +2717,29 @@ 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); // 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| { + 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.base.options.system_libs.keys()) |link_lib| { + for (self.lib_dirs) |lib_dir_path| { + 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) { @@ -2662,7 +2748,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; @@ -2675,19 +2761,19 @@ 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 (self.base.options.libc_installation) |libc_installation| { + if (comp.config.link_libc) { + if (comp.libc_installation) |libc_installation| { try argv.append("-L"); try argv.append(libc_installation.crt_dir.?); } if (have_dynamic_linker) { - if (self.base.options.dynamic_linker) |dynamic_linker| { + if (target.dynamic_linker.get()) |dynamic_linker| { try argv.append("-dynamic-linker"); try argv.append(dynamic_linker); } @@ -2695,11 +2781,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); } @@ -2707,7 +2793,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; @@ -2735,15 +2821,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); @@ -2752,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.options.system_libs.keys(); - const system_libs_values = self.base.options.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. @@ -2788,21 +2873,21 @@ 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 (self.base.options.libc_installation != null) { - const needs_grouping = self.base.options.link_mode == .Static; + comp.link_error_flags.missing_libc = false; + if (comp.config.link_libc) { + 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)); if (needs_grouping) try argv.append("--end-group"); @@ -2815,12 +2900,12 @@ 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", })); } else { - self.error_flags.missing_libc = true; + comp.link_error_flags.missing_libc = true; } } } @@ -2836,21 +2921,21 @@ 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"); } - 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"); } - if (self.base.options.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..]); } @@ -2920,7 +3005,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| { @@ -2937,7 +3022,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 +3031,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 +3088,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.?]; @@ -3040,7 +3128,8 @@ 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 + 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; @@ -3054,7 +3143,8 @@ fn writeElfHeader(self: *Elf) !void { }; index += 1; - const endian = self.base.options.target.cpu.arch.endian(); + const target = comp.root_mod.resolved_target.result; + const endian = target.cpu.arch.endian(); hdr_buf[index] = switch (endian) { .little => elf.ELFDATA2LSB, .big => elf.ELFDATA2MSB, @@ -3072,10 +3162,12 @@ fn writeElfHeader(self: *Elf) !void { assert(index == 16); - const elf_type: elf.ET = switch (self.base.options.output_mode) { - .Exe => if (self.base.options.pie) .DYN else .EXEC, + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const elf_type: elf.ET = switch (output_mode) { + .Exe => if (comp.config.pie) .DYN else .EXEC, .Obj => .REL, - .Lib => switch (self.base.options.link_mode) { + .Lib => switch (link_mode) { .Static => @as(elf.ET, .REL), .Dynamic => .DYN, }, @@ -3083,7 +3175,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; @@ -3201,7 +3293,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); } @@ -3220,6 +3311,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); @@ -3234,7 +3328,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 (comp.link_eh_frame_hdr) { self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self); } @@ -3248,7 +3342,6 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { for (self.shdrs.items) |shdr| { if (self.getStartStopBasename(shdr)) |name| { - const gpa = self.base.allocator; try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); @@ -3265,6 +3358,9 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { } fn allocateLinkerDefinedSymbols(self: *Elf) void { + const comp = self.base.comp; + const link_mode = comp.config.link_mode; + // _DYNAMIC if (self.dynamic_section_index) |shndx| { const shdr = &self.shdrs.items[shndx]; @@ -3276,7 +3372,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; } @@ -3347,7 +3443,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 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); @@ -3394,6 +3490,8 @@ fn initOutputSections(self: *Elf) !void { } fn initSyntheticSections(self: *Elf) !void { + 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| { @@ -3408,7 +3506,7 @@ fn initSyntheticSections(self: *Elf) !void { .offset = std.math.maxInt(u64), }); - if (self.base.options.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, @@ -3502,8 +3600,8 @@ 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; - break :blk self.base.options.dynamic_linker != null; + if (self.base.isStatic() and !comp.config.pie) break :blk false; + break :blk target.dynamic_linker.get() != null; }; if (needs_interp) { self.interp_section_index = try self.addSection(.{ @@ -3515,7 +3613,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 comp.config.pie) { self.dynstrtab_section_index = try self.addSection(.{ .name = ".dynstr", .flags = elf.SHF_ALLOC, @@ -3613,7 +3711,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; @@ -3700,7 +3798,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, }); @@ -3732,7 +3830,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, @@ -3806,8 +3904,8 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { try self.dynamic.addNeeded(shared_object, self); } - if (self.isDynLib()) { - if (self.base.options.soname) |soname| { + if (self.base.isDynLib()) { + if (self.soname) |soname| { try self.dynamic.setSoname(soname, self); } } @@ -3821,8 +3919,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); @@ -3872,7 +3971,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 +4076,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 +4103,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 +4286,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 +4344,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 = target.dynamic_linker.get().?.len + 1; } if (self.hash_section_index) |index| { @@ -4453,7 +4553,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 +4791,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 +4879,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 +4952,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,17 +5035,18 @@ 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 = 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| { @@ -5065,7 +5166,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 +5236,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 +5261,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 +5322,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 +5401,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 { @@ -5393,9 +5496,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 = .{}; @@ -5406,19 +5511,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 ), @@ -5429,7 +5536,7 @@ const CsuObjects = struct { // zig fmt: on } } else { - switch (link_options.target.os.tag) { + switch (target.os.tag) { .linux => { switch (mode) { // zig fmt: off @@ -5440,7 +5547,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. @@ -5448,7 +5555,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) { @@ -5510,16 +5617,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"; @@ -5576,39 +5683,6 @@ const CsuObjects = struct { } }; -pub fn calcImageBase(self: Elf) u64 { - if (self.isDynLib()) return 0; - if (self.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, @@ -5648,8 +5722,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, @@ -5694,7 +5769,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.* = .{ @@ -5798,8 +5873,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; } @@ -5821,14 +5897,15 @@ 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}); 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; } @@ -5838,8 +5915,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); } @@ -5887,11 +5965,12 @@ 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) { 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; @@ -5923,11 +6002,11 @@ 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) { - 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; @@ -5939,8 +6018,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; } @@ -5971,7 +6051,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. @@ -5983,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 = &comp.link_errors.items[err.index]; err_msg.msg = try std.fmt.allocPrint(gpa, format, args); } @@ -5994,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 = &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; @@ -6003,14 +6085,18 @@ const ErrorWithNotes = struct { }; pub fn addErrorWithNotes(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { - try self.misc_errors.ensureUnusedCapacity(self.base.allocator, 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 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) }; + 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 }; } @@ -6020,9 +6106,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; } @@ -6032,17 +6119,19 @@ 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; } fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { - const gpa = self.base.allocator; + const comp = self.base.comp; + const gpa = comp.gpa; const max_notes = 4; - try self.misc_errors.ensureUnusedCapacity(gpa, undefs.count()); + try comp.link_errors.ensureUnusedCapacity(gpa, undefs.count()); var it = undefs.iterator(); while (it.next()) |entry| { @@ -6427,6 +6516,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/Elf/Archive.zig b/src/link/Elf/Archive.zig index 686647a290fe553ac4cb4b5da90201e99bc1cf1c..65135abbc77acc9d50733ced7732ba5380cd57e3 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/Atom.zig b/src/link/Elf/Atom.zig index ec12f177212d96d3adebb4e529d9d73947a8e432..a7b876f619a2f51b1421637420d7d3021a24d8f1 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; @@ -375,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; @@ -543,7 +545,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 +555,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 +589,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 +659,12 @@ 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) { + const comp = elf_file.base.comp; + assert(!elf_file.base.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, }; } @@ -746,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()], @@ -760,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); } @@ -956,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))); @@ -966,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", @@ -979,7 +986,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/LdScript.zig b/src/link/Elf/LdScript.zig index 803e2e146946bed529efe76ad9ecaf27640f1ea7..34cecf5879934d39abaf90b02a805c9a80792ecb 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 bc51cfc1f17db8f9c266b2b777e8a2afa407c3e4..b9fffa1a4a657661508653938d63a796b4a761dd 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 6b0cc66c33e31e662714a7c6faa92c01a9e76d45..b6dced258ce08bb4832b8702161e19b5e2b5cc09 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}", @@ -65,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)) @@ -148,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| { @@ -184,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); @@ -247,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", @@ -275,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") { @@ -292,13 +295,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.options.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; }; @@ -306,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); @@ -338,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; @@ -438,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; @@ -448,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); } @@ -512,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; @@ -621,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); @@ -680,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); @@ -740,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); @@ -748,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); @@ -855,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 2a39477805baa39f996f2d6a1bb0d59f5db8e832..e5e87cc51e6d0d520557a5a6576292e94074a98e 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -47,13 +47,15 @@ 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(); 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}", @@ -100,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); @@ -145,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(); @@ -294,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/Symbol.zig b/src/link/Elf/Symbol.zig index 3dd35dfe63a0a59e0ef534fb9f7ae1413d4bdbb8..7c7d3fd17c9582c9b64df8583d6305126ec950b9 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 7a1fa214357769e182809cffc40a1e89ccc358a4..a29c3ab69c488644350f4604607d6e7a323caf18 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, @@ -76,7 +77,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.allocator; + 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,14 +98,18 @@ 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) { - self.dwarf = Dwarf.init(gpa, &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, } } 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); @@ -155,13 +161,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 +175,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 +188,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 +202,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 +275,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); @@ -363,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; @@ -411,6 +418,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 +429,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 +455,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 +473,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 +516,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 +610,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 +676,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 +724,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 +760,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 +791,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 +804,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 +832,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 +858,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 +888,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)); @@ -911,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).?; @@ -929,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); } @@ -971,8 +986,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 +1041,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 +1050,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 +1133,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 +1196,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); @@ -1245,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); } @@ -1261,8 +1278,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 +1325,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 +1381,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 +1484,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 +1502,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/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 1d24285b30c024ac747848d69c3c6da5d6bd86c8..75401824abe56a5386b0281651a9990104b098b8 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| { @@ -268,7 +271,7 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { } } - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { offset += 4; // NULL terminator } @@ -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 ade2b75782a8795fa88b8153415a9cda2c469270..d95dd78b331fdbce59b71be7fab6e090bef24311 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 25a9975f01e4966f2749e56e71e438b70089f1c9..68a36e14ce4e8b455dd8631946db35b4b3c282aa 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| { @@ -32,7 +34,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 +51,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.base.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; @@ -86,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); } @@ -213,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 }); @@ -246,12 +249,14 @@ pub const ZigGotSection = struct { } pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { - const index = try zig_got.allocateEntry(elf_file.base.allocator); + const comp = elf_file.base.comp; + 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); symbol.flags.has_zig_got = true; - if (elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.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| { @@ -287,7 +292,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]; @@ -346,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); @@ -477,14 +485,16 @@ pub const GotSection = struct { } pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { - 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 = .got; entry.symbol_index = sym_index; 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.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file))) { got.flags.needs_rela = true; } @@ -497,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 @@ -507,13 +519,15 @@ 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; 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; @@ -522,13 +536,15 @@ 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; 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; @@ -537,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; @@ -560,7 +578,8 @@ pub const GotSection = struct { } pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void { - const is_dyn_lib = elf_file.isDynLib(); + const comp = elf_file.base.comp; + const is_dyn_lib = elf_file.base.isDynLib(); const apply_relocs = true; // TODO add user option for this for (got.entries.items) |entry| { @@ -575,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 elf_file.base.options.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; @@ -622,8 +641,10 @@ pub const GotSection = struct { } pub fn addRela(got: GotSection, elf_file: *Elf) !void { - const is_dyn_lib = elf_file.isDynLib(); - try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file)); + const comp = elf_file.base.comp; + const gpa = comp.gpa; + const is_dyn_lib = elf_file.base.isDynLib(); + try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file)); for (got.entries.items) |entry| { const symbol = switch (entry.tag) { @@ -651,7 +672,7 @@ pub const GotSection = struct { }); continue; } - if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and + if ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file)) { elf_file.addRelaDynAssumeCapacity(.{ @@ -724,7 +745,8 @@ pub const GotSection = struct { } pub fn numRela(got: GotSection, elf_file: *Elf) usize { - const is_dyn_lib = elf_file.isDynLib(); + const comp = elf_file.base.comp; + const is_dyn_lib = elf_file.base.isDynLib(); var num: usize = 0; for (got.entries.items) |entry| { const symbol = switch (entry.tag) { @@ -733,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 elf_file.base.options.pie)) and + ((elf_file.base.isDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.?.isAbs(elf_file))) { num += 1; @@ -840,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; @@ -848,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 { @@ -888,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); @@ -1003,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; @@ -1012,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 { @@ -1070,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; @@ -1082,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) { @@ -1122,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); @@ -1155,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; @@ -1237,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); @@ -1325,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); @@ -1427,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); @@ -1483,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, @@ -1501,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), @@ -1575,7 +1613,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 61446b3300d62273005a251c5f0ef51fe69da848..cb26aa0ca34ec0178688bcf67c0f0e43fbb6c13f 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1,6 +1,7 @@ base: File, +entry_name: ?[]const u8, -/// 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 zcu_object_sub_path. llvm_object: ?*LlvmObject = null, /// Debug symbols bundle (or dSym). @@ -67,9 +68,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, @@ -77,12 +75,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) = .{}, @@ -143,89 +135,167 @@ 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); +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, +compatibility_version: ?std.SemanticVersion, - if (options.emit == null) { - return createEmpty(allocator, options); +/// 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); } +} - const emit = options.emit.?; - const mode: Mode = mode: { - if (options.use_llvm or options.module == null or options.cache_mode == .whole) - break :mode .zld; - break :mode .incremental; +/// 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, +}; + +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*MachO { + const target = comp.root_mod.resolved_target.result; + assert(target.ofmt == .macho); + const use_llvm = comp.config.use_llvm; + const gpa = comp.gpa; + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + + // 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, + }, + .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, + .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, + }, }; - const sub_path = if (mode == .zld) blk: { - if (options.module == null) { - // No point in opening a file, we would not write anything to it. - // Initialize with empty. - return createEmpty(allocator, 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), - }); - } else emit.sub_path; - errdefer if (mode == .zld) allocator.free(sub_path); - - const self = try createEmpty(allocator, options); + 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 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. - self.base.intermediary_basename = 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.determineMode(options), + .mode = link.File.determineMode(false, output_mode, link_mode), }); - errdefer file.close(); self.base.file = file; - if (!options.strip and options.module != null) { + 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( - allocator, + arena, "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", - .{sub_path}, + .{emit.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(); - 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, }); self.d_sym = .{ - .allocator = allocator, - .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32), + .allocator = gpa, + .dwarf = link.File.Dwarf.init(&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(); + 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); @@ -234,75 +304,59 @@ 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); - - self.* = .{ - .base = .{ - .tag = .macho, - .options = options, - .allocator = gpa, - .file = null, - }, - .mode = if (options.use_llvm or options.module == null or options.cache_mode == .whole) - .zld - else - .incremental, - }; - - if (options.use_llvm and options.module != null) { - self.llvm_object = try LlvmObject.create(gpa, options); - } - - log.debug("selected linker mode '{s}'", .{@tagName(self.mode)}); - - return self; +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*MachO { + // 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 { - if (self.base.options.emit == null) { - if (self.llvm_object) |llvm_object| { - try llvm_object.flushModule(comp, prog_node); - } - return; - } +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 (self.base.options.output_mode == .Lib and self.base.options.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 self.misc_errors.ensureUnusedCapacity(self.base.allocator, 1); - self.misc_errors.appendAssumeCapacity(.{ - .msg = try self.base.allocator.dupe(u8, "TODO: non-LLVM archiver for MachO object files"), + 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; } } 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; + if (self.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); + try self.base.emitLlvmObject(arena, llvm_object, prog_node); + return; } - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - var sub_prog_node = prog_node.start("MachO Flush", 0); sub_prog_node.activate(); defer sub_prog_node.end(); - const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; + 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 @@ -334,97 +388,44 @@ 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"; - - 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(self.base.allocator); - } - self.dylibs.clearRetainingCapacity(); - self.dylibs_map.clearRetainingCapacity(); - self.referenced_dylibs.clearRetainingCapacity(); - - var dependent_libs = std.fifo.LinearFifo(DylibReExportInfo, .Dynamic).init(arena); - - for (libs.keys(), libs.values()) |path, lib| { - const in_file = try std.fs.cwd().openFile(path, .{}); - defer in_file.close(); - - var parse_ctx = ParseErrorCtx.init(self.base.allocator); - defer parse_ctx.deinit(); - - 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); + 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 (libs.keys(), libs.values()) |path, lib| { + const in_file = try std.fs.cwd().openFile(path, .{}); + defer in_file.close(); + + var parse_ctx = ParseErrorCtx.init(gpa); + defer parse_ctx.deinit(); + + 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) { - self.error_flags.no_entry_point_found = true; + comp.link_error_flags.no_entry_point_found = true; } if (self.unresolved.count() > 0) { try self.reportUndefined(); @@ -445,7 +446,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. @@ -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); @@ -509,21 +510,21 @@ 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. // 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| { - try codesig.addEntitlements(self.base.allocator, path); + 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); } 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); @@ -535,7 +536,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]; @@ -551,22 +552,22 @@ 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) { - try load_commands.writeDylibIdLC(self.base.allocator, &self.base.options, lc_writer); + .Lib => if (comp.config.link_mode == .Dynamic) { + try load_commands.writeDylibIdLC(self, lc_writer); }, else => {}, } - try load_commands.writeRpathLCs(self.base.allocator, &self.base.options, lc_writer); + try load_commands.writeRpathLCs(self, lc_writer); try lc_writer.writeStruct(macho.source_version_command{ .version = 0, }); { - const platform = Platform.fromTarget(self.base.options.target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const platform = Platform.fromTarget(target); + 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()) { @@ -590,7 +591,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); } @@ -598,23 +599,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. @@ -641,33 +625,20 @@ pub fn resolveLibSystem( self: *MachO, arena: Allocator, comp: *Compilation, - search_dirs: []const []const u8, out_libs: anytype, ) !void { - var tmp_arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); - 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) { + if (self.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{ comp.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; }, }; @@ -775,7 +746,8 @@ fn parseObject( const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + 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))); @@ -798,8 +770,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))) @@ -826,8 +798,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)) { @@ -868,7 +842,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 +866,8 @@ fn parseArchive( must_link: bool, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + 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? @@ -922,8 +897,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))) @@ -973,7 +948,8 @@ fn parseDylib( dylib_options: DylibOpts, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + 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; @@ -997,8 +973,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))) @@ -1019,7 +995,9 @@ fn parseLibStub( dylib_options: DylibOpts, ctx: *ParseErrorCtx, ) ParseError!void { - const gpa = self.base.allocator; + 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(); @@ -1027,7 +1005,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]; @@ -1050,7 +1028,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, @@ -1072,7 +1050,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; @@ -1080,7 +1058,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.*)); }; @@ -1098,7 +1076,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.allocator; + const comp = self.base.comp; + const gpa = comp.gpa; while (dependent_libs.readItem()) |dep_id| { defer dep_id.id.deinit(gpa); @@ -1118,7 +1097,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; } @@ -1162,7 +1141,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| { @@ -1194,7 +1174,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 @@ -1237,8 +1218,9 @@ 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 cpu_arch = self.base.options.target.cpu.arch; + const gpa = self.base.comp.gpa; + 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); @@ -1264,11 +1246,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); @@ -1290,7 +1273,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 +1452,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 +1464,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 +1519,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 +1544,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(); @@ -1593,9 +1577,10 @@ 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.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 +1607,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); @@ -1643,16 +1628,19 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { } pub fn resolveSymbols(self: *MachO) !void { + 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. - if (self.base.options.output_mode == .Exe) { - const entry_name = self.base.options.entry orelse load_commands.default_entry_point; - _ = try self.addUndefined(entry_name, .{}); + if (output_mode == .Exe) { + if (self.entry_name) |entry_name| { + _ = 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 (comp.force_undefined_symbols.keys()) |sym_name| { _ = try self.addUndefined(sym_name, .{}); } @@ -1667,7 +1655,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", .{}); } @@ -1686,7 +1674,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 +1788,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 +1817,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]; @@ -1863,9 +1851,10 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { } fn resolveSymbolsAtLoading(self: *MachO) !void { - const is_lib = self.base.options.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 output_mode = self.base.comp.config.output_mode; + const is_lib = output_mode == .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; while (next_sym < self.unresolved.count()) { @@ -1899,6 +1888,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 +1899,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 +1919,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(); @@ -2024,15 +2014,10 @@ 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 { - 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 +2109,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 +2136,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| { @@ -2169,9 +2156,10 @@ fn allocateGlobal(self: *MachO) !u32 { return index; } -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); +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, 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, @@ -2180,19 +2168,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 stub_index = try self.stub_table.allocateEntry(self.base.allocator, 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(self.base.options.target.cpu.arch), + .reserved2 = stubs.stubSize(cpu_arch), }); self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ .flags = macho.S_REGULAR | @@ -2206,13 +2197,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; - _ = try self.tlv_ptr_table.allocateEntry(self.base.allocator, target); +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, 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, @@ -2236,7 +2228,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,8 +2272,8 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; @@ -2318,7 +2311,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 +2359,8 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) const tracy = trace(@src()); defer tracy.end(); + const comp = self.base.comp; + const gpa = comp.gpa; const decl = mod.declPtr(decl_index); if (decl.val.getExternFunc(mod)) |_| { @@ -2375,14 +2370,14 @@ 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; } 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); @@ -2391,7 +2386,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,8 +2444,8 @@ fn updateLazySymbolAtom( atom_index: Atom.Index, section_index: u8, ) !void { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; var required_alignment: Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -2514,8 +2509,9 @@ 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 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(); if (!gop.found_existing) gop.value_ptr.* = .{}; const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { @@ -2529,7 +2525,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 => {}, @@ -2545,7 +2541,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 @@ -2556,7 +2552,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 +2636,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), @@ -2655,17 +2652,17 @@ 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 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.?; @@ -2673,7 +2670,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.?; @@ -2694,8 +2691,8 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); const required_alignment = decl.getAlignment(mod); @@ -2782,12 +2779,10 @@ 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(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -2912,8 +2907,8 @@ pub fn deleteDeclExport( if (self.llvm_object) |_| return; const metadata = self.decls.getPtr(decl_index) orelse return; - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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; @@ -2941,7 +2936,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,7 +2946,8 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); log.debug("freeDecl {*}", .{decl}); @@ -2960,7 +2956,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,8 +2989,8 @@ pub fn lowerAnonDecl( explicit_alignment: InternPool.Alignment, src_loc: Module.SrcLoc, ) !codegen.Result { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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), @@ -3057,11 +3053,18 @@ 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.allocator; - const cpu_arch = self.base.options.target.cpu.arch; + 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(); if (self.pagezero_segment_cmd_index == null) { @@ -3078,7 +3081,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 }); @@ -3098,7 +3101,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), @@ -3134,7 +3137,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, @@ -3172,7 +3175,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, @@ -3207,13 +3210,14 @@ fn populateMissingMetadata(self: *MachO) !void { } fn calcPagezeroSize(self: *MachO) u64 { - const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize; - 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 output_mode = self.base.comp.config.output_mode; + 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; - 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; @@ -3228,7 +3232,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,8 +3253,9 @@ 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 page_size = getPageSize(self.base.options.target.cpu.arch); + const gpa = self.base.comp.gpa; + 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)); @@ -3304,7 +3310,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); @@ -3344,7 +3351,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); @@ -3521,7 +3529,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 }); @@ -3555,7 +3563,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; @@ -3582,7 +3591,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 +3614,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| { @@ -3642,7 +3651,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); @@ -3688,14 +3698,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)); @@ -3715,7 +3725,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 +3756,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| { @@ -3797,7 +3807,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); @@ -3885,12 +3896,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 +3934,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); @@ -4015,7 +4027,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); @@ -4046,7 +4059,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 +4146,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 +4224,15 @@ 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 comp = self.base.comp; + const gpa = comp.gpa; var locals = std.ArrayList(macho.nlist_64).init(gpa); defer locals.deinit(); @@ -4272,7 +4287,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 (comp.config.debug_format != .strip) { for (self.objects.items) |object| { assert(self.d_sym == null); // TODO try self.generateSymbolStabs(object, &locals); @@ -4322,7 +4337,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 +4465,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 +4551,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 +4580,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; @@ -4650,13 +4665,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. @@ -4667,11 +4683,13 @@ 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; - 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, .{ @@ -4679,7 +4697,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()); @@ -4693,10 +4711,13 @@ 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; - 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; @@ -4708,7 +4729,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; }, @@ -4817,7 +4838,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 +4863,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 +5044,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); @@ -5060,15 +5082,16 @@ 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. /// 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 entry_name = self.entry_name orelse return null; const global = self.getGlobal(entry_name) orelse return null; return global; } @@ -5086,11 +5109,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; } @@ -5171,7 +5196,9 @@ pub fn handleAndReportParseError( err: ParseError, ctx: *const ParseErrorCtx, ) error{OutOfMemory}!void { - const cpu_arch = self.base.options.target.cpu.arch; + const target = self.base.comp.root_mod.resolved_target.result; + const gpa = self.base.comp.gpa; + const cpu_arch = target.cpu.arch; switch (err) { error.DylibAlreadyExists => {}, error.IncompatibleDylibVersion => { @@ -5188,7 +5215,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) { @@ -5206,7 +5233,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, @@ -5226,14 +5253,15 @@ fn reportMissingLibraryError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; - try self.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.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5246,15 +5274,16 @@ fn reportDependencyError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; - try self.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.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = try notes.toOwnedSlice(), }); @@ -5266,12 +5295,13 @@ pub fn reportParseError( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; - try self.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.misc_errors.appendAssumeCapacity(.{ + comp.link_errors.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, format, args), .notes = notes, }); @@ -5283,21 +5313,23 @@ pub fn reportUnresolvedBoundarySymbol( comptime format: []const u8, args: anytype, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; - try self.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.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.allocator; + const comp = self.base.comp; + const gpa = comp.gpa; const count = self.unresolved.count(); - try self.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]; @@ -5318,7 +5350,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { }; err_msg.notes = try notes.toOwnedSlice(); - self.misc_errors.appendAssumeCapacity(err_msg); + comp.link_errors.appendAssumeCapacity(err_msg); } } @@ -5327,8 +5359,9 @@ fn reportSymbolCollision( first: SymbolWithLoc, other: SymbolWithLoc, ) error{OutOfMemory}!void { - const gpa = self.base.allocator; - try self.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(); @@ -5351,12 +5384,13 @@ fn reportSymbolCollision( }) }; err_msg.notes = try notes.toOwnedSlice(); - self.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.allocator; - try self.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); @@ -5374,7 +5408,7 @@ fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{Ou else unreachable; - self.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, @@ -5623,6 +5657,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/Atom.zig b/src/link/MachO/Atom.zig index 290c67c45e2ebbbd41c12cbabcf6df5056a4ade3..d76a6de841ceeb356e76afd68d05d5a34dfec31f 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); @@ -387,7 +391,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 +439,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 +453,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 +473,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 +605,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 +1199,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 +1219,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 +1236,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 f204093290e308a8dd61868dab1900eee864fb85..74a4afeb5415227b1587615a6e1e725277a2cede 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); @@ -196,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) { @@ -243,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; } @@ -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; @@ -566,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/Object.zig b/src/link/MachO/Object.zig index 0c68d706446fb38f8f3ede2a606da1f1836dc045..ad069b845e4d37a1d2336e56e09703228016fb99 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -342,19 +342,23 @@ 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(); for (sections, 0..) |sect, id| { @@ -448,7 +452,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; @@ -554,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, @@ -670,13 +675,15 @@ 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", .{}); } - 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 +711,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 +721,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 +735,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 +753,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, @@ -765,8 +772,10 @@ 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 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 { // 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 +827,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 +842,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 74be9eb0d561f1982117b864edbdb9bac193d0c7..85c19c7608f3b34425cb994a6ec02ccd82767417 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 be6c9dbb34538c0adf4135fa03071f07eab5b104..7223b5555f7e1cb21c4daced621812711b315a72 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 dda82385e185d62156ed6db8137f9732bf872467..fe3740e82667d725d1811ca73b7e73fad5db5029 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(); @@ -33,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.options.output_mode) { + const comp = macho_file.base.comp; + + switch (comp.config.output_mode) { .Exe => { // Add entrypoint as GC root if (macho_file.getEntryPoint()) |global| { @@ -60,7 +63,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 (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); @@ -118,7 +121,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 +133,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 +153,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 +182,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 +194,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 +215,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 +276,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 +316,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 +347,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 +368,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 +401,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 0f021a569cc1ada45aa4054a2af40107cc4af166..4b51d09683d5063302bb8fea6e159b562439d102 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); @@ -35,8 +36,10 @@ 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 gpa = macho_file.base.allocator; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var size: u32 = 0; for (macho_file.objects.items, 0..) |*object, object_id| { @@ -86,8 +89,10 @@ 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 gpa = macho_file.base.allocator; + const target = macho_file.base.comp.root_mod.resolved_target.result; + const cpu_arch = target.cpu.arch; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var eh_records = std.AutoArrayHashMap(u32, EhFrameRecord(true)).init(gpa); defer { @@ -109,11 +114,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 +158,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 +283,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 +307,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 +325,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 +347,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 +365,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 +381,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 f06441573997c78f0ba7a44fd90b7dc802f55da0..e155a7a8ed34c3bc81a3ecc306e11068b8d4d10a 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.base.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), }); @@ -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,16 +473,17 @@ 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 options = comp.bin_file.options; - - 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 => 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/thunks.zig b/src/link/MachO/thunks.zig index 774a8f73449c350d585df173320468cef35da639..f080de7f80dfeb6af7daca794b6ad094fe2a89f9 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 e627b91f11dae5f6e305c53a3992dcd42649118c..b266bfeb47b8106d11c907b475131982f56abdb1 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -1,31 +1,29 @@ 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.allocator; - const options = &macho_file.base.options; - const target = options.target; + 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 = 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 = 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: { - try macho_file.flushModule(comp, prog_node); + const module_obj_path: ?[]const u8 = if (opt_zcu != null) blk: { + 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.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; @@ -34,22 +32,24 @@ pub fn linkWithZld( sub_prog_node.context.refresh(); defer sub_prog_node.end(); + const output_mode = comp.config.output_mode; + const link_mode = 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 = 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 +57,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 +68,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.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(comp.root_mod.strip); + try MachO.hashAddFrameworks(&man, macho_file.frameworks); + man.hash.addListOfBytes(macho_file.base.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(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 // need the digest and the lock. @@ -125,13 +123,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 +148,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 +156,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 +173,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 +188,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 +197,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,19 +226,19 @@ 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})); - 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 { @@ -248,44 +246,38 @@ pub fn linkWithZld( } } - if (options.sysroot) |syslibroot| { + if (comp.sysroot) |syslibroot| { try argv.append("-syslibroot"); try argv.append(syslibroot); } - for (options.rpath_list) |rpath| { + for (macho_file.base.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})); - } + try argv.appendSlice(&.{ + "-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}), + }); - if (options.headerpad_size) |headerpad_size| { - try argv.append("-headerpad_size"); - try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{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| { - try argv.append("-e"); - try argv.append(entry); + if (macho_file.entry_name) |entry_name| { + try argv.appendSlice(&.{ "-e", entry_name }); } - for (options.objects) |obj| { + for (objects) |obj| { if (obj.must_link) { try argv.append("-force_load"); } @@ -303,7 +295,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 +305,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 +316,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 +327,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,14 +396,14 @@ pub fn linkWithZld( }; } - if (gc_sections) { + if (macho_file.base.gc_sections) { try dead_strip.gcAtoms(macho_file); } try macho_file.createDyldPrivateAtom(); try macho_file.createTentativeDefAtoms(); - if (macho_file.base.options.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. @@ -470,7 +454,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) |_| { @@ -511,7 +495,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. @@ -519,7 +503,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 +523,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,22 +539,22 @@ 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) { - try load_commands.writeDylibIdLC(gpa, &macho_file.base.options, lc_writer); + .Lib => if (link_mode == .Dynamic) { + 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, }); { - const platform = Platform.fromTarget(macho_file.base.options.target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const platform = Platform.fromTarget(target); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(macho_file); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else { @@ -598,11 +582,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| { @@ -621,13 +605,14 @@ 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); - 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}); + 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); + 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}); } macho_file.pagezero_segment_cmd_index = @intCast(macho_file.segments.items.len); @@ -695,7 +680,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| { @@ -768,8 +754,10 @@ fn writeDyldPrivateAtom(macho_file: *MachO) !void { } fn writeThunks(macho_file: *MachO) !void { - assert(macho_file.base.options.target.cpu.arch == .aarch64); - const gpa = macho_file.base.allocator; + const target = macho_file.base.comp.root_mod.resolved_target.result; + assert(target.cpu.arch == .aarch64); + 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]; @@ -789,7 +777,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); @@ -803,8 +792,10 @@ 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 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.?]; const la_symbol_ptr_header = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_section_index.?]; @@ -825,8 +816,10 @@ 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 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.?]; const capacity = math.cast(usize, stub_helper_header.size) orelse return error.Overflow; @@ -868,8 +861,10 @@ 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 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.?]; const stub_helper_header = macho_file.sections.items(.header)[macho_file.stub_helper_section_index.?]; @@ -900,7 +895,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(); @@ -977,11 +973,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; @@ -1004,7 +1001,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.?); } @@ -1056,7 +1053,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]; @@ -1079,11 +1076,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(), @@ -1106,6 +1102,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 @@ -1188,7 +1185,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/NvPtx.zig b/src/link/NvPtx.zig index 606c5f12375463a64ef8ae39039b57b6fb8912cd..111b59fc3ba5b3834ad839734f4cb9b8cb35d25e 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -24,46 +24,62 @@ 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, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*NvPtx { + 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; - if (!options.target.cpu.arch.isNvptx()) return error.PtxArchNotSupported; + 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 (options.target.os.tag) { + 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, comp); + const nvptx = try arena.create(NvPtx); nvptx.* = .{ .base = .{ .tag = .nvptx, - .options = options, + .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, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, }, .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, + 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, comp, emit, 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 { @@ -80,9 +96,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); } @@ -90,32 +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 { - if (build_options.skip_non_native) { +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"); - } - 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.ptx_file_name, - }; - 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. + _ = arena; + _ = self; + _ = prog_node; + @panic("TODO: rewrite the NvPtx.flushModule function"); } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index b608b291615e59d7f213b7dd6974f423fdd8d92d..a635b0bf5b23a5313aa80daf48bb497bd9f0a8cc 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 @@ -174,7 +173,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); @@ -206,7 +205,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,38 +293,51 @@ 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; - const sixtyfour_bit: bool = switch (options.target.ptrBitWidth()) { +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; + const output_mode = comp.config.output_mode; + + 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 = 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, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, }, .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(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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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) { @@ -379,6 +392,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 +400,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 +411,8 @@ 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 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); @@ -404,15 +420,15 @@ 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, // 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(); @@ -448,14 +464,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 mod = self.base.comp.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 +482,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 +515,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 +535,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,17 +553,18 @@ 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 mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + 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; @@ -558,7 +577,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 +590,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; } } @@ -588,16 +608,18 @@ 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); +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 (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, .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 { @@ -645,12 +667,17 @@ 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"); } - _ = comp; + _ = 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; + const tracy = trace(@src()); defer tracy.end(); @@ -662,7 +689,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| { @@ -691,12 +718,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 +736,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 { @@ -741,9 +768,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| { @@ -770,9 +797,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; } @@ -783,9 +810,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 @@ -807,9 +834,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| { @@ -830,9 +857,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; } @@ -851,9 +878,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; } @@ -871,9 +898,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; } @@ -883,9 +910,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) @@ -894,17 +921,17 @@ 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()); } } } - 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; @@ -934,7 +961,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; @@ -985,6 +1012,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 +1022,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,41 +1033,42 @@ 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 // 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) { 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 +1076,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 +1119,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(); @@ -1100,7 +1131,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)) { @@ -1134,7 +1165,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.comp.module.?)); errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); if (!gop.found_existing) gop.value_ptr.* = .{}; @@ -1153,15 +1185,15 @@ 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; } fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Index) !void { - const gpa = self.base.allocator; - const mod = self.base.options.module.?; + const gpa = self.base.comp.gpa; + const mod = self.base.comp.module.?; var required_alignment: InternPool.Alignment = .none; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1206,8 +1238,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 +1247,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 +1312,39 @@ 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, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*Plan9 { + 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; - 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, comp, emit, options); errdefer self.base.destroy(); - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ + const file = try emit.directory.handle.createFile(emit.sub_path, .{ .read = true, - .mode = link.determineMode(options), + .mode = link.File.determineMode( + use_lld, + comp.config.output_mode, + comp.config.link_mode, + ), }); errdefer file.close(); self.base.file = file; - self.bases = defaultBaseAddrs(options.target.cpu.arch); + self.bases = defaultBaseAddrs(target.cpu.arch); - try self.syms.appendSlice(self.base.allocator, &.{ + const gpa = comp.gpa; + + 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 @@ -1323,7 +1370,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 @@ -1349,7 +1396,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]); }; @@ -1396,7 +1443,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")) @@ -1439,7 +1486,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)) { @@ -1480,7 +1527,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(); @@ -1490,9 +1543,9 @@ 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.?; + 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); @@ -1538,11 +1591,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 ac36a391ecdd64e19db0a6f6534ed0bd1042db83..7b66d914bf1bd00ae931db0acd69fed07565aee6 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); @@ -47,48 +46,73 @@ base: link.File, object: codegen.Object, -pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { - const self = try gpa.create(SpirV); +pub const base_tag: link.File.Tag = .spirv; + +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, - .options = options, + .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, - .allocator = gpa, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + .rpath_list = options.rpath_list, }, .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, + comp: *Compilation, + emit: Compilation.Emit, + options: link.File.OpenOptions, +) !*SpirV { + 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; - 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, 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(sub_path, .{ .truncate = true, .read = true }); + const file = try emit.directory.handle.createFile(emit.sub_path, .{ + .truncate = true, + .read = true, + }); spirv.base.file = file; return spirv; } @@ -149,19 +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 { - 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); - } +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(); @@ -171,7 +193,10 @@ 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(); + try writeCapabilities(spv, target); try writeMemoryModel(spv, target); @@ -183,7 +208,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 @@ -191,11 +216,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, }); @@ -203,6 +228,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 }, @@ -212,13 +238,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, @@ -237,7 +265,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 513922f247771a5b51015cbb944ca831e0eb4cfa..185d80258882eb6607cf38ef65f0b766ff7979c0 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -37,6 +37,12 @@ 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, +initial_memory: ?u64, +max_memory: ?u64, /// 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. @@ -191,6 +197,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 +372,126 @@ 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, + 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); +} - if (options.use_llvm and options.use_lld) { - return createEmpty(allocator, 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; + assert(target.ofmt == .wasm); + + 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 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. + // 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, + }, + .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, + + .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); } + errdefer wasm.base.destroy(); - const wasm_bin = try createEmpty(allocator, options); - errdefer wasm_bin.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 or !comp.config.have_zcu)) { + // LLVM emits the object file (if any); LLD links it into the final product. + return wasm; } - // TODO: read the file and keep valid parts instead of truncating - const file = try options.emit.?.directory.handle.createFile(sub_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; + + const file = try 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 +504,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 +532,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,90 +541,68 @@ 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 (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; -} - -pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { - const wasm = try gpa.create(Wasm); - errdefer gpa.destroy(wasm); - wasm.* = .{ - .base = .{ - .tag = .wasm, - .options = options, - .file = null, - .allocator = gpa, - }, - .name = undefined, - }; - - if (options.use_llvm) { - wasm.llvm_object = try LlvmObject.create(gpa, options); - } 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 { - 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 +639,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,27 +653,29 @@ 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; 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(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 +697,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 +706,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 +733,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 +750,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 +764,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 +772,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 +809,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 +847,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 +878,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 +886,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 +898,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 +917,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 +937,11 @@ fn writeI32Const(writer: anytype, val: u32) !void { } fn setupInitMemoryFunction(wasm: *Wasm) !void { + 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 // dropped in __wasm_init_memory, which is registered as the start function @@ -889,21 +951,21 @@ 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").?; 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(); // 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 @@ -937,14 +999,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. @@ -969,7 +1031,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); @@ -1012,12 +1074,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; } @@ -1040,14 +1102,18 @@ 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 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; } // 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(); @@ -1086,7 +1152,10 @@ 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 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; @@ -1156,7 +1225,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( @@ -1221,10 +1290,14 @@ 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 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| { 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,21 +1305,21 @@ 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); } } - 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); - 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 +1329,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); } } @@ -1270,8 +1343,9 @@ 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.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| { @@ -1292,8 +1366,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 +1452,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 +1480,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 +1491,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 +1554,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 +1567,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 +1606,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 mod = wasm.base.options.module.?; + const gpa = wasm.base.comp.gpa; + 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); 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,7 +1670,8 @@ 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 mod = wasm.base.options.module.?; + const gpa = wasm.base.comp.gpa; + const mod = wasm.base.comp.module.?; assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions const decl = mod.declPtr(decl_index); @@ -1599,14 +1679,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 +1703,25 @@ const LowerConstResult = union(enum) { }; fn lowerConst(wasm: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { - const mod = wasm.base.options.module.?; + const gpa = wasm.base.comp.gpa; + const mod = wasm.base.comp.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 +1744,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 +1754,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 +1773,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,7 +1791,9 @@ pub fn getDeclVAddr( decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo, ) !u64 { - const mod = wasm.base.options.module.?; + 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); const target_atom_index = try wasm.getOrCreateAtomForDecl(decl_index); @@ -1718,24 +1802,24 @@ 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, // 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,9 +1835,10 @@ 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 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; @@ -1779,13 +1864,15 @@ 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 mod = wasm.base.options.module.?; + 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) { assert(reloc_info.addend == 0); // addend not allowed for function relocations @@ -1793,17 +1880,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), }); } @@ -1814,7 +1901,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; @@ -1840,8 +1932,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 +1970,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 +2005,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 +2029,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 +2049,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 mod = wasm.base.options.module.?; + const gpa = wasm.base.comp.gpa; + 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); - 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 +2090,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 +2111,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.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. @@ -2048,6 +2140,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 +2148,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 +2161,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 +2174,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 +2225,13 @@ 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 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.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 +2243,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 +2252,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 +2263,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, @@ -2183,27 +2279,27 @@ 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 import_memory) and kind.data == .uninitialized) { @memset(atom.code.items, 0); } - 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 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.*; 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); 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(wasm.base.allocator, .{ + try wasm.segments.append(gpa, .{ .alignment = atom.alignment, .size = 0, .offset = 0, @@ -2212,7 +2308,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 +2324,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 +2332,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); } } @@ -2344,7 +2441,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(); @@ -2363,12 +2460,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 +2486,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 +2499,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,9 +2538,10 @@ 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(); + 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: { @@ -2456,19 +2556,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 +2580,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 +2632,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 +2643,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 +2651,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 +2664,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 +2684,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 +2710,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 +2725,13 @@ fn setupStartSection(wasm: *Wasm) !void { } fn initializeTLSFunction(wasm: *Wasm) !void { - if (!wasm.base.options.shared_memory) return; + const comp = wasm.base.comp; + const gpa = comp.gpa; + const shared_memory = comp.config.shared_memory; - var function_body = std.ArrayList(u8).init(wasm.base.allocator); + if (!shared_memory) return; + + var function_body = std.ArrayList(u8).init(gpa); defer function_body.deinit(); const writer = function_body.writer(); @@ -2684,6 +2791,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 +2826,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 +2872,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 +2901,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 +2910,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 +2923,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 +2948,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,10 +2984,12 @@ fn mergeTypes(wasm: *Wasm) !void { } fn setupExports(wasm: *Wasm) !void { - if (wasm.base.options.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.base.options.export_symbol_names; + const force_exp_names = wasm.export_symbol_names; if (force_exp_names.len > 0) { var failed_exports = false; @@ -2898,16 +3011,16 @@ 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(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: { 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,15 +3039,16 @@ 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}); } 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 = 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}); @@ -2948,33 +3062,33 @@ fn setupStart(wasm: *Wasm) !void { } // Ensure the symbol is exported so host environment can access it - if (wasm.base.options.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 - // 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 // 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.options.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); - 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)))); } @@ -2997,7 +3111,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)); @@ -3010,7 +3124,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); @@ -3021,7 +3135,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)))); } @@ -3036,7 +3150,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; @@ -3062,7 +3176,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; @@ -3077,7 +3191,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}); @@ -3088,29 +3202,32 @@ 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 comp = wasm.base.comp; + const gpa = 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); + const shared_memory = comp.config.shared_memory; 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 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(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 +3300,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,14 +3321,15 @@ 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; - const mod = wasm.base.options.module.?; + const mod = wasm.base.comp.module.?; 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 +3341,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 +3353,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 +3363,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, @@ -3259,7 +3379,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); @@ -3269,10 +3389,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 +3402,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 +3411,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 +3424,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 +3433,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 +3443,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(); @@ -3357,49 +3480,44 @@ 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 { - if (wasm.base.options.emit == null) { - if (wasm.llvm_object) |llvm_object| { - return try llvm_object.flushModule(comp, prog_node); - } - return; - } +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 (build_options.have_llvm and wasm.base.options.use_lld) { - return wasm.linkWithLLD(comp, prog_node); - } else if (wasm.base.options.use_llvm and !wasm.base.options.use_lld) { - return wasm.linkWithZld(comp, prog_node); + if (use_lld) { + return wasm.linkWithLLD(arena, prog_node); + } else if (use_llvm) { + 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 = wasm.base.allocator; - const options = wasm.base.options; + 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 = 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 = 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. - 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 - try wasm.flushModule(comp, prog_node); + 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(arena, 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; @@ -3416,12 +3534,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 = 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 +3549,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 +3558,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.entry_name); + man.hash.add(wasm.base.stack_size); + man.hash.add(wasm.base.build_id); + 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); + 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 +3605,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 = 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 (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 (comp.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 +3645,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 +3688,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| { @@ -3578,12 +3704,15 @@ 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 comp = wasm.base.comp; + 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); @@ -3593,16 +3722,13 @@ 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 - var arena_instance = std.heap.ArenaAllocator.init(wasm.base.allocator); - defer arena_instance.deinit(); - const arena = arena_instance.allocator(); + const objects = 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); } @@ -3634,7 +3760,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 (comp.module) |mod| { var decl_it = wasm.decls.iterator(); while (decl_it.next()) |entry| { const decl = mod.declPtr(entry.key_ptr.*); @@ -3649,8 +3775,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, @@ -3685,7 +3815,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(comp.module.?); } } @@ -3711,6 +3841,14 @@ fn writeToFile( feature_count: u32, arena: Allocator, ) !void { + 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; // The amount of sections that will be written @@ -3719,9 +3857,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 = comp.config.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(); @@ -3759,8 +3897,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); @@ -3774,8 +3910,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); @@ -3937,7 +4073,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, @@ -3955,7 +4091,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 +4102,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 { @@ -4079,14 +4215,14 @@ 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 (comp.config.debug_format != .strip) { try wasm.emitNameSection(&binary_bytes, arena); } - if (!wasm.base.options.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.options.build_id) { + switch (wasm.base.build_id) { .none => {}, .fast => { var id: [16]u8 = undefined; @@ -4112,7 +4248,7 @@ fn writeToFile( } // if (wasm.dwarf) |*dwarf| { - // const mod = wasm.base.options.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. @@ -4121,7 +4257,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 { @@ -4299,6 +4435,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, @@ -4337,7 +4475,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; } @@ -4362,8 +4500,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(); @@ -4441,26 +4581,30 @@ 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(); - var arena_allocator = std.heap.ArenaAllocator.init(wasm.base.allocator); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); + 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 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 gpa = comp.gpa; + + 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. - const module_obj_path: ?[]const u8 = if (wasm.base.options.module != null) blk: { - try wasm.flushModule(comp, prog_node); + const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { + try wasm.flushModule(arena, 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; @@ -4469,23 +4613,21 @@ 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 = 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; break :blk null; }; - const target = wasm.base.options.target; - 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. @@ -4493,7 +4635,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); } @@ -4502,20 +4644,20 @@ 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.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.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.addOptionalBytes(wasm.entry_name); + man.hash.add(wasm.base.stack_size); + man.hash.add(wasm.base.build_id); + 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.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); } @@ -4553,8 +4695,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; @@ -4573,7 +4715,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 - @@ -4582,59 +4724,57 @@ 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"); } - 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) { + if (comp.config.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 { @@ -4646,42 +4786,39 @@ 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 (comp.config.rdynamic) { try argv.append("--export-dynamic"); } - if (wasm.base.options.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"); } - // 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) { + if (wasm.import_symbols) { try argv.append("--allow-undefined"); } - if (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { + if (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic) { try argv.append("--shared"); } - if (wasm.base.options.pie) { + if (comp.config.pie) { try argv.append("--pie"); } // 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"); // } @@ -4692,26 +4829,25 @@ 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 = comp.config.output_mode == .Exe or + (comp.config.output_mode == .Lib and comp.config.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 (comp.wasi_emulated_libs) |crt_file| { try argv.append(try comp.get_libc_crt_file( arena, wasi_libc.emulatedLibCRFileLibName(crt_file), )); } - 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); } @@ -4720,7 +4856,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; @@ -4742,9 +4878,9 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.options.output_mode != .Obj and - !wasm.base.options.skip_linker_dependencies and - !wasm.base.options.link_libc) + if (comp.config.output_mode != .Obj and + !comp.skip_linker_dependencies and + !comp.config.link_libc) { try argv.append(comp.libc_static_lib.?.full_object_path); } @@ -4753,7 +4889,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append(p); } - if (wasm.base.options.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..]); } @@ -4828,7 +4964,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) + 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 @@ -4838,7 +4974,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| { @@ -5089,10 +5225,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; } } @@ -5113,14 +5252,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 +5271,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,19 +5283,20 @@ 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; + const comp = wasm.base.comp; 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(comp.config.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 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); @@ -5200,3 +5342,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/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 610c534c88758d6fb7d503a397918bc6d332d431..f0c21b8c89c8a4fb84752a816f3a4a3fae02d5cf 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 3f22d8575643948a5e5c5f045fa1a4741d582c03..4442234bd2997243a52a94d0ac9ee3ba9fdd267c 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"); @@ -88,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 @@ -270,8 +271,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")) { @@ -322,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 = resolveTargetQueryOrFatal(.{}); 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(); @@ -404,37 +404,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 +477,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 +496,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 +514,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 +550,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 +566,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 +761,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 +787,11 @@ 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,54 +819,29 @@ 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; 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_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; 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; @@ -867,25 +854,17 @@ 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_evented_io = false; var test_no_exec = false; - var entry: ?[]const u8 = null; + var entry: Compilation.CreateOptions.Entry = .default; 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 stack_size: ?u64 = null; + var image_base: ?u64 = null; var link_eh_frame_hdr = false; var link_emit_relocs = false; var each_lib_rpath: ?bool = null; - var build_id: ?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 build_id: ?std.zig.BuildId = null; var runtime_args_start: ?usize = null; var test_filter: ?[]const u8 = null; var test_name_prefix: ?[]const u8 = null; @@ -893,16 +872,14 @@ 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 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; - 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; @@ -910,63 +887,103 @@ 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 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 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 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 cc_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`. + .any_c_source_files = 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 = .{}, + .resolved_system_libs = .{}, + .wasi_emulated_libs = .{}, + + .c_source_files = .{}, + .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 // 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 +994,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 +1016,77 @@ fn buildOutputType( } else { fatal("unexpected end-of-parameter mark: --", .{}); } + } 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 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 mod_name = args_iter.nextOrFatal(); + const root_src_orig = args_iter.nextOrFatal(); + + 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, + }); + } + + // 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 (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); - - 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, - }); - } - } - - 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, - }); - } - - try modules.put(mod_name, .{ - .mod = try Package.Module.create(arena, .{ + gop.value_ptr.* = .{ + .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, - }); - } 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(); + }, + .cc_argv = try cc_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; } 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 +1099,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,12 +1112,12 @@ 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; + 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", .{}); @@ -1086,46 +1128,40 @@ 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..]; + 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| { - 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| { - 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.?))) 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 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(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(args_iter.nextOrFatal()); + try create_module.framework_dirs.append(arena, args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-framework")) { - try frameworks.put(gpa, args_iter.nextOrFatal(), .{}); + try create_module.frameworks.put(arena, args_iter.nextOrFatal(), .{}); } else if (mem.eql(u8, arg, "-weak_framework")) { - try frameworks.put(gpa, 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(gpa, 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=")) { 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| { @@ -1168,7 +1204,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 +1215,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 cc_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, &cc_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, &cc_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, &cc_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, &cc_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, &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(.iframeworkwithsysroot, arg, path, false); - try framework_dirs.append(path); // Forward to the backend as -F + 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(); version = std.SemanticVersion.parse(next_arg) catch |err| { @@ -1222,23 +1257,23 @@ 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(); + create_module.sysroot = next_arg; + try cc_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")) { @@ -1258,7 +1293,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 +1333,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 +1341,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,11 +1410,11 @@ 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; + create_module.opts.rdynamic = true; } else if (mem.eql(u8, arg, "-fsoname")) { soname = .yes_default_value; } else if (mem.startsWith(u8, arg, "-fsoname=")) { @@ -1432,36 +1467,36 @@ 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")) { - 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; } 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"; + create_module.opts.debug_format = .{ .dwarf = .@"32" }; } else if (mem.eql(u8, arg, "-gdwarf64")) { - dwarf_format = .@"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")) { 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")) { @@ -1475,7 +1510,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")) { @@ -1518,13 +1555,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 (entry) { + .default, .disabled => entry = .enabled, + .enabled, .named => {}, + } } else if (mem.eql(u8, arg, "-fno-entry")) { - linker_force_entry = false; + 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 +1576,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")) { @@ -1551,7 +1591,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), }); @@ -1585,37 +1625,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 create_module.lib_dir_args.append(arena, arg[2..]); } else if (mem.startsWith(u8, arg, "-F")) { - try framework_dirs.append(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 // 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 cc_argv.append(arena, arg); } else if (mem.startsWith(u8, arg, "-I")) { - try cssan.addIncludePath(.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")) { @@ -1626,23 +1666,31 @@ 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)) { + .shared_library => { + try create_module.link_objects.append(arena, .{ .path = arg }); + create_module.opts.any_dyn_libs = true; + }, + .object, .static_library => { + try create_module.link_objects.append(arena, .{ .path = arg }); + }, + .res => { + try create_module.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 +1698,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,19 +1718,15 @@ 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; - want_native_include_dirs = true; + create_module.opts.ensure_libc_on_non_freestanding = true; + create_module.opts.ensure_libcpp_on_non_freestanding = arg_mode == .cpp; + 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 @@ -1733,24 +1779,37 @@ fn buildOutputType( } }, .other => { - try clang_argv.appendSlice(it.other_args); + try cc_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, - }), + .shared_library => { + 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 create_module.link_objects.append(arena, .{ + .path = it.only_arg, + .must_link = must_link, + }); + }, + .res => { + try create_module.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 +1819,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 +1840,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 create_module.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 +1859,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,26 +1877,26 @@ 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, + .rdynamic => create_module.opts.rdynamic = true, .wl => { var split_it = mem.splitScalar(u8, it.only_arg, ','); while (split_it.next()) |linker_arg| { @@ -1847,7 +1910,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), }); @@ -1870,7 +1933,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 +1975,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 cc_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 cc_argv.append(arena, "-gline-tables-only"); } else { - try clang_argv.appendSlice(it.other_args); + try cc_argv.appendSlice(arena, it.other_args); } }, .gdwarf32 => { - strip = false; - dwarf_format = .@"32"; + mod_opts.strip = false; + create_module.opts.debug_format = .{ .dwarf = .@"32" }; }, .gdwarf64 => { - strip = false; - dwarf_format = .@"64"; + mod_opts.strip = false; + create_module.opts.debug_format = .{ .dwarf = .@"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 cc_argv.appendSlice(arena, it.other_args); } }, .linker_script => linker_script = it.only_arg, @@ -1964,65 +2027,63 @@ 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 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("-###"); + try cc_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 create_module.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 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(it.other_args); + try cc_argv.appendSlice(arena, it.other_args); }, - .framework_dir => try framework_dirs.append(it.only_arg), - .framework => try frameworks.put(gpa, it.only_arg, .{}), - .nostdlibinc => want_native_include_dirs = false, - .strip => strip = true, + .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 => { - 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; + create_module.sysroot = it.only_arg; }, .entry => { - entry = it.only_arg; + 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 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) { 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}); }; } @@ -2077,30 +2138,25 @@ fn buildOutputType( } provided_name = name[prefix..end]; } else if (mem.eql(u8, arg, "-rpath")) { - try rpath_list.append(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 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")) { - 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")) { - 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| { @@ -2131,7 +2187,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 @@ -2145,9 +2201,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 +2211,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; + 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,17 +2223,17 @@ 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 { + 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")) { @@ -2208,10 +2264,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=")) { @@ -2232,19 +2285,13 @@ fn buildOutputType( }; have_version = true; } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { - entry = linker_args_it.nextOrFatal(); + 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| { - 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| { - 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")) { @@ -2262,7 +2309,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")) { @@ -2276,7 +2323,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")) { @@ -2290,44 +2337,40 @@ 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(gpa, 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(gpa, 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(gpa, 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 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 +2404,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 create_module.link_objects.append(arena, .{ .path = linker_args_it.nextOrFatal(), .must_link = true, }); @@ -2369,7 +2412,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, }); @@ -2402,22 +2445,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 +2477,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 +2494,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,8 +2508,8 @@ fn buildOutputType( } }, } - if (c_source_files.items.len == 0 and - link_objects.items.len == 0 and + if (create_module.c_source_files.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. @@ -2476,258 +2519,115 @@ 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, - }); - } + 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}); + } - 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, - }); - } - } + 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 = "builtin.zig"; + } - const dep_mod = modules.get(dep.name) orelse { - fatal("module '{s}' depends on module '{s}' which does not exist", .{ - kv.key_ptr.*, dep.name, + 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, }); - }; - - try kv.value_ptr.mod.deps.put(arena, dep.expose, dep_mod.mod); + } + create_module.opts.have_zcu = true; + break :b src_path; } - } - } - if (arg_mode == .build and optimize_mode == .ReleaseSmall and strip == null) - strip = true; + if (create_module.modules.count() != 0) + break :implicit_root_mod; - 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 (create_module.c_source_files.items.len >= 1) + break :b create_module.c_source_files.items[0].src_path; - if (root_src_file == null and arg_mode == .zig_test) { - fatal("`zig test` expects a zig source file argument", .{}); - } + 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; + + 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", .{}); - 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.zig.CrossTarget.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.zig.CrossTarget.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 cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options); - const target_info = try detectNativeTargetInfo(cross_target); - - if (target_info.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_info.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_info.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) { - // 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_info.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_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))) - { - 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 (use_lld) |opt| { - if (opt and cross_target.isDarwin()) { - fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{}); - } + break :implicit_root_mod; + }; + + // See duplicate logic: ModCreationGlobalFlags + 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 (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); + 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(), + .sub_path = fs.path.dirname(src_path) orelse "", + }, + .root_src_path = fs.path.basename(src_path), + }, + .cc_argv = try cc_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 (want_lto) |opt| { - if (opt and cross_target.isDarwin()) { - fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{}); - } + if (!create_module.opts.have_zcu and arg_mode == .zig_test) { + fatal("`zig test` expects a zig source file argument", .{}); } - 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,290 +2657,119 @@ 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 resolved_system_libs: std.MultiArrayList(struct { - name: []const u8, - lib: Compilation.SystemLib, - }) = .{}; - - var libc_installation: ?LibCInstallation = null; - if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, cross_target) catch |err| { - fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); - }; - } - - for (system_libs.keys(), system_libs.values()) |lib_name, info| { - if (target_util.is_libc_lib_name(target_info.target, lib_name)) { - link_libc = true; - continue; - } - if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { - link_libcpp = true; - continue; - } - switch (target_util.classifyCompilerRtLibName(target_info.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; - }, - } - - if (target_info.target.isMinGW()) { - const exists = mingw.libExists(arena, target_info.target, zig_lib_directory, lib_name) catch |err| { - fatal("failed to check zig installation for DLL import libs: {s}", .{ - @errorName(err), - }); + var global_cache_directory: Compilation.Directory = l: { + if (override_global_cache_dir) |p| { + break :l .{ + .handle = try fs.cwd().makeOpenPath(p, .{}), + .path = p, }; - if (exists) { - try resolved_system_libs.append(arena, .{ - .name = lib_name, - .lib = .{ - .needed = true, - .weak = false, - .path = null, + } + 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(); + + 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; + create_module.opts.emit_bin = emit_bin != .no; + 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| { + if (cli_mod.resolved == null) + fatal("module '{s}' declared but not used", .{key}); + } + + // 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 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; - } - } - - if (fs.path.isAbsolute(lib_name)) { - fatal("cannot use absolute path as a system library: {s}", .{lib_name}); - } - - if (target_info.target.os.tag == .wasi) { - if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { - try wasi_emulated_libs.append(crt_file); - continue; - } - } - - try external_system_libs.append(arena, .{ - .name = lib_name, - .info = info, - }); - } - // 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 - (external_system_libs.len != 0 or want_native_include_dirs)) - { - const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { - fatal("unable to detect native system paths: {s}", .{@errorName(err)}); - }; - for (paths.warnings.items) |warning| { - warn("{s}", .{warning}); - } - - try clang_argv.ensureUnusedCapacity(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); - } - - if (builtin.target.os.tag == .windows and - target_info.target.abi == .msvc and - external_system_libs.len != 0) - { - if (libc_installation == null) { - libc_installation = try LibCInstallation.findNative(.{ - .allocator = arena, - .verbose = true, - .target = cross_target.toTarget(), + .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(), }); - - try lib_dirs.appendSlice(&.{ 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 (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 (lib_dirs.items) |lib_dir_path| { - if (try accessLibPath( - &test_path, - &checked_paths, - lib_dir_path, - lib_name, - target_info.target, - info.preferred_mode, - )) { - 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, .{ - .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.target, - info.fallbackMode(), - )) { - 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, .{ - .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.target, - info.preferred_mode, - )) { - 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, .{ - .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.target, - info.fallbackMode(), - )) { - 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, .{ - .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; + 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, }, - } - @compileError("unreachable"); + .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 (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); + 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)", .{}); } } - // After this point, resolved_system_libs is used instead of 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(); @@ -3052,10 +2781,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, @@ -3090,15 +2819,15 @@ 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)) { - const total_obj_count = c_source_files.items.len + + 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) + - rc_source_files.items.len + - link_objects.items.len; + create_module.rc_source_files.items.len + + create_module.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)}); } } @@ -3108,10 +2837,12 @@ 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, - .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 @@ -3120,7 +2851,7 @@ fn buildOutputType( }, }; - const a_out_basename = switch (object_format) { + const a_out_basename = switch (target.ofmt) { .coff => "a.exe", else => "a.out", }; @@ -3142,9 +2873,9 @@ fn buildOutputType( }, .basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, - .target = target_info.target, - .output_mode = output_mode, - .link_mode = link_mode, + .target = target, + .output_mode = create_module.resolved_options.output_mode, + .link_mode = create_module.resolved_options.link_mode, .version = optional_version, }), }, @@ -3262,15 +2993,15 @@ 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.resolved_options.output_mode) { .Obj => false, - .Lib => (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 // 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; @@ -3296,76 +3027,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(); @@ -3381,37 +3046,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 @@ -3420,7 +3085,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 @@ -3448,20 +3113,35 @@ 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, .{ + const comp = Compilation.create(gpa, arena, .{ .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_info.target, - .is_native_os = cross_target.isNativeOs(), - .is_native_abi = cross_target.isNativeAbi(), - .dynamic_linker = target_info.dynamic_linker.get(), - .sysroot = sysroot, - .output_mode = output_mode, + .sysroot = create_module.sysroot, .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, @@ -3469,45 +3149,21 @@ 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, + .lib_dirs = create_module.lib_dirs.items, + .rpath_list = create_module.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, + .link_objects = create_module.link_objects.items, + .framework_dirs = create_module.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, .version_script = version_script, .disable_c_depfile = disable_c_depfile, @@ -3516,18 +3172,15 @@ 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, - .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, @@ -3542,7 +3195,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, @@ -3551,20 +3203,16 @@ fn buildOutputType( .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, + .stack_size = stack_size, + .image_base = image_base, .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, - .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, @@ -3574,21 +3222,16 @@ 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, + .disable_lld_caching = disable_lld_caching, + .cache_mode = cache_mode, .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, @@ -3598,13 +3241,15 @@ 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, + .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 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}); @@ -3632,7 +3277,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.getBuiltinDependency(); + const source = builtin_mod.builtin_file.?.source; + return std.io.getStdOut().writeAll(source); } switch (listen) { .none => {}, @@ -3681,7 +3328,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); @@ -3693,10 +3340,10 @@ 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; + 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, }); @@ -3706,23 +3353,24 @@ 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_info.target.os.tag == .windows) { + } else if (target.os.tag == .windows) { try test_exec_args.appendSlice(&.{ "--subsystem", "console", "-lkernel32", "-lntdll", }); } - 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,11 +3390,11 @@ fn buildOutputType( test_exec_args.items, self_exe_path.?, arg_mode, - &target_info, + &target, &comp_destroyed, all_args, runtime_args_start, - link_libc, + create_module.resolved_options.link_libc, ); } @@ -3754,6 +3402,522 @@ 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), + 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), + 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( + 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; + 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. + // 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; + 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 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 = 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.?, + 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) { + 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", .{}), + 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", .{}), + 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", .{}), + }; + } + + 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.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); + } + + return mod; +} + fn saveState(comp: *Compilation, debug_incremental: bool) void { if (debug_incremental) { comp.saveState() catch |err| { @@ -3805,7 +3969,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(); @@ -3827,7 +3991,7 @@ fn serve( continue; } - if (comp.bin_file.options.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { try comp.makeBinFileWritable(); } @@ -3862,7 +4026,7 @@ fn serve( // test_exec_args, // self_exe_path.?, // arg_mode, - // target_info, + // target, // true, // &comp_destroyed, // all_args, @@ -3877,7 +4041,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); @@ -3967,63 +4131,76 @@ 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.options.emit) |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.bin_file.options.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; } } -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 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); @@ -4061,7 +4238,9 @@ fn parseCrossTargetOrReportFatalError( } 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), + }), }; } @@ -4072,17 +4251,17 @@ 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, 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); @@ -4106,7 +4285,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) { @@ -4122,7 +4301,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 }); }; @@ -4174,7 +4353,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 @@ -4182,16 +4361,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); @@ -4263,13 +4442,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; }, @@ -4287,24 +4466,25 @@ 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]; - 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(); + 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) }); }; @@ -4313,14 +4493,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); @@ -4330,14 +4510,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"); @@ -4385,7 +4566,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); } }, @@ -4667,9 +4848,12 @@ 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 = .{ + .os_tag = .windows, + .abi = .msvc, + }; + 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) { // fall back to mingw @@ -4692,9 +4876,12 @@ 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 = .{ + .os_tag = .windows, + .abi = .gnu, + }; + 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 .{ .include_paths = detected_libc.libc_include_dir_list, @@ -4755,9 +4942,10 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } } - const cross_target = try parseCrossTargetOrReportFatalError(gpa, .{ + const target_query = parseTargetQueryOrReportFatalError(gpa, .{ .arch_os_abi = target_arch_os_abi, }); + const target = resolveTargetQueryOrFatal(target_query); if (print_includes) { var arena_state = std.heap.ArenaAllocator.init(gpa); @@ -4767,7 +4955,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) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; break :libc libc; @@ -4782,8 +4970,7 @@ 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 is_native_abi = target_query.isNativeAbi(); const libc_dirs = Compilation.detectLibCIncludeDirs( arena, @@ -4813,20 +5000,18 @@ 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) 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); - var libc = LibCInstallation.findNative(.{ .allocator = gpa, .verbose = true, - .target = target_info.target, + .target = target, }) catch |err| { fatal("unable to detect native libc: {s}", .{@errorName(err)}); }; @@ -4918,6 +5103,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 @@ -5024,7 +5210,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")) { @@ -5114,12 +5300,16 @@ 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 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_info.target, + .target = resolved_target.result, .output_mode = .Exe, }); const emit_bin: Compilation.EmitLoc = .{ @@ -5130,29 +5320,62 @@ 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| - .{ - .root = .{ - .root_dir = Cache.Directory.cwd(), - .sub_path = fs.path.dirname(build_runner_path) orelse "", - }, - .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", - }; + 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", + }; - var build_mod: Package.Module = .{ - .root = .{ .root_dir = build_root.directory }, - .root_src_path = build_root.build_zig_basename, + const config = try Compilation.Config.resolve(.{ + .output_mode = .Exe, + .resolved_target = resolved_target, + .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 = .{ + .resolved_target = resolved_target, + }, + .global = config, + .parent = null, + .builtin_mod = null, + }); + + const builtin_mod = root_mod.getBuiltinDependency(); + + 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 +5419,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 +5448,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 +5468,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,22 +5510,18 @@ 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, .{ + const comp = Compilation.create(gpa, arena, .{ .zig_lib_directory = zig_lib_directory, .local_cache_directory = local_cache_directory, .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(), - .dynamic_linker = target_info.dynamic_linker.get(), - .output_mode = .Exe, - .main_mod = &main_mod, + .config = config, + .root_mod = root_mod, + .main_mod = build_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, @@ -5311,17 +5541,16 @@ 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, }; - 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}, - ); + // 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; }; @@ -5515,7 +5744,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", @@ -5725,7 +5954,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", @@ -5805,15 +6034,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); @@ -6270,10 +6497,6 @@ test "fds" { gimmeMoreOfThoseSweetSweetFileDescriptors(); } -fn detectNativeTargetInfo(cross_target: std.zig.CrossTarget) !std.zig.system.NativeTargetInfo { - return std.zig.system.NativeTargetInfo.detect(cross_target); -} - const usage_ast_check = \\Usage: zig ast-check [file] \\ @@ -6378,7 +6601,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", @@ -6551,7 +6774,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", @@ -6670,24 +6893,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_cross_target: std.zig.CrossTarget = .{}; - const host_target_info = try detectNativeTargetInfo(host_cross_target); + const host_query: std.Target.Query = .{}; + const host_target = resolveTargetQueryOrFatal(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 " ++ @@ -6703,8 +6926,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 " ++ @@ -6720,8 +6943,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 " ++ @@ -6737,8 +6960,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 " ++ @@ -6754,7 +6977,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 => "", @@ -6764,8 +6987,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 => "", @@ -6814,18 +7037,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 @@ -6872,8 +7099,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 }; @@ -7249,11 +7477,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 @@ -7262,7 +7501,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"; @@ -7288,25 +7530,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, @@ -7514,3 +7756,28 @@ 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)}); +} + +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) }); +} diff --git a/src/mingw.zig b/src/mingw.zig index 5a36e00824018e7b9060cd66746c0a7bc487adea..d8f34477830473738d96dd12ed74ee917e39f2a6 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); @@ -274,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(); diff --git a/src/musl.zig b/src/musl.zig index bbb3c145bb1bc5f8c02d04a2bf1d803a25cd19db..c244257a7017f19a5757cb735d8130020c4ebd79 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"); @@ -33,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); @@ -46,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); @@ -60,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); @@ -77,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); @@ -94,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.* @@ -185,57 +196,87 @@ 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); }, .libc_so => { - const target = comp.getTarget(); + 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 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 sub_compilation = try Compilation.create(comp.gpa, .{ + 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 = cc_argv, + .parent = null, + .builtin_mod = null, + }); + + const sub_compilation = try Compilation.create(comp.gpa, arena, .{ .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.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, .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" }), + .owner = root_mod, + }, }, - .clang_argv = clang_argv, .skip_linker_dependencies = true, .soname = "libc.so", }); @@ -248,12 +289,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.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ - sub_compilation.bin_file.options.emit.?.sub_path, - }), - .lock = sub_compilation.bin_file.toOwnedLock(), - }); + comp.crt_files.putAssumeCapacityNoClobber(basename, try sub_compilation.toCrtFile()); }, } } diff --git a/src/print_env.zig b/src/print_env.zig index 89c6ffe754bc8c1c3accedfbb3baa6300ac23643..46ca10d1493237f8fb3f7c926faa333a01bf428f 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/src/target.zig b/src/target.zig index cac9aa11b064a042c9438daef0afd54988d7df83..5ae5c420c2e3e181a07ec88ab921cd4409638849 100644 --- a/src/target.zig +++ b/src/target.zig @@ -2,6 +2,9 @@ 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; pub const ArchOsAbi = struct { arch: std.Target.Cpu.Arch, @@ -204,11 +207,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) { @@ -314,6 +324,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 @@ -343,6 +361,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(); } @@ -356,96 +381,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 { @@ -465,12 +400,16 @@ 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), + .bpfel, .bpfeb => false, + else => true, + }; } pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.OptimizeMode { @@ -709,3 +648,37 @@ 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 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, + }; +} diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 2d5f0bc685de5ab1150f7e02446620a4aaa7d7aa..3c0ff26314f30f1fd832d15ed6a8a9254980d3e6 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, }); } } diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 2084fd765d928eecf5f8cdf8bb243f4f1e4380dd..4d692444efab1ee22476f35ee0ff29bc02a9ac0a 100644 Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index ac09066552f5514ca5b41bd85bac9e7b4703d187..e99925f2288621c66aec53b3b87d712d14bc5906 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 2f390413321b5eb852e218345c6877a1790bfc3a..9bbdde4777a3c459e4252554b4b1d828a3e74129 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 bee713843846d14906290c0b9f33566920f644b4..26724a1df00072a2dbeffd9c2746e29907ecc548 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, 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.Target.Query = .{ + .cpu_arch = .x86_64, + .os_tag = .linux, + }; -pub fn addCases(ctx: *Cases) !void { { - 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 a3bdf5b8f141e0fd2e23ea4befe0f6789cd2fab4..ec3726e94d0665cac0c99abc84836dcc5b3b8f17 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 3c7964fae1ef7085067dcc0f621b291a44d4a913..865af0a4889f87e51675bc89c00e14e1b9120e7b 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 bb44073e386f1563aff60792d5a0a532b6260f32..9b5c9da662925f6ce86c3284b6bdd674da8c26bf 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 049a8f5a8ffb55a436d6e77846932bd48006004e..63aff339a9760071fe7cd5f8d964021cd157464f 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 4055ec9219eb247b155a2307829d80db1ca718f3..dafbf867ed2d6bfa8750594380c60baa7158e398 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"}); + \\ + , + .c_source_flags = &.{"-fcommon"}, + }); - const d_o = addObject(b, "d", opts); - addCSourceBytes(d_o, "int baz;", &.{"-fcommon"}); + const d_o = addObject(b, opts, .{ + .name = "d", + .c_source_bytes = "int baz;", + .c_source_flags = &.{"-fcommon"}, + }); - const lib = addStaticLibrary(b, "lib", opts); + 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,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, "a", opts); - addCSourceBytes(dso, + const dso = addSharedLibrary(b, opts, .{ + .name = "a", + .c_source_bytes = \\#include \\__attribute__((ifunc("resolve_foobar"))) \\void foobar(void); @@ -1244,16 +1330,19 @@ fn testIFuncDso(b: *Build, opts: Options) *Step { \\static Func *resolve_foobar(void) { \\ return real_foobar; \\} - , &.{}); + , + }); dso.linkLibC(); - const exe = addExecutable(b, "main", opts); - 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); @@ -1283,7 +1372,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 +1384,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 +1401,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 +1427,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 +1450,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 +1465,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 +1481,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 +1496,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 +1524,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 +1540,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 +1567,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 +1591,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 +1609,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 +1642,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 +1683,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 +1763,7 @@ fn testInitArrayOrder(b: *Build, opts: Options) *Step { exe.addObject(g_o); exe.addObject(h_o); - if (opts.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; } @@ -1666,7 +1778,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 +1807,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 +1827,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 +1872,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 +1893,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 +1934,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 +1956,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 +1991,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 +2011,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 +2040,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 +2069,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 +2099,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 +2133,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 +2171,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 +2199,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 +2216,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 +2225,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 +2247,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 +2257,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 +2265,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 +2281,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 +2295,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 +2315,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 +2376,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 +2393,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 +2417,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 +2447,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 +2462,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 +2494,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 +2533,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 +2558,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 +2584,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 +2602,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 +2626,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 +2642,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 +2650,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 +2684,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 +2699,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 +2745,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 +2758,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 +2770,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 +2788,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 +2804,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 +2826,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 +2840,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 +2860,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 +2873,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 +2904,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 +2921,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 +2935,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 +2955,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 +2970,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 +2984,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 +3004,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 +3023,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 +3075,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 +3094,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 +3128,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 +3137,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 +3152,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 +3165,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 +3194,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 +3213,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 +3247,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 +3261,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 +3288,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 +3307,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 +3325,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 +3338,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 +3356,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 +3379,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 +3393,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 +3407,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 +3431,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 +3476,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 +3498,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 +3529,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 +3559,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 +3603,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 +3628,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 +3650,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 +3674,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 +3697,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 +3714,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 +3730,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 +3755,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 +3765,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 +3780,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,13 +3828,11 @@ 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"); 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 a104633fd76478353fc4d4a2fb4bbd33b588076b..bb8d5d056daf1f30a1ca968a395156757670a8c7 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 = std.zig.CrossTarget.parse( + .target = b.resolveTargetQuery(std.Target.Query.parse( .{ .arch_os_abi = t }, - ) catch unreachable, + ) catch unreachable), }); + exe.addCSourceFile(.{ .file = .{ .path = "main.c" } }); exe.linkLibC(); // TODO: actually test the output _ = exe.getEmittedBin(); diff --git a/test/link/interdependent_static_c_libs/build.zig b/test/link/interdependent_static_c_libs/build.zig index 757c0d419b6364ed3cf7f5d3a89a0ac657ca5a9a..01ed218cce3f73d12e19b71b891739f9311d243f 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 b08a929d8b30a4bb664f13ecaf125dee64410506..ccce03bb0b4f35a6ca5b9d2a7ac0a40e4f3e5deb 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.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-" ++ 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); @@ -108,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 f172d9af17a2b3b12a7aabfbac369e9c145b6fee..8a5016f9b7d70a241350f85dea994dd44c1fc4ba 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,14 @@ 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 5b19daab3cfd02ac856d1f3a9105514f41d7943a..53bcefb9308bf328acfd6515b7cea9b5f57546ba 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.result) 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 89096bba387d9f9f9cab34338c76507361c037d6..fe835b5715a03190ce930b7c2ddec9a19c08e42e 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 3d7a884bd028b061de2090bfeab6479e4df5d7ea..f4456b111cc88ec80ef2dd1f81f305ec936e4aa0 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 aa396f7a3bc5e5d072b44ba218b70644df05cf64..59c666aa27ec944bc1e50654ab5ed9a53efd6ece 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 8b8449b6b214d58ab3f7b5015e39188324348aeb..a5bb28df9f57fb04ccf7c38b1618fe7d3a683704 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 52d7f2eac8a33617c1a85f8f12c770a3c0fe7a1c..7ab8c16dfeba4af31276952f7dfdaaf1e4d57b5d 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 beebfbdd021cb242698d7ace713ab3df0dd25262..abd7175eae408064e6e98df2736cb85338f8dbd8 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 6a1350770271cc47a70af3da9636d2f680e857cf..af38930ae88d2c8aae740bff1099cc5acb7e282a 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 9675935a9c3c0fe10ae7a58c526493c96ffa56a4..0ef717f2927e7e33ed3fb929edceaba72c2bac39 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 f48e612d95d4072cb5caa035f909217ca305ec94..72f340b204bf9d1f15e1db2c071aff8bc744613c 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 5b93541a5a0b98f6e56bdf58636f034d7ab556f4..7827552bcfdc98ac4c691354e162880f2e854e4e 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 3c0bb7c5725ca46240b5c44e30d507403e6ea4d3..b982224e8566837c19024cfb0f5d4f9977c2c902 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 113034f96f9f0f33d3c9cd559beb45e6fca4171e..91ddfe530c5a09149f5d119911907452b490aea5 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 45c046fe0bf52f15c7fc219685ce1d16d4008c57..83a3e75e2db480675dd20a40ebea55e401641fd9 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 cc9d2bd6465f7a641e9b286337145fc7a95864bd..a07493a8b1555ef912c1fd8e48ed8d42c8c3fc38 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 979c0aa943276b6c26dd64c018cdeb4b4b2e858e..26bbdc2673647c5e98417410252519a843fea875 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 183d3cb9d3ef8d4138ed5b9f2834303b5064fac0..53743fafdfd562e729b1526220897b1d176c7f2d 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 1ca7f28f11081ee12a093a1b276cb485ec673699..cee2aa9fd506b7b31b5db0d785bd4a61d62b1a85 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 d9a9481fa0be9d415c2c0727ca40261003f21dfa..44c96ecf7ebabe47bc3132f18280960ba7f38b91 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 b76de65b0eac79a2bc8b401da135e45483cd1429..181d2df91ab4d931c726c1f5f390cc944697bb17 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 48496bd9d51e3b0a5c7133aa5cf0f5c429547189..28a2602ea5e3a0f40ebeb671933a46b8469f3297 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 1cfaac49103fdddf8993ff4bc5fc519a24c49dbf..f35438369c90d113d2afaeb4855a1e8a13e0593f 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 ba11004f29b9e9af07efd552ea587f2778dde360..547f72c25fc3759ec9729f1f590dfae3747471a0 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 443f698ea6beb13800c708e8ff40159457599de5..af2ac8a9c63084c3db3d563040e39820bb18b7c2 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 96c4a67568bf9faa58ef0f846da66b064a251c3b..534cc4e51a1dd6f2445ac8d466a861fd2ae02bfa 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 dfb41b7457e73751eb61c8af211fef57579a5cdc..2a430443d4556159406540999708bcd12b8576be 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 7ae7c7c2d6529dd13e253cdfbcd18c8822725335..0d73b9f4eaa4347b446feefbcb0db1796738e640 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 e5a4b79acd8f47bf88556690754902a07ce3ff06..d0ea78bbd66c4f8f82eb6eb7b4aa9131b5426ab3 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 95aea2913e9ff3ccb3526accf0c18e939cd80ff3..1d5e031848b91c948bc95ba34e737ab4c825eb02 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 9cf28ea31ef81b1e020efd0e98ba00ae4d8da4ff..6f9e82d09df3683cd29894a472a3bc67c28b15c9 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 c569225f8b2548782f4229886db5497322aa749f..3a1592f394d5e2337350688edfe44c5765d12969 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 f1bba98d5f4bcebbf40a802aabf23641ec2ee7dc..bba00d5c12813b576f913da6c90b57348b424fd6 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 2183ccd5855af1af8b2ff33fd3c09a9eaceed579..ab2893ce3c6a6f3ff6fbb98a89f4704af0530718 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 d361dc140e96eb9a30380017b7a6eb8ec78f71a7..41a00eefc97da3c7bf3f3da33991aa2124ac9ff2 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 a505899520421601f1ddaa2c5aba23d3f4b36b89..baa2b6d61e81e96a24226481321d4b8f972cabea 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 5a139acb3e6b891f770897a1b1de6468d085dfe4..aca66e4f7157f88b4ca7a80f17d5b0119e2f100d 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 c883063dc5143a482f9db629402ced88958b4d6a..e3fe860f54062a9c140cede530202272233064f6 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 b66521a45691933968b968861d71b42a9dc863b8..4fb777e1232d19c4932be302083bf5776613c970 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 6ab2e4a7a320405b0c4e59409d20a25400f261ff..86073ff9770d6c48ddfd4abe8fb104d39809319b 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 a1d660d13582e21895f355bff503a3adcddc4fd5..f8751d99c049d83e19e3e5187e88fff116a8fdd6 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 93c0f10e1475c78b818c75f62d0e532ab17c461b..e95c27827ed0b5dc95dbdf7820e692bf04a66cfc 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 88ded91403a56128506fb9dcc17ca03896b171d8..a318ddb1f97d9688d685a73e0151d4ebce9ea4e8 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 6f01925a9fc286374d3108819925634f3f411db8..99eb161a58920ac6571eb6d074804cb707996cf8 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 }, @@ -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 c3748570e89c4101b9e2037f42bcff23e06ad395..fd4c66db89786aa5c2507bf6bfeb96333975bdce 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 262f8e9ac76e491afe43c7d89370a03195d9be80..6fedf43bf729240ac71977ccc9fa611305891169 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.Target.Query, 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.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); @@ -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.result; + 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, @@ -538,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| { @@ -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,10 +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)}); - if (host.getExternalExecutor(&target_info, .{ .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; } @@ -666,7 +667,7 @@ pub fn lowerToBuildSteps( "--", "-lc", "-target", - case.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; @@ -692,9 +693,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)}); - if (host.getExternalExecutor(&target_info, .{ .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. } @@ -1159,9 +1158,9 @@ const TestManifest = struct { } fn getDefaultParser(comptime T: type) ParseFn(T) { - if (T == CrossTarget) return struct { + if (T == std.Target.Query) return struct { fn parse(str: []const u8) anyerror!T { - return CrossTarget.parse(.{ .arch_os_abi = str }); + return std.Target.Query.parse(.{ .arch_os_abi = str }); } }.parse; @@ -1198,7 +1197,8 @@ const builtin = @import("builtin"); const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const CrossTarget = std.zig.CrossTarget; +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"); @@ -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.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); @@ -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,8 +1385,16 @@ pub fn main() !void { return runCases(&ctx, zig_exe_path); } +fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget { + return .{ + .query = query, + .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); @@ -1467,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; @@ -1477,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(); @@ -1568,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, @@ -1704,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. } @@ -1723,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 diff --git a/test/src/CompareOutput.zig b/test/src/CompareOutput.zig index 39226f03692912ec26db8469c3cc6bd2db950afb..b3570b6ee22408d35208369f332d24d1cd5997e1 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 c42e9114be8c383e45c7657694adb90b24a641d3..191c35009147f16a5b1e762678a59b543801eefd 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})", .{ @@ -77,7 +56,8 @@ fn addExpect( .name = "test", .root_source_file = write_src.files.items[0].getPath(), .optimize = optimize_mode, - .target = .{}, + .target = b.host, + .error_tracing = mode_config.error_tracing, }); const run = b.addRunArtifact(exe); diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig index cd2d0d9e3b16449d924107442106727a5686a554..544f9a53098a7dab579bf4360ca0242e9d801fa1 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 a71886099f7a6bac0b98f1199c2a21d71c230964..528e370918c37f73f580b0e6e93f9e3f68e68fe9 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 = 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 { @@ -109,7 +108,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/stack_traces.zig b/test/stack_traces.zig index 0ace004bc64c8430f36148f7874b0951812b741c..467c53bcb935e67169d4306a420f0c2cf8da021d 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(); diff --git a/test/standalone.zig b/test/standalone.zig index fc455a2aa71c154011d38791e2d5e221560c4630..b26e85c15930ef8db317be34a16186c9d89cb436 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. @@ -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"), @@ -262,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/c_compiler/build.zig b/test/standalone/c_compiler/build.zig index a2191f2f2eb5e972dad38e8dd14cb29fdd16e1c0..0550ad8cee75d899469c206ff0ae6d93f48102e0 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.result.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 b874a7acc5e63e7c689f270e8c0e967f50711a4a..89558c00e6096842c03a24172537b9ff39b0718d 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/coff_dwarf/build.zig b/test/standalone/coff_dwarf/build.zig index b85b44b686cbedbffff958ca4994d97563360107..cd7c17efb37e3addc102196e7dbbf956e713e6a8 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" }, diff --git a/test/standalone/compiler_rt_panic/build.zig b/test/standalone/compiler_rt_panic/build.zig index 3d22319bacf512edf330486cd2f9ac4fb707f305..8ad7732a931b5fe2f3b15f0a3c3a20ce31d48f99 100644 --- a/test/standalone/compiler_rt_panic/build.zig +++ b/test/standalone/compiler_rt_panic/build.zig @@ -7,8 +7,8 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const abi = target.getAbi(); - if (target.getObjectFormat() != .elf or !(abi.isMusl() or 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", diff --git a/test/standalone/dep_diamond/build.zig b/test/standalone/dep_diamond/build.zig index 6c6d9b6d1a2586cd7f0526ae6e03e3e82b5267fb..9190b29594cf3cd82c4cbbe7814295629d05bf03 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 e70e775401821c0f7567cc850dd793c1d5d2fbac..04589d9b5ba4da05bc81dedd2a1a80b595421c3c 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 2e2cf4ea4d4feb3afa7baebb80046130424ad11e..a6334e6a9763f265532571d09473cc000028fbb5 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 175118d33192cb167898f696f2dbd4d386a53c7f..33d53ad166ba11f8dbc85c8ca355429459a776c2 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 63eed997ceb62904cbd30cdfd6fb2314a75d53a2..b155554997531ef9b8111d381b02da498ccc0e7c 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/depend_on_main_mod/build.zig b/test/standalone/depend_on_main_mod/build.zig new file mode 100644 index 0000000000000000000000000000000000000000..bbef64693e59f8864d49e0a68509931011a2969e --- /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 0000000000000000000000000000000000000000..0a52bce8aa6fc1244df88629162c9e2af4a77c9a --- /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 0000000000000000000000000000000000000000..0735fff4c790e3877e9479d0835cc630683b44fb --- /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(); +} diff --git a/test/standalone/embed_generated_file/build.zig b/test/standalone/embed_generated_file/build.zig index ca05c33c39a65bdefd093668e947de5651bd801d..3f67cdea5421acf0630f49222e61d3b0ba1fb4c0 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 27ec75be22df62f59cea4ee19b176e70239bce1e..a2fe48312827853e9c34ff6ddcef65a293c418dd 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 153380e91ded1b36891c41f2318caf150726b05c..401deb3dc4d117242c7cbfa6d349fb83748bd447 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 d560027265cbcd7b5b33ada5f7c694824d11ed3f..13b7fcfa0e5ffc9b1bee178a37414b586d5253d6 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 c05490a3e5b97ba90915e1e04321a6e03dc22bf6..d1ec55ab53494ce9a9fb4f9e4484b785e29fae47 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 18168688445d57cf132e6794703391aa1654f30c..356f12a3d90297eba96d03b645538340bda2438d 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.result) 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 e69b4bfdd593bd5a87bc93d53466544929505abd..c591b3058b5de164bbee70e6d21361a4df657bcd 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 e6d01192d3cf0f8c6bbb3495b6302dd29b7305f3..aaf8f6c3149b308e5e685f5c6ef2fbc8e973f316 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 fb60ac28a114ad45ac9684513483b8babc3ae533..9a80dae256fec810274b3ffad465bcb34f4d082e 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 d53ba992ea3ed052c563d5f6c1623e3a33798cd0..5dc686a77924c4af8432a60541dca3ae49ab6553 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_5825/build.zig b/test/standalone/issue_5825/build.zig index a6573175399b322c6664ee3bb78d2a5f7545101d..078a9415701b70c9ff27a90bedc4622f4eb410b3 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", diff --git a/test/standalone/issue_8550/build.zig b/test/standalone/issue_8550/build.zig index a7815618744b9ca914e44dbc6588cf422405df9b..557019cfdc044379d3ccc8fd68f73d0987389449 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 5dc605e71111998657c33e879ce8e15a61692280..140f276ebe0479b129508ade6b6c4e59b6b78db5 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 286489912b392f4e891fddef0b3e91e9ce27eb41..0000000000000000000000000000000000000000 --- 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 87d61fa63e887512abddd3a1c64891c53cf95595..0000000000000000000000000000000000000000 --- 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 d1b67592b5b05c4ab9d9aa6bf1c0ddbc36015705..0000000000000000000000000000000000000000 --- 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 b675be9eebe4b6b461d0f0ccabeb0cc2991570d0..e91f87e13284d128d65c0a9a184d8c07d35a4c5a 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 980e52ad3baa8b86829eefa0ce8c86e9986e6cec..aa648145a831785b5a19b56a7934f1cbd6efac0d 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 d87610ba220a369e4e3e7a36615d512e48e353b0..97cf91c1fbc3876df28d99ab2af11c21a449753d 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 1efcd5c26e87b77a3a0fbef4b2003bcece91c3be..2e9f99ff4b67a50df466ee7dd6750a3210fc8938 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 30f4b2ede49bbef528ad751a84ddf41add170462..207f924f9be97a393082b55959a39de8c5f6ce1d 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 10e0a6a5127da5e62fd732391ceb08d4c9c2dbc8..d61d5025743366a9bd56addc9423d3ef13a37fc3 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.result.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 4b4a154225c47c9bebf2f6e775679a62db6a62ad..4d409295e866f31c8e8a787c05b7853a560c8e33 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 628210452c428a7e750a6a638663d78854facf18..463a533ac4009996e377b802e415f0621b612618 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 = if (target.result.isDarwin()) true else null, + .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.result.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 = if (target.result.isDarwin()) true else null, + .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 1e3e80c36323fdce2b05cacd1fe2fda7108b7d7a..244107b0f1e180b83f91b922e5220442e28b849a 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 e64781d9914255a937a5c9ad3c51c263376a3f64..4875bd9128c73bbff18c2f630879ef9591262966 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 b67da4681905bf12b429afb6e894a8094ea4d877..2d903f973a1fd83482f201f70c8ea059471793ff 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 f277718898277da412e4748e5e201938fac9c7b1..af8e68d7178942ebff7377597da8a4035eabb63b 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 9476fa7839db720e358535a8932641678c1dfb40..51117515715a8e58ea5bd3a9982273db9a9ece2c 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 target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu, - }; + }); - add(b, native_target, .any, test_step); - add(b, cross_target, .any, test_step); + add(b, b.host, .any, test_step); + add(b, target, .any, test_step); - add(b, native_target, .gnu, test_step); - add(b, cross_target, .gnu, test_step); + add(b, b.host, .gnu, test_step); + add(b, 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 6c865f0a9fc10b1bb16aa88c812338a49e40105e..a52cbd7202a35c503d6e1f0720615541ab93445a 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 4e5c1937f733e5b0fdc84be5862bc80858c8062f..dacfc841c1a7059eab0c79a4ca5f48b33e6b58ba 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 808ffad6ee171b6eb93189c61b894e805d80bc12..b2fb1e4bca9cc343e475f47a1963ebcdd4414237 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.Target.Query = .{}, 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.Target.Query.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.Target.Query.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8a", }) catch unreachable, }, .{ - .target = CrossTarget.parse(.{ + .target = std.Target.Query.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.Target.Query.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.Target.Query = .{}, 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.* = .{ @@ -1035,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.result; + 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) @@ -1052,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 @@ -1093,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; @@ -1105,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 = test_target.target, + .target = resolved_target, .max_rss = max_rss, .filter = options.test_filter, .link_libc = test_target.link_libc, @@ -1113,24 +1112,24 @@ 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" - 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" 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" }); - 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; } @@ -1147,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 = altered_target, + .target = b.resolveTargetQuery(altered_query), .zig_lib_dir = .{ .path = "lib" }, }); compile_c.addCSourceFile(.{ @@ -1178,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. @@ -1229,41 +1228,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.result; + + 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 +1294,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( diff --git a/test/translate_c.zig b/test/translate_c.zig index 2b87da4067555f19f785c96643398838d4959d41..a3908108306fbdf7f74b9395cb6259655e5ce2ae 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, diff --git a/tools/docgen.zig b/tools/docgen.zig index 669f6bca8d5df7383f3219c974ed16288e6f9f6b..1003db0b5ac21964abddd0e05dfaad15b5491153 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 => {},