aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf/Object.zig
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-10-20 01:44:25 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-11-22 19:34:47 -0500
commit66a7c09defec1fe4f4f1751e36acc412e3ca8ea9 (patch)
tree6ceb71191d103f008418111f749aedb55faf8e59 /src/link/Elf/Object.zig
parentb2c62bcbf64a3ffa2af6a8e441f1c12e10c598ec (diff)
downloadzig-66a7c09defec1fe4f4f1751e36acc412e3ca8ea9.tar.gz
zig-66a7c09defec1fe4f4f1751e36acc412e3ca8ea9.zip
link: use target to determine risc-v eflag validity
Diffstat (limited to 'src/link/Elf/Object.zig')
-rw-r--r--src/link/Elf/Object.zig103
1 files changed, 72 insertions, 31 deletions
diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig
index 688e51f3f1..65a62ff1a6 100644
--- a/src/link/Elf/Object.zig
+++ b/src/link/Elf/Object.zig
@@ -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);
-
- self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
- self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
-
- 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;
+) !void {
+ switch (target.cpu.arch) {
+ .riscv64 => {
+ const features = target.cpu.features;
+ const flags: riscv.Eflags = @bitCast(e_flags);
+ var any_errors: bool = false;
+
+ // For an input object to target an ABI that the target CPU doesn't have enabled
+ // is invalid, and will throw an error.
+
+ // 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 => {},
}
}