Commit 39759b90fc

Andrew Kelley <andrew@ziglang.org>
2020-01-21 07:22:37
make zig targets show native cpu name and features
1 parent e640d01
Changed files (6)
lib/std/target.zig
@@ -631,9 +631,9 @@ pub const Target = union(enum) {
         };
     }
 
-    pub fn cpuFeaturesList(self: Target) []const *const Cpu.Feature {
+    pub fn cpuFeatureSet(self: Target) Cpu.Feature.Set {
         return switch (self.getCpuFeatures()) {
-            .baseline => self.arch.baselineFeatures(),
+            .baseline => self.getArch().baselineFeatures(),
             .cpu => |cpu| cpu.features,
             .features => |features| features,
         };
src/main.cpp
@@ -1372,7 +1372,7 @@ int main(int argc, char **argv) {
         return main_exit(root_progress_node, EXIT_SUCCESS);
     }
     case CmdTargets:
-        return stage2_cmd_targets();
+        return stage2_cmd_targets(buf_ptr(&zig_triple_buf));
     case CmdNone:
         return print_full_usage(arg0, stderr, EXIT_FAILURE);
     }
src/userland.cpp
@@ -141,7 +141,7 @@ void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
     *len = strlen(cpu_features->builtin_str);
 }
 
-int stage2_cmd_targets(void) {
+int stage2_cmd_targets(const char *zig_triple) {
     const char *msg = "stage0 called stage2_cmd_targets";
     stage2_panic(msg, strlen(msg));
 }
src/userland.h
@@ -213,7 +213,7 @@ ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatu
         const char **ptr, size_t *len);
 
 // ABI warning
-ZIG_EXTERN_C int stage2_cmd_targets(void);
+ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
 
 
 #endif
src-self-hosted/print_targets.zig
@@ -9,6 +9,7 @@ pub fn cmdTargets(
     allocator: *Allocator,
     args: []const []const u8,
     stdout: *io.OutStream(fs.File.WriteError),
+    native_target: Target,
 ) !void {
     const BOS = io.BufferedOutStream(fs.File.WriteError);
     var bos = BOS.init(stdout);
@@ -76,22 +77,34 @@ pub fn cmdTargets(
     try jws.objectField("native");
     try jws.beginObject();
     {
-        const triple = try Target.current.zigTriple(allocator);
+        const triple = try native_target.zigTriple(allocator);
         defer allocator.free(triple);
         try jws.objectField("triple");
         try jws.emitString(triple);
     }
     try jws.objectField("arch");
-    try jws.emitString(@tagName(Target.current.getArch()));
+    try jws.emitString(@tagName(native_target.getArch()));
     try jws.objectField("os");
-    try jws.emitString(@tagName(Target.current.getOs()));
+    try jws.emitString(@tagName(native_target.getOs()));
     try jws.objectField("abi");
-    try jws.emitString(@tagName(Target.current.getAbi()));
+    try jws.emitString(@tagName(native_target.getAbi()));
     try jws.objectField("cpuName");
-    switch (Target.current.getCpuFeatures()) {
+    switch (native_target.getCpuFeatures()) {
         .baseline, .features => try jws.emitNull(),
         .cpu => |cpu| try jws.emitString(cpu.name),
     }
+    {
+        try jws.objectField("cpuFeatures");
+        try jws.beginArray();
+        const feature_set = native_target.cpuFeatureSet();
+        for (native_target.getArch().allFeaturesList()) |feature, i| {
+            if (feature_set.isEnabled(@intCast(u8, i))) {
+                try jws.arrayElem();
+                try jws.emitString(feature.name);
+            }
+        }
+        try jws.endArray();
+    }
     try jws.endObject();
 
     try jws.endObject();
src-self-hosted/stage1.zig
@@ -539,19 +539,82 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
     node.context.maybeRefresh();
 }
 
+fn cpuFeaturesFromLLVM(
+    arch: Target.Arch,
+    llvm_cpu_name_z: ?[*:0]const u8,
+    llvm_cpu_features_opt: ?[*:0]const u8,
+) !Target.CpuFeatures {
+    if (llvm_cpu_name_z) |cpu_name_z| {
+        const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
+
+        for (arch.allCpus()) |cpu| {
+            const this_llvm_name = cpu.llvm_name orelse continue;
+            if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
+                return Target.CpuFeatures{ .cpu = cpu };
+            }
+        }
+    }
+
+    var set = arch.baselineFeatures();
+    const llvm_cpu_features = llvm_cpu_features_opt orelse return Target.CpuFeatures{
+        .features = set,
+    };
+
+    var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
+    while (it.next()) |decorated_llvm_feat| {
+        var op: enum {
+            add,
+            sub,
+        } = undefined;
+        var llvm_feat: []const u8 = undefined;
+        if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
+            op = .add;
+            llvm_feat = decorated_llvm_feat[1..];
+        } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
+            op = .sub;
+            llvm_feat = decorated_llvm_feat[1..];
+        } else {
+            return error.InvalidLlvmCpuFeaturesFormat;
+        }
+        for (arch.allFeaturesList()) |feature, index| {
+            const this_llvm_name = feature.llvm_name orelse continue;
+            if (mem.eql(u8, llvm_feat, this_llvm_name)) {
+                switch (op) {
+                    .add => set.addFeature(@intCast(u8, index)),
+                    .sub => set.removeFeature(@intCast(u8, index)),
+                }
+                break;
+            }
+        }
+    }
+    return Target.CpuFeatures{ .features = set };
+}
+
 // ABI warning
