From b7bdd8b8bf259c11c508d3c428473ac5c3358f59 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Mon, 6 Jan 2025 13:05:36 -0800 Subject: [PATCH] Target: update the extra features before resolving the dynamic linker --- lib/std/zig/system.zig | 90 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 591e369ff763..9c2cad3be163 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -342,7 +342,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { os.version_range.linux.android = android; } - const cpu = switch (query.cpu_model) { + var cpu = switch (query.cpu_model) { .native => detectNativeCpuAndFeatures(query_cpu_arch, os, query), .baseline => Target.Cpu.baseline(query_cpu_arch, os), .determined_by_arch_os => if (query.cpu_arch == null) @@ -354,55 +354,22 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { break :backup_cpu_detection Target.Cpu.baseline(query_cpu_arch, os); }; - var result = try detectAbiAndDynamicLinker(cpu, os, query); - - // It's possible that we detect the native ABI, but fail to detect the OS version or were told - // to use the default OS version range. In that case, while we can't determine the exact native - // OS version, we do at least know that some ABIs require a particular OS version (by way of - // `std.zig.target.available_libcs`). So in this case, adjust the OS version to the minimum that - // we know is required. - if (result.abi != query_abi and query.os_version_min == null) { - const result_ver_range = &result.os.version_range; - const abi_ver_range = result.os.tag.defaultVersionRange(result.cpu.arch, result.abi).version_range; - - switch (result.os.tag.versionRangeTag()) { - .none => {}, - .semver => if (result_ver_range.semver.min.order(abi_ver_range.semver.min) == .lt) { - result_ver_range.semver.min = abi_ver_range.semver.min; - }, - inline .hurd, .linux => |t| { - if (@field(result_ver_range, @tagName(t)).range.min.order(@field(abi_ver_range, @tagName(t)).range.min) == .lt) { - @field(result_ver_range, @tagName(t)).range.min = @field(abi_ver_range, @tagName(t)).range.min; - } - - if (@field(result_ver_range, @tagName(t)).glibc.order(@field(abi_ver_range, @tagName(t)).glibc) == .lt and - query.glibc_version == null) - { - @field(result_ver_range, @tagName(t)).glibc = @field(abi_ver_range, @tagName(t)).glibc; - } - }, - .windows => if (!result_ver_range.windows.min.isAtLeast(abi_ver_range.windows.min)) { - result_ver_range.windows.min = abi_ver_range.windows.min; - }, - } - } - // 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 (result.cpu.arch) { + switch (query_cpu_arch) { .x86 => { if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ .@"16bit_mode", .@"32bit_mode", })) { - switch (result.abi) { - .code16 => result.cpu.features.addFeature( + switch (query_abi) { + .code16 => cpu.features.addFeature( @intFromEnum(Target.x86.Feature.@"16bit_mode"), ), - else => result.cpu.features.addFeature( + else => cpu.features.addFeature( @intFromEnum(Target.x86.Feature.@"32bit_mode"), ), } @@ -413,32 +380,65 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { // What do we do if the user specifies +thumb_mode? }, .thumb, .thumbeb => { - result.cpu.features.addFeature( + cpu.features.addFeature( @intFromEnum(Target.arm.Feature.thumb_mode), ); }, else => {}, } updateCpuFeatures( - &result.cpu.features, - result.cpu.arch.allFeaturesList(), + &cpu.features, + cpu.arch.allFeaturesList(), query.cpu_features_add, query.cpu_features_sub, ); - if (result.cpu.arch == .hexagon) { + if (cpu.arch == .hexagon) { // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize` // command line parameter for the Hexagon backend to 0, so that no constants get placed in // the SDA. (This of course breaks down if the user passes `-G ` to Clang...) We can't do // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command // line options in LLVM are shared globally. So just force this feature off. Lovely stuff. - result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); + cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); } // https://github.com/llvm/llvm-project/issues/105978 - if (result.cpu.arch.isArm() and result.floatAbi() == .soft) { - result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); + if (cpu.arch.isArm() and query_abi.floatAbi() == .soft) { + cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); + } + + var result = try detectAbiAndDynamicLinker(cpu, os, query); + + // It's possible that we detect the native ABI, but fail to detect the OS version or were told + // to use the default OS version range. In that case, while we can't determine the exact native + // OS version, we do at least know that some ABIs require a particular OS version (by way of + // `std.zig.target.available_libcs`). So in this case, adjust the OS version to the minimum that + // we know is required. + if (result.abi != query_abi and query.os_version_min == null) { + const result_ver_range = &result.os.version_range; + const abi_ver_range = result.os.tag.defaultVersionRange(result.cpu.arch, result.abi).version_range; + + switch (result.os.tag.versionRangeTag()) { + .none => {}, + .semver => if (result_ver_range.semver.min.order(abi_ver_range.semver.min) == .lt) { + result_ver_range.semver.min = abi_ver_range.semver.min; + }, + inline .hurd, .linux => |t| { + if (@field(result_ver_range, @tagName(t)).range.min.order(@field(abi_ver_range, @tagName(t)).range.min) == .lt) { + @field(result_ver_range, @tagName(t)).range.min = @field(abi_ver_range, @tagName(t)).range.min; + } + + if (@field(result_ver_range, @tagName(t)).glibc.order(@field(abi_ver_range, @tagName(t)).glibc) == .lt and + query.glibc_version == null) + { + @field(result_ver_range, @tagName(t)).glibc = @field(abi_ver_range, @tagName(t)).glibc; + } + }, + .windows => if (!result_ver_range.windows.min.isAtLeast(abi_ver_range.windows.min)) { + result_ver_range.windows.min = abi_ver_range.windows.min; + }, + } } return result;