progress towards merging
see BRANCH_TODO file
This commit is contained in:
parent
c15623428e
commit
a867b43366
55
BRANCH_TODO
Normal file
55
BRANCH_TODO
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
Finish these thigns before merging teh branch
|
||||||
|
|
||||||
|
* need to populate builtin.zig cpu_features, undefined is incorrect. I guess for zig0 it will be always baseline
|
||||||
|
* need to populate std.Target.current.cpu_features even for native target
|
||||||
|
|
||||||
|
* finish refactoring target/arch/*
|
||||||
|
* `zig builtin` integration
|
||||||
|
* move target details to better location
|
||||||
|
* +foo,-bar vs foo,bar
|
||||||
|
* baseline features
|
||||||
|
|
||||||
|
|
||||||
|
const riscv32_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 riscv64_default_features: []*const std.target.Feature = &[_]*const std.target.Feature{
|
||||||
|
&std.target.riscv.feature_bit64,
|
||||||
|
&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,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -57,11 +57,11 @@ pub const Buffer = struct {
|
|||||||
|
|
||||||
/// The caller owns the returned memory. The Buffer becomes null and
|
/// The caller owns the returned memory. The Buffer becomes null and
|
||||||
/// is safe to `deinit`.
|
/// is safe to `deinit`.
|
||||||
pub fn toOwnedSlice(self: *Buffer) []u8 {
|
pub fn toOwnedSlice(self: *Buffer) [:0]u8 {
|
||||||
const allocator = self.list.allocator;
|
const allocator = self.list.allocator;
|
||||||
const result = allocator.shrink(self.list.items, self.len());
|
const result = allocator.shrink(self.list.items, self.len());
|
||||||
self.* = initNull(allocator);
|
self.* = initNull(allocator);
|
||||||
return result;
|
return result[0 .. result.len - 1 :0];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
|
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
|
||||||
|
@ -1199,8 +1199,6 @@ pub const LibExeObjStep = struct {
|
|||||||
|
|
||||||
subsystem: ?builtin.SubSystem = null,
|
subsystem: ?builtin.SubSystem = null,
|
||||||
|
|
||||||
target_details: ?std.target.TargetDetails = null,
|
|
||||||
|
|
||||||
const LinkObject = union(enum) {
|
const LinkObject = union(enum) {
|
||||||
StaticPath: []const u8,
|
StaticPath: []const u8,
|
||||||
OtherStep: *LibExeObjStep,
|
OtherStep: *LibExeObjStep,
|
||||||
@ -1386,10 +1384,6 @@ pub const LibExeObjStep = struct {
|
|||||||
self.computeOutFileNames();
|
self.computeOutFileNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTargetDetails(self: *LibExeObjStep, target_details: std.target.TargetDetails) void {
|
|
||||||
self.target_details = target_details;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setTargetGLibC(self: *LibExeObjStep, major: u32, minor: u32, patch: u32) void {
|
pub fn setTargetGLibC(self: *LibExeObjStep, major: u32, minor: u32, patch: u32) void {
|
||||||
self.target_glibc = Version{
|
self.target_glibc = Version{
|
||||||
.major = major,
|
.major = major,
|
||||||
@ -1974,34 +1968,33 @@ pub const LibExeObjStep = struct {
|
|||||||
|
|
||||||
switch (self.target) {
|
switch (self.target) {
|
||||||
.Native => {},
|
.Native => {},
|
||||||
.Cross => {
|
.Cross => |cross| {
|
||||||
try zig_args.append("-target");
|
try zig_args.append("-target");
|
||||||
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
|
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
|
||||||
|
|
||||||
|
switch (cross.cpu_features) {
|
||||||
|
.baseline => {},
|
||||||
|
.cpu => |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 (Target.Cpu.Feature.isEnabled(features, @intCast(u7, i))) {
|
||||||
|
try feature_str_buffer.append(feature.name);
|
||||||
|
try feature_str_buffer.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try zig_args.append(feature_str_buffer.toSlice());
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.target_details) |td| {
|
|
||||||
switch (td) {
|
|
||||||
.cpu => |cpu| {
|
|
||||||
try zig_args.append("--cpu");
|
|
||||||
try zig_args.append(cpu.name);
|
|
||||||
},
|
|
||||||
.features => |features| {
|
|
||||||
try zig_args.append("--features");
|
|
||||||
|
|
||||||
var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0);
|
|
||||||
defer feature_str_buffer.deinit();
|
|
||||||
|
|
||||||
for (features) |feature| {
|
|
||||||
try feature_str_buffer.append(feature.name);
|
|
||||||
try feature_str_buffer.append(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
try zig_args.append(feature_str_buffer.toOwnedSlice());
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.target_glibc) |ver| {
|
if (self.target_glibc) |ver| {
|
||||||
try zig_args.append("-target-glibc");
|
try zig_args.append("-target-glibc");
|
||||||
try zig_args.append(builder.fmt("{}.{}.{}", .{ ver.major, ver.minor, ver.patch }));
|
try zig_args.append(builder.fmt("{}.{}.{}", .{ ver.major, ver.minor, ver.patch }));
|
||||||
|
@ -15,6 +15,12 @@ pub const ObjectFormat = std.Target.ObjectFormat;
|
|||||||
/// Deprecated: use `std.Target.SubSystem`.
|
/// Deprecated: use `std.Target.SubSystem`.
|
||||||
pub const SubSystem = std.Target.SubSystem;
|
pub const SubSystem = std.Target.SubSystem;
|
||||||
|
|
||||||
|
/// Deprecated: use `std.Target.Cross.CpuFeatures`.
|
||||||
|
pub const CpuFeatures = std.Target.Cross.CpuFeatures;
|
||||||
|
|
||||||
|
/// Deprecated: use `std.Target.Cpu`.
|
||||||
|
pub const Cpu = std.Target.Cpu;
|
||||||
|
|
||||||
/// `explicit_subsystem` is missing when the subsystem is automatically detected,
|
/// `explicit_subsystem` is missing when the subsystem is automatically detected,
|
||||||
/// so Zig standard library has the subsystem detection logic here. This should generally be
|
/// so Zig standard library has the subsystem detection logic here. This should generally be
|
||||||
/// used rather than `explicit_subsystem`.
|
/// used rather than `explicit_subsystem`.
|
||||||
|
@ -1138,6 +1138,11 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
|
|||||||
size.* += bytes.len;
|
size.* += bytes.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
|
||||||
|
const result = try allocPrint(allocator, fmt ++ "\x00", args);
|
||||||
|
return result[0 .. result.len - 1 :0];
|
||||||
|
}
|
||||||
|
|
||||||
test "bufPrintInt" {
|
test "bufPrintInt" {
|
||||||
var buffer: [100]u8 = undefined;
|
var buffer: [100]u8 = undefined;
|
||||||
const buf = buffer[0..];
|
const buf = buffer[0..];
|
||||||
|
@ -556,3 +556,21 @@ pub fn refAllDecls(comptime T: type) void {
|
|||||||
if (!builtin.is_test) return;
|
if (!builtin.is_test) return;
|
||||||
_ = declarations(T);
|
_ = declarations(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a slice of pointers to public declarations of a namespace.
|
||||||
|
pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const Decl {
|
||||||
|
const S = struct {
|
||||||
|
fn declNameLessThan(lhs: *const Decl, rhs: *const Decl) bool {
|
||||||
|
return mem.lessThan(u8, lhs.name, rhs.name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
comptime {
|
||||||
|
const decls = declarations(Namespace);
|
||||||
|
var array: [decls.len]*const Decl = undefined;
|
||||||
|
for (decls) |decl, i| {
|
||||||
|
array[i] = &@field(Namespace, decl.name);
|
||||||
|
}
|
||||||
|
std.sort.sort(*const Decl, &array, S.declNameLessThan);
|
||||||
|
return &array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -211,7 +211,7 @@ pub fn initTLS() ?*elf.Phdr {
|
|||||||
|
|
||||||
if (tls_phdr) |phdr| {
|
if (tls_phdr) |phdr| {
|
||||||
// If the cpu is arm-based, check if it supports the TLS register
|
// If the cpu is arm-based, check if it supports the TLS register
|
||||||
if (builtin.arch == builtin.Arch.arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) {
|
if (builtin.arch == .arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) {
|
||||||
// If the CPU does not support TLS via a coprocessor register,
|
// If the CPU does not support TLS via a coprocessor register,
|
||||||
// a kernel helper function can be used instead on certain linux kernels.
|
// a kernel helper function can be used instead on certain linux kernels.
|
||||||
// See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c.
|
// See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c.
|
||||||
|
@ -60,7 +60,6 @@ pub const rand = @import("rand.zig");
|
|||||||
pub const rb = @import("rb.zig");
|
pub const rb = @import("rb.zig");
|
||||||
pub const sort = @import("sort.zig");
|
pub const sort = @import("sort.zig");
|
||||||
pub const ascii = @import("ascii.zig");
|
pub const ascii = @import("ascii.zig");
|
||||||
pub const target = @import("target.zig");
|
|
||||||
pub const testing = @import("testing.zig");
|
pub const testing = @import("testing.zig");
|
||||||
pub const time = @import("time.zig");
|
pub const time = @import("time.zig");
|
||||||
pub const unicode = @import("unicode.zig");
|
pub const unicode = @import("unicode.zig");
|
||||||
|
@ -101,6 +101,22 @@ pub const Target = union(enum) {
|
|||||||
renderscript32,
|
renderscript32,
|
||||||
renderscript64,
|
renderscript64,
|
||||||
|
|
||||||
|
pub const aarch64 = @import("target/aarch64.zig");
|
||||||
|
pub const amdgpu = @import("target/amdgpu.zig");
|
||||||
|
pub const arm = @import("target/arm.zig");
|
||||||
|
pub const avr = @import("target/avr.zig");
|
||||||
|
pub const bpf = @import("target/bpf.zig");
|
||||||
|
pub const hexagon = @import("target/hexagon.zig");
|
||||||
|
pub const mips = @import("target/mips.zig");
|
||||||
|
pub const msp430 = @import("target/msp430.zig");
|
||||||
|
pub const nvptx = @import("target/nvptx.zig");
|
||||||
|
pub const powerpc = @import("target/powerpc.zig");
|
||||||
|
pub const riscv = @import("target/riscv.zig");
|
||||||
|
pub const sparc = @import("target/sparc.zig");
|
||||||
|
pub const systemz = @import("target/systemz.zig");
|
||||||
|
pub const wasm = @import("target/wasm.zig");
|
||||||
|
pub const x86 = @import("target/x86.zig");
|
||||||
|
|
||||||
pub const Arm32 = enum {
|
pub const Arm32 = enum {
|
||||||
v8_5a,
|
v8_5a,
|
||||||
v8_4a,
|
v8_4a,
|
||||||
@ -184,6 +200,71 @@ pub const Target = union(enum) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parseCpu(arch: Arch, cpu_name: []const u8) !*const Cpu {
|
||||||
|
for (arch.allCpus()) |cpu| {
|
||||||
|
if (mem.eql(u8, cpu_name, cpu.name)) {
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
/// 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 set: @Vector(2, Cpu.Feature.Set) = [2]Cpu.Feature.Set{ 0, arch.baselineFeatures() };
|
||||||
|
var mode: enum {
|
||||||
|
unknown,
|
||||||
|
baseline,
|
||||||
|
whitelist,
|
||||||
|
} = .unknown;
|
||||||
|
|
||||||
|
var it = mem.tokenize(features_text, ",");
|
||||||
|
while (it.next()) |item_text| {
|
||||||
|
const feature_name = blk: {
|
||||||
|
if (mem.startsWith(u8, item_text, "+")) {
|
||||||
|
switch (mode) {
|
||||||
|
.unknown, .baseline => mode = .baseline,
|
||||||
|
.whitelist => return error.InvalidCpuFeatures,
|
||||||
|
}
|
||||||
|
break :blk item_text[1..];
|
||||||
|
} else if (mem.startsWith(u8, item_text, "-")) {
|
||||||
|
switch (mode) {
|
||||||
|
.unknown, .baseline => mode = .baseline,
|
||||||
|
.whitelist => return error.InvalidCpuFeatures,
|
||||||
|
}
|
||||||
|
break :blk item_text[1..];
|
||||||
|
} else {
|
||||||
|
switch (mode) {
|
||||||
|
.unknown, .whitelist => mode = .whitelist,
|
||||||
|
.baseline => return error.InvalidCpuFeatures,
|
||||||
|
}
|
||||||
|
break :blk item_text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (arch.allFeaturesList()) |feature, index| {
|
||||||
|
if (mem.eql(u8, feature_name, feature.name)) {
|
||||||
|
set |= @splat(2, 1 << index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return error.UnknownCpuFeature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (mode) {
|
||||||
|
.unknown, .whitelist => set[0],
|
||||||
|
.baseline => set[1],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toElfMachine(arch: Arch) std.elf.EM {
|
pub fn toElfMachine(arch: Arch) std.elf.EM {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
.avr => ._AVR,
|
.avr => ._AVR,
|
||||||
@ -296,6 +377,98 @@ pub const Target = union(enum) {
|
|||||||
=> .Big,
|
=> .Big,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a name that matches the lib/std/target/* directory name.
|
||||||
|
pub fn genericName(arch: Arch) []const u8 {
|
||||||
|
return switch (arch) {
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => "arm",
|
||||||
|
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
|
||||||
|
.avr => "avr",
|
||||||
|
.bpfel, .bpfeb => "bpf",
|
||||||
|
.hexagon => "hexagon",
|
||||||
|
.mips, .mipsel, .mips64, .mips64el => "mips",
|
||||||
|
.msp430 => "msp430",
|
||||||
|
.powerpc, .powerpc64, .powerpc64le => "powerpc",
|
||||||
|
.amdgcn => "amdgpu",
|
||||||
|
.riscv32, .riscv64 => "riscv",
|
||||||
|
.sparc, .sparcv9, .sparcel => "sparc",
|
||||||
|
.s390x => "systemz",
|
||||||
|
.i386, .x86_64 => "x86",
|
||||||
|
.nvptx, .nvptx64 => "nvptx",
|
||||||
|
.wasm32, .wasm64 => "wasm",
|
||||||
|
else => @tagName(arch),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All CPU features Zig is aware of, sorted lexicographically by name.
|
||||||
|
pub fn allFeaturesList(arch: Arch) []const *const Cpu.Feature {
|
||||||
|
return switch (arch) {
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => arm.all_features,
|
||||||
|
.aarch64, .aarch64_be, .aarch64_32 => aarch64.all_features,
|
||||||
|
.avr => avr.all_features,
|
||||||
|
.bpfel, .bpfeb => bpf.all_features,
|
||||||
|
.hexagon => hexagon.all_features,
|
||||||
|
.mips, .mipsel, .mips64, .mips64el => mips.all_features,
|
||||||
|
.msp430 => msp430.all_features,
|
||||||
|
.powerpc, .powerpc64, .powerpc64le => powerpc.all_features,
|
||||||
|
.amdgcn => amdgpu.all_features,
|
||||||
|
.riscv32, .riscv64 => riscv.all_features,
|
||||||
|
.sparc, .sparcv9, .sparcel => sparc.all_features,
|
||||||
|
.s390x => systemz.all_features,
|
||||||
|
.i386, .x86_64 => x86.all_features,
|
||||||
|
.nvptx, .nvptx64 => nvptx.all_features,
|
||||||
|
.wasm32, .wasm64 => wasm.all_features,
|
||||||
|
|
||||||
|
else => &[0]*const Cpu.Feature{},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.baseline_features,
|
||||||
|
.aarch64, .aarch64_be, .aarch64_32 => aarch64.cpu.generic.features,
|
||||||
|
.avr => avr.baseline_features,
|
||||||
|
.bpfel, .bpfeb => bpf.baseline_features,
|
||||||
|
.hexagon => hexagon.baseline_features,
|
||||||
|
.mips, .mipsel, .mips64, .mips64el => mips.baseline_features,
|
||||||
|
.msp430 => msp430.baseline_features,
|
||||||
|
.powerpc, .powerpc64, .powerpc64le => powerpc.baseline_features,
|
||||||
|
.amdgcn => amdgpu.baseline_features,
|
||||||
|
.riscv32, .riscv64 => riscv.baseline_features,
|
||||||
|
.sparc, .sparcv9, .sparcel => sparc.baseline_features,
|
||||||
|
.s390x => systemz.baseline_features,
|
||||||
|
.i386, .x86_64 => x86.baseline_features,
|
||||||
|
.nvptx, .nvptx64 => nvptx.baseline_features,
|
||||||
|
.wasm32, .wasm64 => wasm.baseline_features,
|
||||||
|
|
||||||
|
else => &[0]*const Cpu.Feature{},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All CPUs Zig is aware of, sorted lexicographically by name.
|
||||||
|
pub fn allCpus(arch: Arch) []const *const Cpu {
|
||||||
|
return switch (arch) {
|
||||||
|
.arm, .armeb, .thumb, .thumbeb => arm.all_cpus,
|
||||||
|
.aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus,
|
||||||
|
.avr => avr.all_cpus,
|
||||||
|
.bpfel, .bpfeb => bpf.all_cpus,
|
||||||
|
.hexagon => hexagon.all_cpus,
|
||||||
|
.mips, .mipsel, .mips64, .mips64el => mips.all_cpus,
|
||||||
|
.msp430 => msp430.all_cpus,
|
||||||
|
.powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus,
|
||||||
|
.amdgcn => amdgpu.all_cpus,
|
||||||
|
.riscv32, .riscv64 => riscv.all_cpus,
|
||||||
|
.sparc, .sparcv9, .sparcel => sparc.all_cpus,
|
||||||
|
.s390x => systemz.all_cpus,
|
||||||
|
.i386, .x86_64 => x86.all_cpus,
|
||||||
|
.nvptx, .nvptx64 => nvptx.all_cpus,
|
||||||
|
.wasm32, .wasm64 => wasm.all_cpus,
|
||||||
|
|
||||||
|
else => &[0]*const Cpu{},
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Abi = enum {
|
pub const Abi = enum {
|
||||||
@ -323,6 +496,28 @@ pub const Target = union(enum) {
|
|||||||
macabi,
|
macabi,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Cpu = struct {
|
||||||
|
name: []const u8,
|
||||||
|
llvm_name: ?[:0]const u8,
|
||||||
|
features: Feature.Set,
|
||||||
|
|
||||||
|
pub const Feature = struct {
|
||||||
|
/// The bit index into `Set`.
|
||||||
|
index: u8,
|
||||||
|
name: []const u8,
|
||||||
|
llvm_name: ?[:0]const u8,
|
||||||
|
description: []const u8,
|
||||||
|
dependencies: Set,
|
||||||
|
|
||||||
|
/// A bit set of all the features.
|
||||||
|
pub const Set = u128;
|
||||||
|
|
||||||
|
pub fn isEnabled(set: Set, arch_feature_index: u7) bool {
|
||||||
|
return (set & (@as(Set, 1) << arch_feature_index)) != 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub const ObjectFormat = enum {
|
pub const ObjectFormat = enum {
|
||||||
unknown,
|
unknown,
|
||||||
coff,
|
coff,
|
||||||
@ -346,6 +541,19 @@ pub const Target = union(enum) {
|
|||||||
arch: Arch,
|
arch: Arch,
|
||||||
os: Os,
|
os: Os,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
|
cpu_features: CpuFeatures = .baseline,
|
||||||
|
|
||||||
|
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.
|
||||||
|
cpu: *const Cpu,
|
||||||
|
|
||||||
|
/// Explicitly provide the entire CPU feature set.
|
||||||
|
features: Cpu.Feature.Set,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const current = Target{
|
pub const current = Target{
|
||||||
@ -353,11 +561,20 @@ pub const Target = union(enum) {
|
|||||||
.arch = builtin.arch,
|
.arch = builtin.arch,
|
||||||
.os = builtin.os,
|
.os = builtin.os,
|
||||||
.abi = builtin.abi,
|
.abi = builtin.abi,
|
||||||
|
.cpu_features = builtin.cpu_features,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const stack_align = 16;
|
pub const stack_align = 16;
|
||||||
|
|
||||||
|
pub fn cpuFeatures(self: Target) []const *const Cpu.Feature {
|
||||||
|
return switch (self.cpu_features) {
|
||||||
|
.baseline => self.arch.baselineFeatures(),
|
||||||
|
.cpu => |cpu| cpu.features,
|
||||||
|
.features => |features| features,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
|
pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
|
||||||
return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{
|
return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{
|
||||||
@tagName(self.getArch()),
|
@tagName(self.getArch()),
|
||||||
@ -496,7 +713,7 @@ pub const Target = union(enum) {
|
|||||||
pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch {
|
pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch {
|
||||||
const info = @typeInfo(Arch);
|
const info = @typeInfo(Arch);
|
||||||
inline for (info.Union.fields) |field| {
|
inline for (info.Union.fields) |field| {
|
||||||
if (text.len >= field.name.len and mem.eql(u8, text[0..field.name.len], field.name)) {
|
if (mem.eql(u8, text, field.name)) {
|
||||||
if (field.field_type == void) {
|
if (field.field_type == void) {
|
||||||
return @as(Arch, @field(Arch, field.name));
|
return @as(Arch, @field(Arch, field.name));
|
||||||
} else {
|
} else {
|
||||||
@ -514,31 +731,6 @@ pub const Target = union(enum) {
|
|||||||
return error.UnknownArchitecture;
|
return error.UnknownArchitecture;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parseArchTag(text: []const u8) ParseArchSubError!@TagType(Arch) {
|
|
||||||
const info = @typeInfo(Arch);
|
|
||||||
inline for (info.Union.fields) |field| {
|
|
||||||
if (text.len >= field.name.len and mem.eql(u8, text[0..field.name.len], field.name)) {
|
|
||||||
if (text.len == field.name.len) return @as(@TagType(Arch), @field(Arch, field.name));
|
|
||||||
|
|
||||||
if (field.field_type == void) {
|
|
||||||
return error.UnknownArchitecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sub_info = @typeInfo(field.field_type);
|
|
||||||
inline for (sub_info.Enum.fields) |sub_field| {
|
|
||||||
const combined = field.name ++ sub_field.name;
|
|
||||||
if (mem.eql(u8, text, combined)) {
|
|
||||||
return @as(@TagType(Arch), @field(Arch, field.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.UnknownSubArchitecture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.UnknownArchitecture;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parseOs(text: []const u8) !Os {
|
pub fn parseOs(text: []const u8) !Os {
|
||||||
const info = @typeInfo(Os);
|
const info = @typeInfo(Os);
|
||||||
inline for (info.Enum.fields) |field| {
|
inline for (info.Enum.fields) |field| {
|
||||||
@ -841,83 +1033,3 @@ pub const Target = union(enum) {
|
|||||||
return .unavailable;
|
return .unavailable;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const aarch64 = @import("target/aarch64.zig");
|
|
||||||
pub const amdgpu = @import("target/amdgpu.zig");
|
|
||||||
pub const arm = @import("target/arm.zig");
|
|
||||||
pub const avr = @import("target/avr.zig");
|
|
||||||
pub const bpf = @import("target/bpf.zig");
|
|
||||||
pub const hexagon = @import("target/hexagon.zig");
|
|
||||||
pub const mips = @import("target/mips.zig");
|
|
||||||
pub const msp430 = @import("target/msp430.zig");
|
|
||||||
pub const nvptx = @import("target/nvptx.zig");
|
|
||||||
pub const powerpc = @import("target/powerpc.zig");
|
|
||||||
pub const riscv = @import("target/riscv.zig");
|
|
||||||
pub const sparc = @import("target/sparc.zig");
|
|
||||||
pub const systemz = @import("target/systemz.zig");
|
|
||||||
pub const wasm = @import("target/wasm.zig");
|
|
||||||
pub const x86 = @import("target/x86.zig");
|
|
||||||
|
|
||||||
pub const Feature = struct {
|
|
||||||
name: []const u8,
|
|
||||||
llvm_name: ?[]const u8,
|
|
||||||
description: []const u8,
|
|
||||||
|
|
||||||
dependencies: []*const Feature,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Cpu = struct {
|
|
||||||
name: []const u8,
|
|
||||||
llvm_name: ?[]const u8,
|
|
||||||
|
|
||||||
dependencies: []*const Feature,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const TargetDetails = union(enum) {
|
|
||||||
cpu: *const Cpu,
|
|
||||||
features: []*const Feature,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn getFeaturesForArch(arch: @TagType(Target.Arch)) []*const Feature {
|
|
||||||
return switch (arch) {
|
|
||||||
.arm, .armeb, .thumb, .thumbeb => arm.features,
|
|
||||||
.aarch64, .aarch64_be, .aarch64_32 => aarch64.features,
|
|
||||||
.avr => avr.features,
|
|
||||||
.bpfel, .bpfeb => bpf.features,
|
|
||||||
.hexagon => hexagon.features,
|
|
||||||
.mips, .mipsel, .mips64, .mips64el => mips.features,
|
|
||||||
.msp430 => msp430.features,
|
|
||||||
.powerpc, .powerpc64, .powerpc64le => powerpc.features,
|
|
||||||
.amdgcn => amdgpu.features,
|
|
||||||
.riscv32, .riscv64 => riscv.features,
|
|
||||||
.sparc, .sparcv9, .sparcel => sparc.features,
|
|
||||||
.s390x => systemz.features,
|
|
||||||
.i386, .x86_64 => x86.features,
|
|
||||||
.nvptx, .nvptx64 => nvptx.features,
|
|
||||||
.wasm32, .wasm64 => wasm.features,
|
|
||||||
|
|
||||||
else => &[_]*const Feature{},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getCpusForArch(arch: @TagType(Target.Arch)) []*const Cpu {
|
|
||||||
return switch (arch) {
|
|
||||||
.arm, .armeb, .thumb, .thumbeb => arm.cpus,
|
|
||||||
.aarch64, .aarch64_be, .aarch64_32 => aarch64.cpus,
|
|
||||||
.avr => avr.cpus,
|
|
||||||
.bpfel, .bpfeb => bpf.cpus,
|
|
||||||
.hexagon => hexagon.cpus,
|
|
||||||
.mips, .mipsel, .mips64, .mips64el => mips.cpus,
|
|
||||||
.msp430 => msp430.cpus,
|
|
||||||
.powerpc, .powerpc64, .powerpc64le => powerpc.cpus,
|
|
||||||
.amdgcn => amdgpu.cpus,
|
|
||||||
.riscv32, .riscv64 => riscv.cpus,
|
|
||||||
.sparc, .sparcv9, .sparcel => sparc.cpus,
|
|
||||||
.s390x => systemz.cpus,
|
|
||||||
.i386, .x86_64 => x86.cpus,
|
|
||||||
.nvptx, .nvptx64 => nvptx.cpus,
|
|
||||||
.wasm32, .wasm64 => wasm.cpus,
|
|
||||||
|
|
||||||
else => &[_]*const Cpu{},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,9 @@ const Error = extern enum {
|
|||||||
OperationAborted,
|
OperationAborted,
|
||||||
BrokenPipe,
|
BrokenPipe,
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
|
NotLazy,
|
||||||
|
IsAsync,
|
||||||
|
ImportOutsidePkgPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FILE = std.c.FILE;
|
const FILE = std.c.FILE;
|
||||||
@ -150,7 +153,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
|
|||||||
const argc_usize = @intCast(usize, argc);
|
const argc_usize = @intCast(usize, argc);
|
||||||
var arg_i: usize = 0;
|
var arg_i: usize = 0;
|
||||||
while (arg_i < argc_usize) : (arg_i += 1) {
|
while (arg_i < argc_usize) : (arg_i += 1) {
|
||||||
try args_list.append(std.mem.toSliceConst(u8, argv[arg_i]));
|
try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout = &std.io.getStdOut().outStream().stream;
|
stdout = &std.io.getStdOut().outStream().stream;
|
||||||
@ -532,7 +535,7 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
|
|||||||
// ABI warning
|
// ABI warning
|
||||||
export fn stage2_list_features_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_dependencies: bool) void {
|
export fn stage2_list_features_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_dependencies: bool) void {
|
||||||
printFeaturesForArch(arch_name_ptr[0..arch_name_len], show_dependencies) catch |err| {
|
printFeaturesForArch(arch_name_ptr[0..arch_name_len], show_dependencies) catch |err| {
|
||||||
std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) });
|
std.debug.warn("Failed to list features: {}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,11 +543,11 @@ fn printFeaturesForArch(arch_name: []const u8, show_dependencies: bool) !void {
|
|||||||
const stdout_stream = &std.io.getStdOut().outStream().stream;
|
const stdout_stream = &std.io.getStdOut().outStream().stream;
|
||||||
|
|
||||||
const arch = Target.parseArchTag(arch_name) catch {
|
const arch = Target.parseArchTag(arch_name) catch {
|
||||||
std.debug.warn("Failed to parse arch '{}'\nInvoke 'zig targets' for a list of valid architectures\n", .{ arch_name });
|
std.debug.warn("Failed to parse arch '{}'\nInvoke 'zig targets' for a list of valid architectures\n", .{arch_name});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
try stdout_stream.print("Available features for {}:\n", .{ @tagName(arch) });
|
try stdout_stream.print("Available features for {}:\n", .{@tagName(arch)});
|
||||||
|
|
||||||
const features = std.target.getFeaturesForArch(arch);
|
const features = std.target.getFeaturesForArch(arch);
|
||||||
|
|
||||||
@ -556,18 +559,18 @@ fn printFeaturesForArch(arch_name: []const u8, show_dependencies: bool) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (features) |feature| {
|
for (features) |feature| {
|
||||||
try stdout_stream.print(" {}", .{ feature.name });
|
try stdout_stream.print(" {}", .{feature.name});
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < longest_len - feature.name.len) : (i += 1) {
|
while (i < longest_len - feature.name.len) : (i += 1) {
|
||||||
try stdout_stream.write(" ");
|
try stdout_stream.write(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
try stdout_stream.print(" - {}\n", .{ feature.description });
|
try stdout_stream.print(" - {}\n", .{feature.description});
|
||||||
|
|
||||||
if (show_dependencies and feature.dependencies.len > 0) {
|
if (show_dependencies and feature.dependencies.len > 0) {
|
||||||
for (feature.dependencies) |dependency| {
|
for (feature.dependencies) |dependency| {
|
||||||
try stdout_stream.print(" {}\n", .{ dependency.name });
|
try stdout_stream.print(" {}\n", .{dependency.name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,7 +579,7 @@ fn printFeaturesForArch(arch_name: []const u8, show_dependencies: bool) !void {
|
|||||||
// ABI warning
|
// ABI warning
|
||||||
export fn stage2_list_cpus_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_dependencies: bool) void {
|
export fn stage2_list_cpus_for_arch(arch_name_ptr: [*]const u8, arch_name_len: usize, show_dependencies: bool) void {
|
||||||
printCpusForArch(arch_name_ptr[0..arch_name_len], show_dependencies) catch |err| {
|
printCpusForArch(arch_name_ptr[0..arch_name_len], show_dependencies) catch |err| {
|
||||||
std.debug.warn("Failed to list features: {}\n", .{ @errorName(err) });
|
std.debug.warn("Failed to list features: {}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,13 +587,13 @@ fn printCpusForArch(arch_name: []const u8, show_dependencies: bool) !void {
|
|||||||
const stdout_stream = &std.io.getStdOut().outStream().stream;
|
const stdout_stream = &std.io.getStdOut().outStream().stream;
|
||||||
|
|
||||||
const arch = Target.parseArchTag(arch_name) catch {
|
const arch = Target.parseArchTag(arch_name) catch {
|
||||||
std.debug.warn("Failed to parse arch '{}'\nInvoke 'zig targets' for a list of valid architectures\n", .{ arch_name });
|
std.debug.warn("Failed to parse arch '{}'\nInvoke 'zig targets' for a list of valid architectures\n", .{arch_name});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const cpus = std.target.getCpusForArch(arch);
|
const cpus = std.target.getCpusForArch(arch);
|
||||||
|
|
||||||
try stdout_stream.print("Available cpus for {}:\n", .{ @tagName(arch) });
|
try stdout_stream.print("Available cpus for {}:\n", .{@tagName(arch)});
|
||||||
|
|
||||||
var longest_len: usize = 0;
|
var longest_len: usize = 0;
|
||||||
for (cpus) |cpu| {
|
for (cpus) |cpu| {
|
||||||
@ -600,78 +603,97 @@ fn printCpusForArch(arch_name: []const u8, show_dependencies: bool) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (cpus) |cpu| {
|
for (cpus) |cpu| {
|
||||||
try stdout_stream.print(" {}", .{ cpu.name });
|
try stdout_stream.print(" {}", .{cpu.name});
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < longest_len - cpu.name.len) : (i += 1) {
|
while (i < longest_len - cpu.name.len) : (i += 1) {
|
||||||
try stdout_stream.write(" ");
|
try stdout_stream.write(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
try stdout_stream.write("\n");
|
try stdout_stream.write("\n");
|
||||||
|
|
||||||
if (show_dependencies and cpu.dependencies.len > 0) {
|
if (show_dependencies and cpu.dependencies.len > 0) {
|
||||||
for (cpu.dependencies) |dependency| {
|
for (cpu.dependencies) |dependency| {
|
||||||
try stdout_stream.print(" {}\n", .{ dependency.name });
|
try stdout_stream.print(" {}\n", .{dependency.name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const null_terminated_empty_string = (&[_]u8 { 0 })[0..0 :0];
|
const Stage2CpuFeatures = struct {
|
||||||
|
allocator: *mem.Allocator,
|
||||||
|
cpu_features: Target.CpuFeatures,
|
||||||
|
|
||||||
fn toNullTerminatedStringAlloc(allocator: *std.mem.Allocator, str: []const u8) ![:0]const u8 {
|
llvm_cpu_name: ?[:0]const u8,
|
||||||
var buffer = try std.Buffer.init(allocator, str);
|
llvm_features_str: ?[:0]const u8,
|
||||||
|
|
||||||
const len = buffer.len();
|
|
||||||
|
|
||||||
// Don't deinit since we steal all the buffer's memory here.
|
|
||||||
return buffer.list.toOwnedSlice()[0..len :0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Stage2TargetDetails = struct {
|
|
||||||
allocator: *std.mem.Allocator,
|
|
||||||
target_details: std.target.TargetDetails,
|
|
||||||
|
|
||||||
llvm_cpu_str: [:0]const u8,
|
|
||||||
llvm_features_str: [:0]const u8,
|
|
||||||
|
|
||||||
builtin_str: [:0]const u8,
|
builtin_str: [:0]const u8,
|
||||||
|
cache_hash: [:0]const u8,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
fn initCpu(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), cpu: *const std.target.Cpu) !Self {
|
fn initBaseline(allocator: *mem.Allocator) !Self {
|
||||||
var builtin_str_buffer = try std.Buffer.init(
|
const builtin_str = try std.fmt.allocPrint0(allocator, "CpuFeatures.baseline;\n");
|
||||||
allocator,
|
errdefer allocator.free(builtin_str);
|
||||||
"@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
|
|
||||||
|
|
||||||
try builtin_str_buffer.append(@tagName(arch));
|
const cache_hash = try std.fmt.allocPrint0(allocator, "\n\n");
|
||||||
try builtin_str_buffer.append(".cpu_");
|
errdefer allocator.free(cache_hash);
|
||||||
try builtin_str_buffer.append(cpu.name);
|
|
||||||
try builtin_str_buffer.append("};");
|
|
||||||
|
|
||||||
const cpu_string = cpu.llvm_name orelse "";
|
|
||||||
|
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.target_details = .{
|
.cpu_features = .{ .cpu = cpu },
|
||||||
.cpu = cpu,
|
.llvm_cpu_name = null,
|
||||||
},
|
.llvm_features_str = null,
|
||||||
.llvm_cpu_str = try toNullTerminatedStringAlloc(allocator, cpu_string),
|
.builtin_str = builtin_str,
|
||||||
.llvm_features_str = null_terminated_empty_string,
|
.cache_hash = cache_hash,
|
||||||
.builtin_str = builtin_str_buffer.toSliceConst(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initFeatures(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), features: []*const std.target.Feature) !Self {
|
fn initCpu(allocator: *mem.Allocator, arch: Target.Arch, cpu: *const Target.Cpu) !Self {
|
||||||
var builtin_str_buffer = try std.Buffer.init(
|
const builtin_str = try std.fmt.allocPrint0(
|
||||||
allocator,
|
allocator,
|
||||||
"@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
|
"CpuFeatures{{ .cpu = &Arch.{}.cpu.{} }};\n",
|
||||||
|
arch.genericName(),
|
||||||
|
cpu.name,
|
||||||
|
);
|
||||||
|
errdefer allocator.free(builtin_str);
|
||||||
|
|
||||||
|
const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{x}", cpu.name, cpu.features);
|
||||||
|
errdefer allocator.free(cache_hash);
|
||||||
|
|
||||||
|
return Self{
|
||||||
|
.allocator = allocator,
|
||||||
|
.cpu_features = .{ .cpu = cpu },
|
||||||
|
.llvm_cpu_name = cpu.llvm_name,
|
||||||
|
.llvm_features_str = null,
|
||||||
|
.builtin_str = builtin_str,
|
||||||
|
.cache_hash = cache_hash,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initFeatures(
|
||||||
|
allocator: *mem.Allocator,
|
||||||
|
arch: Target.Arch,
|
||||||
|
features: Target.Cpu.Feature.Set,
|
||||||
|
) !Self {
|
||||||
|
const cache_hash = try std.fmt.allocPrint0(allocator, "\n{x}", features);
|
||||||
|
errdefer allocator.free(cache_hash);
|
||||||
|
|
||||||
|
const generic_arch_name = arch.genericName();
|
||||||
|
var builtin_str_buffer = try std.Buffer.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"CpuFeatures{{ .features = Arch.{}.featureSet(&[_]Arch.{}.Feature{{\n",
|
||||||
|
generic_arch_name,
|
||||||
|
generic_arch_name,
|
||||||
|
);
|
||||||
|
defer builtin_str_buffer.deinit();
|
||||||
|
|
||||||
var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
|
var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
|
||||||
|
defer llvm_features_buffer.deinit();
|
||||||
|
|
||||||
// First, disable all features.
|
// First, disable all features.
|
||||||
// This way, we only get the ones the user requests.
|
// This way, we only get the ones the user requests.
|
||||||
for (std.target.getFeaturesForArch(arch)) |feature| {
|
for (arch.allFeatures()) |feature| {
|
||||||
if (feature.llvm_name) |llvm_name| {
|
if (feature.llvm_name) |llvm_name| {
|
||||||
try llvm_features_buffer.append("-");
|
try llvm_features_buffer.append("-");
|
||||||
try llvm_features_buffer.append(llvm_name);
|
try llvm_features_buffer.append(llvm_name);
|
||||||
@ -684,232 +706,117 @@ const Stage2TargetDetails = struct {
|
|||||||
try llvm_features_buffer.append("+");
|
try llvm_features_buffer.append("+");
|
||||||
try llvm_features_buffer.append(llvm_name);
|
try llvm_features_buffer.append(llvm_name);
|
||||||
try llvm_features_buffer.append(",");
|
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(" .");
|
||||||
|
try builtin_str_buffer.append(feature.name);
|
||||||
|
try builtin_str_buffer.append(",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
try builtin_str_buffer.append("}};");
|
if (mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")) {
|
||||||
|
llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try builtin_str_buffer.append("})};\n");
|
||||||
|
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.target_details = std.target.TargetDetails{
|
.cpu_features = .{ .features = features },
|
||||||
.features = features,
|
.llvm_cpu_name = null,
|
||||||
},
|
.llvm_features_str = llvm_features_buffer.toOwnedSlice(),
|
||||||
.llvm_cpu_str = null_terminated_empty_string,
|
.builtin_str = builtin_str_buffer.toOwnedSlice(),
|
||||||
.llvm_features_str = llvm_features_buffer.toSliceConst(),
|
.cache_hash = cache_hash,
|
||||||
.builtin_str = builtin_str_buffer.toSliceConst(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deinit(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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
export fn stage2_target_details_parse_cpu(arch_str: ?[*:0]const u8, cpu_str: ?[*:0]const u8) ?*Stage2TargetDetails {
|
export fn stage2_cpu_features_parse_cpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) *Stage2CpuFeatures {
|
||||||
if (cpu_str == null) return null;
|
return parseCpu(arch_name, cpu_name) catch |err| switch (err) {
|
||||||
if (arch_str == null) return null;
|
error.OutOfMemory => @panic("out of memory"),
|
||||||
|
|
||||||
const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_str.?)) catch {
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
return parseCpu(arch, std.mem.toSliceConst(u8, cpu_str.?)) catch |err| {
|
|
||||||
switch (err) {
|
|
||||||
error.OutOfMemory => @panic("out of memory"),
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABI warning
|
fn parseCpu(arch_name: [*:0]const u8, cpu_name: [*:0]const u8) !*Stage2CpuFeatures {
|
||||||
export fn stage2_target_details_parse_features(arch_str: ?[*:0]const u8, features_str: ?[*:0]const u8) ?*Stage2TargetDetails {
|
const arch = try Target.parseArchSub(mem.toSliceConst(u8, arch_name));
|
||||||
if (features_str == null) return null;
|
const cpu = try arch.parseCpu(mem.toSliceConst(u8, cpu_name));
|
||||||
if (arch_str == null) return null;
|
|
||||||
|
|
||||||
const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_str.?)) catch return null;
|
|
||||||
return parseFeatures(arch, std.mem.toSliceConst(u8, features_str.?)) catch |err| {
|
|
||||||
switch (err) {
|
|
||||||
error.OutOfMemory => @panic("out of memory"),
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parseCpu(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2TargetDetails {
|
const ptr = try allocator.create(Stage2CpuFeatures);
|
||||||
const allocator = std.heap.c_allocator;
|
errdefer std.heap.c_allocator.destroy(ptr);
|
||||||
|
|
||||||
const cpus = std.target.getCpusForArch(arch);
|
ptr.* = try Stage2CpuFeatures.initCpu(std.heap.c_allocator, arch, cpu);
|
||||||
|
errdefer ptr.deinit();
|
||||||
for (cpus) |cpu| {
|
|
||||||
if (std.mem.eql(u8, str, cpu.name)) {
|
|
||||||
const ptr = try allocator.create(Stage2TargetDetails);
|
|
||||||
ptr.* = try Stage2TargetDetails.initCpu(std.heap.c_allocator, arch, cpu);
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.InvalidCpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2TargetDetails {
|
|
||||||
const allocator = std.heap.c_allocator;
|
|
||||||
|
|
||||||
const known_features = std.target.getFeaturesForArch(arch);
|
|
||||||
|
|
||||||
var features = std.ArrayList(*const std.target.Feature).init(allocator);
|
|
||||||
defer features.deinit();
|
|
||||||
|
|
||||||
var start: usize = 0;
|
|
||||||
while (start < str.len) {
|
|
||||||
const next_comma_pos = std.mem.indexOfScalar(u8, str[start..], ',') orelse str.len - start;
|
|
||||||
const feature_str = std.mem.trim(u8, str[start..start+next_comma_pos], " ");
|
|
||||||
|
|
||||||
start += next_comma_pos + 1;
|
|
||||||
|
|
||||||
if (feature_str.len == 0) continue;
|
|
||||||
|
|
||||||
var feature: ?*const std.target.Feature = null;
|
|
||||||
for (known_features) |known_feature| {
|
|
||||||
if (std.mem.eql(u8, feature_str, known_feature.name)) {
|
|
||||||
feature = known_feature;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feature) |f| {
|
|
||||||
features.append(f) catch @panic("out of memory");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return error.InvalidFeature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const features_slice = features.toOwnedSlice();
|
|
||||||
|
|
||||||
const ptr = try allocator.create(Stage2TargetDetails);
|
|
||||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features_slice);
|
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
export fn stage2_target_details_get_cache_str(target_details: ?*const Stage2TargetDetails) [*:0]const u8 {
|
export fn stage2_cpu_features_parse_features(
|
||||||
if (target_details) |td| {
|
arch_name: [*:0]const u8,
|
||||||
return @as([*:0]const u8, switch (td.target_details) {
|
features_text: [*:0]const u8,
|
||||||
.cpu => td.llvm_cpu_str,
|
) *Stage2CpuFeatures {
|
||||||
.features => td.llvm_features_str,
|
return parseFeatures(arch_name, features_text) catch |err| switch (err) {
|
||||||
});
|
error.OutOfMemory => @panic("out of memory"),
|
||||||
}
|
|
||||||
|
|
||||||
return @as([*:0]const u8, null_terminated_empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ABI warning
|
|
||||||
export fn stage2_target_details_get_llvm_cpu(target_details: ?*const Stage2TargetDetails) [*:0]const u8 {
|
|
||||||
if (target_details) |td| {
|
|
||||||
return @as([*:0]const u8, td.llvm_cpu_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return @as([*:0]const u8, null_terminated_empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ABI warning
|
|
||||||
export fn stage2_target_details_get_llvm_features(target_details: ?*const Stage2TargetDetails) [*:0]const u8 {
|
|
||||||
if (target_details) |td| {
|
|
||||||
return @as([*:0]const u8, td.llvm_features_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return @as([*:0]const u8, null_terminated_empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ABI warning
|
|
||||||
export fn stage2_target_details_get_builtin_str(target_details: ?*const Stage2TargetDetails) [*:0]const u8 {
|
|
||||||
if (target_details) |td| {
|
|
||||||
return @as([*:0]const u8, td.builtin_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return @as([*:0]const u8, null_terminated_empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
const riscv32_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 riscv64_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
|
|
||||||
&std.target.riscv.feature_bit64,
|
|
||||||
&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 => blk: {
|
|
||||||
const ptr = try allocator.create(Stage2TargetDetails);
|
|
||||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, riscv32_default_features);
|
|
||||||
break :blk ptr;
|
|
||||||
},
|
|
||||||
.riscv64 => blk: {
|
|
||||||
const ptr = try allocator.create(Stage2TargetDetails);
|
|
||||||
ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, riscv64_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,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
ptr.* = try Stage2CpuFeatures.initBaseline(std.heap.c_allocator);
|
||||||
|
errdefer ptr.deinit();
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABI warning
|
||||||
|
export fn stage2_cpu_features_get_cache_hash(
|
||||||
|
cpu_features: *const Stage2CpuFeatures,
|
||||||
|
ptr: *[*:0]const u8,
|
||||||
|
len: *usize,
|
||||||
|
) void {
|
||||||
|
ptr.* = cpu_features.cache_hash.ptr;
|
||||||
|
len.* = cpu_features.cache_hash.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABI warning
|
||||||
|
export fn stage2_cpu_features_get_builtin_str(
|
||||||
|
cpu_features: *const Stage2CpuFeatures,
|
||||||
|
ptr: *[*:0]const u8,
|
||||||
|
len: *usize,
|
||||||
|
) void {
|
||||||
|
ptr.* = cpu_features.builtin_str.ptr;
|
||||||
|
len.* = cpu_features.builtin_str.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABI warning
|
||||||
|
export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
|
||||||
|
return cpu_features.llvm_cpu_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABI warning
|
||||||
|
export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
|
||||||
|
return cpu_features.llvm_features_str;
|
||||||
|
}
|
||||||
|
@ -2215,8 +2215,6 @@ struct CodeGen {
|
|||||||
|
|
||||||
const char **clang_argv;
|
const char **clang_argv;
|
||||||
size_t clang_argv_len;
|
size_t clang_argv_len;
|
||||||
|
|
||||||
Stage2TargetDetails *target_details;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZigVar {
|
struct ZigVar {
|
||||||
|
@ -8573,6 +8573,17 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
|||||||
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
|
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
|
||||||
buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
|
buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
|
||||||
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
|
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
|
||||||
|
{
|
||||||
|
buf_append_str(contents, "pub const cpu_features: CpuFeatures = ");
|
||||||
|
if (g->zig_target->cpu_features != nullptr) {
|
||||||
|
const char *ptr;
|
||||||
|
size_t len;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {
|
if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {
|
||||||
buf_appendf(contents,
|
buf_appendf(contents,
|
||||||
"pub const glibc_version: ?Version = Version{.major = %d, .minor = %d, .patch = %d};\n",
|
"pub const glibc_version: ?Version = Version{.major = %d, .minor = %d, .patch = %d};\n",
|
||||||
@ -8602,14 +8613,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
|||||||
"pub var test_functions: []TestFn = undefined; // overwritten later\n"
|
"pub var test_functions: []TestFn = undefined; // overwritten later\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_appendf(contents, "pub const target_details: ?@import(\"std\").target.TargetDetails = ");
|
|
||||||
if (g->target_details) {
|
|
||||||
buf_appendf(contents, "%s", stage2_target_details_get_builtin_str(g->target_details));
|
|
||||||
} else {
|
|
||||||
buf_appendf(contents, "null;");
|
|
||||||
}
|
|
||||||
buf_appendf(contents, "\n");
|
|
||||||
|
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
@ -8648,6 +8651,12 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
|||||||
cache_int(&cache_hash, g->zig_target->vendor);
|
cache_int(&cache_hash, g->zig_target->vendor);
|
||||||
cache_int(&cache_hash, g->zig_target->os);
|
cache_int(&cache_hash, g->zig_target->os);
|
||||||
cache_int(&cache_hash, g->zig_target->abi);
|
cache_int(&cache_hash, g->zig_target->abi);
|
||||||
|
if (g->zig_target->cpu_features != nullptr) {
|
||||||
|
const char *ptr;
|
||||||
|
size_t len;
|
||||||
|
stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len);
|
||||||
|
cache_str(&cache_hash, ptr);
|
||||||
|
}
|
||||||
if (g->zig_target->glibc_version != nullptr) {
|
if (g->zig_target->glibc_version != nullptr) {
|
||||||
cache_int(&cache_hash, g->zig_target->glibc_version->major);
|
cache_int(&cache_hash, g->zig_target->glibc_version->major);
|
||||||
cache_int(&cache_hash, g->zig_target->glibc_version->minor);
|
cache_int(&cache_hash, g->zig_target->glibc_version->minor);
|
||||||
@ -8659,10 +8668,6 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
|||||||
cache_bool(&cache_hash, g->link_eh_frame_hdr);
|
cache_bool(&cache_hash, g->link_eh_frame_hdr);
|
||||||
cache_int(&cache_hash, detect_subsystem(g));
|
cache_int(&cache_hash, detect_subsystem(g));
|
||||||
|
|
||||||
if (g->target_details) {
|
|
||||||
cache_str(&cache_hash, stage2_target_details_get_cache_str(g->target_details));
|
|
||||||
}
|
|
||||||
|
|
||||||
Buf digest = BUF_INIT;
|
Buf digest = BUF_INIT;
|
||||||
buf_resize(&digest, 0);
|
buf_resize(&digest, 0);
|
||||||
if ((err = cache_hit(&cache_hash, &digest))) {
|
if ((err = cache_hit(&cache_hash, &digest))) {
|
||||||
@ -8793,9 +8798,9 @@ static void init(CodeGen *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Override CPU and features if defined by user.
|
// Override CPU and features if defined by user.
|
||||||
if (g->target_details) {
|
if (g->zig_target->cpu_features != nullptr) {
|
||||||
target_specific_cpu_args = stage2_target_details_get_llvm_cpu(g->target_details);
|
target_specific_cpu_args = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features);
|
||||||
target_specific_features = stage2_target_details_get_llvm_features(g->target_details);
|
target_specific_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
|
g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
|
||||||
@ -9123,15 +9128,19 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
|
|||||||
args.append("-target");
|
args.append("-target");
|
||||||
args.append(buf_ptr(&g->llvm_triple_str));
|
args.append(buf_ptr(&g->llvm_triple_str));
|
||||||
|
|
||||||
if (g->target_details) {
|
const char *llvm_cpu = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features);
|
||||||
|
if (llvm_cpu != nullptr) {
|
||||||
args.append("-Xclang");
|
args.append("-Xclang");
|
||||||
args.append("-target-cpu");
|
args.append("-target-cpu");
|
||||||
args.append("-Xclang");
|
args.append("-Xclang");
|
||||||
args.append(stage2_target_details_get_llvm_cpu(g->target_details));
|
args.append(llvm_cpu);
|
||||||
|
}
|
||||||
|
const char *llvm_target_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features);
|
||||||
|
if (llvm_target_features != nullptr) {
|
||||||
args.append("-Xclang");
|
args.append("-Xclang");
|
||||||
args.append("-target-feature");
|
args.append("-target-feature");
|
||||||
args.append("-Xclang");
|
args.append("-Xclang");
|
||||||
args.append(stage2_target_details_get_llvm_features(g->target_details));
|
args.append(llvm_target_features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10328,6 +10337,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
|||||||
cache_int(ch, g->zig_target->vendor);
|
cache_int(ch, g->zig_target->vendor);
|
||||||
cache_int(ch, g->zig_target->os);
|
cache_int(ch, g->zig_target->os);
|
||||||
cache_int(ch, g->zig_target->abi);
|
cache_int(ch, g->zig_target->abi);
|
||||||
|
if (g->zig_target->cpu_features != nullptr) {
|
||||||
|
const char *ptr;
|
||||||
|
size_t len;
|
||||||
|
stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len);
|
||||||
|
cache_str(ch, ptr);
|
||||||
|
}
|
||||||
if (g->zig_target->glibc_version != nullptr) {
|
if (g->zig_target->glibc_version != nullptr) {
|
||||||
cache_int(ch, g->zig_target->glibc_version->major);
|
cache_int(ch, g->zig_target->glibc_version->major);
|
||||||
cache_int(ch, g->zig_target->glibc_version->minor);
|
cache_int(ch, g->zig_target->glibc_version->minor);
|
||||||
@ -10375,10 +10390,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
|||||||
cache_buf_opt(ch, g->dynamic_linker_path);
|
cache_buf_opt(ch, g->dynamic_linker_path);
|
||||||
cache_buf_opt(ch, g->version_script_path);
|
cache_buf_opt(ch, g->version_script_path);
|
||||||
|
|
||||||
if (g->target_details) {
|
|
||||||
cache_str(ch, stage2_target_details_get_cache_str(g->target_details));
|
|
||||||
}
|
|
||||||
|
|
||||||
// gen_c_objects appends objects to g->link_objects which we want to include in the hash
|
// gen_c_objects appends objects to g->link_objects which we want to include in the hash
|
||||||
gen_c_objects(g);
|
gen_c_objects(g);
|
||||||
cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
|
cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
|
||||||
@ -10661,7 +10672,6 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
|
|||||||
|
|
||||||
CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
|
CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
|
||||||
parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_global_cache_dir(), false, child_progress_node);
|
parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_global_cache_dir(), false, child_progress_node);
|
||||||
child_gen->target_details = parent_gen->target_details;
|
|
||||||
child_gen->root_out_name = buf_create_from_str(name);
|
child_gen->root_out_name = buf_create_from_str(name);
|
||||||
child_gen->disable_gen_h = true;
|
child_gen->disable_gen_h = true;
|
||||||
child_gen->want_stack_check = WantStackCheckDisabled;
|
child_gen->want_stack_check = WantStackCheckDisabled;
|
||||||
|
24
src/main.cpp
24
src/main.cpp
@ -955,9 +955,9 @@ int main(int argc, char **argv) {
|
|||||||
targets_list_features_arch = argv[i];
|
targets_list_features_arch = argv[i];
|
||||||
} else if (strcmp(arg, "--list-cpus") == 0) {
|
} else if (strcmp(arg, "--list-cpus") == 0) {
|
||||||
targets_list_cpus_arch = argv[i];
|
targets_list_cpus_arch = argv[i];
|
||||||
} else if (strcmp(arg, "--cpu") == 0) {
|
} else if (strcmp(arg, "-target-cpu") == 0) {
|
||||||
cpu = argv[i];
|
cpu = argv[i];
|
||||||
} else if (strcmp(arg, "--features") == 0) {
|
} else if (strcmp(arg, "-target-feature") == 0) {
|
||||||
features = argv[i];
|
features = argv[i];
|
||||||
}else {
|
}else {
|
||||||
fprintf(stderr, "Invalid argument: %s\n", arg);
|
fprintf(stderr, "Invalid argument: %s\n", arg);
|
||||||
@ -1074,27 +1074,26 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stage2TargetDetails *target_details = nullptr;
|
|
||||||
if (cpu && features) {
|
if (cpu && features) {
|
||||||
fprintf(stderr, "--cpu and --features options not allowed together\n");
|
fprintf(stderr, "-target-cpu and -target-feature options not allowed together\n");
|
||||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||||
} else if (cpu) {
|
} else if (cpu) {
|
||||||
target_details = stage2_target_details_parse_cpu(target_arch_name(target.arch), cpu);
|
target.cpu_features = stage2_cpu_features_parse_cpu(target_arch_name(target.arch), cpu);
|
||||||
if (!target_details) {
|
if (!target.cpu_features) {
|
||||||
fprintf(stderr, "invalid --cpu value\n");
|
fprintf(stderr, "invalid -target-cpu value\n");
|
||||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else if (features) {
|
} else if (features) {
|
||||||
target_details = stage2_target_details_parse_features(target_arch_name(target.arch), features);
|
target.cpu_features = stage2_cpu_features_parse_features(target_arch_name(target.arch), features);
|
||||||
if (!target_details) {
|
if (!target.cpu_features) {
|
||||||
fprintf(stderr, "invalid --features value\n");
|
fprintf(stderr, "invalid -target-feature value\n");
|
||||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no details are specified and we are not native, load
|
// If no details are specified and we are not native, load
|
||||||
// cross-compilation default features.
|
// cross-compilation default features.
|
||||||
if (!target.is_native) {
|
if (!target.is_native) {
|
||||||
target_details = stage2_target_details_get_default(target_arch_name(target.arch), target_os_name(target.os));
|
target.cpu_features = stage2_cpu_features_baseline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,7 +1147,6 @@ int main(int argc, char **argv) {
|
|||||||
g->want_stack_check = want_stack_check;
|
g->want_stack_check = want_stack_check;
|
||||||
g->want_sanitize_c = want_sanitize_c;
|
g->want_sanitize_c = want_sanitize_c;
|
||||||
g->want_single_threaded = want_single_threaded;
|
g->want_single_threaded = want_single_threaded;
|
||||||
g->target_details = target_details;
|
|
||||||
Buf *builtin_source = codegen_generate_builtin_source(g);
|
Buf *builtin_source = codegen_generate_builtin_source(g);
|
||||||
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
|
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
|
||||||
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
|
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
|
||||||
@ -1303,8 +1301,6 @@ int main(int argc, char **argv) {
|
|||||||
codegen_add_rpath(g, rpath_list.at(i));
|
codegen_add_rpath(g, rpath_list.at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
g->target_details = target_details;
|
|
||||||
|
|
||||||
codegen_set_rdynamic(g, rdynamic);
|
codegen_set_rdynamic(g, rdynamic);
|
||||||
if (mmacosx_version_min && mios_version_min) {
|
if (mmacosx_version_min && mios_version_min) {
|
||||||
fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
|
fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
|
||||||
|
@ -91,6 +91,7 @@ struct ZigTarget {
|
|||||||
Os os;
|
Os os;
|
||||||
ZigLLVM_EnvironmentType abi;
|
ZigLLVM_EnvironmentType abi;
|
||||||
ZigGLibCVersion *glibc_version; // null means default
|
ZigGLibCVersion *glibc_version; // null means default
|
||||||
|
Stage2CpuFeatures *cpu_features;
|
||||||
bool is_native;
|
bool is_native;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,26 +89,44 @@ void stage2_progress_complete_one(Stage2ProgressNode *node) {}
|
|||||||
void stage2_progress_disable_tty(Stage2Progress *progress) {}
|
void stage2_progress_disable_tty(Stage2Progress *progress) {}
|
||||||
void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
|
void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
|
||||||
|
|
||||||
void stage2_list_features_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {}
|
void stage2_list_features_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {
|
||||||
void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {}
|
const char *msg = "stage0 called stage2_list_features_for_arch";
|
||||||
Stage2TargetDetails *stage2_target_details_parse_cpu(const char *arch, const char *str) {
|
stage2_panic(msg, strlen(msg));
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
Stage2TargetDetails *stage2_target_details_parse_features(const char *arch, const char *str) {
|
|
||||||
return nullptr;
|
void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures) {
|
||||||
|
const char *msg = "stage0 called stage2_list_cpus_for_arch";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
}
|
}
|
||||||
const char *stage2_target_details_get_cache_str(const Stage2TargetDetails *target_details) {
|
Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *str) {
|
||||||
return "";
|
const char *msg = "stage0 called stage2_cpu_features_parse_cpu";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
}
|
}
|
||||||
const char *stage2_target_details_get_llvm_cpu(const Stage2TargetDetails *target_details) {
|
Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *str) {
|
||||||
return "";
|
const char *msg = "stage0 called stage2_cpu_features_parse_features";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
}
|
}
|
||||||
const char *stage2_target_details_get_llvm_features(const Stage2TargetDetails *target_details) {
|
Stage2CpuFeatures *stage2_cpu_features_baseline(void) {
|
||||||
return "";
|
const char *msg = "stage0 called stage2_cpu_features_baseline";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
}
|
}
|
||||||
const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details) {
|
void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
|
||||||
return "";
|
const char **ptr, size_t *len)
|
||||||
|
{
|
||||||
|
const char *msg = "stage0 called stage2_cpu_features_get_cache_hash";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
}
|
}
|
||||||
Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os) {
|
const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
|
||||||
return nullptr;
|
const char *msg = "stage0 called stage2_cpu_features_get_llvm_cpu";
|
||||||
|
stage2_panic(msg, strlen(msg));
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
@ -181,27 +181,29 @@ ZIG_EXTERN_C void stage2_list_features_for_arch(const char *arch_name_ptr, size_
|
|||||||
ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures);
|
ZIG_EXTERN_C void stage2_list_cpus_for_arch(const char *arch_name_ptr, size_t arch_name_len, bool show_subfeatures);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
struct Stage2TargetDetails;
|
struct Stage2CpuFeatures;
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_parse_cpu(const char *arch, const char *str);
|
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_cpu(const char *arch, const char *cpu_name);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_parse_features(const char *arch, const char *str);
|
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_parse_features(const char *arch, const char *features);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C const char *stage2_target_details_get_cache_str(const Stage2TargetDetails *target_details);
|
ZIG_EXTERN_C Stage2CpuFeatures *stage2_cpu_features_baseline(void);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C const char *stage2_target_details_get_llvm_cpu(const Stage2TargetDetails *target_details);
|
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C const char *stage2_target_details_get_llvm_features(const Stage2TargetDetails *target_details);
|
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details);
|
ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
|
||||||
|
const char **ptr, size_t *len);
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os);
|
ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
|
||||||
|
const char **ptr, size_t *len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user