mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 15:12:31 +00:00
link: use target to determine risc-v eflag validity
Some checks are pending
ci / x86_64-linux-debug (push) Waiting to run
ci / x86_64-linux-release (push) Waiting to run
ci / aarch64-linux-debug (push) Waiting to run
ci / aarch64-linux-release (push) Waiting to run
ci / x86_64-macos-release (push) Waiting to run
ci / aarch64-macos-debug (push) Waiting to run
ci / aarch64-macos-release (push) Waiting to run
ci / x86_64-windows-debug (push) Waiting to run
ci / x86_64-windows-release (push) Waiting to run
ci / aarch64-windows (push) Waiting to run
Some checks are pending
ci / x86_64-linux-debug (push) Waiting to run
ci / x86_64-linux-release (push) Waiting to run
ci / aarch64-linux-debug (push) Waiting to run
ci / aarch64-linux-release (push) Waiting to run
ci / x86_64-macos-release (push) Waiting to run
ci / aarch64-macos-debug (push) Waiting to run
ci / aarch64-macos-release (push) Waiting to run
ci / x86_64-windows-debug (push) Waiting to run
ci / x86_64-windows-release (push) Waiting to run
ci / aarch64-windows (push) Waiting to run
This commit is contained in:
parent
b2c62bcbf6
commit
66a7c09def
@ -113,8 +113,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty,
|
||||
merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty,
|
||||
comment_merge_section_index: ?Merge.Section.Index = null,
|
||||
|
||||
first_eflags: ?elf.Word = null,
|
||||
|
||||
/// `--verbose-link` output.
|
||||
/// Initialized on creation, appended to as inputs are added, printed during `flush`.
|
||||
dump_argv_list: std.ArrayListUnmanaged([]const u8),
|
||||
@ -791,7 +789,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
|
||||
.res => unreachable,
|
||||
.dso_exact => @panic("TODO"),
|
||||
.object => |obj| try parseObject(self, obj),
|
||||
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, &self.first_eflags, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
|
||||
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
|
||||
.dso => |dso| try parseDso(gpa, diags, dso, &self.shared_objects, &self.files, target),
|
||||
}
|
||||
}
|
||||
@ -1124,7 +1122,6 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
const diags = &self.base.comp.link_diags;
|
||||
const first_eflags = &self.first_eflags;
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const debug_fmt_strip = self.base.comp.config.debug_format == .strip;
|
||||
const default_sym_version = self.default_sym_version;
|
||||
@ -1145,7 +1142,7 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
|
||||
try self.objects.append(gpa, index);
|
||||
|
||||
const object = self.file(index).?.object;
|
||||
try object.parseCommon(gpa, diags, obj.path, handle, target, first_eflags);
|
||||
try object.parseCommon(gpa, diags, obj.path, handle, target);
|
||||
if (!self.base.isStaticLib()) {
|
||||
try object.parse(gpa, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version);
|
||||
}
|
||||
@ -1156,7 +1153,6 @@ fn parseArchive(
|
||||
diags: *Diags,
|
||||
file_handles: *std.ArrayListUnmanaged(File.Handle),
|
||||
files: *std.MultiArrayList(File.Entry),
|
||||
first_eflags: *?elf.Word,
|
||||
target: std.Target,
|
||||
debug_fmt_strip: bool,
|
||||
default_sym_version: elf.Versym,
|
||||
@ -1179,7 +1175,7 @@ fn parseArchive(
|
||||
const object = &files.items(.data)[index].object;
|
||||
object.index = index;
|
||||
object.alive = init_alive;
|
||||
try object.parseCommon(gpa, diags, obj.path, obj.file, target, first_eflags);
|
||||
try object.parseCommon(gpa, diags, obj.path, obj.file, target);
|
||||
if (!is_static_lib)
|
||||
try object.parse(gpa, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
|
||||
try objects.append(gpa, index);
|
||||
|
@ -99,7 +99,6 @@ pub fn parseCommon(
|
||||
path: Path,
|
||||
handle: fs.File,
|
||||
target: std.Target,
|
||||
first_eflags: *?elf.Word,
|
||||
) !void {
|
||||
const offset = if (self.archive) |ar| ar.offset else 0;
|
||||
const file_size = (try handle.stat()).size;
|
||||
@ -114,7 +113,7 @@ pub fn parseCommon(
|
||||
@tagName(self.header.?.e_machine),
|
||||
});
|
||||
}
|
||||
try validateEFlags(diags, path, target, self.header.?.e_flags, first_eflags);
|
||||
try validateEFlags(diags, path, target, self.header.?.e_flags);
|
||||
|
||||
if (self.header.?.e_shnum == 0) return;
|
||||
|
||||
@ -180,39 +179,81 @@ pub fn parseCommon(
|
||||
}
|
||||
}
|
||||
|
||||
fn validateEFlags(
|
||||
pub fn validateEFlags(
|
||||
diags: *Diags,
|
||||
path: Path,
|
||||
target: std.Target,
|
||||
e_flags: elf.Word,
|
||||
first_eflags: *?elf.Word,
|
||||
) error{LinkFailure}!void {
|
||||
if (first_eflags.*) |*self_eflags| {
|
||||
switch (target.cpu.arch) {
|
||||
.riscv64 => {
|
||||
if (e_flags != self_eflags.*) {
|
||||
const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
|
||||
const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
|
||||
) !void {
|
||||
switch (target.cpu.arch) {
|
||||
.riscv64 => {
|
||||
const features = target.cpu.features;
|
||||
const flags: riscv.Eflags = @bitCast(e_flags);
|
||||
var any_errors: bool = false;
|
||||
|
||||
self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
|
||||
self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
|
||||
// For an input object to target an ABI that the target CPU doesn't have enabled
|
||||
// is invalid, and will throw an error.
|
||||
|
||||
var any_errors: bool = false;
|
||||
if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
|
||||
any_errors = true;
|
||||
diags.addParseError(path, "cannot link object files with different float-point ABIs", .{});
|
||||
}
|
||||
if (self_riscv_eflags.rve != riscv_eflags.rve) {
|
||||
any_errors = true;
|
||||
diags.addParseError(path, "cannot link object files with different RVEs", .{});
|
||||
}
|
||||
if (any_errors) return error.LinkFailure;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
} else {
|
||||
first_eflags.* = e_flags;
|
||||
// Invalid when
|
||||
// 1. The input uses C and we do not.
|
||||
if (flags.rvc and !std.Target.riscv.featureSetHas(features, .c)) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting the C feature without having the C feature enabled",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
// Invalid when
|
||||
// 1. We use E and the input does not.
|
||||
// 2. The input uses E and we do not.
|
||||
if (std.Target.riscv.featureSetHas(features, .e) != flags.rve) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"{s}",
|
||||
.{
|
||||
if (flags.rve)
|
||||
"cannot link object file targeting the E feature without having the E feature enabled"
|
||||
else
|
||||
"cannot link object file not targeting the E feature while having the E feature enabled",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Invalid when
|
||||
// 1. We use total store order and the input does not.
|
||||
// 2. The input uses total store order and we do not.
|
||||
if (flags.tso != std.Target.riscv.featureSetHas(features, .ztso)) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting the TSO memory model without having the ztso feature enabled",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
const fabi: riscv.Eflags.FloatAbi =
|
||||
if (std.Target.riscv.featureSetHas(features, .d))
|
||||
.double
|
||||
else if (std.Target.riscv.featureSetHas(features, .f))
|
||||
.single
|
||||
else
|
||||
.soft;
|
||||
|
||||
if (flags.fabi != fabi) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting a different floating-point ABI. targeting {s}, found {s}",
|
||||
.{ @tagName(fabi), @tagName(flags.fabi) },
|
||||
);
|
||||
}
|
||||
|
||||
if (any_errors) return error.LinkFailure;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,18 +70,20 @@ fn bitSlice(
|
||||
return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
|
||||
}
|
||||
|
||||
pub const RiscvEflags = packed struct(u32) {
|
||||
pub const Eflags = packed struct(u32) {
|
||||
rvc: bool,
|
||||
fabi: enum(u2) {
|
||||
fabi: FloatAbi,
|
||||
rve: bool,
|
||||
tso: bool,
|
||||
_reserved: u19 = 0,
|
||||
_unused: u8 = 0,
|
||||
|
||||
pub const FloatAbi = enum(u2) {
|
||||
soft = 0b00,
|
||||
single = 0b01,
|
||||
double = 0b10,
|
||||
quad = 0b11,
|
||||
},
|
||||
rve: bool,
|
||||
tso: bool,
|
||||
_reserved: u19,
|
||||
_unused: u8,
|
||||
};
|
||||
};
|
||||
|
||||
const mem = std.mem;
|
||||
|
Loading…
Reference in New Issue
Block a user