Commit 48c7e6c48b
Changed files (13)
lib
std
src-self-hosted
lib/std/target/avr.zig
@@ -2378,7 +2378,3 @@ pub const all_cpus = &[_]*const Cpu{
&cpu.avrxmega7,
&cpu.m3000,
};
-
-pub const baseline_features = featureSet(&[_]Feature{
- .avr0,
-});
lib/std/target/riscv.zig
@@ -69,11 +69,39 @@ pub const all_features = blk: {
};
pub const cpu = struct {
+ pub const baseline_rv32 = Cpu{
+ .name = "baseline_rv32",
+ .llvm_name = "generic-rv32",
+ .features = featureSet(&[_]Feature{
+ .a,
+ .c,
+ .d,
+ .f,
+ .m,
+ .relax,
+ }),
+ };
+
+ pub const baseline_rv64 = Cpu{
+ .name = "baseline_rv64",
+ .llvm_name = "generic-rv64",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .a,
+ .c,
+ .d,
+ .f,
+ .m,
+ .relax,
+ }),
+ };
+
pub const generic_rv32 = Cpu{
.name = "generic_rv32",
.llvm_name = "generic-rv32",
.features = featureSet(&[_]Feature{}),
};
+
pub const generic_rv64 = Cpu{
.name = "generic_rv64",
.llvm_name = "generic-rv64",
@@ -87,25 +115,8 @@ pub const cpu = struct {
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
+ &cpu.baseline_rv32,
+ &cpu.baseline_rv64,
&cpu.generic_rv32,
&cpu.generic_rv64,
};
-
-pub const baseline_32_features = featureSet(&[_]Feature{
- .a,
- .c,
- .d,
- .f,
- .m,
- .relax,
-});
-
-pub const baseline_64_features = featureSet(&[_]Feature{
- .@"64bit",
- .a,
- .c,
- .d,
- .f,
- .m,
- .relax,
-});
lib/std/build.zig
@@ -484,6 +484,7 @@ pub const Builder = struct {
.arch = builtin.arch,
.os = builtin.os,
.abi = builtin.abi,
+ .cpu_features = builtin.cpu_features,
},
}).linuxTriple(self.allocator);
@@ -1375,6 +1376,7 @@ pub const LibExeObjStep = struct {
.arch = target_arch,
.os = target_os,
.abi = target_abi,
+ .cpu_features = target_arch.getBaselineCpuFeatures(),
},
});
}
@@ -1972,25 +1974,41 @@ pub const LibExeObjStep = struct {
try zig_args.append("-target");
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
- switch (cross.cpu_features) {
- .baseline => {},
- .cpu => |cpu| {
+ const all_features = self.target.getArch().allFeaturesList();
+ var populated_cpu_features = cross.cpu_features.cpu.features;
+ populated_cpu_features.populateDependencies(all_features);
+
+ if (populated_cpu_features.eql(cross.cpu_features.features)) {
+ // The CPU name alone is sufficient.
+ // If it is the baseline CPU, no command line args are required.
+ if (cross.cpu_features.cpu != self.target.getArch().getBaselineCpuFeatures().cpu) {
try zig_args.append("-target-cpu");
- try zig_args.append(cpu.name);
- },
- .features => |features| {
- try zig_args.append("-target-cpu-features");
-
- var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0);
- for (self.target.getArch().allFeaturesList()) |feature, i| {
- if (features.isEnabled(@intCast(Target.Cpu.Feature.Set.Index, i))) {
- try feature_str_buffer.append(feature.name);
- try feature_str_buffer.append(",");
- }
+ try zig_args.append(cross.cpu_features.cpu.name);
+ }
+ } else {
+ try zig_args.append("-target-cpu");
+ try zig_args.append(cross.cpu_features.cpu.name);
+
+ try zig_args.append("-target-feature");
+ var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0);
+ for (all_features) |feature, i_usize| {
+ const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
+ const in_cpu_set = populated_cpu_features.isEnabled(i);
+ const in_actual_set = cross.cpu_features.features.isEnabled(i);
+ if (in_cpu_set and !in_actual_set) {
+ try feature_str_buffer.appendByte('-');
+ try feature_str_buffer.append(feature.name);
+ try feature_str_buffer.appendByte(',');
+ } else if (!in_cpu_set and in_actual_set) {
+ try feature_str_buffer.appendByte('+');
+ try feature_str_buffer.append(feature.name);
+ try feature_str_buffer.appendByte(',');
}
-
- try zig_args.append(feature_str_buffer.toSlice());
- },
+ }
+ if (mem.endsWith(u8, feature_str_buffer.toSliceConst(), ",")) {
+ feature_str_buffer.shrink(feature_str_buffer.len() - 1);
+ }
+ try zig_args.append(feature_str_buffer.toSliceConst());
}
},
}
lib/std/target.zig
@@ -172,6 +172,15 @@ pub const Target = union(enum) {
r6,
};
+ pub fn subArchName(arch: Arch) ?[]const u8 {
+ return switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => |arm32| @tagName(arm32),
+ .aarch64, .aarch64_be, .aarch64_32 => |arm64| @tagName(arm64),
+ .kalimba => |kalimba| @tagName(kalimba),
+ else => return null,
+ };
+ }
+
pub fn subArchFeature(arch: Arch) ?u8 {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => |arm32| switch (arm32) {
@@ -251,24 +260,12 @@ pub const Target = union(enum) {
return error.UnknownCpu;
}
- /// This parsing function supports 2 syntaxes.
- /// * Comma-separated list of features, with + or - in front of each feature. This
- /// form represents a deviation from baseline.
- /// * Comma-separated list of features, with no + or - in front of each feature. This
- /// form represents an exclusive list of enabled features; no other features besides
- /// the ones listed, and their dependencies, will be enabled.
+ /// Comma-separated list of features, with + or - in front of each feature. This
+ /// form represents a deviation from baseline CPU, which is provided as a parameter.
/// Extra commas are ignored.
- pub fn parseCpuFeatureSet(arch: Arch, features_text: []const u8) !Cpu.Feature.Set {
- // Here we compute both and choose the correct result at the end, based
- // on whether or not we saw + and - signs.
- var whitelist_set = Cpu.Feature.Set.empty;
- var baseline_set = arch.baselineFeatures();
- var mode: enum {
- unknown,
- baseline,
- whitelist,
- } = .unknown;
-
+ pub fn parseCpuFeatureSet(arch: Arch, cpu: *const Cpu, features_text: []const u8) !Cpu.Feature.Set {
+ const all_features = arch.allFeaturesList();
+ var set = cpu.features;
var it = mem.tokenize(features_text, ",");
while (it.next()) |item_text| {
var feature_name: []const u8 = undefined;
@@ -277,40 +274,20 @@ pub const Target = union(enum) {
sub,
} = undefined;
if (mem.startsWith(u8, item_text, "+")) {
- switch (mode) {
- .unknown, .baseline => mode = .baseline,
- .whitelist => return error.InvalidCpuFeatures,
- }
op = .add;
feature_name = item_text[1..];
} else if (mem.startsWith(u8, item_text, "-")) {
- switch (mode) {
- .unknown, .baseline => mode = .baseline,
- .whitelist => return error.InvalidCpuFeatures,
- }
op = .sub;
feature_name = item_text[1..];
} else {
- switch (mode) {
- .unknown, .whitelist => mode = .whitelist,
- .baseline => return error.InvalidCpuFeatures,
- }
- op = .add;
- feature_name = item_text;
+ return error.InvalidCpuFeatures;
}
- const all_features = arch.allFeaturesList();
for (all_features) |feature, index_usize| {
const index = @intCast(Cpu.Feature.Set.Index, index_usize);
if (mem.eql(u8, feature_name, feature.name)) {
switch (op) {
- .add => {
- baseline_set.addFeature(index);
- whitelist_set.addFeature(index);
- },
- .sub => {
- baseline_set.removeFeature(index);
- whitelist_set.removeFeature(index);
- },
+ .add => set.addFeature(index),
+ .sub => set.removeFeature(index),
}
break;
}
@@ -319,10 +296,8 @@ pub const Target = union(enum) {
}
}
- return switch (mode) {
- .unknown, .whitelist => whitelist_set,
- .baseline => baseline_set,
- };
+ set.populateDependencies(all_features);
+ return set;
}
pub fn toElfMachine(arch: Arch) std.elf.EM {
@@ -485,29 +460,37 @@ pub const Target = 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.
- pub fn baselineFeatures(arch: Arch) Cpu.Feature.Set {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => arm.cpu.generic.features,
- .aarch64, .aarch64_be, .aarch64_32 => aarch64.cpu.generic.features,
- .avr => avr.baseline_features,
- .bpfel, .bpfeb => bpf.cpu.generic.features,
- .hexagon => hexagon.cpu.generic.features,
- .mips, .mipsel => mips.cpu.mips32.features,
- .mips64, .mips64el => mips.cpu.mips64.features,
- .msp430 => msp430.cpu.generic.features,
- .powerpc, .powerpc64, .powerpc64le => powerpc.cpu.generic.features,
- .amdgcn => amdgpu.cpu.generic.features,
- .riscv32 => riscv.baseline_32_features,
- .riscv64 => riscv.baseline_64_features,
- .sparc, .sparcv9, .sparcel => sparc.cpu.generic.features,
- .s390x => systemz.cpu.generic.features,
- .i386 => x86.cpu.pentium4.features,
- .x86_64 => x86.cpu.x86_64.features,
- .nvptx, .nvptx64 => nvptx.cpu.sm_20.features,
- .wasm32, .wasm64 => wasm.cpu.generic.features,
-
- else => Cpu.Feature.Set.empty,
+ pub fn getBaselineCpuFeatures(arch: Arch) CpuFeatures {
+ const S = struct {
+ const generic_cpu = Cpu{
+ .name = "generic",
+ .llvm_name = null,
+ .features = Cpu.Feature.Set.empty,
+ };
+ };
+ const cpu = switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic,
+ .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
+ .avr => &avr.cpu.avr1,
+ .bpfel, .bpfeb => &bpf.cpu.generic,
+ .hexagon => &hexagon.cpu.generic,
+ .mips, .mipsel => &mips.cpu.mips32,
+ .mips64, .mips64el => &mips.cpu.mips64,
+ .msp430 => &msp430.cpu.generic,
+ .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
+ .amdgcn => &amdgpu.cpu.generic,
+ .riscv32 => &riscv.cpu.baseline_rv32,
+ .riscv64 => &riscv.cpu.baseline_rv64,
+ .sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
+ .s390x => &systemz.cpu.generic,
+ .i386 => &x86.cpu.pentium4,
+ .x86_64 => &x86.cpu.x86_64,
+ .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
+ .wasm32, .wasm64 => &wasm.cpu.generic,
+
+ else => &S.generic_cpu,
};
+ return CpuFeatures.initFromCpu(arch, cpu);
}
/// All CPUs Zig is aware of, sorted lexicographically by name.
@@ -685,19 +668,28 @@ pub const Target = union(enum) {
arch: Arch,
os: Os,
abi: Abi,
- cpu_features: CpuFeatures = .baseline,
+ cpu_features: CpuFeatures,
};
- 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.
+ pub const CpuFeatures = struct {
+ /// The CPU to target. It has a set of features
+ /// which are overridden with the `features` field.
cpu: *const Cpu,
/// Explicitly provide the entire CPU feature set.
features: Cpu.Feature.Set,
+
+ pub fn initFromCpu(arch: Arch, cpu: *const Cpu) CpuFeatures {
+ var features = cpu.features;
+ if (arch.subArchFeature()) |sub_arch_index| {
+ features.addFeature(sub_arch_index);
+ }
+ features.populateDependencies(arch.allFeaturesList());
+ return CpuFeatures{
+ .cpu = cpu,
+ .features = features,
+ };
+ }
};
pub const current = Target{
@@ -718,14 +710,6 @@ pub const Target = union(enum) {
};
}
- pub fn cpuFeatureSet(self: Target) Cpu.Feature.Set {
- return switch (self.getCpuFeatures()) {
- .baseline => self.getArch().baselineFeatures(),
- .cpu => |cpu| cpu.features,
- .features => |features| features,
- };
- }
-
pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{
@tagName(self.getArch()),
@@ -791,14 +775,18 @@ pub const Target = union(enum) {
});
}
+ /// TODO: Support CPU features here?
+ /// https://github.com/ziglang/zig/issues/4261
pub fn parse(text: []const u8) !Target {
var it = mem.separate(text, "-");
const arch_name = it.next() orelse return error.MissingArchitecture;
const os_name = it.next() orelse return error.MissingOperatingSystem;
const abi_name = it.next();
+ const arch = try parseArchSub(arch_name);
var cross = Cross{
- .arch = try parseArchSub(arch_name),
+ .arch = arch,
+ .cpu_features = arch.getBaselineCpuFeatures(),
.os = try parseOs(os_name),
.abi = undefined,
};
src/codegen.cpp
@@ -8581,7 +8581,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
stage2_cpu_features_get_builtin_str(g->zig_target->cpu_features, &ptr, &len);
buf_append_mem(contents, ptr, len);
} else {
- buf_append_str(contents, ".baseline;\n");
+ buf_append_str(contents, "arch.getBaselineCpuFeatures();\n");
}
}
if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {
src/main.cpp
@@ -866,7 +866,7 @@ int main(int argc, char **argv) {
cpu = argv[i];
} else if (strcmp(arg, "-target-feature") == 0) {
features = argv[i];
- }else {
+ } else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return print_error_usage(arg0);
}
@@ -984,35 +984,10 @@ int main(int argc, char **argv) {
Buf zig_triple_buf = BUF_INIT;
target_triple_zig(&zig_triple_buf, &target);
- if (cpu && features) {
- fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");
+ const char *stage2_triple_arg = target.is_native ? nullptr : buf_ptr(&zig_triple_buf);
+ if ((err = stage2_cpu_features_parse(&target.cpu_features, stage2_triple_arg, cpu, features))) {
+ fprintf(stderr, "unable to initialize CPU features: %s\n", err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
- } else if (cpu) {
- if ((err = stage2_cpu_features_parse_cpu(&target.cpu_features, buf_ptr(&zig_triple_buf), cpu))) {
- fprintf(stderr, "-target-cpu error: %s\n", err_str(err));
- return main_exit(root_progress_node, EXIT_FAILURE);
- }
- } else if (features) {
- if ((err = stage2_cpu_features_parse_features(&target.cpu_features, buf_ptr(&zig_triple_buf),
- 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, buf_ptr(&zig_triple_buf),
- 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 ((err = stage2_cpu_features_baseline(&target.cpu_features, buf_ptr(&zig_triple_buf)))) {
- fprintf(stderr, "unable to determine baseline CPU features: %s\n", err_str(err));
- return main_exit(root_progress_node, EXIT_FAILURE);
- }
}
if (output_dir != nullptr && enable_cache == CacheOptOn) {
src/userland.cpp
@@ -2,7 +2,8 @@
// src-self-hosted/stage1.zig
#include "userland.h"
-#include "ast_render.hpp"
+#include "util.hpp"
+#include "zig_llvm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -96,32 +97,30 @@ struct Stage2CpuFeatures {
const char *cache_hash;
};
-Error stage2_cpu_features_parse_cpu(Stage2CpuFeatures **out, const char *zig_triple, const char *str) {
- const char *msg = "stage0 called stage2_cpu_features_parse_cpu";
- stage2_panic(msg, strlen(msg));
-}
-Error stage2_cpu_features_parse_features(Stage2CpuFeatures **out, const char *zig_triple, const char *str) {
- const char *msg = "stage0 called stage2_cpu_features_parse_features";
- stage2_panic(msg, strlen(msg));
-}
-Error stage2_cpu_features_baseline(Stage2CpuFeatures **out, const char *zig_triple) {
- 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 *zig_triple,
- const char *llvm_cpu_name, const char *llvm_features)
+Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple,
+ const char *cpu_name, const char *cpu_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;
+ if (zig_triple == nullptr) {
+ Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
+ result->llvm_cpu_name = ZigLLVMGetHostCPUName();
+ result->llvm_cpu_features = ZigLLVMGetNativeFeatures();
+ result->builtin_str = "arch.getBaselineCpuFeatures();\n";
+ result->cache_hash = "native\n\n";
+ *out = result;
+ return ErrorNone;
+ }
+ if (cpu_name == nullptr && cpu_features == nullptr) {
+ Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
+ result->builtin_str = "arch.getBaselineCpuFeatures();\n";
+ result->cache_hash = "\n\n";
+ *out = result;
+ return ErrorNone;
+ }
+
+ const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features";
+ stage2_panic(msg, strlen(msg));
}
+
void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
const char **ptr, size_t *len)
{
src/userland.h
@@ -184,20 +184,8 @@ ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
struct Stage2CpuFeatures;
// ABI warning
-ZIG_EXTERN_C Error stage2_cpu_features_parse_cpu(struct Stage2CpuFeatures **result,
- const char *zig_triple, const char *cpu_name);
-
-// ABI warning
-ZIG_EXTERN_C Error stage2_cpu_features_parse_features(struct Stage2CpuFeatures **result,
- const char *zig_triple, const char *features);
-
-// ABI warning
-ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result,
- const char *zig_triple);
-
-// ABI warning
-ZIG_EXTERN_C Error stage2_cpu_features_llvm(struct Stage2CpuFeatures **result,
- const char *zig_triple, const char *llvm_cpu_name, const char *llvm_features);
+ZIG_EXTERN_C Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result,
+ const char *zig_triple, const char *cpu_name, const char *cpu_features);
// ABI warning
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
src-self-hosted/print_targets.zig
@@ -227,16 +227,14 @@ pub fn cmdTargets(
try jws.objectField("abi");
try jws.emitString(@tagName(native_target.getAbi()));
try jws.objectField("cpuName");
- switch (native_target.getCpuFeatures()) {
- .baseline, .features => try jws.emitNull(),
- .cpu => |cpu| try jws.emitString(cpu.name),
- }
+ const cpu_features = native_target.getCpuFeatures();
+ try jws.emitString(cpu_features.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))) {
+ for (native_target.getArch().allFeaturesList()) |feature, i_usize| {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
+ if (cpu_features.features.isEnabled(index)) {
try jws.arrayElem();
try jws.emitString(feature.name);
}
src-self-hosted/stage1.zig
@@ -540,74 +540,66 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
node.context.maybeRefresh();
}
-/// I have observed the CPU name reported by LLVM being incorrect. On
-/// the SourceHut build services, LLVM 9.0 reports the CPU as "athlon-xp",
-/// which is a 32-bit CPU, even though the system is 64-bit and the reported
-/// CPU features include, among other things, +64bit.
-/// So the strategy taken here is that we observe both reported CPU, and the
-/// reported CPU features. The features are trusted more; but if the features
-/// match exactly the features of the reported CPU, then we trust the reported CPU.
fn cpuFeaturesFromLLVM(
arch: Target.Arch,
llvm_cpu_name_z: ?[*:0]const u8,
llvm_cpu_features_opt: ?[*:0]const u8,
) !Target.CpuFeatures {
- var set = arch.baselineFeatures();
- const llvm_cpu_features = llvm_cpu_features_opt orelse return Target.CpuFeatures{
- .features = set,
- };
+ var result = arch.getBaselineCpuFeatures();
- const all_features = arch.allFeaturesList();
+ if (llvm_cpu_name_z) |cpu_name_z| {
+ const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
- 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 (all_features) |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)),
- }
+ for (arch.allCpus()) |cpu| {
+ const this_llvm_name = cpu.llvm_name orelse continue;
+ if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
+ // Here we use the non-dependencies-populated set,
+ // so that subtracting features later in this function
+ // affect the prepopulated set.
+ result = Target.CpuFeatures{
+ .cpu = cpu,
+ .features = cpu.features,
+ };
break;
}
}
}
- if (llvm_cpu_name_z) |cpu_name_z| {
- const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
+ const all_features = arch.allFeaturesList();
- for (arch.allCpus()) |cpu| {
- const this_llvm_name = cpu.llvm_name orelse continue;
- if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
- // Only trust the CPU if the reported features exactly match.
- var populated_reported_features = set;
- populated_reported_features.populateDependencies(all_features);
- var populated_cpu_features = cpu.features;
- populated_cpu_features.populateDependencies(all_features);
- if (populated_reported_features.eql(populated_cpu_features)) {
- return Target.CpuFeatures{ .cpu = cpu };
- } else {
- return Target.CpuFeatures{ .features = set };
+ if (llvm_cpu_features_opt) |llvm_cpu_features| {
+ 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 (all_features) |feature, index_usize| {
+ const this_llvm_name = feature.llvm_name orelse continue;
+ if (mem.eql(u8, llvm_feat, this_llvm_name)) {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
+ switch (op) {
+ .add => result.features.addFeature(index),
+ .sub => result.features.removeFeature(index),
+ }
+ break;
}
}
}
}
- return Target.CpuFeatures{ .features = set };
+ result.features.populateDependencies(all_features);
+ return result;
}
// ABI warning
@@ -639,7 +631,6 @@ const Stage2CpuFeatures = struct {
allocator: *mem.Allocator,
cpu_features: Target.CpuFeatures,
- llvm_cpu_name: ?[*:0]const u8,
llvm_features_str: ?[*:0]const u8,
builtin_str: [:0]const u8,
@@ -647,125 +638,64 @@ const Stage2CpuFeatures = struct {
const Self = @This();
- fn createBaseline(allocator: *mem.Allocator, arch: Target.Arch) !*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);
-
- self.* = Self{
- .allocator = allocator,
- .cpu_features = .baseline,
- .llvm_cpu_name = null,
- .llvm_features_str = try initLLVMFeatures(allocator, arch, arch.baselineFeatures()),
- .builtin_str = builtin_str,
- .cache_hash = cache_hash,
- };
-
- return self;
- }
-
- fn createFromLLVM(
- allocator: *mem.Allocator,
- zig_triple: [*: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 cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name_z, llvm_cpu_features);
- switch (cpu_features) {
- .baseline => return createBaseline(allocator, arch),
- .cpu => |cpu| return createFromCpu(allocator, arch, cpu),
- .features => |features| return createFromCpuFeatures(allocator, arch, features),
- }
- }
-
- 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 = &Target.{}.cpu.{} }};\n", .{
- arch.genericName(),
- cpu.name,
- });
- errdefer allocator.free(builtin_str);
-
- const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ cpu.name, cpu.features.asBytes() });
- errdefer allocator.free(cache_hash);
-
- self.* = Self{
- .allocator = allocator,
- .cpu_features = .{ .cpu = cpu },
- .llvm_cpu_name = if (cpu.llvm_name) |n| n.ptr else null,
- .llvm_features_str = null,
- .builtin_str = builtin_str,
- .cache_hash = cache_hash,
- };
- return self;
- }
-
- fn initLLVMFeatures(
- allocator: *mem.Allocator,
- arch: Target.Arch,
- feature_set: Target.Cpu.Feature.Set,
- ) ![*:0]const u8 {
- var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
- defer llvm_features_buffer.deinit();
-
- const all_features = arch.allFeaturesList();
- var populated_feature_set = feature_set;
- if (arch.subArchFeature()) |sub_arch_index| {
- populated_feature_set.addFeature(sub_arch_index);
- }
- populated_feature_set.populateDependencies(all_features);
- for (all_features) |feature, index| {
- const llvm_name = feature.llvm_name orelse continue;
- const plus_or_minus = "-+"[@boolToInt(populated_feature_set.isEnabled(@intCast(u8, index)))];
- try llvm_features_buffer.appendByte(plus_or_minus);
- try llvm_features_buffer.append(llvm_name);
- try llvm_features_buffer.append(",");
- }
- assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
- llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
-
- return llvm_features_buffer.toOwnedSlice().ptr;
+ fn createFromNative(allocator: *mem.Allocator) !*Self {
+ const arch = Target.current.getArch();
+ const llvm = @import("llvm.zig");
+ const llvm_cpu_name = llvm.GetHostCPUName();
+ const llvm_cpu_features = llvm.GetNativeFeatures();
+ const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features);
+ return createFromCpuFeatures(allocator, arch, cpu_features);
}
fn createFromCpuFeatures(
allocator: *mem.Allocator,
arch: Target.Arch,
- feature_set: Target.Cpu.Feature.Set,
+ cpu_features: Target.CpuFeatures,
) !*Self {
const self = try allocator.create(Self);
errdefer allocator.destroy(self);
- const cache_hash = try std.fmt.allocPrint0(allocator, "\n{}", .{feature_set.asBytes()});
+ const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
+ cpu_features.cpu.name,
+ cpu_features.features.asBytes(),
+ });
errdefer allocator.free(cache_hash);
const generic_arch_name = arch.genericName();
- var builtin_str_buffer = try std.Buffer.allocPrint(
- allocator,
+ var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
\\CpuFeatures{{
+ \\ .cpu = &Target.{}.cpu.{},
\\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
\\
- ,
- .{ generic_arch_name, generic_arch_name },
- );
+ , .{
+ generic_arch_name,
+ cpu_features.cpu.name,
+ generic_arch_name,
+ generic_arch_name,
+ });
defer builtin_str_buffer.deinit();
- for (arch.allFeaturesList()) |feature, index| {
- if (!feature_set.isEnabled(@intCast(u8, index))) continue;
+ var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
+ defer llvm_features_buffer.deinit();
+
+ for (arch.allFeaturesList()) |feature, index_usize| {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
+ const is_enabled = cpu_features.features.isEnabled(index);
+
+ if (feature.llvm_name) |llvm_name| {
+ const plus_or_minus = "-+"[@boolToInt(is_enabled)];
+ try llvm_features_buffer.appendByte(plus_or_minus);
+ try llvm_features_buffer.append(llvm_name);
+ try llvm_features_buffer.append(",");
+ }
- // TODO some kind of "zig identifier escape" function rather than
- // unconditionally using @"" syntax
- try builtin_str_buffer.append(" .@\"");
- try builtin_str_buffer.append(feature.name);
- try builtin_str_buffer.append("\",\n");
+ if (is_enabled) {
+ // TODO some kind of "zig identifier escape" function rather than
+ // unconditionally using @"" syntax
+ try builtin_str_buffer.append(" .@\"");
+ try builtin_str_buffer.append(feature.name);
+ try builtin_str_buffer.append("\",\n");
+ }
}
try builtin_str_buffer.append(
@@ -774,11 +704,13 @@ const Stage2CpuFeatures = struct {
\\
);
+ assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
+ llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
+
self.* = Self{
.allocator = allocator,
- .cpu_features = .{ .features = feature_set },
- .llvm_cpu_name = null,
- .llvm_features_str = try initLLVMFeatures(allocator, arch, feature_set),
+ .cpu_features = cpu_features,
+ .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr,
.builtin_str = builtin_str_buffer.toOwnedSlice(),
.cache_hash = cache_hash,
};
@@ -794,12 +726,13 @@ const Stage2CpuFeatures = struct {
};
// ABI warning
-export fn stage2_cpu_features_parse_cpu(
+export fn stage2_cpu_features_parse(
result: **Stage2CpuFeatures,
- zig_triple: [*:0]const u8,
- cpu_name: [*:0]const u8,
+ zig_triple: ?[*:0]const u8,
+ cpu_name: ?[*:0]const u8,
+ cpu_features: ?[*:0]const u8,
) Error {
- result.* = parseCpu(zig_triple, cpu_name) catch |err| switch (err) {
+ result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) {
error.OutOfMemory => return .OutOfMemory,
error.UnknownArchitecture => return .UnknownArchitecture,
error.UnknownSubArchitecture => return .UnknownSubArchitecture,
@@ -807,110 +740,61 @@ export fn stage2_cpu_features_parse_cpu(
error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
error.MissingOperatingSystem => return .MissingOperatingSystem,
error.MissingArchitecture => return .MissingArchitecture,
- };
- return .None;
-}
-
-fn parseCpu(zig_triple: [*:0]const u8, cpu_name_z: [*:0]const u8) !*Stage2CpuFeatures {
- const cpu_name = mem.toSliceConst(u8, cpu_name_z);
- const target = try Target.parse(mem.toSliceConst(u8, zig_triple));
- const arch = target.Cross.arch;
- const cpu = arch.parseCpu(cpu_name) catch |err| switch (err) {
- error.UnknownCpu => {
- std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
- cpu_name,
- @tagName(arch),
- });
- for (arch.allCpus()) |cpu| {
- std.debug.warn(" {}\n", .{cpu.name});
- }
- process.exit(1);
- },
- else => |e| return e,
- };
- return Stage2CpuFeatures.createFromCpu(std.heap.c_allocator, arch, cpu);
-}
-
-// ABI warning
-export fn stage2_cpu_features_parse_features(
- result: **Stage2CpuFeatures,
- zig_triple: [*:0]const u8,
- features_text: [*:0]const u8,
-) Error {
- result.* = parseFeatures(zig_triple, features_text) catch |err| switch (err) {
- error.OutOfMemory => return .OutOfMemory,
+ error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
error.InvalidCpuFeatures => return .InvalidCpuFeatures,
- error.UnknownArchitecture => return .UnknownArchitecture,
- error.UnknownSubArchitecture => return .UnknownSubArchitecture,
- error.UnknownOperatingSystem => return .UnknownOperatingSystem,
- error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
- error.MissingOperatingSystem => return .MissingOperatingSystem,
- error.MissingArchitecture => return .MissingArchitecture,
};
return .None;
}
-fn parseFeatures(zig_triple: [*:0]const u8, features_text: [*:0]const u8) !*Stage2CpuFeatures {
- const target = try Target.parse(mem.toSliceConst(u8, zig_triple));
+fn stage2ParseCpuFeatures(
+ zig_triple_oz: ?[*:0]const u8,
+ cpu_name_oz: ?[*:0]const u8,
+ cpu_features_oz: ?[*:0]const u8,
+) !*Stage2CpuFeatures {
+ const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator);
+ const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z));
const arch = target.Cross.arch;
- const set = arch.parseCpuFeatureSet(mem.toSliceConst(u8, features_text)) catch |err| switch (err) {
- error.UnknownCpuFeature => {
- std.debug.warn("Unknown CPU features specified.\nAvailable CPU features for architecture '{}':\n", .{
- @tagName(arch),
- });
- for (arch.allFeaturesList()) |feature| {
- std.debug.warn(" {}\n", .{feature.name});
- }
- process.exit(1);
- },
- else => |e| return e,
- };
- return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, set);
-}
-// ABI warning
-export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures, zig_triple: [*:0]const u8) Error {
- result.* = cpuFeaturesBaseline(zig_triple) catch |err| switch (err) {
- error.OutOfMemory => return .OutOfMemory,
- error.UnknownArchitecture => return .UnknownArchitecture,
- error.UnknownSubArchitecture => return .UnknownSubArchitecture,
- error.UnknownOperatingSystem => return .UnknownOperatingSystem,
- error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
- error.MissingOperatingSystem => return .MissingOperatingSystem,
- error.MissingArchitecture => return .MissingArchitecture,
- };
- return .None;
-}
-
-fn cpuFeaturesBaseline(zig_triple: [*:0]const u8) !*Stage2CpuFeatures {
- const target = try Target.parse(mem.toSliceConst(u8, zig_triple));
- const arch = target.Cross.arch;
- return Stage2CpuFeatures.createBaseline(std.heap.c_allocator, arch);
-}
+ const cpu = if (cpu_name_oz) |cpu_name_z| blk: {
+ const cpu_name = mem.toSliceConst(u8, cpu_name_z);
+ break :blk arch.parseCpu(cpu_name) catch |err| switch (err) {
+ error.UnknownCpu => {
+ std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
+ cpu_name,
+ @tagName(arch),
+ });
+ for (arch.allCpus()) |cpu| {
+ std.debug.warn(" {}\n", .{cpu.name});
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
+ };
+ } else target.Cross.cpu_features.cpu;
+
+ var set = if (cpu_features_oz) |cpu_features_z| blk: {
+ const cpu_features = mem.toSliceConst(u8, cpu_features_z);
+ break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) {
+ error.UnknownCpuFeature => {
+ std.debug.warn(
+ \\Unknown CPU features specified.
+ \\Available CPU features for architecture '{}':
+ \\
+ , .{@tagName(arch)});
+ for (arch.allFeaturesList()) |feature| {
+ std.debug.warn(" {}\n", .{feature.name});
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
+ };
+ } else cpu.features;
-// ABI warning
-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,
-) Error {
- result.* = Stage2CpuFeatures.createFromLLVM(
- std.heap.c_allocator,
- zig_triple,
- llvm_cpu_name,
- llvm_cpu_features,
- ) catch |err| switch (err) {
- error.OutOfMemory => return .OutOfMemory,
- error.UnknownArchitecture => return .UnknownArchitecture,
- error.UnknownSubArchitecture => return .UnknownSubArchitecture,
- error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
- error.UnknownOperatingSystem => return .UnknownOperatingSystem,
- error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
- error.MissingOperatingSystem => return .MissingOperatingSystem,
- error.MissingArchitecture => return .MissingArchitecture,
- };
- return .None;
+ set.populateDependencies(arch.allFeaturesList());
+ return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{
+ .cpu = cpu,
+ .features = set,
+ });
}
// ABI warning
@@ -935,7 +819,7 @@ export fn stage2_cpu_features_get_builtin_str(
// ABI warning
export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
- return cpu_features.llvm_cpu_name;
+ return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null;
}
// ABI warning
test/compile_errors.zig
@@ -1,5 +1,6 @@
const tests = @import("tests.zig");
const builtin = @import("builtin");
+const Target = @import("std").Target;
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("non-exhaustive enums",
@@ -272,9 +273,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack",
});
- tc.target = tests.Target{
- .Cross = tests.CrossTarget{
+ tc.target = Target{
+ .Cross = .{
.arch = .wasm32,
+ .cpu_features = Target.Arch.wasm32.getBaselineCpuFeatures(),
.os = .wasi,
.abi = .none,
},
@@ -673,9 +675,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs",
});
- tc.target = tests.Target{
- .Cross = tests.CrossTarget{
+ tc.target = Target{
+ .Cross = .{
.arch = .x86_64,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.os = .linux,
.abi = .gnu,
},
test/tests.zig
@@ -38,236 +38,260 @@ const TestTarget = struct {
disable_native: bool = false,
};
-const test_targets = [_]TestTarget{
- TestTarget{},
- TestTarget{
- .link_libc = true,
- },
- TestTarget{
- .single_threaded = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .x86_64,
- .abi = .none,
+const test_targets = blk: {
+ // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
+ // (where N is roughly 160, which technically makes it O(1), but it adds up to a
+ // lot of branches)
+ @setEvalBranchQuota(50000);
+ break :blk [_]TestTarget{
+ TestTarget{},
+ TestTarget{
+ .link_libc = true,
+ },
+ TestTarget{
+ .single_threaded = true,
+ },
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .x86_64,
+ .abi = .none,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ },
},
},
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .x86_64,
- .abi = .gnu,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .x86_64,
+ .abi = .gnu,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .x86_64,
- .abi = .musl,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .x86_64,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ .abi = .musl,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .i386,
- .abi = .none,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .i386,
+ .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
+ .abi = .none,
+ },
},
},
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .i386,
- .abi = .musl,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .i386,
+ .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
+ .abi = .musl,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
- .abi = .none,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = Target.Arch{ .aarch64 = .v8_5a },
+ .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
+ .abi = .none,
+ },
},
},
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
- .abi = .musl,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = Target.Arch{ .aarch64 = .v8_5a },
+ .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
+ .abi = .musl,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
- .abi = .gnu,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = Target.Arch{ .aarch64 = .v8_5a },
+ .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
+ .abi = .gnu,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
- .abi = .none,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = Target.Arch{ .arm = .v8_5a },
+ .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
+ .abi = .none,
+ },
},
},
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
- .abi = .musleabihf,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = Target.Arch{ .arm = .v8_5a },
+ .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
+ .abi = .musleabihf,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
- // TODO https://github.com/ziglang/zig/issues/3287
- //TestTarget{
- // .target = Target{
- // .Cross = CrossTarget{
- // .os = .linux,
- // .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
- // .abi = .gnueabihf,
- // },
- // },
- // .link_libc = true,
- //},
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .mipsel,
- .abi = .none,
+ // TODO https://github.com/ziglang/zig/issues/3287
+ //TestTarget{
+ // .target = Target{
+ // .Cross = CrossTarget{
+ // .os = .linux,
+ // .arch = Target.Arch{ .arm = .v8_5a },
+ // .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
+ // .abi = .gnueabihf,
+ // },
+ // },
+ // .link_libc = true,
+ //},
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .mipsel,
+ .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
+ .abi = .none,
+ },
},
},
- },
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = .mipsel,
- .abi = .musl,
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .linux,
+ .arch = .mipsel,
+ .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
+ .abi = .musl,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .macosx,
- .arch = .x86_64,
- .abi = .gnu,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .macosx,
+ .arch = .x86_64,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ .abi = .gnu,
+ },
},
+ // TODO https://github.com/ziglang/zig/issues/3295
+ .disable_native = true,
},
- // TODO https://github.com/ziglang/zig/issues/3295
- .disable_native = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .windows,
- .arch = .i386,
- .abi = .msvc,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .windows,
+ .arch = .i386,
+ .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
+ .abi = .msvc,
+ },
},
},
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .windows,
- .arch = .x86_64,
- .abi = .msvc,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .windows,
+ .arch = .x86_64,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ .abi = .msvc,
+ },
},
},
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .windows,
- .arch = .i386,
- .abi = .gnu,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .windows,
+ .arch = .i386,
+ .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
+ .abi = .gnu,
+ },
},
+ .link_libc = true,
},
- .link_libc = true,
- },
-
- TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .windows,
- .arch = .x86_64,
- .abi = .gnu,
+
+ TestTarget{
+ .target = Target{
+ .Cross = CrossTarget{
+ .os = .windows,
+ .arch = .x86_64,
+ .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ .abi = .gnu,
+ },
},
+ .link_libc = true,
+ },
+
+ // Do the release tests last because they take a long time
+ TestTarget{
+ .mode = .ReleaseFast,
+ },
+ TestTarget{
+ .link_libc = true,
+ .mode = .ReleaseFast,
},
- .link_libc = true,
- },
-
- // Do the release tests last because they take a long time
- TestTarget{
- .mode = .ReleaseFast,
- },
- TestTarget{
- .link_libc = true,
- .mode = .ReleaseFast,
- },
- TestTarget{
- .mode = .ReleaseFast,
- .single_threaded = true,
- },
-
- TestTarget{
- .mode = .ReleaseSafe,
- },
- TestTarget{
- .link_libc = true,
- .mode = .ReleaseSafe,
- },
- TestTarget{
- .mode = .ReleaseSafe,
- .single_threaded = true,
- },
-
- TestTarget{
- .mode = .ReleaseSmall,
- },
- TestTarget{
- .link_libc = true,
- .mode = .ReleaseSmall,
- },
- TestTarget{
- .mode = .ReleaseSmall,
- .single_threaded = true,
- },
+ TestTarget{
+ .mode = .ReleaseFast,
+ .single_threaded = true,
+ },
+
+ TestTarget{
+ .mode = .ReleaseSafe,
+ },
+ TestTarget{
+ .link_libc = true,
+ .mode = .ReleaseSafe,
+ },
+ TestTarget{
+ .mode = .ReleaseSafe,
+ .single_threaded = true,
+ },
+
+ TestTarget{
+ .mode = .ReleaseSmall,
+ },
+ TestTarget{
+ .link_libc = true,
+ .mode = .ReleaseSmall,
+ },
+ TestTarget{
+ .mode = .ReleaseSmall,
+ .single_threaded = true,
+ },
+ };
};
const max_stdout_size = 1 * 1024 * 1024; // 1 MB
test/translate_c.zig
@@ -1,5 +1,6 @@
const tests = @import("tests.zig");
const builtin = @import("builtin");
+const Target = @import("std").Target;
pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("empty declaration",
@@ -1005,7 +1006,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
- .Cross = .{ .os = .linux, .arch = .i386, .abi = .none },
+ .Cross = .{
+ .os = .linux,
+ .arch = .i386,
+ .abi = .none,
+ .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
+ },
},
\\void __attribute__((fastcall)) foo1(float *a);
\\void __attribute__((stdcall)) foo2(float *a);
@@ -1021,7 +1027,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
- .Cross = .{ .os = .linux, .arch = .{ .arm = .v8_5a }, .abi = .none },
+ .Cross = .{
+ .os = .linux,
+ .arch = .{ .arm = .v8_5a },
+ .abi = .none,
+ .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
+ },
},
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
@@ -1031,7 +1042,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
- .Cross = .{ .os = .linux, .arch = .{ .aarch64 = .v8_5a }, .abi = .none },
+ .Cross = .{
+ .os = .linux,
+ .arch = .{ .aarch64 = .v8_5a },
+ .abi = .none,
+ .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
+ },
},
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
, &[_][]const u8{