Commit f3dd9bbdac

Andrew Kelley <andrew@ziglang.org>
2020-01-20 19:40:25
improve `zig targets`
1 parent bf82929
lib/std/builtin.zig
@@ -18,8 +18,8 @@ pub const ObjectFormat = std.Target.ObjectFormat;
 /// Deprecated: use `std.Target.SubSystem`.
 pub const SubSystem = std.Target.SubSystem;
 
-/// Deprecated: use `std.Target.Cross.CpuFeatures`.
-pub const CpuFeatures = std.Target.Cross.CpuFeatures;
+/// Deprecated: use `std.Target.CpuFeatures`.
+pub const CpuFeatures = std.Target.CpuFeatures;
 
 /// Deprecated: use `std.Target.Cpu`.
 pub const Cpu = std.Target.Cpu;
lib/std/target.zig
@@ -569,18 +569,18 @@ pub const Target = union(enum) {
         os: Os,
         abi: Abi,
         cpu_features: CpuFeatures = .baseline,
+    };
 
-        pub const CpuFeatures = union(enum) {
-            /// The "default" set of CPU features for cross-compiling. A conservative set
-            /// of features that is expected to be supported on most available hardware.
-            baseline,
+    pub const CpuFeatures = union(enum) {
+        /// The "default" set of CPU features for cross-compiling. A conservative set
+        /// of features that is expected to be supported on most available hardware.
+        baseline,
 
-            /// Target one specific CPU.
-            cpu: *const Cpu,
+        /// Target one specific CPU.
+        cpu: *const Cpu,
 
-            /// Explicitly provide the entire CPU feature set.
-            features: Cpu.Feature.Set,
-        };
+        /// Explicitly provide the entire CPU feature set.
+        features: Cpu.Feature.Set,
     };
 
     pub const current = Target{
@@ -594,8 +594,15 @@ pub const Target = union(enum) {
 
     pub const stack_align = 16;
 
-    pub fn cpuFeatures(self: Target) []const *const Cpu.Feature {
-        return switch (self.cpu_features) {
+    pub fn getCpuFeatures(self: Target) CpuFeatures {
+        return switch (self) {
+            .Native => builtin.cpu_features,
+            .Cross => |cross| cross.cpu_features,
+        };
+    }
+
+    pub fn cpuFeaturesList(self: Target) []const *const Cpu.Feature {
+        return switch (self.getCpuFeatures()) {
             .baseline => self.arch.baselineFeatures(),
             .cpu => |cpu| cpu.features,
             .features => |features| features,
src/ir.cpp
@@ -22349,7 +22349,11 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
             return ira->codegen->invalid_instruction;
     }
 
-    assert(target->value->type->id == ZigTypeIdEnum);
+    if (target->value->type->id != ZigTypeIdEnum) {
+        ir_add_error(ira, target,
+            buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target->value->type->name)));
+        return ira->codegen->invalid_instruction;
+    }
 
     if (target->value->type->data.enumeration.src_field_count == 1 &&
         !target->value->type->data.enumeration.non_exhaustive) {
src-self-hosted/main.zig
@@ -79,7 +79,7 @@ pub fn main() !void {
     } else if (mem.eql(u8, cmd, "libc")) {
         return cmdLibC(allocator, cmd_args);
     } else if (mem.eql(u8, cmd, "targets")) {
-        return cmdTargets(allocator, cmd_args);
+        return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout);
     } else if (mem.eql(u8, cmd, "version")) {
         return cmdVersion(allocator, cmd_args);
     } else if (mem.eql(u8, cmd, "zen")) {
@@ -789,48 +789,6 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
     }
 }
 
-// cmd:targets /////////////////////////////////////////////////////////////////////////////////////
-
-pub fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
-    try stdout.write("Architectures:\n");
-    {
-        comptime var i: usize = 0;
-        inline while (i < @memberCount(builtin.Arch)) : (i += 1) {
-            comptime const arch_tag = @memberName(builtin.Arch, i);
-            // NOTE: Cannot use empty string, see #918.
-            comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
-
-            try stdout.print("  {}{}", .{ arch_tag, native_str });
-        }
-    }
-    try stdout.write("\n");
-
-    try stdout.write("Operating Systems:\n");
-    {
-        comptime var i: usize = 0;
-        inline while (i < @memberCount(Target.Os)) : (i += 1) {
-            comptime const os_tag = @memberName(Target.Os, i);
-            // NOTE: Cannot use empty string, see #918.
-            comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
-
-            try stdout.print("  {}{}", .{ os_tag, native_str });
-        }
-    }
-    try stdout.write("\n");
-
-    try stdout.write("C ABIs:\n");
-    {
-        comptime var i: usize = 0;
-        inline while (i < @memberCount(Target.Abi)) : (i += 1) {
-            comptime const abi_tag = @memberName(Target.Abi, i);
-            // NOTE: Cannot use empty string, see #918.
-            comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";
-
-            try stdout.print("  {}{}", .{ abi_tag, native_str });
-        }
-    }
-}
-
 fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
     try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
 }
