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 {...@@ -640,12 +640,18 @@ pub const Builder = struct {
640 const mcpu = self.option([]const u8, "cpu", "Target CPU");640 const mcpu = self.option([]const u8, "cpu", "Target CPU");
641641
642 const triple = maybe_triple orelse return args.default_target;642 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
644 var diags: CrossTarget.ParseOptions.Diagnostics = .{};649 var diags: CrossTarget.ParseOptions.Diagnostics = .{};
645 const selected_target = CrossTarget.parse(.{650 const selected_target = CrossTarget.parse(.{
646 .arch_os_abi = triple,651 .arch_os_abi = triple,
647 .cpu_features = mcpu,652 .cpu_features = mcpu,
648 .diagnostics = &diags,653 .diagnostics = &diags,
654 .cpu_features = cpu_features,
649 }) catch |err| switch (err) {655 }) catch |err| switch (err) {
650 error.UnknownCpuModel => {656 error.UnknownCpuModel => {
651 warn("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':\n", .{657 warn("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':\n", .{
...@@ -699,20 +705,63 @@ pub const Builder = struct {...@@ -699,20 +705,63 @@ pub const Builder = struct {
699705
700 if (args.whitelist) |list| whitelist_check: {706 if (args.whitelist) |list| whitelist_check: {
701 // Make sure it's a match of one of the list.707 // 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{};
702 for (list) |t| {711 for (list) |t| {
712 mismatch_cpu_features = true;
713 mismatch_triple = true;
714
703 const t_triple = t.zigTriple(self.allocator) catch unreachable;715 const t_triple = t.zigTriple(self.allocator) catch unreachable;
704 if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {716 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 }
706 }725 }
707 }726 }
708 warn("Chosen target '{s}' does not match one of the supported targets:\n", .{727 if (mismatch_triple) {
709 selected_canonicalized_triple,728 warn("Chosen target '{s}' does not match one of the supported targets:\n", .{
710 });729 selected_canonicalized_triple,
711 for (list) |t| {730 });
712 const t_triple = t.zigTriple(self.allocator) catch unreachable;731 for (list) |t| {
713 warn(" {s}\n", .{t_triple});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", .{});
714 }764 }
715 warn("\n", .{});
716 self.markInvalidUserInput();765 self.markInvalidUserInput();
717 return args.default_target;766 return args.default_target;
718 }767 }
lib/std/target.zig+9-2
...@@ -664,8 +664,15 @@ pub const Target = struct {...@@ -664,8 +664,15 @@ pub const Target = struct {
664 return @ptrCast(*const [byte_count]u8, &set.ints);664 return @ptrCast(*const [byte_count]u8, &set.ints);
665 }665 }
666666
667 pub fn eql(set: Set, other: Set) bool {667 pub fn eql(set: Set, other_set: Set) bool {
668 return mem.eql(usize, &set.ints, &other.ints);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));
669 }676 }
670 };677 };
671678