Skip to content

Commit 66a7c09

Browse files
Rexicon226andrewrk
authored andcommitted
link: use target to determine risc-v eflag validity
1 parent b2c62bc commit 66a7c09

File tree

3 files changed

+84
-45
lines changed

3 files changed

+84
-45
lines changed

src/link/Elf.zig

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty,
113113
merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty,
114114
comment_merge_section_index: ?Merge.Section.Index = null,
115115

116-
first_eflags: ?elf.Word = null,
117-
118116
/// `--verbose-link` output.
119117
/// Initialized on creation, appended to as inputs are added, printed during `flush`.
120118
dump_argv_list: std.ArrayListUnmanaged([]const u8),
@@ -791,7 +789,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
791789
.res => unreachable,
792790
.dso_exact => @panic("TODO"),
793791
.object => |obj| try parseObject(self, obj),
794-
.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),
792+
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
795793
.dso => |dso| try parseDso(gpa, diags, dso, &self.shared_objects, &self.files, target),
796794
}
797795
}
@@ -1124,7 +1122,6 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
11241122

11251123
const gpa = self.base.comp.gpa;
11261124
const diags = &self.base.comp.link_diags;
1127-
const first_eflags = &self.first_eflags;
11281125
const target = self.base.comp.root_mod.resolved_target.result;
11291126
const debug_fmt_strip = self.base.comp.config.debug_format == .strip;
11301127
const default_sym_version = self.default_sym_version;
@@ -1145,7 +1142,7 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
11451142
try self.objects.append(gpa, index);
11461143