src-self-hosted/print_targets.zig
@@ -0,0 +1,101 @@
+const std = @import("std");
+const fs = std.fs;
+const io = std.io;
+const mem = std.mem;
+const Allocator = mem.Allocator;
+const Target = std.Target;
+
+pub fn cmdTargets(
+    allocator: *Allocator,
+    args: []const []const u8,
+    stdout: *io.OutStream(fs.File.WriteError),
+) !void {
+    const BOS = io.BufferedOutStream(fs.File.WriteError);
+    var bos = BOS.init(stdout);
+    var jws = std.json.WriteStream(BOS.Stream, 6).init(&bos.stream);
+
+    try jws.beginObject();
+
+    try jws.objectField("arch");
+    try jws.beginObject();
+    {
+        inline for (@typeInfo(Target.Arch).Union.fields) |field| {
+            try jws.objectField(field.name);
+            if (field.field_type == void) {
+                try jws.emitNull();
+            } else {
+                try jws.emitString(@typeName(field.field_type));
+            }
+        }
+    }
+    try jws.endObject();
+
+    try jws.objectField("subArch");
+    try jws.beginObject();
+    const sub_arch_list = [_]type{
+        Target.Arch.Arm32,
+        Target.Arch.Arm64,
+        Target.Arch.Kalimba,
+        Target.Arch.Mips,
+    };
+    inline for (sub_arch_list) |SubArch| {
+        try jws.objectField(@typeName(SubArch));
+        try jws.beginArray();
+        inline for (@typeInfo(SubArch).Enum.fields) |field| {
+            try jws.arrayElem();
+            try jws.emitString(field.name);
+        }
+        try jws.endArray();
+    }
+    try jws.endObject();
+
+    try jws.objectField("os");
+    try jws.beginArray();
+    {
+        comptime var i: usize = 0;
+        inline while (i < @memberCount(Target.Os)) : (i += 1) {
+            const os_tag = @memberName(Target.Os, i);
+            try jws.arrayElem();
+            try jws.emitString(os_tag);
+        }
+    }
+    try jws.endArray();
+
+    try jws.objectField("abi");
+    try jws.beginArray();
+    {
+        comptime var i: usize = 0;
+        inline while (i < @memberCount(Target.Abi)) : (i += 1) {
+            const abi_tag = @memberName(Target.Abi, i);
+            try jws.arrayElem();
+            try jws.emitString(abi_tag);
+        }
+    }
+    try jws.endArray();
+
+    try jws.objectField("native");
+    try jws.beginObject();
+    {
+        const triple = try Target.current.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.objectField("os");
+    try jws.emitString(@tagName(Target.current.getOs()));
+    try jws.objectField("abi");
+    try jws.emitString(@tagName(Target.current.getAbi()));
+    try jws.objectField("cpuName");
+    switch (Target.current.getCpuFeatures()) {
+        .baseline, .features => try jws.emitNull(),
+        .cpu => |cpu| try jws.emitString(cpu.name),
+    }
+    try jws.endObject();
+
+    try jws.endObject();
+
+    try bos.stream.writeByte('\n');
+    return bos.flush();
+}
src-self-hosted/stage1.zig
@@ -539,7 +539,11 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
 
 // ABI warning
 export fn stage2_cmd_targets() c_int {
-    self_hosted_main.cmdTargets(std.heap.c_allocator, &[0][]u8{}) catch |err| {
+    @import("print_targets.zig").cmdTargets(
+        std.heap.c_allocator,
+        &[0][]u8{},
+        &std.io.getStdOut().outStream().stream,
+    ) catch |err| {
         std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
         return -1;
     };
@@ -548,7 +552,7 @@ export fn stage2_cmd_targets() c_int {
 
 const Stage2CpuFeatures = struct {
     allocator: *mem.Allocator,
-    cpu_features: Target.Cross.CpuFeatures,
+    cpu_features: Target.CpuFeatures,
 
     llvm_cpu_name: ?[*:0]const u8,
     llvm_features_str: ?[*:0]const u8,
BRANCH_TODO
@@ -1,12 +1,8 @@
 Finish these thigns before merging teh branch
 
- * it gets the wrong answers with `-target-feature -sse,-avx`
-
+ * zig targets
+   - use non-reflection based cpu detection?
  * finish refactoring target/arch/*
- * `zig builtin` integration 
- * move target details to better location
- * +foo,-bar vs foo,bar
- * baseline features
 
 
 const riscv32_default_features: []*const std.target.Feature = &[_]*const std.target.Feature{
@@ -38,5 +34,3 @@ const i386_default_features_freestanding: []*const std.target.Feature = &[_]*con
     &std.target.x86.feature_slowUnalignedMem16,
     &std.target.x86.feature_x87,
 };
-
-