authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-05-10 10:59:52+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-12 09:43:49+02:00
loge260cfae85ccee253d85a9ecb713380c8fbb0ded
treebaa2466f4ba0164be9aad139b17ade39d81f5014
parent30ace64fc4881e1799dfdbf2b034dc3b5a29f1d1

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.

3 files changed, 88 insertions(+), 9 deletions(-)

lib/std/os/bits/darwin.zig+35
...@@ -1751,3 +1751,38 @@ pub const IOCPARM_MASK = 0x1fff;...@@ -1751,3 +1751,38 @@ pub const IOCPARM_MASK = 0x1fff;
1751fn ior(inout: u32, group: usize, num: usize, len: usize) usize {1751fn ior(inout: u32, group: usize, num: usize, len: usize) usize {
1752 return (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num));1752 return (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num));
1753}1753}
1754
1755// CPU families mapping
1756pub const CPUFAMILY = enum(u32) {
1757 UNKNOWN = 0,
1758 POWERPC_G3 = 0xcee41549,
1759 POWERPC_G4 = 0x77c184ae,
1760 POWERPC_G5 = 0xed76d8aa,
1761 INTEL_6_13 = 0xaa33392b,
1762 INTEL_PENRYN = 0x78ea4fbc,
1763 INTEL_NEHALEM = 0x6b5a4cd2,
1764 INTEL_WESTMERE = 0x573b5eec,
1765 INTEL_SANDYBRIDGE = 0x5490b78c,
1766 INTEL_IVYBRIDGE = 0x1f65e835,
1767 INTEL_HASWELL = 0x10b282dc,
1768 INTEL_BROADWELL = 0x582ed09c,
1769 INTEL_SKYLAKE = 0x37fc219f,
1770 INTEL_KABYLAKE = 0x0f817246,
1771 ARM_9 = 0xe73283ae,
1772 ARM_11 = 0x8ff620d8,
1773 ARM_XSCALE = 0x53b005f5,
1774 ARM_12 = 0xbd1b0ae9,
1775 ARM_13 = 0x0cc90e64,
1776 ARM_14 = 0x96077ef1,
1777 ARM_15 = 0xa8511bca,
1778 ARM_SWIFT = 0x1e2d6381,
1779 ARM_CYCLONE = 0x37a09642,
1780 ARM_TYPHOON = 0x2c91a47e,
1781 ARM_TWISTER = 0x92fb37c8,
1782 ARM_HURRICANE = 0x67ceee93,
1783 ARM_MONSOON_MISTRAL = 0xe81e7ef6,
1784 ARM_VORTEX_TEMPEST = 0x07d34b9f,
1785 ARM_LIGHTNING_THUNDER = 0x462504d2,
1786 ARM_FIRESTORM_ICESTORM = 0x1b588bb3,
1787 _,
1788};
lib/std/zig/system.zig+7-4
...@@ -982,12 +982,15 @@ pub const NativeTargetInfo = struct {...@@ -982,12 +982,15 @@ pub const NativeTargetInfo = struct {
982 else => {},982 else => {},
983 }983 }
984984
985 switch (std.Target.current.os.tag) {
986 .linux => return linux.detectNativeCpuAndFeatures(),
987 .macos => return macos.detectNativeCpuAndFeatures(),
988 else => {},
989 }
990
985 // This architecture does not have CPU model & feature detection yet.991 // This architecture does not have CPU model & feature detection yet.
986 // See https://github.com/ziglang/zig/issues/4591992 // See https://github.com/ziglang/zig/issues/4591
987 if (std.Target.current.os.tag != .linux)993 return null;
988 return null;
989
990 return linux.detectNativeCpuAndFeatures();
991 }994 }
992};995};
993996
lib/std/zig/system/macos.zig+46-5
...@@ -7,10 +7,13 @@ const std = @import("std");...@@ -7,10 +7,13 @@ const std = @import("std");
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const mem = std.mem;8const mem = std.mem;
9const testing = std.testing;9const testing = std.testing;
10const os = std.os;
11
12const Target = std.Target;
1013
11/// Detect macOS version.14/// Detect macOS version.
12/// `os` is not modified in case of error.15/// `target_os` is not modified in case of error.
13pub fn detect(os: *std.Target.Os) !void {16pub fn detect(target_os: *Target.Os) !void {
14 // Drop use of osproductversion sysctl because:17 // Drop use of osproductversion sysctl because:
15 // 1. only available 10.13.4 High Sierra and later18 // 1. only available 10.13.4 High Sierra and later
16 // 2. when used from a binary built against < SDK 11.0 it returns 10.16 and masks Big Sur 11.x version19 // 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 {...@@ -60,8 +63,8 @@ pub fn detect(os: *std.Target.Os) !void {
60 if (parseSystemVersion(bytes)) |ver| {63 if (parseSystemVersion(bytes)) |ver| {
61 // never return non-canonical `10.(16+)`64 // never return non-canonical `10.(16+)`
62 if (!(ver.major == 10 and ver.minor >= 16)) {65 if (!(ver.major == 10 and ver.minor >= 16)) {
63 os.version_range.semver.min = ver;66 target_os.version_range.semver.min = ver;
64 os.version_range.semver.max = ver;67 target_os.version_range.semver.max = ver;
65 return;68 return;
66 }69 }
67 continue;70 continue;
...@@ -410,7 +413,7 @@ fn testVersionEquality(expected: std.builtin.Version, got: std.builtin.Version)...@@ -410,7 +413,7 @@ fn testVersionEquality(expected: std.builtin.Version, got: std.builtin.Version)
410/// `-syslibroot` param of the linker.413/// `-syslibroot` param of the linker.
411/// The caller needs to free the resulting path slice.414/// The caller needs to free the resulting path slice.
412pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 {415pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 {
413 assert(std.Target.current.isDarwin());416 assert(Target.current.isDarwin());
414 const argv = &[_][]const u8{ "xcrun", "--show-sdk-path" };417 const argv = &[_][]const u8{ "xcrun", "--show-sdk-path" };
415 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });418 const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
416 defer {419 defer {
...@@ -426,3 +429,41 @@ pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 {...@@ -426,3 +429,41 @@ pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 {
426 const syslibroot = mem.trimRight(u8, result.stdout, "\r\n");429 const syslibroot = mem.trimRight(u8, result.stdout, "\r\n");
427 return mem.dupe(allocator, u8, syslibroot);430 return mem.dupe(allocator, u8, syslibroot);
428}431}
432
433pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
434 var cpu_family: os.CPUFAMILY = undefined;
435 var len: usize = @sizeOf(os.CPUFAMILY);
436 os.sysctlbynameZ("hw.cpufamily", &cpu_family, &len, null, 0) catch |err| switch (err) {
437 error.NameTooLong => unreachable, // constant, known good value
438 error.PermissionDenied => unreachable, // only when setting values,
439 error.SystemResources => unreachable, // memory already on the stack
440 error.UnknownName => unreachable, // constant, known good value
441 error.Unexpected => unreachable, // EFAULT: stack should be safe, EISDIR/ENOTDIR: constant, known good value
442 };
443
444 const current_arch = Target.current.cpu.arch;
445 switch (current_arch) {
446 .aarch64, .aarch64_be, .aarch64_32 => {
447 const model = switch (cpu_family) {
448 .ARM_FIRESTORM_ICESTORM => &Target.aarch64.cpu.apple_a14,
449 .ARM_LIGHTNING_THUNDER => &Target.aarch64.cpu.apple_a13,
450 .ARM_VORTEX_TEMPEST => &Target.aarch64.cpu.apple_a12,
451 .ARM_MONSOON_MISTRAL => &Target.aarch64.cpu.apple_a11,
452 .ARM_HURRICANE => &Target.aarch64.cpu.apple_a10,
453 .ARM_TWISTER => &Target.aarch64.cpu.apple_a9,
454 .ARM_TYPHOON => &Target.aarch64.cpu.apple_a8,
455 .ARM_CYCLONE => &Target.aarch64.cpu.cyclone,
456 else => return null,
457 };
458
459 return Target.Cpu{
460 .arch = current_arch,
461 .model = model,
462 .features = model.features,
463 };
464 },
465 else => {},
466 }
467
468 return null;
469}