| author | |
| committer | |
| log | bd6ef21f8556b3872c5780eee70621e6c66a0aa4 |
| tree | 8b7c28b324ff41905b26d28c5e0c3441f93c06f0 |
| parent | c8f1e0d6d8f3ccfa952e9612903783baa9b2c12f |
| signature |
6 files changed, 123 insertions(+), 4 deletions(-)
src-self-hosted/stage1.zig+91-4| ... | @@ -531,12 +531,12 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz | ... | @@ -531,12 +531,12 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz |
| 531 | 531 | ||
| 532 | // ABI warning | 532 | // ABI warning |
| 533 | export fn stage2_list_features_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_subfeatures: bool) void { | 533 | export fn stage2_list_features_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_subfeatures: bool) void { |
| 534 | print_features_for_arch(arch_name_ptr[0..arch_name_len], show_subfeatures) catch |err| { | 534 | printFeaturesForArch(arch_name_ptr[0..arch_name_len], show_subfeatures) catch |err| { |
| 535 | std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) }); | 535 | std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) }); |
| 536 | }; | 536 | }; |
| 537 | } | 537 | } |
| 538 | 538 | ||
| 539 | fn print_features_for_arch(arch_name: []const u8, show_subfeatures: bool) !void { | 539 | fn printFeaturesForArch(arch_name: []const u8, show_subfeatures: bool) !void { |
| 540 | const stdout_stream = &std.io.getStdOut().outStream().stream; | 540 | const stdout_stream = &std.io.getStdOut().outStream().stream; |
| 541 | 541 | ||
| 542 | const arch = Target.parseArchTag(arch_name) catch { | 542 | const arch = Target.parseArchTag(arch_name) catch { |
| ... | @@ -575,12 +575,12 @@ fn print_features_for_arch(arch_name: []const u8, show_subfeatures: bool) !void | ... | @@ -575,12 +575,12 @@ fn print_features_for_arch(arch_name: []const u8, show_subfeatures: bool) !void |
| 575 | 575 | ||
| 576 | // ABI warning | 576 | // ABI warning |
| 577 | export fn stage2_list_cpus_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_subfeatures: bool) void { | 577 | export fn stage2_list_cpus_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_subfeatures: bool) void { |
| 578 | print_cpus_for_arch(arch_name_ptr[0..arch_name_len], show_subfeatures) catch |err| { | 578 | printCpusForArch(arch_name_ptr[0..arch_name_len], show_subfeatures) catch |err| { |
| 579 | std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) }); | 579 | std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) }); |
| 580 | }; | 580 | }; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | fn print_cpus_for_arch(arch_name: []const u8, show_subfeatures: bool) !void { | 583 | fn printCpusForArch(arch_name: []const u8, show_subfeatures: bool) !void { |
| 584 | const stdout_stream = &std.io.getStdOut().outStream().stream; | 584 | const stdout_stream = &std.io.getStdOut().outStream().stream; |
| 585 | 585 | ||
| 586 | const arch = Target.parseArchTag(arch_name) catch { | 586 | const arch = Target.parseArchTag(arch_name) catch { |
| ... | @@ -618,3 +618,90 @@ fn print_cpus_for_arch(arch_name: []const u8, show_subfeatures: bool) !void { | ... | @@ -618,3 +618,90 @@ fn print_cpus_for_arch(arch_name: []const u8, show_subfeatures: bool) !void { |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | // use target_arch_name(ZigLLVM_ArchType) to get name from main.cpp 'target'. | 620 | // use target_arch_name(ZigLLVM_ArchType) to get name from main.cpp 'target'. |
| 621 | // ABI warning | ||
| 622 | export fn stage2_validate_cpu_and_features( | ||
| 623 | arch_name: [*:0]const u8, | ||
| 624 | cpu: ?[*:0]const u8, | ||
| 625 | features: ?[*:0]const u8, | ||
| 626 | ) bool { | ||
| 627 | const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_name)) catch { | ||
| 628 | std.debug.warn("Failed to parse arch '{}'\nInvoke 'zig targets' for a list of valid architectures\n", .{ arch_name }); | ||
| 629 | return false; | ||
| 630 | }; | ||
| 631 | |||
| 632 | const res = validateCpuAndFeatures( | ||
| 633 | arch, | ||
| 634 | if (cpu) |def_cpu| std.mem.toSliceConst(u8, def_cpu) else "", | ||
| 635 | if (features) |def_features| std.mem.toSliceConst(u8, def_features) else ""); | ||
| 636 | |||
| 637 | switch (res) { | ||
| 638 | .Ok => return true, | ||
| 639 | .InvalidCpu => |invalid_cpu| { | ||
| 640 | std.debug.warn("Invalid CPU '{}'\n", .{ invalid_cpu }); | ||
| 641 | return false; | ||
| 642 | }, | ||
| 643 | .InvalidFeaturesString => { | ||
| 644 | std.debug.warn("Invalid features string\n", .{}); | ||
| 645 | std.debug.warn("Must have format \"+yes_feature,-no_feature\"\n", .{}); | ||
| 646 | return false; | ||
| 647 | }, | ||
| 648 | .InvalidFeature => |invalid_feature| { | ||
| 649 | std.debug.warn("Invalid feature '{}'\n", .{ invalid_feature }); | ||
| 650 | return false; | ||
| 651 | } | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | const ValidateCpuAndFeaturesResult = union(enum) { | ||
| 656 | Ok, | ||
| 657 | InvalidCpu: []const u8, | ||
| 658 | InvalidFeaturesString, | ||
| 659 | InvalidFeature: []const u8, | ||
| 660 | }; | ||
| 661 | |||
| 662 | fn validateCpuAndFeatures(arch: @TagType(std.Target.Arch), cpu: []const u8, features: []const u8) ValidateCpuAndFeaturesResult { | ||
| 663 | |||
| 664 | const known_cpus = std.target.getCpusForArch(arch); | ||
| 665 | const known_features = std.target.getFeaturesForArch(arch); | ||
| 666 | |||
| 667 | if (cpu.len > 0) { | ||
| 668 | var found_cpu = false; | ||
| 669 | for (known_cpus) |known_cpu| { | ||
| 670 | if (std.mem.eql(u8, cpu, known_cpu.name)) { | ||
| 671 | found_cpu = true; | ||
| 672 | break; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | if (!found_cpu) { | ||
| 677 | return .{ .InvalidCpu = cpu }; | ||
| 678 | } | ||
| 679 | } | ||
| 680 | |||
| 681 | if (features.len > 0) { | ||
| 682 | var start: usize = 0; | ||
| 683 | while (start < features.len) { | ||
| 684 | const next_comma_pos = std.mem.indexOfScalar(u8, features[start..], ',') orelse features.len - start; | ||
| 685 | var feature = features[start..start+next_comma_pos]; | ||
| 686 | |||
| 687 | if (feature.len < 2) return .{ .InvalidFeaturesString = {} }; | ||
| 688 | |||
| 689 | if (feature[0] != '+' and feature[0] != '-') return .{ .InvalidFeaturesString = {} }; | ||
| 690 | feature = feature[1..]; | ||
| 691 | |||
| 692 | var found_feature = false; | ||
| 693 | for (known_features) |known_feature| { | ||
| 694 | if (std.mem.eql(u8, feature, known_feature.name)) { | ||
| 695 | found_feature = true; | ||
| 696 | break; | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | if (!found_feature) return .{ .InvalidFeature = feature }; | ||
| 701 | |||
| 702 | start += next_comma_pos + 1; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | return .{ .Ok = {} }; | ||
| 707 | } |
src/all_types.hpp+3| ... | @@ -2215,6 +2215,9 @@ struct CodeGen { | ... | @@ -2215,6 +2215,9 @@ struct CodeGen { |
| 2215 | 2215 | ||
| 2216 | const char **clang_argv; | 2216 | const char **clang_argv; |
| 2217 | size_t clang_argv_len; | 2217 | size_t clang_argv_len; |
| 2218 | |||
| 2219 | const char *llvm_cpu; | ||
| 2220 | const char *llvm_features; | ||
| 2218 | }; | 2221 | }; |
| 2219 | 2222 | ||
| 2220 | struct ZigVar { | 2223 | struct ZigVar { |
src/codegen.cpp+9| ... | @@ -8800,6 +8800,15 @@ static void init(CodeGen *g) { | ... | @@ -8800,6 +8800,15 @@ static void init(CodeGen *g) { |
| 8800 | target_specific_features = ""; | 8800 | target_specific_features = ""; |
| 8801 | } | 8801 | } |
| 8802 | 8802 | ||
| 8803 | // Override CPU and features if non-null. | ||
| 8804 | if (g->llvm_cpu != nullptr) { | ||
| 8805 | target_specific_cpu_args = g->llvm_cpu; | ||
| 8806 | } | ||
| 8807 | |||
| 8808 | if (g->llvm_features != nullptr) { | ||
| 8809 | target_specific_features = g->llvm_features; | ||
| 8810 | } | ||
| 8811 | |||
| 8803 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), | 8812 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), |
| 8804 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, | 8813 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, |
| 8805 | LLVMCodeModelDefault, g->function_sections); | 8814 | LLVMCodeModelDefault, g->function_sections); |
src/main.cpp+16| ... | @@ -100,6 +100,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { | ... | @@ -100,6 +100,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 100 | " --override-lib-dir [arg] override path to Zig lib directory\n" | 100 | " --override-lib-dir [arg] override path to Zig lib directory\n" |
| 101 | " -ffunction-sections places each function in a separate section\n" | 101 | " -ffunction-sections places each function in a separate section\n" |
| 102 | " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" | 102 | " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" |
| 103 | " --cpu [cpu] compile for [cpu] on the current target\n" | ||
| 104 | " --features [feature_str] compile with features in [feature_str] on the current target\n" | ||
| 103 | "\n" | 105 | "\n" |
| 104 | "Link Options:\n" | 106 | "Link Options:\n" |
| 105 | " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n" | 107 | " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n" |
| ... | @@ -533,6 +535,8 @@ int main(int argc, char **argv) { | ... | @@ -533,6 +535,8 @@ int main(int argc, char **argv) { |
| 533 | WantStackCheck want_stack_check = WantStackCheckAuto; | 535 | WantStackCheck want_stack_check = WantStackCheckAuto; |
| 534 | WantCSanitize want_sanitize_c = WantCSanitizeAuto; | 536 | WantCSanitize want_sanitize_c = WantCSanitizeAuto; |
| 535 | bool function_sections = false; | 537 | bool function_sections = false; |
| 538 | const char *cpu = ""; | ||
| 539 | const char *features = ""; | ||
| 536 | 540 | ||
| 537 | const char *targets_list_features_arch = nullptr; | 541 | const char *targets_list_features_arch = nullptr; |
| 538 | const char *targets_list_cpus_arch = nullptr; | 542 | const char *targets_list_cpus_arch = nullptr; |
| ... | @@ -951,6 +955,10 @@ int main(int argc, char **argv) { | ... | @@ -951,6 +955,10 @@ int main(int argc, char **argv) { |
| 951 | targets_list_features_arch = argv[i]; | 955 | targets_list_features_arch = argv[i]; |
| 952 | } else if (strcmp(arg, "--list-cpus") == 0) { | 956 | } else if (strcmp(arg, "--list-cpus") == 0) { |
| 953 | targets_list_cpus_arch = argv[i]; | 957 | targets_list_cpus_arch = argv[i]; |
| 958 | } else if (strcmp(arg, "--cpu") == 0) { | ||
| 959 | cpu = argv[i]; | ||
| 960 | } else if (strcmp(arg, "--features") == 0) { | ||
| 961 | features = argv[i]; | ||
| 954 | }else { | 962 | }else { |
| 955 | fprintf(stderr, "Invalid argument: %s\n", arg); | 963 | fprintf(stderr, "Invalid argument: %s\n", arg); |
| 956 | return print_error_usage(arg0); | 964 | return print_error_usage(arg0); |
| ... | @@ -1248,6 +1256,7 @@ int main(int argc, char **argv) { | ... | @@ -1248,6 +1256,7 @@ int main(int argc, char **argv) { |
| 1248 | g->system_linker_hack = system_linker_hack; | 1256 | g->system_linker_hack = system_linker_hack; |
| 1249 | g->function_sections = function_sections; | 1257 | g->function_sections = function_sections; |
| 1250 | 1258 | ||
| 1259 | |||
| 1251 | for (size_t i = 0; i < lib_dirs.length; i += 1) { | 1260 | for (size_t i = 0; i < lib_dirs.length; i += 1) { |
| 1252 | codegen_add_lib_dir(g, lib_dirs.at(i)); | 1261 | codegen_add_lib_dir(g, lib_dirs.at(i)); |
| 1253 | } | 1262 | } |
| ... | @@ -1269,6 +1278,13 @@ int main(int argc, char **argv) { | ... | @@ -1269,6 +1278,13 @@ int main(int argc, char **argv) { |
| 1269 | codegen_add_rpath(g, rpath_list.at(i)); | 1278 | codegen_add_rpath(g, rpath_list.at(i)); |
| 1270 | } | 1279 | } |
| 1271 | 1280 | ||
| 1281 | if (!stage2_validate_cpu_and_features(target_arch_name(target.arch), cpu, features)) { | ||
| 1282 | return 1; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | g->llvm_cpu = cpu; | ||
| 1286 | g->llvm_features = features; | ||
| 1287 | |||
| 1272 | codegen_set_rdynamic(g, rdynamic); | 1288 | codegen_set_rdynamic(g, rdynamic); |
| 1273 | if (mmacosx_version_min && mios_version_min) { | 1289 | if (mmacosx_version_min && mios_version_min) { |
| 1274 | fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n"); | 1290 | fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n"); |
src/userland.cpp+1| ... | @@ -91,3 +91,4 @@ void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_coun | ... | @@ -91,3 +91,4 @@ void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_coun |
| 91 | 91 | ||
| 92 | void stage2_list_features_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {} | 92 | void stage2_list_features_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {} |
| 93 | void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {} | 93 | void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {} |
| 94 | bool stage2_validate_cpu_and_features(const char *arch_name, const char *cpu, const char *features) { return true; } |
src/userland.h+3| ... | @@ -180,4 +180,7 @@ ZIG_EXTERN_C void stage2_list_features_for_arch(const char *arch_name_ptr, size_ | ... | @@ -180,4 +180,7 @@ ZIG_EXTERN_C void stage2_list_features_for_arch(const char *arch_name_ptr, size_ |
| 180 | // ABI warning | 180 | // ABI warning |
| 181 | ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures); | 181 | ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures); |
| 182 | 182 | ||
| 183 | // ABI warning | ||
| 184 | ZIG_EXTERN_C bool stage2_validate_cpu_and_features(const char *arch_name, const char *cpu, const char *features); | ||
| 185 | |||
| 183 | #endif | 186 | #endif |