authorgravatar for ed.dean515@gmail.comEdward Dean <ed.dean515@gmail.com> 2021-02-24 19:45:45+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-11 13:32:28-07:00
log7ba175cd8b6fe421cd9c75c03006d2325906076c
tree605b7fbc8d5830d1887da9c4d696de61c34d8286
parent45212e3b33151b016ae4a597a898db0cc13d4e6b

Add CPU feature check to standardTargetOptions

If there is a mismatch of CPU features provided compared to the whitelist, then will fail the build and print what the expected CPU model is and the feature set for the model. Also prints what features need to be removed.

2 files changed, 66 insertions(+), 10 deletions(-)

lib/std/build.zig+57-8
......@@ -640,12 +640,18 @@ pub const Builder = struct {
640640 const mcpu = self.option([]const u8, "cpu", "Target CPU");
641641
642642 const triple = maybe_triple orelse return args.default_target;
643 const cpu_features = self.option(
644 []const u8,
645 "mcpu",
646 "The list of CPU features to add or subtract",
647 );
643648
644649 var diags: CrossTarget.ParseOptions.Diagnostics = .{};
645650 const selected_target = CrossTarget.parse(.{
646651 .arch_os_abi = triple,
647652 .cpu_features = mcpu,
648653 .diagnostics = &diags,
654 .cpu_features = cpu_features,
649655 }) catch |err| switch (err) {
650656 error.UnknownCpuModel => {
651657 warn("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':\n", .{
......@@ -699,20 +705,63 @@ pub const Builder = struct {
699705
700706 if (args.whitelist) |list| whitelist_check: {
701707 // Make sure it's a match of one of the list.
708 var mismatch_triple = true;
709 var mismatch_cpu_features = true;
710 var whitelist_item = CrossTarget{};
702711 for (list) |t| {
712 mismatch_cpu_features = true;
713 mismatch_triple = true;
714
703715 const t_triple = t.zigTriple(self.allocator) catch unreachable;
704716 if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
705 break :whitelist_check;
717 mismatch_triple = false;
718 whitelist_item = t;
719 if (t.getCpuFeatures().subSet(selected_target.getCpuFeatures())) {
720 mismatch_cpu_features = false;
721 break :whitelist_check;
722 } else {
723 break;
724 }
706725 }
707726 }
708 warn("Chosen target '{s}' does not match one of the supported targets:\n", .{
709 selected_canonicalized_triple,
710 });
711 for (list) |t| {
712 const t_triple = t.zigTriple(self.allocator) catch unreachable;
713 warn(" {s}\n", .{t_triple});
727 if (mismatch_triple) {
728 warn("Chosen target '{s}' does not match one of the supported targets:\n", .{
729 selected_canonicalized_triple,
730 });
731 for (list) |t| {
732 const t_triple = t.zigTriple(self.allocator) catch unreachable;
733 warn(" {s}\n", .{t_triple});
734 }
735 warn("\n", .{});
736 } else { // mismatch_cpu_features
737 const whitelist_cpu = whitelist_item.getCpu();
738 const selected_cpu = selected_target.getCpu();
739 warn("Chosen CPU model '{s}' does not match one of the supported targets:\n", .{
740 selected_cpu.model.name,
741 });
742 warn(" Supported feature Set: ", .{});
743 const all_features = whitelist_cpu.arch.allFeaturesList();
744 var populated_cpu_features = whitelist_cpu.model.features;
745 populated_cpu_features.populateDependencies(all_features);
746 for (all_features) |feature, i_usize| {
747 const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
748 const in_cpu_set = populated_cpu_features.isEnabled(i);
749 if (in_cpu_set) {
750 warn("{s} ", .{feature.name});
751 }
752 }
753 warn("\n", .{});
754 warn(" Remove: ", .{});
755 for (all_features) |feature, i_usize| {
756 const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
757 const in_cpu_set = populated_cpu_features.isEnabled(i);
758 const in_actual_set = selected_cpu.features.isEnabled(i);
759 if (in_actual_set and !in_cpu_set) {
760 warn("{s} ", .{feature.name});
761 }
762 }
763 warn("\n", .{});
714764 }
715 warn("\n", .{});
716765 self.markInvalidUserInput();
717766 return args.default_target;
718767 }
lib/std/target.zig+9-2
......@@ -664,8 +664,15 @@ pub const Target = struct {
664664 return @ptrCast(*const [byte_count]u8, &set.ints);
665665 }
666666
667 pub fn eql(set: Set, other: Set) bool {
668 return mem.eql(usize, &set.ints, &other.ints);
667 pub fn eql(set: Set, other_set: Set) bool {
668 return mem.eql(usize, &set.ints, &other_set.ints);
669 }
670
671 /// Is the other set a sub set of this set
672 pub fn subSet(set: Set, other_set: Set) bool {
673 return std.meta.eql((@as(std.meta.Vector(usize_count, usize), set.ints) &
674 @as(std.meta.Vector(usize_count, usize), other_set.ints)),
675 @as(std.meta.Vector(usize_count, usize), other_set.ints));
669676 }
670677 };
671678