authorgravatar for lgustaf1@binghamton.eduLayne Gustafson <lgustaf1@binghamton.edu> 2020-01-08 22:29:12-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-19 20:53:20-05:00
logfd17a9962b07147a5b20487ab8e4d9bc0aa946cd
tree8d7bfb464f4db3669bc246970cb233f414d57643
parent03dd376b55a57cbc10269f771f72ced1eaa7aabb
signaturelock-open Commit is signed but in an unrecognized format.

Add defaut feature support


5 files changed, 141 insertions(+), 69 deletions(-)

src-self-hosted/stage1.zig+126-51
......@@ -625,6 +625,63 @@ const Stage2TargetDetails = struct {
625625 llvm_features_str: [:0]const u8,
626626
627627 builtin_str: [:0]const u8,
628
629 const Self = @This();
630
631 fn initCpu(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), cpu: *const std.target.Cpu) !Self {
632 var builtin_str_buffer = try std.Buffer.init(
633 allocator,
634 "@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
635 defer builtin_str_buffer.deinit();
636
637 try builtin_str_buffer.append(@tagName(arch));
638 try builtin_str_buffer.append(".cpu_");
639 try builtin_str_buffer.append(cpu.name);
640 try builtin_str_buffer.append("};");
641 return Self{
642 .allocator = allocator,
643 .target_details = .{
644 .cpu = cpu,
645 },
646 .llvm_cpu_str = cpu.name,
647 .llvm_features_str = "",
648 .builtin_str = builtin_str_buffer.toOwnedSlice(),
649 };
650 }
651
652 fn initFeatures(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), features: []*const std.target.Feature) !Self {
653 var builtin_str_buffer = try std.Buffer.init(
654 allocator,
655 "@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
656 defer builtin_str_buffer.deinit();
657
658 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
659 defer llvm_features_buffer.deinit();
660
661 for (features) |feature| {
662 try llvm_features_buffer.append("+");
663 try llvm_features_buffer.append(feature.llvm_name);
664 try llvm_features_buffer.append(",");
665
666 try builtin_str_buffer.append("&@import(\"std\").target.");
667 try builtin_str_buffer.append(@tagName(arch));
668 try builtin_str_buffer.append(".feature_");
669 try builtin_str_buffer.append(feature.name);
670 try builtin_str_buffer.append(",");
671 }
672
673 try builtin_str_buffer.append("}};");
674
675 return Self{
676 .allocator = allocator,
677 .target_details = std.target.TargetDetails{
678 .features = features,
679 },
680 .llvm_cpu_str = "",
681 .llvm_features_str = llvm_features_buffer.toOwnedSlice(),
682 .builtin_str = builtin_str_buffer.toOwnedSlice(),
683 };
684 }
628685};
629686
630687// ABI warning
......@@ -658,32 +715,14 @@ export fn stage2_target_details_parse_features(arch_str: ?[*:0]const u8, feature
658715}
659716
660717fn parseCpu(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2TargetDetails {
718 const allocator = std.heap.c_allocator;
719
661720 const cpus = std.target.getCpusForArch(arch);
662721
663722 for (cpus) |cpu| {
664723 if (std.mem.eql(u8, str, cpu.name)) {
665 const allocator = std.heap.c_allocator;
666
667 var builtin_str_buffer = try std.Buffer.init(
668 allocator,
669 "@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
670 defer builtin_str_buffer.deinit();
671
672 try builtin_str_buffer.append(@tagName(arch));
673 try builtin_str_buffer.append(".cpu_");
674 try builtin_str_buffer.append(cpu.name);
675 try builtin_str_buffer.append("};");
676
677724 const ptr = try allocator.create(Stage2TargetDetails);
678 ptr.* = .{
679 .allocator = allocator,
680 .target_details = .{
681 .cpu = cpu,
682 },
683 .llvm_cpu_str = cpu.name,
684 .llvm_features_str = "",
685 .builtin_str = builtin_str_buffer.toOwnedSlice(),
686 };
725 ptr.* = try Stage2TargetDetails.initCpu(std.heap.c_allocator, arch, cpu);
687726
688727 return ptr;
689728 }
......@@ -700,11 +739,6 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
700739 var features = std.ArrayList(*const std.target.Feature).init(allocator);
701740 defer features.deinit();
702741
703 var builtin_str_buffer = try std.Buffer.init(
704 allocator,
705 "@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
706 defer builtin_str_buffer.deinit();
707
708742 var start: usize = 0;
709743 while (start < str.len) {
710744 const next_comma_pos = std.mem.indexOfScalar(u8, str[start..], ',') orelse str.len - start;
......@@ -725,39 +759,15 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
725759 if (feature) |f| {
726760 features.append(f) catch @panic("out of memory");
727761
728 try builtin_str_buffer.append("&@import(\"std\").target.");
729 try builtin_str_buffer.append(@tagName(arch));
730 try builtin_str_buffer.append(".feature_");
731 try builtin_str_buffer.append(f.name);
732 try builtin_str_buffer.append(",");
733762 } else {
734763 return error.InvalidFeature;
735764 }
736765 }
737766
738 try builtin_str_buffer.append("}};");
739
740767 const features_slice = features.toOwnedSlice();
741768
742 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
743 defer llvm_features_buffer.deinit();
744
745 for (features_slice) |feature| {
746 try llvm_features_buffer.append("+");
747 try llvm_features_buffer.append(feature.llvm_name);
748 try llvm_features_buffer.append(",");
749 }
750
751769 const ptr = try allocator.create(Stage2TargetDetails);
752 ptr.* = Stage2TargetDetails{
753 .allocator = allocator,
754 .target_details = std.target.TargetDetails{
755 .features = features_slice,
756 },
757 .llvm_cpu_str = "",
758 .llvm_features_str = llvm_features_buffer.toOwnedSlice(),
759 .builtin_str = builtin_str_buffer.toOwnedSlice(),
760 };
770 ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features_slice);
761771
762772 return ptr;
763773}
......@@ -800,3 +810,68 @@ export fn stage2_target_details_get_builtin_str(target_details: ?*const Stage2Ta
800810
801811 return @as([*:0]const u8, "");
802812}
813
814const riscv_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
815 &std.target.riscv.feature_a,
816 &std.target.riscv.feature_c,
817 &std.target.riscv.feature_d,
818 &std.target.riscv.feature_f,
819 &std.target.riscv.feature_m,
820 &std.target.riscv.feature_relax,
821};
822
823const i386_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
824 &std.target.x86.feature_cmov,
825 &std.target.x86.feature_cx8,
826 &std.target.x86.feature_fxsr,
827 &std.target.x86.feature_mmx,
828 &std.target.x86.feature_nopl,
829 &std.target.x86.feature_sse,
830 &std.target.x86.feature_sse2,
831 &std.target.x86.feature_slowUnalignedMem16,
832 &std.target.x86.feature_x87,
833};
834
835// Same as above but without sse.
836const i386_default_features_freestanding: []*const std.target.Feature = &[_]*const std.target.Feature {
837 &std.target.x86.feature_cmov,
838 &std.target.x86.feature_cx8,
839 &std.target.x86.feature_fxsr,
840 &std.target.x86.feature_mmx,
841 &std.target.x86.feature_nopl,
842 &std.target.x86.feature_slowUnalignedMem16,
843 &std.target.x86.feature_x87,
844};
845
846// ABI warning
847export fn stage2_target_details_get_default(arch_str: ?[*:0]const u8, os_str: ?[*:0]const u8) ?*Stage2TargetDetails {
848 if (arch_str == null) return null;
849 if (os_str == null) return null;
850
851 const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_str.?)) catch return null;
852 const os = Target.parseOs(std.mem.toSliceConst(u8, os_str.?)) catch return null;
853
854 return createDefaultTargetDetails(arch, os) catch return null;
855}
856
857fn createDefaultTargetDetails(arch: @TagType(std.Target.Arch), os: std.Target.Os) !?*Stage2TargetDetails {
858 const allocator = std.heap.c_allocator;
859
860 return switch (arch) {
861 .riscv32, .riscv64 => blk: {
862 const ptr = try allocator.create(Stage2TargetDetails);
863 ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, riscv_default_features);
864 break :blk ptr;
865 },
866 .i386 => blk: {
867 const ptr = try allocator.create(Stage2TargetDetails);
868 const features = switch (os) {
869 .freestanding => i386_default_features_freestanding,
870 else => i386_default_features,
871 };
872 ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features);
873 break :blk ptr;
874 },
875 else => null,
876 };
877}
src/codegen.cpp+3-18
......@@ -8781,8 +8781,9 @@ static void init(CodeGen *g) {
87818781 reloc_mode = LLVMRelocStatic;
87828782 }
87838783
8784 const char *target_specific_cpu_args;
8785 const char *target_specific_features;
8784 const char *target_specific_cpu_args = "";
8785 const char *target_specific_features = "";
8786
87868787 if (g->zig_target->is_native) {
87878788 // LLVM creates invalid binaries on Windows sometimes.
87888789 // See https://github.com/ziglang/zig/issues/508
......@@ -8794,22 +8795,6 @@ static void init(CodeGen *g) {
87948795 target_specific_cpu_args = ZigLLVMGetHostCPUName();
87958796 target_specific_features = ZigLLVMGetNativeFeatures();
87968797 }
8797 } else if (target_is_riscv(g->zig_target)) {
8798 // TODO https://github.com/ziglang/zig/issues/2883
8799 // Be aware of https://github.com/ziglang/zig/issues/3275
8800 target_specific_cpu_args = "";
8801 target_specific_features = riscv_default_features;
8802 } else if (g->zig_target->arch == ZigLLVM_x86) {
8803 // This is because we're really targeting i686 rather than i386.
8804 // It's pretty much impossible to use many of the language features
8805 // such as fp16 if you stick use the x87 only. This is also what clang
8806 // uses as base cpu.
8807 // TODO https://github.com/ziglang/zig/issues/2883
8808 target_specific_cpu_args = "pentium4";
8809 target_specific_features = (g->zig_target->os == OsFreestanding) ? "-sse": "";
8810 } else {
8811 target_specific_cpu_args = "";
8812 target_specific_features = "";
88138798 }
88148799
88158800 // Override CPU and features if defined by user.
src/main.cpp+6
......@@ -1090,6 +1090,12 @@ int main(int argc, char **argv) {
10901090 fprintf(stderr, "invalid --features value\n");
10911091 return main_exit(root_progress_node, EXIT_FAILURE);
10921092 }
1093 } else {
1094 // If no details are specified and we are not native, load
1095 // cross-compilation default features.
1096 if (!target.is_native) {
1097 target_details = stage2_target_details_get_default(target_arch_name(target.arch), target_os_name(target.os));
1098 }
10931099 }
10941100
10951101 if (output_dir != nullptr && enable_cache == CacheOptOn) {
src/userland.cpp+3
......@@ -109,3 +109,6 @@ const char *stage2_target_details_get_llvm_features(const Stage2TargetDetails *t
109109const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details) {
110110 return "";
111111}
112Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os) {
113 return nullptr;
114}
src/userland.h+3
......@@ -201,4 +201,7 @@ ZIG_EXTERN_C const char *stage2_target_details_get_llvm_features(const Stage2Tar
201201// ABI warning
202202ZIG_EXTERN_C const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details);
203203
204// ABI warning
205ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os);
206
204207#endif