| ... | @@ -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"); |
| 641 | | 641 | |
| 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 | ); |
| 643 | | 648 | |
| 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 { |
| 699 | | 705 | |
| 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 | } |