authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-19 13:52:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-19 20:54:05-05:00
loga313f153841df8caa3af8fc80966c8f61a856f51
treec3bec9cc198079ee945c3e5c6d5734dd5c8183e6
parenta867b43366c7fb132ec44a03f9b40ead888900fb
signaturelock-open Commit is signed but in an unrecognized format.

figure out zig0/stage1 and scanning for native CPU


4 files changed, 172 insertions(+), 72 deletions(-)

src-self-hosted/stage1.zig+106-40
...@@ -632,24 +632,77 @@ const Stage2CpuFeatures = struct {...@@ -632,24 +632,77 @@ const Stage2CpuFeatures = struct {
632632
633 const Self = @This();633 const Self = @This();
634634
635 fn initBaseline(allocator: *mem.Allocator) !Self {635 fn createBaseline(allocator: *mem.Allocator) !*Self {
636 const builtin_str = try std.fmt.allocPrint0(allocator, "CpuFeatures.baseline;\n");636 const self = try allocator.create(Self);
637 errdefer allocator.destroy(self);
638
639 const builtin_str = try std.fmt.allocPrint0(allocator, ".baseline;\n");
637 errdefer allocator.free(builtin_str);640 errdefer allocator.free(builtin_str);
638641
639 const cache_hash = try std.fmt.allocPrint0(allocator, "\n\n");642 const cache_hash = try std.fmt.allocPrint0(allocator, "\n\n");
640 errdefer allocator.free(cache_hash);643 errdefer allocator.free(cache_hash);
641644
642 return Self{645 self.* = Self{
643 .allocator = allocator,646 .allocator = allocator,
644 .cpu_features = .{ .cpu = cpu },647 .cpu_features = .baseline,
645 .llvm_cpu_name = null,648 .llvm_cpu_name = null,
646 .llvm_features_str = null,649 .llvm_features_str = null,
647 .builtin_str = builtin_str,650 .builtin_str = builtin_str,
648 .cache_hash = cache_hash,651 .cache_hash = cache_hash,
649 };652 };
653 return self;
654 }
655
656 fn createFromLLVM(
657 allocator: *mem.Allocator,
658 arch: [*:0]const u8,
659 llvm_cpu_name_z: [*:0]const u8,
660 llvm_cpu_features: [*:0]const u8,
661 ) !*Self {
662 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
663 const llvm_cpu_name = mem.toSliceConst(u8, llvm_cpu_name_z);
664
665 for (arch.allCpus()) |cpu| {
666 const this_llvm_name = cpu.llvm_name orelse continue;
667 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
668 return createFromCpu(allocator, arch, cpu);
669 }
670 }
671
672 var set = arch.baselineFeatures();
673 var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
674 while (it.next()) |decorated_llvm_feat| {
675 var op: enum {
676 add,
677 sub,
678 } = undefined;
679 var llvm_feat: []const u8 = undefined;
680 if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
681 op = .add;
682 llvm_feat = decorated_llvm_feat[1..];
683 } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
684 op = .sub;
685 llvm_feat = decorated_llvm_feat[1..];
686 } else {
687 return error.InvalidLlvmCpuFeaturesFormat;
688 }
689 for (arch.allFeaturesList()) |feature, index| {
690 if (mem.eql(u8, feature_name, feature.name)) {
691 switch (op) {
692 .add => set |= 1 << index,
693 .sub => set &= ~@as(Target.Cpu.Feature.Set, 1 << index),
694 }
695 break;
696 }
697 }
698 }
699 return createFromCpuFeatures(allocator, arch, set);
650 }700 }
651701
652 fn initCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !Self {702 fn createFromCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !*Self {
703 const self = try allocator.create(Self);
704 errdefer allocator.destroy(self);
705
653 const builtin_str = try std.fmt.allocPrint0(706 const builtin_str = try std.fmt.allocPrint0(
654 allocator,707 allocator,
655 "CpuFeatures{{ .cpu = &Arch.{}.cpu.{} }};\n",708 "CpuFeatures{{ .cpu = &Arch.{}.cpu.{} }};\n",
...@@ -661,7 +714,7 @@ const Stage2CpuFeatures = struct {...@@ -661,7 +714,7 @@ const Stage2CpuFeatures = struct {
661 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{x}", cpu.name, cpu.features);714 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{x}", cpu.name, cpu.features);
662 errdefer allocator.free(cache_hash);715 errdefer allocator.free(cache_hash);
663716
664 return Self{717 self.* = Self{
665 .allocator = allocator,718 .allocator = allocator,
666 .cpu_features = .{ .cpu = cpu },719 .cpu_features = .{ .cpu = cpu },
667 .llvm_cpu_name = cpu.llvm_name,720 .llvm_cpu_name = cpu.llvm_name,
...@@ -669,13 +722,17 @@ const Stage2CpuFeatures = struct {...@@ -669,13 +722,17 @@ const Stage2CpuFeatures = struct {
669 .builtin_str = builtin_str,722 .builtin_str = builtin_str,
670 .cache_hash = cache_hash,723 .cache_hash = cache_hash,
671 };724 };
725 return self;
672 }726 }
673727
674 fn initFeatures(728 fn createFromCpuFeatures(
675 allocator: *mem.Allocator,729 allocator: *mem.Allocator,
676 arch: Target.Arch,730 arch: Target.Arch,
677 features: Target.Cpu.Feature.Set,731 features: Target.Cpu.Feature.Set,
678 ) !Self {732 ) !*Self {
733 const self = try allocator.create(Self);
734 errdefer allocator.destroy(self);
735
679 const cache_hash = try std.fmt.allocPrint0(allocator, "\n{x}", features);736 const cache_hash = try std.fmt.allocPrint0(allocator, "\n{x}", features);
680 errdefer allocator.free(cache_hash);737 errdefer allocator.free(cache_hash);
681738
...@@ -719,7 +776,7 @@ const Stage2CpuFeatures = struct {...@@ -719,7 +776,7 @@ const Stage2CpuFeatures = struct {
719776
720 try builtin_str_buffer.append("})};\n");777 try builtin_str_buffer.append("})};\n");
721778
722 return Self{779 self.* = Self{
723 .allocator = allocator,780 .allocator = allocator,
724 .cpu_features = .{ .features = features },781 .cpu_features = .{ .features = features },
725 .llvm_cpu_name = null,782 .llvm_cpu_name = null,
...@@ -727,68 +784,77 @@ const Stage2CpuFeatures = struct {...@@ -727,68 +784,77 @@ const Stage2CpuFeatures = struct {
727 .builtin_str = builtin_str_buffer.toOwnedSlice(),784 .builtin_str = builtin_str_buffer.toOwnedSlice(),
728 .cache_hash = cache_hash,785 .cache_hash = cache_hash,
729 };786 };
787 return self;
730 }788 }
731789
732 fn deinit(self: *Self) void {790 fn destroy(self: *Self) void {
733 self.allocator.free(self.cache_hash);791 self.allocator.free(self.cache_hash);
734 self.allocator.free(self.builtin_str);792 self.allocator.free(self.builtin_str);
735 if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);793 if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
736 self.* = undefined;794 self.allocator.destroy(self);
737 }795 }
738};796};
739797
740// ABI warning798// ABI warning
741export fn stage2_cpu_features_parse_cpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) *Stage2CpuFeatures {799export fn stage2_cpu_features_parse_cpu(
742 return parseCpu(arch_name, cpu_name) catch |err| switch (err) {800 result: **Stage2CpuFeatures,
743 error.OutOfMemory => @panic("out of memory"),801 arch_name: [*:0]const u8,
802 cpu_name: [*:0]const u8,
803) Error {
804 result.* = parseCpu(arch_name, cpu_name) catch |err| switch (err) {
805 error.OutOfMemory => return .OutOfMemory,
744 };806 };
807 return .None;
745}808}
746809
747fn parseCpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) !*Stage2CpuFeatures {810fn parseCpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) !*Stage2CpuFeatures {
748 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));811 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
749 const cpu = try arch.parseCpu(mem.toSliceConst(u8, cpu_name));812 const cpu = try arch.parseCpu(mem.toSliceConst(u8, cpu_name));
750813 return Stage2CpuFeatures.createFromCpu(std.heap.c_allocator, arch, cpu);
751 const ptr = try allocator.create(Stage2CpuFeatures);
752 errdefer std.heap.c_allocator.destroy(ptr);
753
754 ptr.* = try Stage2CpuFeatures.initCpu(std.heap.c_allocator, arch, cpu);
755 errdefer ptr.deinit();
756
757 return ptr;
758}814}
759815
760// ABI warning816// ABI warning
761export fn stage2_cpu_features_parse_features(817export fn stage2_cpu_features_parse_features(
818 result: **Stage2CpuFeatures,
762 arch_name: [*:0]const u8,819 arch_name: [*:0]const u8,
763 features_text: [*:0]const u8,820 features_text: [*:0]const u8,
764) *Stage2CpuFeatures {821) Error {
765 return parseFeatures(arch_name, features_text) catch |err| switch (err) {822 result.* = parseFeatures(arch_name, features_text) catch |err| switch (err) {
766 error.OutOfMemory => @panic("out of memory"),823 error.OutOfMemory => return .OutOfMemory,
767 };824 };
825 return .None;
768}826}
769827
770fn parseFeatures(arch_name: [*:0]const u8, features_text: [*:0]const u8) !*Stage2CpuFeatures {828fn parseFeatures(arch_name: [*:0]const u8, features_text: [*:0]const u8) !*Stage2CpuFeatures {
771 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));829 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
772 const set = try arch.parseCpuFeatureSet(mem.toSliceConst(u8, features_text));830 const set = try arch.parseCpuFeatureSet(mem.toSliceConst(u8, features_text));
773831 return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, set);
774 const ptr = try std.heap.c_allocator.create(Stage2CpuFeatures);
775 errdefer std.heap.c_allocator.destroy(ptr);
776
777 ptr.* = try Stage2CpuFeatures.initFeatures(std.heap.c_allocator, arch, set);
778 errdefer ptr.deinit();
779
780 return ptr;
781}832}
782833
783// ABI warning834// ABI warning
784export fn stage2_cpu_features_baseline() *Stage2CpuFeatures {835export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures) Error {
785 const ptr = try std.heap.c_allocator.create(Stage2CpuFeatures);836 result.* = Stage2CpuFeatures.createBaseline(std.heap.c_allocator) catch |err| switch (err) {
786 errdefer std.heap.c_allocator.destroy(ptr);837 error.OutOfMemory => return .OutOfMemory,
787838 };
788 ptr.* = try Stage2CpuFeatures.initBaseline(std.heap.c_allocator);839 return .None;
789 errdefer ptr.deinit();840}
790841
791 return ptr;842// ABI warning
843export fn stage2_cpu_features_llvm(
844 result: **Stage2CpuFeatures,
845 arch_name: [*:0]const u8,
846 llvm_cpu_name: [*:0]const u8,
847 llvm_cpu_features: [*:0]const u8,
848) Error {
849 result.* = Stage2CpuFeatures.createFromLLVM(
850 std.heap.c_allocator,
851 arch_name,
852 llvm_cpu_name,
853 llvm_cpu_features,
854 ) catch |err| switch (err) {
855 error.OutOfMemory => return .OutOfMemory,
856 };
857 return .None;
792}858}
793859
794// ABI warning860// ABI warning
src/main.cpp+20-12
...@@ -100,8 +100,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -100,8 +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"103 " -target-cpu [cpu] target one specific CPU by name\n"
104 " --features [feature_str] compile with features in [feature_str] on the current target\n"104 " -target-feature [features] specify the set of CPU features to target\n"
105 "\n"105 "\n"
106 "Link Options:\n"106 "Link Options:\n"
107 " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"107 " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
...@@ -1078,22 +1078,30 @@ int main(int argc, char **argv) {...@@ -1078,22 +1078,30 @@ int main(int argc, char **argv) {
1078 fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");1078 fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");
1079 return main_exit(root_progress_node, EXIT_FAILURE);1079 return main_exit(root_progress_node, EXIT_FAILURE);
1080 } else if (cpu) {1080 } else if (cpu) {
1081 target.cpu_features = stage2_cpu_features_parse_cpu(target_arch_name(target.arch), cpu);1081 if ((err = stage2_cpu_features_parse_cpu(&target.cpu_features, target_arch_name(target.arch), cpu))) {
1082 if (!target.cpu_features) {1082 fprintf(stderr, "-target-cpu error: %s\n", err_str(err));
1083 fprintf(stderr, "invalid -target-cpu value\n");
1084 return main_exit(root_progress_node, EXIT_FAILURE);1083 return main_exit(root_progress_node, EXIT_FAILURE);
1085 }1084 }
1086 } else if (features) {1085 } else if (features) {
1087 target.cpu_features = stage2_cpu_features_parse_features(target_arch_name(target.arch), features);1086 if ((err = stage2_cpu_features_parse_features(&target.cpu_features, target_arch_name(target.arch),
1088 if (!target.cpu_features) {1087 features)))
1089 fprintf(stderr, "invalid -target-feature value\n");1088 {
1089 fprintf(stderr, "-target-feature error: %s\n", err_str(err));
1090 return main_exit(root_progress_node, EXIT_FAILURE);
1091 }
1092 } else if (target.is_native) {
1093 const char *cpu_name = ZigLLVMGetHostCPUName();
1094 const char *cpu_features = ZigLLVMGetNativeFeatures();
1095 if ((err = stage2_cpu_features_llvm(&target.cpu_features, target_arch_name(target.arch),
1096 cpu_name, cpu_features)))
1097 {
1098 fprintf(stderr, "unable to determine native CPU features: %s\n", err_str(err));
1090 return main_exit(root_progress_node, EXIT_FAILURE);1099 return main_exit(root_progress_node, EXIT_FAILURE);
1091 }1100 }
1092 } else {1101 } else {
1093 // If no details are specified and we are not native, load1102 if ((err = stage2_cpu_features_baseline(&target.cpu_features))) {
1094 // cross-compilation default features.1103 fprintf(stderr, "unable to determine baseline CPU features: %s\n", err_str(err));
1095 if (!target.is_native) {1104 return main_exit(root_progress_node, EXIT_FAILURE);
1096 target.cpu_features = stage2_cpu_features_baseline();
1097 }1105 }
1098 }1106 }
10991107
src/userland.cpp+33-13
...@@ -98,35 +98,55 @@ void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len,...@@ -98,35 +98,55 @@ void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len,
98 const char *msg = "stage0 called stage2_list_cpus_for_arch";98 const char *msg = "stage0 called stage2_list_cpus_for_arch";
99 stage2_panic(msg, strlen(msg));99 stage2_panic(msg, strlen(msg));
100}100}
101Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *str) {101
102struct Stage2CpuFeatures {
103 const char *llvm_cpu_name;
104 const char *llvm_cpu_features;
105 const char *builtin_str;
106 const char *cache_hash;
107};
108
109Error stage2_cpu_features_parse_cpu(Stage2CpuFeatures **out, const char *arch, const char *str) {
102 const char *msg = "stage0 called stage2_cpu_features_parse_cpu";110 const char *msg = "stage0 called stage2_cpu_features_parse_cpu";
103 stage2_panic(msg, strlen(msg));111 stage2_panic(msg, strlen(msg));
104}112}
105Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *str) {113Error stage2_cpu_features_parse_features(Stage2CpuFeatures **out, const char *arch, const char *str) {
106 const char *msg = "stage0 called stage2_cpu_features_parse_features";114 const char *msg = "stage0 called stage2_cpu_features_parse_features";
107 stage2_panic(msg, strlen(msg));115 stage2_panic(msg, strlen(msg));
108}116}
109Stage2CpuFeatures *stage2_cpu_features_baseline(void) {117Error stage2_cpu_features_baseline(Stage2CpuFeatures **out) {
110 const char *msg = "stage0 called stage2_cpu_features_baseline";118 Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
111 stage2_panic(msg, strlen(msg));119 result->builtin_str = ".baseline;\n";
120 result->cache_hash = "\n\n";
121 *out = result;
122 return ErrorNone;
123}
124Error stage2_cpu_features_llvm(Stage2CpuFeatures **out, const char *arch,
125 const char *llvm_cpu_name, const char *llvm_features)
126{
127 Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
128 result->llvm_cpu_name = llvm_cpu_name;
129 result->llvm_cpu_features = llvm_features;
130 result->builtin_str = ".baseline;\n";
131 result->cache_hash = "native\n\n";
132 *out = result;
133 return ErrorNone;
112}134}
113void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,135void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
114 const char **ptr, size_t *len)136 const char **ptr, size_t *len)
115{137{
116 const char *msg = "stage0 called stage2_cpu_features_get_cache_hash";138 *ptr = cpu_features->cache_hash;
117 stage2_panic(msg, strlen(msg));139 *len = strlen(cpu_features->cache_hash);
118}140}
119const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {141const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
120 const char *msg = "stage0 called stage2_cpu_features_get_llvm_cpu";142 return cpu_features->llvm_cpu_name;
121 stage2_panic(msg, strlen(msg));
122}143}
123const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {144const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
124 const char *msg = "stage0 called stage2_cpu_features_get_llvm_features";145 return cpu_features->llvm_cpu_features;
125 stage2_panic(msg, strlen(msg));
126}146}
127void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, 147void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
128 const char **ptr, size_t *len)148 const char **ptr, size_t *len)
129{149{
130 const char *msg = "stage0 called stage2_cpu_features_get_builtin_str";150 *ptr = cpu_features->builtin_str;
131 stage2_panic(msg, strlen(msg));151 *len = strlen(cpu_features->builtin_str);
132}152}
src/userland.h+13-7
...@@ -184,26 +184,32 @@ ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t ar...@@ -184,26 +184,32 @@ ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t ar
184struct Stage2CpuFeatures;184struct Stage2CpuFeatures;
185185
186// ABI warning186// ABI warning
187ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *cpu_name);187ZIG_EXTERN_C Error stage2_cpu_features_parse_cpu(struct Stage2CpuFeatures **result,
188 const char *arch, const char *cpu_name);
188189
189// ABI warning190// ABI warning
190ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *features);191ZIG_EXTERN_C Error stage2_cpu_features_parse_features(struct Stage2CpuFeatures **result,
192 const char *arch, const char *features);
191193
192// ABI warning194// ABI warning
193ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_baseline(void);195ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result);
194196
195// ABI warning197// ABI warning
196ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features);198ZIG_EXTERN_C Error stage2_cpu_features_llvm(struct Stage2CpuFeatures **result,
199 const char *arch, const char *llvm_cpu_name, const char *llvm_features);
197200
198// ABI warning201// ABI warning
199ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features);202ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
200203
201// ABI warning204// ABI warning
202ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,205ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
206
207// ABI warning
208ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
203 const char **ptr, size_t *len);209 const char **ptr, size_t *len);
204210
205// ABI warning211// ABI warning
206ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,212ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
207 const char **ptr, size_t *len);213 const char **ptr, size_t *len);
208214
209#endif215#endif