make zig targets show native cpu name and features

This commit is contained in:
Andrew Kelley 2020-01-21 01:22:37 -05:00
parent e640d01535
commit 39759b90fc
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
6 changed files with 101 additions and 57 deletions

View File

@ -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,
};

View File

@ -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();

View File

@ -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,

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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