mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 16:24:51 +00:00
Add defaut feature support
This commit is contained in:
parent
03dd376b55
commit
fd17a9962b
@ -625,6 +625,63 @@ const Stage2TargetDetails = struct {
|
||||
llvm_features_str: [:0]const u8,
|
||||
|
||||
builtin_str: [:0]const u8,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
fn initCpu(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), cpu: *const std.target.Cpu) !Self {
|
||||
var builtin_str_buffer = try std.Buffer.init(
|
||||
allocator,
|
||||
"@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
|
||||
defer builtin_str_buffer.deinit();
|
||||
|
||||
try builtin_str_buffer.append(@tagName(arch));
|
||||
try builtin_str_buffer.append(".cpu_");
|
||||
try builtin_str_buffer.append(cpu.name);
|
||||
try builtin_str_buffer.append("};");
|
||||
return Self{
|
||||
.allocator = allocator,
|
||||
.target_details = .{
|
||||
.cpu = cpu,
|
||||
},
|
||||
.llvm_cpu_str = cpu.name,
|
||||
.llvm_features_str = "",
|
||||
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||
};
|
||||
}
|
||||
|
||||
fn initFeatures(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), features: []*const std.target.Feature) !Self {
|
||||
var builtin_str_buffer = try std.Buffer.init(
|
||||
allocator,
|
||||
"@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
|
||||
defer builtin_str_buffer.deinit();
|
||||
|
||||
var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
|
||||
defer llvm_features_buffer.deinit();
|
||||
|
||||
for (features) |feature| {
|
||||
try llvm_features_buffer.append("+");
|
||||
try llvm_features_buffer.append(feature.llvm_name);
|
||||
try llvm_features_buffer.append(",");
|
||||
|
||||
try builtin_str_buffer.append("&@import(\"std\").target.");
|
||||
try builtin_str_buffer.append(@tagName(arch));
|
||||
try builtin_str_buffer.append(".feature_");
|
||||
try builtin_str_buffer.append(feature.name);
|
||||
try builtin_str_buffer.append(",");
|
||||
}
|
||||
|
||||
try builtin_str_buffer.append("}};");
|
||||
|
||||
return Self{
|
||||
.allocator = allocator,
|
||||
.target_details = std.target.TargetDetails{
|
||||
.features = features,
|
||||
},
|
||||
.llvm_cpu_str = "",
|
||||
.llvm_features_str = llvm_features_buffer.toOwnedSlice(),
|
||||
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// ABI warning
|
||||
@ -658,32 +715,14 @@ export fn stage2_target_details_parse_features(arch_str: ?[*:0]const u8, feature
|
||||
}
|
||||
|
||||
fn parseCpu(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2TargetDetails {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
const cpus = std.target.getCpusForArch(arch);
|
||||
|
||||
for (cpus) |cpu| {
|
||||
if (std.mem.eql(u8, str, cpu.name)) {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
var builtin_str_buffer = try std.Buffer.init(
|
||||
allocator,
|
||||
"@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
|
||||
defer builtin_str_buffer.deinit();
|
||||
|
||||
try builtin_str_buffer.append(@tagName(arch));
|
||||
try builtin_str_buffer.append(".cpu_");
|
||||
try builtin_str_buffer.append(cpu.name);
|
||||
try builtin_str_buffer.append("};");
|
||||
|
||||
const ptr = try allocator.create(Stage2TargetDetails);
|
||||
ptr.* = .{
|
||||
.allocator = allocator,
|
||||
.target_details = .{
|
||||
.cpu = cpu,
|
||||
},
|
||||
.llvm_cpu_str = cpu.name,
|
||||
.llvm_features_str = "",
|
||||
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||
};
|
||||
ptr.* = try Stage2TargetDetails.initCpu(std.heap.c_allocator, arch, cpu);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@ -700,11 +739,6 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
|
||||
var features = std.ArrayList(*const std.target.Feature).init(allocator);
|
||||
defer features.deinit();
|
||||
|
||||
var builtin_str_buffer = try std.Buffer.init(
|
||||
allocator,
|
||||
"@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
|
||||
defer builtin_str_buffer.deinit();
|
||||
|
||||
var start: usize = 0;
|
||||
while (start < str.len) {
|
||||
const next_comma_pos = std.mem.indexOfScalar(u8, str[start..], ',') orelse str.len - start;
|
||||
@ -725,39 +759,15 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
|
||||
if (feature) |f| {
|
||||
features.append(f) catch @panic("out of memory");
|
||||
|
||||
try builtin_str_buffer.append("&@import(\"std\").target.");
|
||||
try builtin_str_buffer.append(@tagName(arch));
|
||||
try builtin_str_buffer.append(".feature_");
|
||||
try builtin_str_buffer.append(f.name);
|
||||
try builtin_str_buffer.append(",");
|
||||
} else {
|
||||
return error.InvalidFeature;
|
||||
}
|
||||
}
|
||||
|
||||
try builtin_str_buffer.append("}};");
|
||||
|
||||
const features_slice = features.toOwnedSlice();
|
||||
|
||||
var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
|
||||
defer llvm_features_buffer.deinit();
|
||||
|
||||
for (features_slice) |feature| {
|
||||
try llvm_features_buffer.append("+");
|
||||
try llvm_features_buffer.append(feature.llvm_name);
|
||||
try llvm_features_buffer.append(",");
|
||||
}
|
||||
|
||||
const ptr = try allocator.create(Stage2TargetDetails);
|
||||
ptr.* = Stage2TargetDetails{
|
||||
.allocator = allocator,
|
||||
.target_details = std.target.TargetDetails{
|
||||
.features = features_slice,
|
||||
},
|
||||
.llvm_cpu_str = "",
|
||||
.llvm_features_str = llvm_features_buffer.toOwnedSlice(),
|
||||
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||
};
|
||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features_slice);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@ -800,3 +810,68 @@ export fn stage2_target_details_get_builtin_str(target_details: ?*const Stage2Ta
|
||||
|
||||
return @as([*:0]const u8, "");
|
||||
}
|
||||
|
||||
const riscv_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
|
||||
&std.target.riscv.feature_a,
|
||||
&std.target.riscv.feature_c,
|
||||
&std.target.riscv.feature_d,
|
||||
&std.target.riscv.feature_f,
|
||||
&std.target.riscv.feature_m,
|
||||
&std.target.riscv.feature_relax,
|
||||
};
|
||||
|
||||
const i386_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
|
||||
&std.target.x86.feature_cmov,
|
||||
&std.target.x86.feature_cx8,
|
||||
&std.target.x86.feature_fxsr,
|
||||
&std.target.x86.feature_mmx,
|
||||
&std.target.x86.feature_nopl,
|
||||
&std.target.x86.feature_sse,
|
||||
&std.target.x86.feature_sse2,
|
||||
&std.target.x86.feature_slowUnalignedMem16,
|
||||
&std.target.x86.feature_x87,
|
||||
};
|
||||
|
||||
// Same as above but without sse.
|
||||
const i386_default_features_freestanding: []*const std.target.Feature = &[_]*const std.target.Feature {
|
||||
&std.target.x86.feature_cmov,
|
||||
&std.target.x86.feature_cx8,
|
||||
&std.target.x86.feature_fxsr,
|
||||
&std.target.x86.feature_mmx,
|
||||
&std.target.x86.feature_nopl,
|
||||
&std.target.x86.feature_slowUnalignedMem16,
|
||||
&std.target.x86.feature_x87,
|
||||
};
|
||||
|
||||
// ABI warning
|
||||
export fn stage2_target_details_get_default(arch_str: ?[*:0]const u8, os_str: ?[*:0]const u8) ?*Stage2TargetDetails {
|
||||
if (arch_str == null) return null;
|
||||
if (os_str == null) return null;
|
||||
|
||||
const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_str.?)) catch return null;
|
||||
const os = Target.parseOs(std.mem.toSliceConst(u8, os_str.?)) catch return null;
|
||||
|
||||
return createDefaultTargetDetails(arch, os) catch return null;
|
||||
}
|
||||
|
||||
fn createDefaultTargetDetails(arch: @TagType(std.Target.Arch), os: std.Target.Os) !?*Stage2TargetDetails {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
return switch (arch) {
|
||||
.riscv32, .riscv64 => blk: {
|
||||
const ptr = try allocator.create(Stage2TargetDetails);
|
||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, riscv_default_features);
|
||||
break :blk ptr;
|
||||
},
|
||||
.i386 => blk: {
|
||||
const ptr = try allocator.create(Stage2TargetDetails);
|
||||
const features = switch (os) {
|
||||
.freestanding => i386_default_features_freestanding,
|
||||
else => i386_default_features,
|
||||
};
|
||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features);
|
||||
break :blk ptr;
|
||||
},
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -8781,8 +8781,9 @@ static void init(CodeGen *g) {
|
||||
reloc_mode = LLVMRelocStatic;
|
||||
}
|
||||
|
||||
const char *target_specific_cpu_args;
|
||||
const char *target_specific_features;
|
||||
const char *target_specific_cpu_args = "";
|
||||
const char *target_specific_features = "";
|
||||
|
||||
if (g->zig_target->is_native) {
|
||||
// LLVM creates invalid binaries on Windows sometimes.
|
||||
// See https://github.com/ziglang/zig/issues/508
|
||||
@ -8794,22 +8795,6 @@ static void init(CodeGen *g) {
|
||||
target_specific_cpu_args = ZigLLVMGetHostCPUName();
|
||||
target_specific_features = ZigLLVMGetNativeFeatures();
|
||||
}
|
||||
} else if (target_is_riscv(g->zig_target)) {
|
||||
// TODO https://github.com/ziglang/zig/issues/2883
|
||||
// Be aware of https://github.com/ziglang/zig/issues/3275
|
||||
target_specific_cpu_args = "";
|
||||
target_specific_features = riscv_default_features;
|
||||
} else if (g->zig_target->arch == ZigLLVM_x86) {
|
||||
// This is because we're really targeting i686 rather than i386.
|
||||
// It's pretty much impossible to use many of the language features
|
||||
// such as fp16 if you stick use the x87 only. This is also what clang
|
||||
// uses as base cpu.
|
||||
// TODO https://github.com/ziglang/zig/issues/2883
|
||||
target_specific_cpu_args = "pentium4";
|
||||
target_specific_features = (g->zig_target->os == OsFreestanding) ? "-sse": "";
|
||||
} else {
|
||||
target_specific_cpu_args = "";
|
||||
target_specific_features = "";
|
||||
}
|
||||
|
||||
// Override CPU and features if defined by user.
|
||||
|
||||
@ -1090,6 +1090,12 @@ int main(int argc, char **argv) {
|
||||
fprintf(stderr, "invalid --features value\n");
|
||||
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_details = stage2_target_details_get_default(target_arch_name(target.arch), target_os_name(target.os));
|
||||
}
|
||||
}
|
||||
|
||||
if (output_dir != nullptr && enable_cache == CacheOptOn) {
|
||||
|
||||
@ -109,3 +109,6 @@ const char *stage2_target_details_get_llvm_features(const Stage2TargetDetails *t
|
||||
const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details) {
|
||||
return "";
|
||||
}
|
||||
Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -201,4 +201,7 @@ ZIG_EXTERN_C const char *stage2_target_details_get_llvm_features(const Stage2Tar
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user