| author | |
| committer | |
| log | 955228b682dc48a3815707f318280af12a3daf00 |
| tree | 10899c853010cf4117778eb6d75ae287f5d77528 |
| parent | 6b3b6ec32c5c45095c77f4af99ec21f7d75b82ef |
| parent | b61678c1b631f78c3a5da4eca2e77ae3577c1093 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36867
Reviewed-by: Andrew Kelley <andrew@ziglang.org>5 files changed, 143 insertions(+), 180 deletions(-)
lib/std/Target.zig+9-16| ... | @@ -499,7 +499,10 @@ pub const Os = struct { | ... | @@ -499,7 +499,10 @@ pub const Os = struct { |
| 499 | 499 | ||
| 500 | break :blk default_min; | 500 | break :blk default_min; |
| 501 | }, | 501 | }, |
| 502 | .android = 29, | 502 | .android = switch (arch) { |
| 503 | .riscv64 => 35, | ||
| 504 | else => 29, | ||
| 505 | }, | ||
| 503 | }, | 506 | }, |
| 504 | }, | 507 | }, |
| 505 | .rtems => .{ | 508 | .rtems => .{ |
| ... | @@ -2532,8 +2535,8 @@ pub const DynamicLinker = struct { | ... | @@ -2532,8 +2535,8 @@ pub const DynamicLinker = struct { |
| 2532 | /// the ABI; it does not necessarily mean that `abi` makes any sense at all for that platform. | 2535 | /// the ABI; it does not necessarily mean that `abi` makes any sense at all for that platform. |
| 2533 | /// The responsibility for determining whether `abi` is valid in this case rests with the | 2536 | /// The responsibility for determining whether `abi` is valid in this case rests with the |
| 2534 | /// caller. `Abi.default()` can be used to pick a best-effort default ABI for such platforms. | 2537 | /// caller. `Abi.default()` can be used to pick a best-effort default ABI for such platforms. |
| 2535 | pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker { | 2538 | pub fn standard(cpu: Cpu, os: Os.Tag, abi: Abi) DynamicLinker { |
| 2536 | return switch (os.tag) { | 2539 | return switch (os) { |
| 2537 | .fuchsia => switch (cpu.arch) { | 2540 | .fuchsia => switch (cpu.arch) { |
| 2538 | .arm, | 2541 | .arm, |
| 2539 | .aarch64, | 2542 | .aarch64, |
| ... | @@ -2833,12 +2836,7 @@ pub const DynamicLinker = struct { | ... | @@ -2833,12 +2836,7 @@ pub const DynamicLinker = struct { |
| 2833 | else => none, | 2836 | else => none, |
| 2834 | }, | 2837 | }, |
| 2835 | 2838 | ||
| 2836 | .dragonfly => if (cpu.arch == .x86_64) initFmt("{s}/libexec/ld-elf.so.2", .{ | 2839 | .dragonfly => if (cpu.arch == .x86_64) init("/libexec/ld-elf.so.2") else none, |
| 2837 | if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false) | ||
| 2838 | "" | ||
| 2839 | else | ||
| 2840 | "/usr", | ||
| 2841 | }) else none, | ||
| 2842 | 2840 | ||
| 2843 | .freebsd => switch (cpu.arch) { | 2841 | .freebsd => switch (cpu.arch) { |
| 2844 | .arm, | 2842 | .arm, |
| ... | @@ -2849,12 +2847,7 @@ pub const DynamicLinker = struct { | ... | @@ -2849,12 +2847,7 @@ pub const DynamicLinker = struct { |
| 2849 | .riscv64, | 2847 | .riscv64, |
| 2850 | .x86, | 2848 | .x86, |
| 2851 | .x86_64, | 2849 | .x86_64, |
| 2852 | => initFmt("{s}/libexec/ld-elf.so.1", .{ | 2850 | => init("/libexec/ld-elf.so.1"), |
| 2853 | if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false) | ||
| 2854 | "" | ||
| 2855 | else | ||
| 2856 | "/usr", | ||
| 2857 | }), | ||
| 2858 | else => none, | 2851 | else => none, |
| 2859 | }, | 2852 | }, |
| 2860 | 2853 | ||
| ... | @@ -2968,7 +2961,7 @@ pub const DynamicLinker = struct { | ... | @@ -2968,7 +2961,7 @@ pub const DynamicLinker = struct { |
| 2968 | }; | 2961 | }; |
| 2969 | 2962 | ||
| 2970 | pub fn standardDynamicLinkerPath(target: *const Target) DynamicLinker { | 2963 | pub fn standardDynamicLinkerPath(target: *const Target) DynamicLinker { |
| 2971 | return DynamicLinker.standard(target.cpu, target.os, target.abi); | 2964 | return DynamicLinker.standard(target.cpu, target.os.tag, target.abi); |
| 2972 | } | 2965 | } |
| 2973 | 2966 | ||
| 2974 | pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { | 2967 | pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { |
lib/std/Target/Query.zig+36-43| ... | @@ -26,33 +26,37 @@ cpu_features_sub: Target.Cpu.Feature.Set = .empty, | ... | @@ -26,33 +26,37 @@ cpu_features_sub: Target.Cpu.Feature.Set = .empty, |
| 26 | /// `null` means native. | 26 | /// `null` means native. |
| 27 | os_tag: ?Target.Os.Tag = null, | 27 | os_tag: ?Target.Os.Tag = null, |
| 28 | 28 | ||
| 29 | /// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native) | 29 | /// `null` means native when `os_tag` is native; otherwise, the default minimum version for |
| 30 | /// then `null` for this field means native. | 30 | /// `cpu_arch`, `os_tag`, and `abi`. |
| 31 | os_version_min: ?OsVersion = null, | 31 | os_version_min: ?OsVersion = null, |
| 32 | 32 | ||
| 33 | /// When cross compiling, `null` means default (latest known OS version). | 33 | /// `null` means native when `os_tag` is native; otherwise, the latest known OS version. |
| 34 | /// When `os_tag` is native, `null` means equal to the native OS version. | ||
| 35 | os_version_max: ?OsVersion = null, | 34 | os_version_max: ?OsVersion = null, |
| 36 | 35 | ||
| 37 | /// `null` means default when cross compiling, or native when `os_tag` is native. | 36 | /// `null` means native when `abi` is native; otherwise, the default minimum version for `cpu_arch`, |
| 38 | /// If `isGnu()` is `false`, this must be `null` and is ignored. | 37 | /// `os_tag`, and `abi`. |
| 38 | /// | ||
| 39 | /// Must be `null` when `abi` is `null` or `isGnu()` is `false`. | ||
| 39 | glibc_version: ?SemanticVersion = null, | 40 | glibc_version: ?SemanticVersion = null, |
| 40 | 41 | ||
| 41 | /// `null` means default when cross compiling, or native when `os_tag` is native. | 42 | /// `null` means native when `abi` is native; otherwise, the default minimum version for `cpu_arch` |
| 42 | /// If `isAndroid()` is `false`, this must be `null` and is ignored. | 43 | /// and `abi`. |
| 44 | /// | ||
| 45 | /// Must be `null` when `abi` is `null` or `isAndroid()` is `false`. | ||
| 43 | android_api_level: ?u32 = null, | 46 | android_api_level: ?u32 = null, |
| 44 | 47 | ||
| 45 | /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. | 48 | /// `null` means native if `os_tag` is native; otherwise, best-effort default for `cpu_arch` and |
| 49 | /// `os_tag`. | ||
| 46 | abi: ?Target.Abi = null, | 50 | abi: ?Target.Abi = null, |
| 47 | 51 | ||
| 48 | /// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path | 52 | /// `null` means default for the `cpu_arch` and `os_tag` combination. |
| 49 | /// based on the `os_tag`. When `dynamic_linker` is a non-`null` empty string, no dynamic | ||
| 50 | /// linker is used regardless of `os_tag`. | ||
| 51 | dynamic_linker: ?Target.DynamicLinker = null, | ||
| 52 | |||
| 53 | /// `null` means default for the cpu/arch/os combo. | ||
| 54 | ofmt: ?Target.ObjectFormat = null, | 53 | ofmt: ?Target.ObjectFormat = null, |
| 55 | 54 | ||
| 55 | /// `null` means native when `abi` is native; otherwise, the standard path based on `cpu_arch`, | ||
| 56 | /// `os_tag`, and `abi`. A non-`null` empty string means no dynamic linker is used regardless of the | ||
| 57 | /// values of other fields. | ||
| 58 | dynamic_linker: ?Target.DynamicLinker = null, | ||
| 59 | |||
| 56 | pub const CpuModel = union(enum) { | 60 | pub const CpuModel = union(enum) { |
| 57 | /// Always native | 61 | /// Always native |
| 58 | native, | 62 | native, |
| ... | @@ -175,12 +179,12 @@ pub const ParseOptions = struct { | ... | @@ -175,12 +179,12 @@ pub const ParseOptions = struct { |
| 175 | /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". | 179 | /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". |
| 176 | cpu_features: ?[]const u8 = null, | 180 | cpu_features: ?[]const u8 = null, |
| 177 | 181 | ||
| 182 | object_format: ?[]const u8 = null, | ||
| 183 | |||
| 178 | /// Absolute path to dynamic linker, to override the default, which is either a natively | 184 | /// Absolute path to dynamic linker, to override the default, which is either a natively |
| 179 | /// detected path, or a standard path. | 185 | /// detected path, or a standard path. |
| 180 | dynamic_linker: ?[]const u8 = null, | 186 | dynamic_linker: ?[]const u8 = null, |
| 181 | 187 | ||
| 182 | object_format: ?[]const u8 = null, | ||
| 183 | |||
| 184 | /// If this is provided, the function will populate some information about parsing failures, | 188 | /// If this is provided, the function will populate some information about parsing failures, |
| 185 | /// so that user-friendly error messages can be delivered. | 189 | /// so that user-friendly error messages can be delivered. |
| 186 | diagnostics: ?*Diagnostics = null, | 190 | diagnostics: ?*Diagnostics = null, |
| ... | @@ -381,12 +385,16 @@ pub fn isNativeCpu(self: Query) bool { | ... | @@ -381,12 +385,16 @@ pub fn isNativeCpu(self: Query) bool { |
| 381 | } | 385 | } |
| 382 | 386 | ||
| 383 | pub fn isNativeOs(self: Query) bool { | 387 | pub fn isNativeOs(self: Query) bool { |
| 384 | return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and | 388 | return self.os_tag == null and |
| 385 | self.dynamic_linker == null and self.glibc_version == null and self.android_api_level == null; | 389 | self.os_version_min == null and |
| 390 | self.os_version_max == null; | ||
| 386 | } | 391 | } |
| 387 | 392 | ||
| 388 | pub fn isNativeAbi(self: Query) bool { | 393 | pub fn isNativeAbi(self: Query) bool { |
| 389 | return self.os_tag == null and self.abi == null; | 394 | return self.os_tag == null and |
| 395 | self.abi == null and | ||
| 396 | self.glibc_version == null and | ||
| 397 | self.android_api_level == null; | ||
| 390 | } | 398 | } |
| 391 | 399 | ||
| 392 | pub fn isNativeTriple(self: Query) bool { | 400 | pub fn isNativeTriple(self: Query) bool { |
| ... | @@ -394,11 +402,13 @@ pub fn isNativeTriple(self: Query) bool { | ... | @@ -394,11 +402,13 @@ pub fn isNativeTriple(self: Query) bool { |
| 394 | } | 402 | } |
| 395 | 403 | ||
| 396 | pub fn isNative(self: Query) bool { | 404 | pub fn isNative(self: Query) bool { |
| 397 | return self.isNativeTriple() and self.ofmt == null; | 405 | return self.isNativeTriple() and |
| 406 | self.ofmt == null and | ||
| 407 | self.dynamic_linker == null; | ||
| 398 | } | 408 | } |
| 399 | 409 | ||
| 400 | pub fn canDetectLibC(self: Query) bool { | 410 | pub fn canDetectLibC(self: Query) bool { |
| 401 | if (self.isNativeOs()) return true; | 411 | if (self.isNativeOs() and self.isNativeAbi()) return true; |
| 402 | if (self.os_tag) |os| { | 412 | if (self.os_tag) |os| { |
| 403 | if (builtin.os.tag == .macos and os.isDarwin()) return true; | 413 | if (builtin.os.tag == .macos and os.isDarwin()) return true; |
| 404 | if (os == .linux) { | 414 | if (os == .linux) { |
| ... | @@ -459,14 +469,14 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 { | ... | @@ -459,14 +469,14 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 { |
| 459 | } | 469 | } |
| 460 | 470 | ||
| 461 | if (self.glibc_version) |v| { | 471 | if (self.glibc_version) |v| { |
| 462 | const name = if (self.abi) |abi| @tagName(abi) else "gnu"; | 472 | const name = @tagName(self.abi.?); |
| 463 | try result.ensureUnusedCapacity(gpa, name.len + 2); | 473 | try result.ensureUnusedCapacity(gpa, name.len + 2); |
| 464 | result.appendAssumeCapacity('-'); | 474 | result.appendAssumeCapacity('-'); |
| 465 | result.appendSliceAssumeCapacity(name); | 475 | result.appendSliceAssumeCapacity(name); |
| 466 | result.appendAssumeCapacity('.'); | 476 | result.appendAssumeCapacity('.'); |
| 467 | try formatVersion(v, gpa, &result); | 477 | try formatVersion(v, gpa, &result); |
| 468 | } else if (self.android_api_level) |lvl| { | 478 | } else if (self.android_api_level) |lvl| { |
| 469 | const name = if (self.abi) |abi| @tagName(abi) else "android"; | 479 | const name = @tagName(self.abi.?); |
| 470 | try result.ensureUnusedCapacity(gpa, name.len + 2); | 480 | try result.ensureUnusedCapacity(gpa, name.len + 2); |
| 471 | result.appendAssumeCapacity('-'); | 481 | result.appendAssumeCapacity('-'); |
| 472 | result.appendSliceAssumeCapacity(name); | 482 | result.appendSliceAssumeCapacity(name); |
| ... | @@ -538,6 +548,7 @@ pub fn allocDescription(self: Query, allocator: Allocator) ![]u8 { | ... | @@ -538,6 +548,7 @@ pub fn allocDescription(self: Query, allocator: Allocator) ![]u8 { |
| 538 | return self.zigTriple(allocator); | 548 | return self.zigTriple(allocator); |
| 539 | } | 549 | } |
| 540 | 550 | ||
| 551 | /// Deprecated; set `glibc_version` directly. Will be removed in 0.18.0. | ||
| 541 | pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { | 552 | pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { |
| 542 | self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; | 553 | self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; |
| 543 | } | 554 | } |
| ... | @@ -599,8 +610,8 @@ pub fn eql(a: Query, b: Query) bool { | ... | @@ -599,8 +610,8 @@ pub fn eql(a: Query, b: Query) bool { |
| 599 | if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false; | 610 | if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false; |
| 600 | if (a.android_api_level != b.android_api_level) return false; | 611 | if (a.android_api_level != b.android_api_level) return false; |
| 601 | if (a.abi != b.abi) return false; | 612 | if (a.abi != b.abi) return false; |
| 602 | if (!dynamicLinkerEqualOpt(a.dynamic_linker, b.dynamic_linker)) return false; | ||
| 603 | if (a.ofmt != b.ofmt) return false; | 613 | if (a.ofmt != b.ofmt) return false; |
| 614 | if (!dynamicLinkerEqualOpt(a.dynamic_linker, b.dynamic_linker)) return false; | ||
| 604 | 615 | ||
| 605 | return true; | 616 | return true; |
| 606 | } | 617 | } |
| ... | @@ -620,24 +631,6 @@ fn dynamicLinkerEqualOpt(a: ?Target.DynamicLinker, b: ?Target.DynamicLinker) boo | ... | @@ -620,24 +631,6 @@ fn dynamicLinkerEqualOpt(a: ?Target.DynamicLinker, b: ?Target.DynamicLinker) boo |
| 620 | test parse { | 631 | test parse { |
| 621 | const io = std.testing.io; | 632 | const io = std.testing.io; |
| 622 | 633 | ||
| 623 | if (builtin.target.isGnuLibC()) { | ||
| 624 | var query = try Query.parse(.{}); | ||
| 625 | query.setGnuLibCVersion(2, 1, 1); | ||
| 626 | |||
| 627 | const text = try query.zigTriple(std.testing.allocator); | ||
| 628 | defer std.testing.allocator.free(text); | ||
| 629 | |||
| 630 | try std.testing.expectEqualSlices(u8, "native-native-gnu.2.1.1", text); | ||
| 631 | } | ||
| 632 | if (builtin.target.abi.isAndroid()) { | ||
| 633 | var query = try Query.parse(.{}); | ||
| 634 | query.android_api_level = 30; | ||
| 635 | |||
| 636 | const text = try query.zigTriple(std.testing.allocator); | ||
| 637 | defer std.testing.allocator.free(text); | ||
| 638 | |||
| 639 | try std.testing.expectEqualSlices(u8, "native-native-android.30", text); | ||
| 640 | } | ||
| 641 | { | 634 | { |
| 642 | const query = try Query.parse(.{ | 635 | const query = try Query.parse(.{ |
| 643 | .arch_os_abi = "aarch64-linux", | 636 | .arch_os_abi = "aarch64-linux", |
lib/std/zig/system.zig+92-107| ... | @@ -374,16 +374,14 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { | ... | @@ -374,16 +374,14 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | var cpu = switch (query.cpu_model) { | 376 | var cpu = switch (query.cpu_model) { |
| 377 | .native => detectNativeCpuAndFeatures(io, query_cpu_arch, os, query), | 377 | .native => detectNativeCpuAndFeatures(io, query_cpu_arch), |
| 378 | .baseline => Target.Cpu.baseline(query_cpu_arch, os), | 378 | .baseline => null, |
| 379 | .determined_by_arch_os => if (query.cpu_arch == null) | 379 | .determined_by_arch_os => if (query.cpu_arch == null) |
| 380 | detectNativeCpuAndFeatures(io, query_cpu_arch, os, query) | 380 | detectNativeCpuAndFeatures(io, query_cpu_arch) |
| 381 | else | 381 | else |
| 382 | Target.Cpu.baseline(query_cpu_arch, os), | 382 | null, |
| 383 | .explicit => |model| model.toCpu(query_cpu_arch), | 383 | .explicit => |model| model.toCpu(query_cpu_arch), |
| 384 | } orelse backup_cpu_detection: { | 384 | } orelse Target.Cpu.baseline(query_cpu_arch, os); |
| 385 | break :backup_cpu_detection Target.Cpu.baseline(query_cpu_arch, os); | ||
| 386 | }; | ||
| 387 | 385 | ||
| 388 | // For x86, we need to populate some CPU feature flags depending on architecture | 386 | // For x86, we need to populate some CPU feature flags depending on architecture |
| 389 | // and mode: | 387 | // and mode: |
| ... | @@ -421,6 +419,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { | ... | @@ -421,6 +419,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { |
| 421 | var result = detectAbiAndDynamicLinker(io, cpu, os, query) catch |err| switch (err) { | 419 | var result = detectAbiAndDynamicLinker(io, cpu, os, query) catch |err| switch (err) { |
| 422 | error.Canceled => |e| return e, | 420 | error.Canceled => |e| return e, |
| 423 | error.Unexpected => |e| return e, | 421 | error.Unexpected => |e| return e, |
| 422 | error.ApiLevelQueryFailed => |e| return e, | ||
| 424 | error.WouldBlock => return error.Unexpected, | 423 | error.WouldBlock => return error.Unexpected, |
| 425 | error.ConnectionResetByPeer => return error.Unexpected, | 424 | error.ConnectionResetByPeer => return error.Unexpected, |
| 426 | error.NotOpenForReading => return error.Unexpected, | 425 | error.NotOpenForReading => return error.Unexpected, |
| ... | @@ -499,27 +498,6 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { | ... | @@ -499,27 +498,6 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { |
| 499 | } | 498 | } |
| 500 | } | 499 | } |
| 501 | 500 | ||
| 502 | if (builtin.os.tag == .linux and result.isBionicLibC() and query.os_tag == null and query.android_api_level == null) { | ||
| 503 | result.os.version_range.linux.android = detectAndroidApiLevel(io) catch |err| return switch (err) { | ||
| 504 | error.InvalidWtf8, | ||
| 505 | error.InvalidBatchScriptArg, | ||
| 506 | => unreachable, // Windows-only | ||
| 507 | error.ApiLevelQueryFailed => |e| e, | ||
| 508 | else => blk: { | ||
| 509 | std.log.err("spawning or reading from getprop failed ({s})", .{@errorName(err)}); | ||
| 510 | switch (err) { | ||
| 511 | error.SystemResources, | ||
| 512 | error.FileSystem, | ||
| 513 | error.ProcessFdQuotaExceeded, | ||
| 514 | error.SystemFdQuotaExceeded, | ||
| 515 | error.SymLinkLoop, | ||
| 516 | => |e| break :blk e, | ||
| 517 | else => break :blk error.ApiLevelQueryFailed, | ||
| 518 | } | ||
| 519 | }, | ||
| 520 | }; | ||
| 521 | } | ||
| 522 | |||
| 523 | return result; | 501 | return result; |
| 524 | } | 502 | } |
| 525 | 503 | ||
| ... | @@ -535,13 +513,12 @@ fn updateCpuFeatures( | ... | @@ -535,13 +513,12 @@ fn updateCpuFeatures( |
| 535 | set.removeFeatureSet(sub_set); | 513 | set.removeFeatureSet(sub_set); |
| 536 | } | 514 | } |
| 537 | 515 | ||
| 538 | fn detectNativeCpuAndFeatures(io: Io, cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { | 516 | fn detectNativeCpuAndFeatures(io: Io, cpu_arch: Target.Cpu.Arch) ?Target.Cpu { |
| 539 | // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, | 517 | const family = builtin.target.cpu.arch.family(); |
| 540 | // although it is a runtime value, is guaranteed to be one of the architectures in the set | 518 | assert(cpu_arch.family() == family); |
| 541 | // of the respective switch prong. | 519 | switch (family) { |
| 542 | switch (builtin.cpu.arch) { | 520 | .loongarch => return @import("system/loongarch.zig").detectNativeCpuAndFeatures(cpu_arch), |
| 543 | .loongarch32, .loongarch64 => return @import("system/loongarch.zig").detectNativeCpuAndFeatures(cpu_arch, os, query), | 521 | .x86 => return @import("system/x86.zig").detectNativeCpuAndFeatures(cpu_arch), |
| 544 | .x86_64, .x86 => return @import("system/x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query), | ||
| 545 | else => {}, | 522 | else => {}, |
| 546 | } | 523 | } |
| 547 | 524 | ||
| ... | @@ -594,11 +571,13 @@ fn abiAndDynamicLinkerFromFile( | ... | @@ -594,11 +571,13 @@ fn abiAndDynamicLinkerFromFile( |
| 594 | ld_info_list: []const LdInfo, | 571 | ld_info_list: []const LdInfo, |
| 595 | query: Target.Query, | 572 | query: Target.Query, |
| 596 | ) AbiAndDynamicLinkerFromFileError!Target { | 573 | ) AbiAndDynamicLinkerFromFileError!Target { |
| 574 | assert(query.abi == null); // See the early exit in `detectAbiAndDynamicLinker`. | ||
| 575 | |||
| 597 | const io = file_reader.io; | 576 | const io = file_reader.io; |
| 598 | var result: Target = .{ | 577 | var result: Target = .{ |
| 599 | .cpu = cpu, | 578 | .cpu = cpu, |
| 600 | .os = os, | 579 | .os = os, |
| 601 | .abi = query.abi orelse Target.Abi.default(cpu.arch, os.tag), | 580 | .abi = Target.Abi.default(cpu.arch, os.tag), |
| 602 | .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), | 581 | .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), |
| 603 | .dynamic_linker = query.dynamic_linker orelse .none, | 582 | .dynamic_linker = query.dynamic_linker orelse .none, |
| 604 | }; | 583 | }; |
| ... | @@ -612,26 +591,25 @@ fn abiAndDynamicLinkerFromFile( | ... | @@ -612,26 +591,25 @@ fn abiAndDynamicLinkerFromFile( |
| 612 | .INTERP => { | 591 | .INTERP => { |
| 613 | got_dyn_section = true; | 592 | got_dyn_section = true; |
| 614 | 593 | ||
| 615 | if (look_for_ld) { | 594 | var interp: Target.DynamicLinker = .none; |
| 616 | const p_filesz = phdr.filesz; | 595 | const p_filesz = phdr.filesz; |
| 617 | if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong; | 596 | if (p_filesz < 2) return error.InvalidElfFile; |
| 618 | const filesz: usize = @intCast(p_filesz); | 597 | if (p_filesz > interp.buffer.len) return error.NameTooLong; |
| 619 | try file_reader.seekTo(phdr.offset); | 598 | const filesz: usize = @intCast(p_filesz); |
| 620 | try file_reader.interface.readSliceAll(result.dynamic_linker.buffer[0..filesz]); | 599 | try file_reader.seekTo(phdr.offset); |
| 621 | // PT.INTERP includes a null byte in filesz. | 600 | try file_reader.interface.readSliceAll(interp.buffer[0..filesz]); |
| 622 | const len = filesz - 1; | 601 | // PT.INTERP includes a null byte in filesz. |
| 623 | // dynamic_linker.max_byte is "max", not "len". | 602 | const len = filesz - 1; |
| 624 | // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. | 603 | // dynamic_linker.max_byte is "max", not "len". |
| 625 | result.dynamic_linker.len = @intCast(len); | 604 | // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. |
| 626 | 605 | interp.len = @intCast(len); | |
| 627 | // Use it to determine ABI. | 606 | |
| 628 | const full_ld_path = result.dynamic_linker.buffer[0..len]; | 607 | // Use it to determine ABI. |
| 629 | for (ld_info_list) |ld_info| { | 608 | for (ld_info_list) |ld_info| { |
| 630 | const standard_ld_basename = fs.path.basename(ld_info.ld.get().?); | 609 | if (std.mem.endsWith(u8, interp.get().?, fs.path.basename(ld_info.ld.get().?))) { |
| 631 | if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) { | 610 | result.abi = ld_info.abi; |
| 632 | result.abi = ld_info.abi; | 611 | if (look_for_ld) result.dynamic_linker = interp; |
| 633 | break; | 612 | break; |
| 634 | } | ||
| 635 | } | 613 | } |
| 636 | } | 614 | } |
| 637 | }, | 615 | }, |
| ... | @@ -653,6 +631,10 @@ fn abiAndDynamicLinkerFromFile( | ... | @@ -653,6 +631,10 @@ fn abiAndDynamicLinkerFromFile( |
| 653 | }; | 631 | }; |
| 654 | } | 632 | } |
| 655 | 633 | ||
| 634 | if (look_for_ld and result.dynamic_linker.get() == null) { | ||
| 635 | result.dynamic_linker = .standard(cpu, os.tag, result.abi); | ||
| 636 | } | ||
| 637 | |||
| 656 | if (!got_dyn_section) { | 638 | if (!got_dyn_section) { |
| 657 | return error.StaticElfFile; | 639 | return error.StaticElfFile; |
| 658 | } | 640 | } |
| ... | @@ -954,17 +936,14 @@ fn glibcVerFromSoFile(file_reader: *Io.File.Reader) !std.SemanticVersion { | ... | @@ -954,17 +936,14 @@ fn glibcVerFromSoFile(file_reader: *Io.File.Reader) !std.SemanticVersion { |
| 954 | /// file recursively. If that does not provide the answer, then the function falls back to | 936 | /// file recursively. If that does not provide the answer, then the function falls back to |
| 955 | /// defaults. | 937 | /// defaults. |
| 956 | fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Target.Query) !Target { | 938 | fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Target.Query) !Target { |
| 957 | const native_target_has_ld = comptime Target.DynamicLinker.kind(builtin.os.tag) != .none; | 939 | const native_os_uses_elf = comptime Target.ObjectFormat.default(builtin.target.os.tag, builtin.target.cpu.arch) == .elf; |
| 958 | const is_linux = builtin.target.os.tag == .linux; | 940 | const native_ld_needs_abi = comptime Target.DynamicLinker.kind(builtin.target.os.tag) == .arch_os_abi; |
| 959 | const is_illumos = builtin.target.os.tag == .illumos; | 941 | if (!native_os_uses_elf or !native_ld_needs_abi or query.os_tag != null or query.abi != null) { |
| 960 | const is_darwin = builtin.target.os.tag.isDarwin(); | ||
| 961 | const have_all_info = query.dynamic_linker != null and | ||
| 962 | query.abi != null and (!is_linux or query.abi.?.isGnu()); | ||
| 963 | const os_is_non_native = query.os_tag != null; | ||
| 964 | // The illumos environment is always the same. | ||
| 965 | if (!native_target_has_ld or have_all_info or os_is_non_native or is_illumos or is_darwin) { | ||
| 966 | return defaultAbiAndDynamicLinker(cpu, os, query); | 942 | return defaultAbiAndDynamicLinker(cpu, os, query); |
| 967 | } | 943 | } |
| 944 | |||
| 945 | assert(os.tag == builtin.target.os.tag); | ||
| 946 | |||
| 968 | // The current target's ABI cannot be relied on for this. For example, we may build the zig | 947 | // The current target's ABI cannot be relied on for this. For example, we may build the zig |
| 969 | // compiler for target riscv64-linux-musl and provide a tarball for users to download. | 948 | // compiler for target riscv64-linux-musl and provide a tarball for users to download. |
| 970 | // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined | 949 | // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined |
| ... | @@ -982,30 +961,17 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ | ... | @@ -982,30 +961,17 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 982 | var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; | 961 | var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; |
| 983 | var ld_info_list_len: usize = 0; | 962 | var ld_info_list_len: usize = 0; |
| 984 | 963 | ||
| 985 | switch (Target.DynamicLinker.kind(os.tag)) { | 964 | for (all_abis) |abi| { |
| 986 | // The OS has no dynamic linker. Leave the list empty and rely on `Abi.default()` to pick | 965 | const ld: Target.DynamicLinker = .standard(cpu, os.tag, abi); |
| 987 | // something sensible in `abiAndDynamicLinkerFromFile()`. | 966 | |
| 988 | .none => {}, | 967 | // Does the generated target triple actually have a standard dynamic linker path? |
| 989 | // The OS has a system-wide dynamic linker. Unfortunately, this implies that there's no | 968 | if (ld.get() == null) continue; |
| 990 | // useful ABI information that we can glean from it merely being present. That means the | 969 | |
| 991 | // best we can do for this case (for now) is also `Abi.default()`. | 970 | ld_info_list_buffer[ld_info_list_len] = .{ |
| 992 | .arch_os => {}, | 971 | .ld = ld, |
| 993 | // The OS can have different dynamic linker paths depending on libc/ABI. In this case, we | 972 | .abi = abi, |
| 994 | // need to gather all the valid arch/OS/ABI combinations. `abiAndDynamicLinkerFromFile()` | 973 | }; |
| 995 | // will then look for a dynamic linker with a matching path on the system and pick the ABI | 974 | ld_info_list_len += 1; |
| 996 | // we associated it with here. | ||
| 997 | .arch_os_abi => for (all_abis) |abi| { | ||
| 998 | const ld = Target.DynamicLinker.standard(cpu, os, abi); | ||
| 999 | |||
| 1000 | // Does the generated target triple actually have a standard dynamic linker path? | ||
| 1001 | if (ld.get() == null) continue; | ||
| 1002 | |||
| 1003 | ld_info_list_buffer[ld_info_list_len] = .{ | ||
| 1004 | .ld = ld, | ||
| 1005 | .abi = abi, | ||
| 1006 | }; | ||
| 1007 | ld_info_list_len += 1; | ||
| 1008 | }, | ||
| 1009 | } | 975 | } |
| 1010 | 976 | ||
| 1011 | const ld_info_list = ld_info_list_buffer[0..ld_info_list_len]; | 977 | const ld_info_list = ld_info_list_buffer[0..ld_info_list_len]; |
| ... | @@ -1034,13 +1000,9 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ | ... | @@ -1034,13 +1000,9 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 1034 | // it uses the file it references instead, doing the same logic | 1000 | // it uses the file it references instead, doing the same logic |
| 1035 | // recursively in case it finds another shebang line. | 1001 | // recursively in case it finds another shebang line. |
| 1036 | 1002 | ||
| 1037 | var file_name: []const u8 = switch (os.tag) { | 1003 | // Since /usr/bin/env is hard-coded into the shebang line of many |
| 1038 | // Since /usr/bin/env is hard-coded into the shebang line of many | 1004 | // portable scripts, it's a reasonably reliable path to start with. |
| 1039 | // portable scripts, it's a reasonably reliable path to start with. | 1005 | var file_name: []const u8 = "/usr/bin/env"; |
| 1040 | else => "/usr/bin/env", | ||
| 1041 | // Haiku does not have a /usr root directory. | ||
| 1042 | .haiku => "/bin/env", | ||
| 1043 | }; | ||
| 1044 | 1006 | ||
| 1045 | while (true) { | 1007 | while (true) { |
| 1046 | const file = Io.Dir.openFileAbsolute(io, file_name, .{}) catch |err| switch (err) { | 1008 | const file = Io.Dir.openFileAbsolute(io, file_name, .{}) catch |err| switch (err) { |
| ... | @@ -1062,7 +1024,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ | ... | @@ -1062,7 +1024,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 1062 | error.NetworkNotFound, | 1024 | error.NetworkNotFound, |
| 1063 | error.FileTooBig, | 1025 | error.FileTooBig, |
| 1064 | error.Unexpected, | 1026 | error.Unexpected, |
| 1065 | => |e| if (e == error.FileNotFound and os.tag == .linux and mem.eql(u8, file_name, "/usr/bin/env")) { | 1027 | => |e| if (builtin.target.os.tag == .linux and e == error.FileNotFound and mem.eql(u8, file_name, "/usr/bin/env")) { |
| 1066 | // Android does not have a /usr directory, so try again | 1028 | // Android does not have a /usr directory, so try again |
| 1067 | file_name = "/system/bin/env"; | 1029 | file_name = "/system/bin/env"; |
| 1068 | continue; | 1030 | continue; |
| ... | @@ -1116,7 +1078,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ | ... | @@ -1116,7 +1078,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 1116 | }; | 1078 | }; |
| 1117 | defer file_reader.file.close(io); | 1079 | defer file_reader.file.close(io); |
| 1118 | 1080 | ||
| 1119 | return abiAndDynamicLinkerFromFile(&file_reader, &header, cpu, os, ld_info_list, query) catch |err| switch (err) { | 1081 | var result = abiAndDynamicLinkerFromFile(&file_reader, &header, cpu, os, ld_info_list, query) catch |err| switch (err) { |
| 1120 | error.FileSystem, | 1082 | error.FileSystem, |
| 1121 | error.SystemResources, | 1083 | error.SystemResources, |
| 1122 | error.SymLinkLoop, | 1084 | error.SymLinkLoop, |
| ... | @@ -1132,6 +1094,29 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ | ... | @@ -1132,6 +1094,29 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 1132 | return defaultAbiAndDynamicLinker(cpu, os, query); | 1094 | return defaultAbiAndDynamicLinker(cpu, os, query); |
| 1133 | }, | 1095 | }, |
| 1134 | }; | 1096 | }; |
| 1097 | |||
| 1098 | if (builtin.target.os.tag == .linux and result.isBionicLibC() and query.android_api_level == null) { | ||
| 1099 | result.os.version_range.linux.android = detectAndroidApiLevel(io) catch |err| return switch (err) { | ||
| 1100 | error.InvalidWtf8, | ||
| 1101 | error.InvalidBatchScriptArg, | ||
| 1102 | => unreachable, // Windows-only | ||
| 1103 | error.ApiLevelQueryFailed => |e| e, | ||
| 1104 | else => blk: { | ||
| 1105 | std.log.err("spawning or reading from getprop failed ({s})", .{@errorName(err)}); | ||
| 1106 | switch (err) { | ||
| 1107 | error.SystemResources, | ||
| 1108 | error.FileSystem, | ||
| 1109 | error.ProcessFdQuotaExceeded, | ||
| 1110 | error.SystemFdQuotaExceeded, | ||
| 1111 | error.SymLinkLoop, | ||
| 1112 | => |e| break :blk e, | ||
| 1113 | else => break :blk error.ApiLevelQueryFailed, | ||
| 1114 | } | ||
| 1115 | }, | ||
| 1116 | }; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | return result; | ||
| 1135 | } | 1120 | } |
| 1136 | 1121 | ||
| 1137 | fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) Target { | 1122 | fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) Target { |
| ... | @@ -1141,7 +1126,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer | ... | @@ -1141,7 +1126,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer |
| 1141 | .os = os, | 1126 | .os = os, |
| 1142 | .abi = abi, | 1127 | .abi = abi, |
| 1143 | .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), | 1128 | .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), |
| 1144 | .dynamic_linker = query.dynamic_linker orelse .standard(cpu, os, abi), | 1129 | .dynamic_linker = query.dynamic_linker orelse .standard(cpu, os.tag, abi), |
| 1145 | }; | 1130 | }; |
| 1146 | } | 1131 | } |
| 1147 | 1132 | ||
| ... | @@ -1169,13 +1154,6 @@ fn detectAndroidApiLevel(io: Io) !u32 { | ... | @@ -1169,13 +1154,6 @@ fn detectAndroidApiLevel(io: Io) !u32 { |
| 1169 | var stdout_buf: [92 + 1]u8 = undefined; | 1154 | var stdout_buf: [92 + 1]u8 = undefined; |
| 1170 | var reader = child.stdout.?.readerStreaming(io, &.{}); | 1155 | var reader = child.stdout.?.readerStreaming(io, &.{}); |
| 1171 | const n = try reader.interface.readSliceShort(&stdout_buf); | 1156 | const n = try reader.interface.readSliceShort(&stdout_buf); |
| 1172 | const api_level = std.fmt.parseInt(u32, stdout_buf[0 .. n - 1], 10) catch |e| { | ||
| 1173 | std.log.err( | ||
| 1174 | "Could not parse API level, unexpected getprop output '{s}' ({s})", | ||
| 1175 | .{ stdout_buf[0 .. n - 1], @errorName(e) }, | ||
| 1176 | ); | ||
| 1177 | return error.ApiLevelQueryFailed; | ||
| 1178 | }; | ||
| 1179 | 1157 | ||
| 1180 | switch (try child.wait(io)) { | 1158 | switch (try child.wait(io)) { |
| 1181 | .exited => |code| if (code != 0) { | 1159 | .exited => |code| if (code != 0) { |
| ... | @@ -1196,7 +1174,14 @@ fn detectAndroidApiLevel(io: Io) !u32 { | ... | @@ -1196,7 +1174,14 @@ fn detectAndroidApiLevel(io: Io) !u32 { |
| 1196 | }, | 1174 | }, |
| 1197 | } | 1175 | } |
| 1198 | 1176 | ||
| 1199 | return api_level; | 1177 | const result = mem.trimEnd(u8, stdout_buf[0..n], "\n"); |
| 1178 | return std.fmt.parseInt(u32, result, 10) catch |e| { | ||
| 1179 | std.log.err( | ||
| 1180 | "Could not parse API level, unexpected getprop output '{s}' ({s})", | ||
| 1181 | .{ result, @errorName(e) }, | ||
| 1182 | ); | ||
| 1183 | return error.ApiLevelQueryFailed; | ||
| 1184 | }; | ||
| 1200 | } | 1185 | } |
| 1201 | 1186 | ||
| 1202 | test { | 1187 | test { |
lib/std/zig/system/loongarch.zig+1-8| ... | @@ -18,14 +18,7 @@ fn setFeature(cpu: *std.Target.Cpu, feature: std.Target.loongarch.Feature, enabl | ... | @@ -18,14 +18,7 @@ fn setFeature(cpu: *std.Target.Cpu, feature: std.Target.loongarch.Feature, enabl |
| 18 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); | 18 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | pub fn detectNativeCpuAndFeatures( | 21 | pub fn detectNativeCpuAndFeatures(arch: std.Target.Cpu.Arch) ?std.Target.Cpu { |
| 22 | arch: std.Target.Cpu.Arch, | ||
| 23 | os: std.Target.Os, | ||
| 24 | query: std.Target.Query, | ||
| 25 | ) ?std.Target.Cpu { | ||
| 26 | _ = os; | ||
| 27 | _ = query; | ||
| 28 | |||
| 29 | const variant: Variant = @fromBackingInt(@intCast(cpucfg(1) & 0b11)); | 22 | const variant: Variant = @fromBackingInt(@intCast(cpucfg(1) & 0b11)); |
| 30 | 23 | ||
| 31 | var cpu: std.Target.Cpu = .{ | 24 | var cpu: std.Target.Cpu = .{ |
lib/std/zig/system/x86.zig+5-6| ... | @@ -41,8 +41,7 @@ inline fn hasMask(input: u32, mask: u32) bool { | ... | @@ -41,8 +41,7 @@ inline fn hasMask(input: u32, mask: u32) bool { |
| 41 | return (input & mask) == mask; | 41 | return (input & mask) == mask; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) Target.Cpu { | 44 | pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch) Target.Cpu { |
| 45 | _ = query; | ||
| 46 | var cpu = Target.Cpu{ | 45 | var cpu = Target.Cpu{ |
| 47 | .arch = arch, | 46 | .arch = arch, |
| 48 | .model = Target.Cpu.Model.generic(arch), | 47 | .model = Target.Cpu.Model.generic(arch), |
| ... | @@ -50,7 +49,7 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T | ... | @@ -50,7 +49,7 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T |
| 50 | }; | 49 | }; |
| 51 | 50 | ||
| 52 | // First we detect features, to use as hints when detecting CPU Model. | 51 | // First we detect features, to use as hints when detecting CPU Model. |
| 53 | detectNativeFeatures(&cpu, os.tag); | 52 | detectNativeFeatures(&cpu); |
| 54 | 53 | ||
| 55 | var leaf = cpuid(0, 0); | 54 | var leaf = cpuid(0, 0); |
| 56 | const max_leaf = leaf.eax; | 55 | const max_leaf = leaf.eax; |
| ... | @@ -90,7 +89,7 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T | ... | @@ -90,7 +89,7 @@ pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: T |
| 90 | // Add the CPU model's feature set into the working set, but then | 89 | // Add the CPU model's feature set into the working set, but then |
| 91 | // override with actual detected features again. | 90 | // override with actual detected features again. |
| 92 | cpu.features.addFeatureSet(cpu.model.features); | 91 | cpu.features.addFeatureSet(cpu.model.features); |
| 93 | detectNativeFeatures(&cpu, os.tag); | 92 | detectNativeFeatures(&cpu); |
| 94 | 93 | ||
| 95 | cpu.features.populateDependencies(cpu.arch.allFeaturesList()); | 94 | cpu.features.populateDependencies(cpu.arch.allFeaturesList()); |
| 96 | 95 | ||
| ... | @@ -215,7 +214,7 @@ fn detectAmdProcessor(cpu: *const Target.Cpu, family: u32, model: u32) ?*const T | ... | @@ -215,7 +214,7 @@ fn detectAmdProcessor(cpu: *const Target.Cpu, family: u32, model: u32) ?*const T |
| 215 | }; | 214 | }; |
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void { | 217 | fn detectNativeFeatures(cpu: *Target.Cpu) void { |
| 219 | var leaf = cpuid(0, 0); | 218 | var leaf = cpuid(0, 0); |
| 220 | 219 | ||
| 221 | const max_level = leaf.eax; | 220 | const max_level = leaf.eax; |
| ... | @@ -268,7 +267,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void { | ... | @@ -268,7 +267,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void { |
| 268 | // Darwin lazily saves the AVX512 context on first use: trust that the OS will | 267 | // Darwin lazily saves the AVX512 context on first use: trust that the OS will |
| 269 | // save the AVX512 context if we use AVX512 instructions, even if the bit is not | 268 | // save the AVX512 context if we use AVX512 instructions, even if the bit is not |
| 270 | // set right now. | 269 | // set right now. |
| 271 | const has_avx512_save = if (os_tag.isDarwin()) | 270 | const has_avx512_save = if (builtin.target.os.tag.isDarwin()) |
| 272 | true | 271 | true |
| 273 | else | 272 | else |
| 274 | xcr0.zmm_hi256 and xcr0.hi16_zmm; | 273 | xcr0.zmm_hi256 and xcr0.hi16_zmm; |