11471144
const object = self.file(index).?.object;
1148-
try object.parseCommon(gpa, diags, obj.path, handle, target, first_eflags);
1145+
try object.parseCommon(gpa, diags, obj.path, handle, target);
11491146
if (!self.base.isStaticLib()) {
11501147
try object.parse(gpa, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version);
11511148
}
@@ -1156,7 +1153,6 @@ fn parseArchive(
11561153
diags: *Diags,
11571154
file_handles: *std.ArrayListUnmanaged(File.Handle),
11581155
files: *std.MultiArrayList(File.Entry),
1159-
first_eflags: *?elf.Word,
11601156
target: std.Target,
11611157
debug_fmt_strip: bool,
11621158
default_sym_version: elf.Versym,
@@ -1179,7 +1175,7 @@ fn parseArchive(
11791175
const object = &files.items(.data)[index].object;
11801176
object.index = index;
11811177
object.alive = init_alive;
1182-
try object.parseCommon(gpa, diags, obj.path, obj.file, target, first_eflags);
1178+
try object.parseCommon(gpa, diags, obj.path, obj.file, target);
11831179
if (!is_static_lib)
11841180
try object.parse(gpa, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
11851181
try objects.append(gpa, index);

src/link/Elf/Object.zig

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ pub fn parseCommon(
9999
path: Path,
100100
handle: fs.File,
101101
target: std.Target,
102-
first_eflags: *?elf.Word,
103102
) !void {
104103
const offset = if (self.archive) |ar| ar.offset else 0;
105104
const file_size = (try handle.stat()).size;
@@ -114,7 +113,7 @@ pub fn parseCommon(
114113
@tagName(self.header.?.e_machine),
115114
});
116115
}
117-
try validateEFlags(diags, path, target, self.header.?.e_flags, first_eflags);
116+
try validateEFlags(diags, path, target, self.header.?.e_flags);
118117

119118
if (self.header.?.e_shnum == 0) return;
120119

@@ -180,39 +179,81 @@ pub fn parseCommon(
180179
}
181180
}
182181

183-
fn validateEFlags(
182+
pub fn validateEFlags(
184183
diags: *Diags,
185184
path: Path,
186185
target: std.Target,
187186
e_flags: elf.Word,
188-
first_eflags: *?elf.Word,
189-
) error{LinkFailure}!void {
190-
if (first_eflags.*) |*self_eflags| {
191-
switch (target.cpu.arch) {
192-
.riscv64 => {
193-
if (e_flags != self_eflags.*) {
194-
const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
195-
const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
196-
197-
self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
198-
self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
199-
200-
var any_errors: bool = false;
201-
if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
202-
any_errors = true;
203-
diags.addParseError(path, "cannot link object files with different float-point ABIs", .{});
204-
}
205-
if (self_riscv_eflags.rve != riscv_eflags.rve) {
206-
any_errors = true;
207-
diags.addParseError(path, "cannot link object files with different RVEs", .{});
208-
}
209-
if (any_errors) return error.LinkFailure;
210-
}
211-
},
212-
else => {},
213-
}
214-
} else {
215-
first_eflags.* = e_flags;
187+
) !void {
188+
switch (target.cpu.arch) {
189+
.riscv64 => {
190+
const features = target.cpu.features;
191+
const flags: riscv.Eflags = @bitCast(e_flags);
192+
var any_errors: bool = false;
193+
194+
// For an input object to target an ABI that the target CPU doesn't have enabled
195+
// is invalid, and will throw an error.
196+
197+
// Invalid when
198+
// 1. The input uses C and we do not.
199+
if (flags.rvc and !std.Target.riscv.featureSetHas(features, .c)) {
200+
any_errors = true;
201+
diags.addParseError(
202+
path,
203+
"cannot link object file targeting the C feature without having the C feature enabled",
204+
.{},
205+
);
206+
}
207+
208+
// Invalid when
209+
// 1. We use E and the input does not.
210+
// 2. The input uses E and we do not.
211+
if (std.Target.riscv.featureSetHas(features, .e) != flags.rve) {
212+
any_errors = true;
213+
diags.addParseError(
214+
path,
215+
"{s}",
216+
.{
217+
if (flags.rve)
218+
"cannot link object file targeting the E feature without having the E feature enabled"
219+
else
220+
"cannot link object file not targeting the E feature while having the E feature enabled",
221+
},
222+
);
223+
}
224+
225+
// Invalid when
226+
// 1. We use total store order and the input does not.
227+
// 2. The input uses total store order and we do not.
228+
if (flags.tso != std.Target.riscv.featureSetHas(features, .ztso)) {
229+
any_errors = true;
230+
diags.addParseError(
231+
path,
232+
"cannot link object file targeting the TSO memory model without having the ztso feature enabled",
233+
.{},
234+
);
235+
}
236+
237+
const fabi: riscv.Eflags.FloatAbi =
238+
if (std.Target.riscv.featureSetHas(features, .d))
239+
.double
240+
else if (std.Target.riscv.featureSetHas(features, .f))
241+
.single
242+
else
243+
.soft;
244+
245+
if (flags.fabi != fabi) {
246+
any_errors = true;
247+
diags.addParseError(
248+
path,
249+
"cannot link object file targeting a different floating-point ABI. targeting {s}, found {s}",
250+
.{ @tagName(fabi), @tagName(flags.fabi) },
251+
);
252+
}
253+
254+
if (any_errors) return error.LinkFailure;
255+
},
256+
else => {},
216257
}
217258
}
218259

src/link/riscv.zig

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,20 @@ fn bitSlice(
7070
return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
7171
}
7272

73-
pub const RiscvEflags = packed struct(u32) {
73+
pub const Eflags = packed struct(u32) {
7474
rvc: bool,
75-
fabi: enum(u2) {
75+
fabi: FloatAbi,
76+
rve: bool,
77+
tso: bool,
78+
_reserved: u19 = 0,
79+
_unused: u8 = 0,
80+
81+
pub const FloatAbi = enum(u2) {
7682
soft = 0b00,
7783
single = 0b01,
7884
double = 0b10,
7985
quad = 0b11,
80-
},
81-
rve: bool,
82-
tso: bool,
83-
_reserved: u19,
84-
_unused: u8,
86+
};
8587
};
8688

8789
const mem = std.mem;

0 commit comments

Comments
 (0)