-export fn stage2_cmd_targets() c_int {
-    @import("print_targets.zig").cmdTargets(
-        std.heap.c_allocator,
-        &[0][]u8{},
-        &std.io.getStdOut().outStream().stream,
-    ) catch |err| {
+export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
+    cmdTargets(zig_triple) catch |err| {
         std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
         return -1;
     };
     return 0;
 }
 
+fn cmdTargets(zig_triple: [*:0]const u8) !void {
+    var target = try Target.parse(mem.toSliceConst(u8, zig_triple));
+    target.Cross.cpu_features = blk: {
+        const llvm = @import("llvm.zig");
+        const llvm_cpu_name = llvm.GetHostCPUName();
+        const llvm_cpu_features = llvm.GetNativeFeatures();
+        break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features);
+    };
+    return @import("print_targets.zig").cmdTargets(
+        std.heap.c_allocator,
+        &[0][]u8{},
+        &std.io.getStdOut().outStream().stream,
+        target,
+    );
+}
+
 const Stage2CpuFeatures = struct {
     allocator: *mem.Allocator,
     cpu_features: Target.CpuFeatures,
@@ -588,49 +651,17 @@ const Stage2CpuFeatures = struct {
     fn createFromLLVM(
         allocator: *mem.Allocator,
         zig_triple: [*:0]const u8,
-        llvm_cpu_name_z: [*:0]const u8,
-        llvm_cpu_features: [*:0]const u8,
+        llvm_cpu_name_z: ?[*:0]const u8,
+        llvm_cpu_features: ?[*:0]const u8,
     ) !*Self {
         const target = try Target.parse(mem.toSliceConst(u8, zig_triple));
         const arch = target.Cross.arch;
-        const llvm_cpu_name = mem.toSliceConst(u8, llvm_cpu_name_z);
-
-        for (arch.allCpus()) |cpu| {
-            const this_llvm_name = cpu.llvm_name orelse continue;
-            if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
-                return createFromCpu(allocator, arch, cpu);
-            }
-        }
-
-        var set = arch.baselineFeatures();
-        var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
-        while (it.next()) |decorated_llvm_feat| {
-            var op: enum {
-                add,
-                sub,
-            } = undefined;
-            var llvm_feat: []const u8 = undefined;
-            if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
-                op = .add;
-                llvm_feat = decorated_llvm_feat[1..];
-            } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
-                op = .sub;
-                llvm_feat = decorated_llvm_feat[1..];
-            } else {
-                return error.InvalidLlvmCpuFeaturesFormat;
-            }
-            for (arch.allFeaturesList()) |feature, index| {
-                const this_llvm_name = feature.llvm_name orelse continue;
-                if (mem.eql(u8, llvm_feat, this_llvm_name)) {
-                    switch (op) {
-                        .add => set.addFeature(@intCast(u8, index)),
-                        .sub => set.removeFeature(@intCast(u8, index)),
-                    }
-                    break;
-                }
-            }
+        const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name_z, llvm_cpu_features);
+        switch (cpu_features) {
+            .baseline => return createBaseline(allocator),
+            .cpu => |cpu| return createFromCpu(allocator, arch, cpu),
+            .features => |features| return createFromCpuFeatures(allocator, arch, features),
         }
-        return createFromCpuFeatures(allocator, arch, set);
     }
 
     fn createFromCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !*Self {
@@ -823,8 +854,8 @@ export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures) Error {
 export fn stage2_cpu_features_llvm(
     result: **Stage2CpuFeatures,
     zig_triple: [*:0]const u8,
-    llvm_cpu_name: [*:0]const u8,
-    llvm_cpu_features: [*:0]const u8,
+    llvm_cpu_name: ?[*:0]const u8,
+    llvm_cpu_features: ?[*:0]const u8,
 ) Error {
     result.* = Stage2CpuFeatures.createFromLLVM(
         std.heap.c_allocator,