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
signature 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 {
632632
633633 const Self = @This();
634634
635 fn initBaseline(allocator: *mem.Allocator) !Self {
636 const builtin_str = try std.fmt.allocPrint0(allocator, "CpuFeatures.baseline;\n");
635 fn createBaseline(allocator: *mem.Allocator) !*Self {
636 const self = try allocator.create(Self);
637 errdefer allocator.destroy(self);
638
639 const builtin_str = try std.fmt.allocPrint0(allocator, ".baseline;\n");
637640 errdefer allocator.free(builtin_str);
638641
639642 const cache_hash = try std.fmt.allocPrint0(allocator, "\n\n");
640643 errdefer allocator.free(cache_hash);
641644
642 return Self{
645 self.* = Self{
643646 .allocator = allocator,
644 .cpu_features = .{ .cpu = cpu },
647 .cpu_features = .baseline,
645648 .llvm_cpu_name = null,
646649 .llvm_features_str = null,
647650 .builtin_str = builtin_str,
648651 .cache_hash = cache_hash,
649652 };
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);
650700 }
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
653706 const builtin_str = try std.fmt.allocPrint0(
654707 allocator,
655708 "CpuFeatures{{ .cpu = &Arch.{}.cpu.{} }};\n",
......@@ -661,7 +714,7 @@ const Stage2CpuFeatures = struct {
661714 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{x}", cpu.name, cpu.features);
662715 errdefer allocator.free(cache_hash);
663716
664 return Self{
717 self.* = Self{
665718 .allocator = allocator,
666719 .cpu_features = .{ .cpu = cpu },
667720 .llvm_cpu_name = cpu.llvm_name,
......@@ -669,13 +722,17 @@ const Stage2CpuFeatures = struct {
669722 .builtin_str = builtin_str,
670723 .cache_hash = cache_hash,
671724 };
725 return self;
672726 }
673727
674 fn initFeatures(
728 fn createFromCpuFeatures(
675729 allocator: *mem.Allocator,
676730 arch: Target.Arch,
677731 features: Target.Cpu.Feature.Set,
678 ) !Self {
732 ) !*Self {
733 const self = try allocator.create(Self);
734 errdefer allocator.destroy(self);
735
679736 const cache_hash = try std.fmt.allocPrint0(allocator, "\n{x}", features);
680737 errdefer allocator.free(cache_hash);
681738
......@@ -719,7 +776,7 @@ const Stage2CpuFeatures = struct {
719776
720777 try builtin_str_buffer.append("})};\n");
721778
722 return Self{
779 self.* = Self{
723780 .allocator = allocator,
724781 .cpu_features = .{ .features = features },
725782 .llvm_cpu_name = null,
......@@ -727,68 +784,77 @@ const Stage2CpuFeatures = struct {
727784 .builtin_str = builtin_str_buffer.toOwnedSlice(),
728785 .cache_hash = cache_hash,
729786 };
787 return self;
730788 }
731789
732 fn deinit(self: *Self) void {
790 fn destroy(self: *Self) void {
733791 self.allocator.free(self.cache_hash);
734792 self.allocator.free(self.builtin_str);
735793 if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
736 self.* = undefined;
794 self.allocator.destroy(self);
737795 }
738796};
739797
740798// ABI warning
741export fn stage2_cpu_features_parse_cpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) *Stage2CpuFeatures {
742 return parseCpu(arch_name, cpu_name) catch |err| switch (err) {
743 error.OutOfMemory => @panic("out of memory"),
799export fn stage2_cpu_features_parse_cpu(
800 result: **Stage2CpuFeatures,
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,
744806 };
807 return .None;
745808}
746809
747810fn parseCpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) !*Stage2CpuFeatures {
748811 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
749812 const cpu = try arch.parseCpu(mem.toSliceConst(u8, cpu_name));
750
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;
813 return Stage2CpuFeatures.createFromCpu(std.heap.c_allocator, arch, cpu);
758814}
759815
760816// ABI warning
761817export fn stage2_cpu_features_parse_features(
818 result: **Stage2CpuFeatures,
762819 arch_name: [*:0]const u8,
763820 features_text: [*:0]const u8,
764) *Stage2CpuFeatures {
765 return parseFeatures(arch_name, features_text) catch |err| switch (err) {
766 error.OutOfMemory => @panic("out of memory"),
821) Error {
822 result.* = parseFeatures(arch_name, features_text) catch |err| switch (err) {
823 error.OutOfMemory => return .OutOfMemory,
767824 };
825 return .None;
768826}
769827
770828fn parseFeatures(arch_name: [*:0]const u8, features_text: [*:0]const u8) !*Stage2CpuFeatures {
771829 const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
772830 const set = try arch.parseCpuFeatureSet(mem.toSliceConst(u8, features_text));
773
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;
831 return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, set);
781832}
782833
783834// ABI warning
784export fn stage2_cpu_features_baseline() *Stage2CpuFeatures {
785 const ptr = try std.heap.c_allocator.create(Stage2CpuFeatures);
786 errdefer std.heap.c_allocator.destroy(ptr);
787
788 ptr.* = try Stage2CpuFeatures.initBaseline(std.heap.c_allocator);
789 errdefer ptr.deinit();
835export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures) Error {
836 result.* = Stage2CpuFeatures.createBaseline(std.heap.c_allocator) catch |err| switch (err) {
837 error.OutOfMemory => return .OutOfMemory,
838 };
839 return .None;
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;
792858}
793859
794860// ABI warning
src/main.cpp+20-12
......@@ -100,8 +100,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
100100 " --override-lib-dir [arg] override path to Zig lib directory\n"
101101 " -ffunction-sections places each function in a separate section\n"
102102 " -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 " -target-cpu [cpu] target one specific CPU by name\n"
104 " -target-feature [features] specify the set of CPU features to target\n"
105105 "\n"
106106 "Link Options:\n"
107107 " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
......@@ -1078,22 +1078,30 @@ int main(int argc, char **argv) {
10781078 fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");
10791079 return main_exit(root_progress_node, EXIT_FAILURE);
10801080 } else if (cpu) {
1081 target.cpu_features = stage2_cpu_features_parse_cpu(target_arch_name(target.arch), cpu);
1082 if (!target.cpu_features) {
1083 fprintf(stderr, "invalid -target-cpu value\n");
1081 if ((err = stage2_cpu_features_parse_cpu(&target.cpu_features, target_arch_name(target.arch), cpu))) {
1082 fprintf(stderr, "-target-cpu error: %s\n", err_str(err));
10841083 return main_exit(root_progress_node, EXIT_FAILURE);
10851084 }
10861085 } else if (features) {
1087 target.cpu_features = stage2_cpu_features_parse_features(target_arch_name(target.arch), features);
1088 if (!target.cpu_features) {
1089 fprintf(stderr, "invalid -target-feature value\n");
1086 if ((err = stage2_cpu_features_parse_features(&target.cpu_features, target_arch_name(target.arch),
1087 features)))
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));
10901099 return main_exit(root_progress_node, EXIT_FAILURE);
10911100 }
10921101 } else {
1093 // If no details are specified and we are not native, load
1094 // cross-compilation default features.
1095 if (!target.is_native) {
1096 target.cpu_features = stage2_cpu_features_baseline();
1102 if ((err = stage2_cpu_features_baseline(&target.cpu_features))) {
1103 fprintf(stderr, "unable to determine baseline CPU features: %s\n", err_str(err));
1104 return main_exit(root_progress_node, EXIT_FAILURE);
10971105 }
10981106 }
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,
9898 const char *msg = "stage0 called stage2_list_cpus_for_arch";
9999 stage2_panic(msg, strlen(msg));
100100}
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) {
102110 const char *msg = "stage0 called stage2_cpu_features_parse_cpu";
103111 stage2_panic(msg, strlen(msg));
104112}
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) {
106114 const char *msg = "stage0 called stage2_cpu_features_parse_features";
107115 stage2_panic(msg, strlen(msg));
108116}
109Stage2CpuFeatures *stage2_cpu_features_baseline(void) {
110 const char *msg = "stage0 called stage2_cpu_features_baseline";
111 stage2_panic(msg, strlen(msg));
117Error stage2_cpu_features_baseline(Stage2CpuFeatures **out) {
118 Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
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;
112134}
113135void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
114136 const char **ptr, size_t *len)
115137{
116 const char *msg = "stage0 called stage2_cpu_features_get_cache_hash";
117 stage2_panic(msg, strlen(msg));
138 *ptr = cpu_features->cache_hash;
139 *len = strlen(cpu_features->cache_hash);
118140}
119141const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
120 const char *msg = "stage0 called stage2_cpu_features_get_llvm_cpu";
121 stage2_panic(msg, strlen(msg));
142 return cpu_features->llvm_cpu_name;
122143}
123144const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
124 const char *msg = "stage0 called stage2_cpu_features_get_llvm_features";
125 stage2_panic(msg, strlen(msg));
145 return cpu_features->llvm_cpu_features;
126146}
127147void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
128148 const char **ptr, size_t *len)
129149{
130 const char *msg = "stage0 called stage2_cpu_features_get_builtin_str";
131 stage2_panic(msg, strlen(msg));
150 *ptr = cpu_features->builtin_str;
151 *len = strlen(cpu_features->builtin_str);
132152}
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
184184struct Stage2CpuFeatures;
185185
186186// 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
189190// 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
192194// ABI warning
193ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_baseline(void);
195ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result);
194196
195197// 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
198201// 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
201204// 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,
203209 const char **ptr, size_t *len);
204210
205211// 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,
207213 const char **ptr, size_t *len);
208214
209215#endif