From e260cfae85ccee253d85a9ecb713380c8fbb0ded Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 10 May 2021 10:59:52 +0200 Subject: [PATCH] stage2: Add CPU feature detection for macos This is mostly meant to detect the current and future AArch64 core types as the x86 part is already taken care of with OS-independent machinery. --- lib/std/os/bits/darwin.zig | 35 +++++++++++++++++++++++++ lib/std/zig/system.zig | 11 +++++--- lib/std/zig/system/macos.zig | 51 ++++++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index e3e09bfb5b..d399c4e8f6 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -1751,3 +1751,38 @@ pub const IOCPARM_MASK = 0x1fff; fn ior(inout: u32, group: usize, num: usize, len: usize) usize { return (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)); } + +// CPU families mapping +pub const CPUFAMILY = enum(u32) { + UNKNOWN = 0, + POWERPC_G3 = 0xcee41549, + POWERPC_G4 = 0x77c184ae, + POWERPC_G5 = 0xed76d8aa, + INTEL_6_13 = 0xaa33392b, + INTEL_PENRYN = 0x78ea4fbc, + INTEL_NEHALEM = 0x6b5a4cd2, + INTEL_WESTMERE = 0x573b5eec, + INTEL_SANDYBRIDGE = 0x5490b78c, + INTEL_IVYBRIDGE = 0x1f65e835, + INTEL_HASWELL = 0x10b282dc, + INTEL_BROADWELL = 0x582ed09c, + INTEL_SKYLAKE = 0x37fc219f, + INTEL_KABYLAKE = 0x0f817246, + ARM_9 = 0xe73283ae, + ARM_11 = 0x8ff620d8, + ARM_XSCALE = 0x53b005f5, + ARM_12 = 0xbd1b0ae9, + ARM_13 = 0x0cc90e64, + ARM_14 = 0x96077ef1, + ARM_15 = 0xa8511bca, + ARM_SWIFT = 0x1e2d6381, + ARM_CYCLONE = 0x37a09642, + ARM_TYPHOON = 0x2c91a47e, + ARM_TWISTER = 0x92fb37c8, + ARM_HURRICANE = 0x67ceee93, + ARM_MONSOON_MISTRAL = 0xe81e7ef6, + ARM_VORTEX_TEMPEST = 0x07d34b9f, + ARM_LIGHTNING_THUNDER = 0x462504d2, + ARM_FIRESTORM_ICESTORM = 0x1b588bb3, + _, +}; diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 6e3a2815d6..5522367d36 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -982,12 +982,15 @@ pub const NativeTargetInfo = struct { else => {}, } + switch (std.Target.current.os.tag) { + .linux => return linux.detectNativeCpuAndFeatures(), + .macos => return macos.detectNativeCpuAndFeatures(), + else => {}, + } + // This architecture does not have CPU model & feature detection yet. // See https://github.com/ziglang/zig/issues/4591 - if (std.Target.current.os.tag != .linux) - return null; - - return linux.detectNativeCpuAndFeatures(); + return null; } }; diff --git a/lib/std/zig/system/macos.zig b/lib/std/zig/system/macos.zig index be892b4834..0b3e639582 100644 --- a/lib/std/zig/system/macos.zig +++ b/lib/std/zig/system/macos.zig @@ -7,10 +7,13 @@ const std = @import("std"); const assert = std.debug.assert; const mem = std.mem; const testing = std.testing; +const os = std.os; + +const Target = std.Target; /// Detect macOS version. -/// `os` is not modified in case of error. -pub fn detect(os: *std.Target.Os) !void { +/// `target_os` is not modified in case of error. +pub fn detect(target_os: *Target.Os) !void { // Drop use of osproductversion sysctl because: // 1. only available 10.13.4 High Sierra and later // 2. when used from a binary built against < SDK 11.0 it returns 10.16 and masks Big Sur 11.x version @@ -60,8 +63,8 @@ pub fn detect(os: *std.Target.Os) !void { if (parseSystemVersion(bytes)) |ver| { // never return non-canonical `10.(16+)` if (!(ver.major == 10 and ver.minor >= 16)) { - os.version_range.semver.min = ver; - os.version_range.semver.max = ver; + target_os.version_range.semver.min = ver; + target_os.version_range.semver.max = ver; return; } continue; @@ -410,7 +413,7 @@ fn testVersionEquality(expected: std.builtin.Version, got: std.builtin.Version) /// `-syslibroot` param of the linker. /// The caller needs to free the resulting path slice. pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 { - assert(std.Target.current.isDarwin()); + assert(Target.current.isDarwin()); const argv = &[_][]const u8{ "xcrun", "--show-sdk-path" }; const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }); defer { @@ -426,3 +429,41 @@ pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 { const syslibroot = mem.trimRight(u8, result.stdout, "\r\n"); return mem.dupe(allocator, u8, syslibroot); } + +pub fn detectNativeCpuAndFeatures() ?Target.Cpu { + var cpu_family: os.CPUFAMILY = undefined; + var len: usize = @sizeOf(os.CPUFAMILY); + os.sysctlbynameZ("hw.cpufamily", &cpu_family, &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 => unreachable, // EFAULT: stack should be safe, EISDIR/ENOTDIR: constant, known good value + }; + + const current_arch = Target.current.cpu.arch; + switch (current_arch) { + .aarch64, .aarch64_be, .aarch64_32 => { + const model = switch (cpu_family) { + .ARM_FIRESTORM_ICESTORM => &Target.aarch64.cpu.apple_a14, + .ARM_LIGHTNING_THUNDER => &Target.aarch64.cpu.apple_a13, + .ARM_VORTEX_TEMPEST => &Target.aarch64.cpu.apple_a12, + .ARM_MONSOON_MISTRAL => &Target.aarch64.cpu.apple_a11, + .ARM_HURRICANE => &Target.aarch64.cpu.apple_a10, + .ARM_TWISTER => &Target.aarch64.cpu.apple_a9, + .ARM_TYPHOON => &Target.aarch64.cpu.apple_a8, + .ARM_CYCLONE => &Target.aarch64.cpu.cyclone, + else => return null, + }; + + return Target.Cpu{ + .arch = current_arch, + .model = model, + .features = model.features, + }; + }, + else => {}, + } + + return null; +}