figure out zig0/stage1 and scanning for native CPU
parent
a867b43366
commit
a313f15384
|
@ -632,24 +632,77 @@ const Stage2CpuFeatures = struct {
|
|||
|
||||
const Self = @This();
|
||||
|
||||
fn initBaseline(allocator: *mem.Allocator) !Self {
|
||||
const builtin_str = try std.fmt.allocPrint0(allocator, "CpuFeatures.baseline;\n");
|
||||
fn createBaseline(allocator: *mem.Allocator) !*Self {
|
||||
const self = try allocator.create(Self);
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
const builtin_str = try std.fmt.allocPrint0(allocator, ".baseline;\n");
|
||||
errdefer allocator.free(builtin_str);
|
||||
|
||||
const cache_hash = try std.fmt.allocPrint0(allocator, "\n\n");
|
||||
errdefer allocator.free(cache_hash);
|
||||
|
||||
return Self{
|
||||
self.* = Self{
|
||||
.allocator = allocator,
|
||||
.cpu_features = .{ .cpu = cpu },
|
||||
.cpu_features = .baseline,
|
||||
.llvm_cpu_name = null,
|
||||
.llvm_features_str = null,
|
||||
.builtin_str = builtin_str,
|
||||
.cache_hash = cache_hash,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
fn initCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !Self {
|
||||
fn createFromLLVM(
|
||||
allocator: *mem.Allocator,
|
||||
arch: [*:0]const u8,
|
||||
llvm_cpu_name_z: [*:0]const u8,
|
||||
llvm_cpu_features: [*:0]const u8,
|
||||
) !*Self {
|
||||
const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
|
||||
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| {
|
||||
if (mem.eql(u8, feature_name, feature.name)) {
|
||||
switch (op) {
|
||||
.add => set |= 1 << index,
|
||||
.sub => set &= ~@as(Target.Cpu.Feature.Set, 1 << index),
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return createFromCpuFeatures(allocator, arch, set);
|
||||
}
|
||||
|
||||
fn createFromCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !*Self {
|
||||
const self = try allocator.create(Self);
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
const builtin_str = try std.fmt.allocPrint0(
|
||||
allocator,
|
||||
"CpuFeatures{{ .cpu = &Arch.{}.cpu.{} }};\n",
|
||||
|
@ -661,7 +714,7 @@ const Stage2CpuFeatures = struct {
|
|||
const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{x}", cpu.name, cpu.features);
|
||||
errdefer allocator.free(cache_hash);
|
||||
|
||||
return Self{
|
||||
self.* = Self{
|
||||
.allocator = allocator,
|
||||
.cpu_features = .{ .cpu = cpu },
|
||||
.llvm_cpu_name = cpu.llvm_name,
|
||||
|
@ -669,13 +722,17 @@ const Stage2CpuFeatures = struct {
|
|||
.builtin_str = builtin_str,
|
||||
.cache_hash = cache_hash,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
fn initFeatures(
|
||||
fn createFromCpuFeatures(
|
||||
allocator: *mem.Allocator,
|
||||
arch: Target.Arch,
|
||||
features: Target.Cpu.Feature.Set,
|
||||
) !Self {
|
||||
) !*Self {
|
||||
const self = try allocator.create(Self);
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
const cache_hash = try std.fmt.allocPrint0(allocator, "\n{x}", features);
|
||||
errdefer allocator.free(cache_hash);
|
||||
|
||||
|
@ -719,7 +776,7 @@ const Stage2CpuFeatures = struct {
|
|||
|
||||
try builtin_str_buffer.append("})};\n");
|
||||
|
||||
return Self{
|
||||
self.* = Self{
|
||||
.allocator = allocator,
|
||||
.cpu_features = .{ .features = features },
|
||||
.llvm_cpu_name = null,
|
||||
|
@ -727,68 +784,77 @@ const Stage2CpuFeatures = struct {
|
|||
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||
.cache_hash = cache_hash,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
fn deinit(self: *Self) void {
|
||||
fn destroy(self: *Self) void {
|
||||
self.allocator.free(self.cache_hash);
|
||||
self.allocator.free(self.builtin_str);
|
||||
if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
|
||||
self.* = undefined;
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
};
|
||||
|
||||
// ABI warning
|
||||
export fn stage2_cpu_features_parse_cpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) *Stage2CpuFeatures {
|
||||
return parseCpu(arch_name, cpu_name) catch |err| switch (err) {
|
||||
error.OutOfMemory => @panic("out of memory"),
|
||||
export fn stage2_cpu_features_parse_cpu(
|
||||
result: **Stage2CpuFeatures,
|
||||
arch_name: [*:0]const u8,
|
||||
cpu_name: [*:0]const u8,
|
||||
) Error {
|
||||
result.* = parseCpu(arch_name, cpu_name) catch |err| switch (err) {
|
||||
error.OutOfMemory => return .OutOfMemory,
|
||||
};
|
||||
return .None;
|
||||
}
|
||||
|
||||
fn parseCpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) !*Stage2CpuFeatures {
|
||||
const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
|
||||
const cpu = try arch.parseCpu(mem.toSliceConst(u8, cpu_name));
|
||||
|
||||
const ptr = try allocator.create(Stage2CpuFeatures);
|
||||
errdefer std.heap.c_allocator.destroy(ptr);
|
||||
|
||||
ptr.* = try Stage2CpuFeatures.initCpu(std.heap.c_allocator, arch, cpu);
|
||||
errdefer ptr.deinit();
|
||||
|
||||
return ptr;
|
||||
return Stage2CpuFeatures.createFromCpu(std.heap.c_allocator, arch, cpu);
|
||||
}
|
||||
|
||||
// ABI warning
|
||||
export fn stage2_cpu_features_parse_features(
|
||||
result: **Stage2CpuFeatures,
|
||||
arch_name: [*:0]const u8,
|
||||
features_text: [*:0]const u8,
|
||||
) *Stage2CpuFeatures {
|
||||
return parseFeatures(arch_name, features_text) catch |err| switch (err) {
|
||||
error.OutOfMemory => @panic("out of memory"),
|
||||
) Error {
|
||||
result.* = parseFeatures(arch_name, features_text) catch |err| switch (err) {
|
||||
error.OutOfMemory => return .OutOfMemory,
|
||||
};
|
||||
return .None;
|
||||
}
|
||||
|
||||
fn parseFeatures(arch_name: [*:0]const u8, features_text: [*:0]const u8) !*Stage2CpuFeatures {
|
||||
const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
|
||||
const set = try arch.parseCpuFeatureSet(mem.toSliceConst(u8, features_text));
|
||||
|
||||
const ptr = try std.heap.c_allocator.create(Stage2CpuFeatures);
|
||||
errdefer std.heap.c_allocator.destroy(ptr);
|
||||
|
||||
ptr.* = try Stage2CpuFeatures.initFeatures(std.heap.c_allocator, arch, set);
|
||||
errdefer ptr.deinit();
|
||||
|
||||
return ptr;
|
||||
return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, set);
|
||||
}
|
||||
|
||||
// ABI warning
|
||||
export fn stage2_cpu_features_baseline() *Stage2CpuFeatures {
|
||||
const ptr = try std.heap.c_allocator.create(Stage2CpuFeatures);
|
||||
errdefer std.heap.c_allocator.destroy(ptr);
|
||||
export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures) Error {
|
||||
result.* = Stage2CpuFeatures.createBaseline(std.heap.c_allocator) catch |err| switch (err) {
|
||||
error.OutOfMemory => return .OutOfMemory,
|
||||
};
|
||||
return .None;
|
||||
}
|
||||
|
||||
ptr.* = try Stage2CpuFeatures.initBaseline(std.heap.c_allocator);
|
||||
errdefer ptr.deinit();
|
||||
|
||||
return ptr;
|
||||
// ABI warning
|
||||
export fn stage2_cpu_features_llvm(
|
||||
result: **Stage2CpuFeatures,
|
||||
arch_name: [*:0]const u8,
|
||||
llvm_cpu_name: [*:0]const u8,
|
||||
llvm_cpu_features: [*:0]const u8,
|
||||
) Error {
|
||||
result.* = Stage2CpuFeatures.createFromLLVM(
|
||||
std.heap.c_allocator,
|
||||
arch_name,
|
||||
llvm_cpu_name,
|
||||
llvm_cpu_features,
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return .OutOfMemory,
|
||||
};
|
||||
return .None;
|
||||
}
|
||||
|
||||
// ABI warning
|
||||
|
|
32
src/main.cpp
32
src/main.cpp
|
@ -100,8 +100,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
|||
" --override-lib-dir [arg] override path to Zig lib directory\n"
|
||||
" -ffunction-sections places each function in a separate section\n"
|
||||
" -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n"
|
||||
" --cpu [cpu] compile for [cpu] on the current target\n"
|
||||
" --features [feature_str] compile with features in [feature_str] on the current target\n"
|
||||
" -target-cpu [cpu] target one specific CPU by name\n"
|
||||
" -target-feature [features] specify the set of CPU features to target\n"
|
||||
"\n"
|
||||
"Link Options:\n"
|
||||
" --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
|
||||
|
@ -1078,22 +1078,30 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
} else if (cpu) {
|
||||
target.cpu_features = stage2_cpu_features_parse_cpu(target_arch_name(target.arch), cpu);
|
||||
if (!target.cpu_features) {
|
||||
fprintf(stderr, "invalid -target-cpu value\n");
|
||||
if ((err = stage2_cpu_features_parse_cpu(&target.cpu_features, target_arch_name(target.arch), cpu))) {
|
||||
fprintf(stderr, "-target-cpu error: %s\n", err_str(err));
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
} else if (features) {
|
||||
target.cpu_features = stage2_cpu_features_parse_features(target_arch_name(target.arch), features);
|
||||
if (!target.cpu_features) {
|
||||
fprintf(stderr, "invalid -target-feature value\n");
|
||||
if ((err = stage2_cpu_features_parse_features(&target.cpu_features, target_arch_name(target.arch),
|
||||
features)))
|
||||
{
|
||||
fprintf(stderr, "-target-feature error: %s\n", err_str(err));
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
} else if (target.is_native) {
|
||||
const char *cpu_name = ZigLLVMGetHostCPUName();
|
||||
const char *cpu_features = ZigLLVMGetNativeFeatures();
|
||||
if ((err = stage2_cpu_features_llvm(&target.cpu_features, target_arch_name(target.arch),
|
||||
cpu_name, cpu_features)))
|
||||
{
|
||||
fprintf(stderr, "unable to determine native CPU features: %s\n", err_str(err));
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
// If no details are specified and we are not native, load
|
||||
// cross-compilation default features.
|
||||
if (!target.is_native) {
|
||||
target.cpu_features = stage2_cpu_features_baseline();
|
||||
if ((err = stage2_cpu_features_baseline(&target.cpu_features))) {
|
||||
fprintf(stderr, "unable to determine baseline CPU features: %s\n", err_str(err));
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,35 +98,55 @@ void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len,
|
|||
const char *msg = "stage0 called stage2_list_cpus_for_arch";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *str) {
|
||||
|
||||
struct Stage2CpuFeatures {
|
||||
const char *llvm_cpu_name;
|
||||
const char *llvm_cpu_features;
|
||||
const char *builtin_str;
|
||||
const char *cache_hash;
|
||||
};
|
||||
|
||||
Error stage2_cpu_features_parse_cpu(Stage2CpuFeatures **out, const char *arch, const char *str) {
|
||||
const char *msg = "stage0 called stage2_cpu_features_parse_cpu";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *str) {
|
||||
Error stage2_cpu_features_parse_features(Stage2CpuFeatures **out, const char *arch, const char *str) {
|
||||
const char *msg = "stage0 called stage2_cpu_features_parse_features";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
Stage2CpuFeatures *stage2_cpu_features_baseline(void) {
|
||||
const char *msg = "stage0 called stage2_cpu_features_baseline";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
Error stage2_cpu_features_baseline(Stage2CpuFeatures **out) {
|
||||
Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
|
||||
result->builtin_str = ".baseline;\n";
|
||||
result->cache_hash = "\n\n";
|
||||
*out = result;
|
||||
return ErrorNone;
|
||||
}
|
||||
Error stage2_cpu_features_llvm(Stage2CpuFeatures **out, const char *arch,
|
||||
const char *llvm_cpu_name, const char *llvm_features)
|
||||
{
|
||||
Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
|
||||
result->llvm_cpu_name = llvm_cpu_name;
|
||||
result->llvm_cpu_features = llvm_features;
|
||||
result->builtin_str = ".baseline;\n";
|
||||
result->cache_hash = "native\n\n";
|
||||
*out = result;
|
||||
return ErrorNone;
|
||||
}
|
||||
void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
|
||||
const char **ptr, size_t *len)
|
||||
{
|
||||
const char *msg = "stage0 called stage2_cpu_features_get_cache_hash";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
*ptr = cpu_features->cache_hash;
|
||||
*len = strlen(cpu_features->cache_hash);
|
||||
}
|
||||
const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
|
||||
const char *msg = "stage0 called stage2_cpu_features_get_llvm_cpu";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
return cpu_features->llvm_cpu_name;
|
||||
}
|
||||
const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
|
||||
const char *msg = "stage0 called stage2_cpu_features_get_llvm_features";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
return cpu_features->llvm_cpu_features;
|
||||
}
|
||||
void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
|
||||
const char **ptr, size_t *len)
|
||||
{
|
||||
const char *msg = "stage0 called stage2_cpu_features_get_builtin_str";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
*ptr = cpu_features->builtin_str;
|
||||
*len = strlen(cpu_features->builtin_str);
|
||||
}
|
||||
|
|
|
@ -184,26 +184,32 @@ ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t ar
|
|||
struct Stage2CpuFeatures;
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *cpu_name);
|
||||
ZIG_EXTERN_C Error stage2_cpu_features_parse_cpu(struct Stage2CpuFeatures **result,
|
||||
const char *arch, const char *cpu_name);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *features);
|
||||
ZIG_EXTERN_C Error stage2_cpu_features_parse_features(struct Stage2CpuFeatures **result,
|
||||
const char *arch, const char *features);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_baseline(void);
|
||||
ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features);
|
||||
ZIG_EXTERN_C Error stage2_cpu_features_llvm(struct Stage2CpuFeatures **result,
|
||||
const char *arch, const char *llvm_cpu_name, const char *llvm_features);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features);
|
||||
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
|
||||
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
|
||||
const char **ptr, size_t *len);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
|
||||
ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
|
||||
const char **ptr, size_t *len);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue