From 7ba175cd8b6fe421cd9c75c03006d2325906076c Mon Sep 17 00:00:00 2001 From: Edward Dean Date: Wed, 24 Feb 2021 19:45:45 +0000 Subject: 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. --- lib/std/build.zig | 65 +++++++++++++++++++++++++++++++++++++++++++++++------- lib/std/target.zig | 11 +++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/std/build.zig b/lib/std/build.zig index 12c98271d5..3bea2187bd 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -640,12 +640,18 @@ pub const Builder = struct { const mcpu = self.option([]const u8, "cpu", "Target CPU"); const triple = maybe_triple orelse return args.default_target; + const cpu_features = self.option( + []const u8, + "mcpu", + "The list of CPU features to add or subtract", + ); var diags: CrossTarget.ParseOptions.Diagnostics = .{}; const selected_target = CrossTarget.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, + .cpu_features = cpu_features, }) catch |err| switch (err) { error.UnknownCpuModel => { warn("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':\n", .{ @@ -699,20 +705,63 @@ pub const Builder = struct { if (args.whitelist) |list| whitelist_check: { // Make sure it's a match of one of the list. + var mismatch_triple = true; + var mismatch_cpu_features = true; + var whitelist_item = CrossTarget{}; for (list) |t| { + mismatch_cpu_features = true; + mismatch_triple = true; + const t_triple = t.zigTriple(self.allocator) catch unreachable; if (mem.eql(u8, t_triple, selected_canonicalized_triple)) { - break :whitelist_check; + mismatch_triple = false; + whitelist_item = t; + if (t.getCpuFeatures().subSet(selected_target.getCpuFeatures())) { + mismatch_cpu_features = false; + break :whitelist_check; + } else { + break; + } } } - warn("Chosen target '{s}' does not match one of the supported targets:\n", .{ - selected_canonicalized_triple, - }); - for (list) |t| { - const t_triple = t.zigTriple(self.allocator) catch unreachable; - warn(" {s}\n", .{t_triple}); + if (mismatch_triple) { + warn("Chosen target '{s}' does not match one of the supported targets:\n", .{ + selected_canonicalized_triple, + }); + for (list) |t| { + const t_triple = t.zigTriple(self.allocator) catch unreachable; + warn(" {s}\n", .{t_triple}); + } + warn("\n", .{}); + } else { // mismatch_cpu_features + const whitelist_cpu = whitelist_item.getCpu(); + const selected_cpu = selected_target.getCpu(); + warn("Chosen CPU model '{s}' does not match one of the supported targets:\n", .{ + selected_cpu.model.name, + }); + warn(" Supported feature Set: ", .{}); + const all_features = whitelist_cpu.arch.allFeaturesList(); + var populated_cpu_features = whitelist_cpu.model.features; + populated_cpu_features.populateDependencies(all_features); + for (all_features) |feature, i_usize| { + const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize); + const in_cpu_set = populated_cpu_features.isEnabled(i); + if (in_cpu_set) { + warn("{s} ", .{feature.name}); + } + } + warn("\n", .{}); + warn(" Remove: ", .{}); + for (all_features) |feature, i_usize| { + const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize); + const in_cpu_set = populated_cpu_features.isEnabled(i); + const in_actual_set = selected_cpu.features.isEnabled(i); + if (in_actual_set and !in_cpu_set) { + warn("{s} ", .{feature.name}); + } + } + warn("\n", .{}); } - warn("\n", .{}); self.markInvalidUserInput(); return args.default_target; } diff --git a/lib/std/target.zig b/lib/std/target.zig index 3fd5cd5f94..55872ad2c6 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -664,8 +664,15 @@ pub const Target = struct { return @ptrCast(*const [byte_count]u8, &set.ints); } - pub fn eql(set: Set, other: Set) bool { - return mem.eql(usize, &set.ints, &other.ints); + pub fn eql(set: Set, other_set: Set) bool { + return mem.eql(usize, &set.ints, &other_set.ints); + } + + /// Is the other set a sub set of this set + pub fn subSet(set: Set, other_set: Set) bool { + return std.meta.eql((@as(std.meta.Vector(usize_count, usize), set.ints) & + @as(std.meta.Vector(usize_count, usize), other_set.ints)), + @as(std.meta.Vector(usize_count, usize), other_set.ints)); } }; -- cgit v1.2.3 From da4081fe21f534157a7a88e2d6b2b6a80ee2f32d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 11 Jun 2021 14:01:13 -0700 Subject: cleanups to previous commit * fix a merge conflict discovered upon rebasing latest master * rename Target.Cpu.Feature.Set.subSet to isSuperSetOf * convert a comment into an assert --- lib/std/build.zig | 13 ++++--------- lib/std/target.zig | 10 +++++----- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/std/build.zig b/lib/std/build.zig index 3bea2187bd..2b8ad8839a 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -637,21 +637,15 @@ pub const Builder = struct { "target", "The CPU architecture, OS, and ABI to build for", ); - const mcpu = self.option([]const u8, "cpu", "Target CPU"); + const mcpu = self.option([]const u8, "cpu", "Target CPU features to add or subtract"); const triple = maybe_triple orelse return args.default_target; - const cpu_features = self.option( - []const u8, - "mcpu", - "The list of CPU features to add or subtract", - ); var diags: CrossTarget.ParseOptions.Diagnostics = .{}; const selected_target = CrossTarget.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, - .cpu_features = cpu_features, }) catch |err| switch (err) { error.UnknownCpuModel => { warn("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':\n", .{ @@ -716,7 +710,7 @@ pub const Builder = struct { if (mem.eql(u8, t_triple, selected_canonicalized_triple)) { mismatch_triple = false; whitelist_item = t; - if (t.getCpuFeatures().subSet(selected_target.getCpuFeatures())) { + if (t.getCpuFeatures().isSuperSetOf(selected_target.getCpuFeatures())) { mismatch_cpu_features = false; break :whitelist_check; } else { @@ -733,7 +727,8 @@ pub const Builder = struct { warn(" {s}\n", .{t_triple}); } warn("\n", .{}); - } else { // mismatch_cpu_features + } else { + assert(mismatch_cpu_features); const whitelist_cpu = whitelist_item.getCpu(); const selected_cpu = selected_target.getCpu(); warn("Chosen CPU model '{s}' does not match one of the supported targets:\n", .{ diff --git a/lib/std/target.zig b/lib/std/target.zig index 55872ad2c6..faebe665ab 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -668,11 +668,11 @@ pub const Target = struct { return mem.eql(usize, &set.ints, &other_set.ints); } - /// Is the other set a sub set of this set - pub fn subSet(set: Set, other_set: Set) bool { - return std.meta.eql((@as(std.meta.Vector(usize_count, usize), set.ints) & - @as(std.meta.Vector(usize_count, usize), other_set.ints)), - @as(std.meta.Vector(usize_count, usize), other_set.ints)); + pub fn isSuperSetOf(set: Set, other_set: Set) bool { + const V = std.meta.Vector(usize_count, usize); + const set_v: V = set.ints; + const other_v: V = other_set.ints; + return @reduce(.And, (set_v & other_v) == other_v); } }; -- cgit v1.2.3