authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-21 22:01:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-21 22:02:13-05:00
logcbe9a51518db6f4e77a4f8c72e8cd9cd02fa7f49
tree9efdeb5bcc24f2cbafec863ee422eede660b2c7c
parent830e0ba2d27b55f999a891d007b24131b790e8c9
signaturelock-open Commit is signed but in an unrecognized format.

don't trust llvm's GetHostCPUName

comment from this commit reproduced here: I have observed the CPU name reported by LLVM being incorrect. On the SourceHut build services, LLVM 9.0 reports the CPU as "athlon-xp", which is a 32-bit CPU, even though the system is 64-bit and the reported CPU features include, among other things, +64bit. So the strategy taken here is that we observe both reported CPU, and the reported CPU features. The features are trusted more; but if the features match exactly the features of the reported CPU, then we trust the reported CPU.

2 files changed, 35 insertions(+), 12 deletions(-)

lib/std/target.zig+4
...@@ -637,6 +637,10 @@ pub const Target = union(enum) {...@@ -637,6 +637,10 @@ pub const Target = union(enum) {
637 pub fn asBytes(set: *const Set) *const [byte_count]u8 {637 pub fn asBytes(set: *const Set) *const [byte_count]u8 {
638 return @ptrCast(*const [byte_count]u8, &set.ints);638 return @ptrCast(*const [byte_count]u8, &set.ints);
639 }639 }
640
641 pub fn eql(set: Set, other: Set) bool {
642 return mem.eql(usize, &set.ints, &other.ints);
643 }
640 };644 };
641645
642 pub fn feature_set_fns(comptime F: type) type {646 pub fn feature_set_fns(comptime F: type) type {
src-self-hosted/stage1.zig+31-12
...@@ -540,27 +540,25 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz...@@ -540,27 +540,25 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
540 node.context.maybeRefresh();540 node.context.maybeRefresh();
541}541}
542542
543/// I have observed the CPU name reported by LLVM being incorrect. On
544/// the SourceHut build services, LLVM 9.0 reports the CPU as "athlon-xp",
545/// which is a 32-bit CPU, even though the system is 64-bit and the reported
546/// CPU features include, among other things, +64bit.
547/// So the strategy taken here is that we observe both reported CPU, and the
548/// reported CPU features. The features are trusted more; but if the features
549/// match exactly the features of the reported CPU, then we trust the reported CPU.
543fn cpuFeaturesFromLLVM(550fn cpuFeaturesFromLLVM(
544 arch: Target.Arch,551 arch: Target.Arch,
545 llvm_cpu_name_z: ?[*:0]const u8,552 llvm_cpu_name_z: ?[*:0]const u8,
546 llvm_cpu_features_opt: ?[*:0]const u8,553 llvm_cpu_features_opt: ?[*:0]const u8,
547) !Target.CpuFeatures {554) !Target.CpuFeatures {
548 if (llvm_cpu_name_z) |cpu_name_z| {
549 const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
550
551 for (arch.allCpus()) |cpu| {
552 const this_llvm_name = cpu.llvm_name orelse continue;
553 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
554 return Target.CpuFeatures{ .cpu = cpu };
555 }
556 }
557 }
558
559 var set = arch.baselineFeatures();555 var set = arch.baselineFeatures();
560 const llvm_cpu_features = llvm_cpu_features_opt orelse return Target.CpuFeatures{556 const llvm_cpu_features = llvm_cpu_features_opt orelse return Target.CpuFeatures{
561 .features = set,557 .features = set,
562 };558 };
563559
560 const all_features = arch.allFeaturesList();
561
564 var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");562 var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
565 while (it.next()) |decorated_llvm_feat| {563 while (it.next()) |decorated_llvm_feat| {
566 var op: enum {564 var op: enum {
...@@ -577,7 +575,7 @@ fn cpuFeaturesFromLLVM(...@@ -577,7 +575,7 @@ fn cpuFeaturesFromLLVM(
577 } else {575 } else {
578 return error.InvalidLlvmCpuFeaturesFormat;576 return error.InvalidLlvmCpuFeaturesFormat;
579 }577 }
580 for (arch.allFeaturesList()) |feature, index| {578 for (all_features) |feature, index| {
581 const this_llvm_name = feature.llvm_name orelse continue;579 const this_llvm_name = feature.llvm_name orelse continue;
582 if (mem.eql(u8, llvm_feat, this_llvm_name)) {580 if (mem.eql(u8, llvm_feat, this_llvm_name)) {
583 switch (op) {581 switch (op) {
...@@ -588,6 +586,27 @@ fn cpuFeaturesFromLLVM(...@@ -588,6 +586,27 @@ fn cpuFeaturesFromLLVM(
588 }586 }
589 }587 }
590 }588 }
589
590 if (llvm_cpu_name_z) |cpu_name_z| {
591 const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
592
593 for (arch.allCpus()) |cpu| {
594 const this_llvm_name = cpu.llvm_name orelse continue;
595 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
596 // Only trust the CPU if the reported features exactly match.
597 var populated_reported_features = set;
598 populated_reported_features.populateDependencies(all_features);
599 var populated_cpu_features = cpu.features;
600 populated_cpu_features.populateDependencies(all_features);
601 if (populated_reported_features.eql(populated_cpu_features)) {
602 return Target.CpuFeatures{ .cpu = cpu };
603 } else {
604 return Target.CpuFeatures{ .features = set };
605 }
606 }
607 }
608 }
609
591 return Target.CpuFeatures{ .features = set };610 return Target.CpuFeatures{ .features = set };
592}611}
593612