diff --git a/lib/std/target.zig b/lib/std/target.zig index 716be8905c..2566a9be37 100644 --- a/lib/std/target.zig +++ b/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, }; diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig index 233b6c106d..f2bab35685 100644 --- a/src-self-hosted/print_targets.zig +++ b/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(); diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index f533d9b34e..eed5804c0d 100644 --- a/src-self-hosted/stage1.zig +++ b/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); - } + 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), } - - 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; - } - } - } - 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, diff --git a/src/main.cpp b/src/main.cpp index 878c15e17c..813eada261 100644 --- a/src/main.cpp +++ b/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); } diff --git a/src/userland.cpp b/src/userland.cpp index 4a658d76c5..9a923e1b86 100644 --- a/src/userland.cpp +++ b/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)); } diff --git a/src/userland.h b/src/userland.h index e84b62aecb..1a07b605e5 100644 --- a/src/userland.h +++ b/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