Skip to content

Commit 7aaebd1

Browse files
authored
Merge pull request #20751 from Rexicon226/riscv-eflags
elf: add riscv eflag collisions
2 parents 2e8acdf + 782a9d1 commit 7aaebd1

File tree

5 files changed

+93
-8
lines changed

5 files changed

+93
-8
lines changed

src/dev.zig

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ pub const Env = enum {
2626
/// - `zig build-* -fno-llvm -fno-lld -target x86_64-linux`
2727
@"x86_64-linux",
2828

29+
/// - sema
30+
/// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux`
31+
@"riscv64-linux",
32+
2933
pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
3034
return switch (dev_env) {
3135
.full => true,
@@ -131,6 +135,12 @@ pub const Env = enum {
131135
=> true,
132136
else => Env.sema.supports(feature),
133137
},
138+
.@"riscv64-linux" => switch (feature) {
139+
.riscv64_backend,
140+
.elf_linker,
141+
=> true,
142+
else => Env.sema.supports(feature),
143+
},
134144
};
135145
}
136146

src/link/Elf.zig

+58-6
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}
229229
/// such as `resolver` and `comdat_groups_table`.
230230
strings: StringTable = .{},
231231

232+
first_eflags: ?elf.Elf64_Word = null,
233+
232234
/// When allocating, the ideal_capacity is calculated by
233235
/// actual_capacity + (actual_capacity / ideal_factor)
234236
const ideal_factor = 3;
@@ -553,7 +555,7 @@ pub fn lowerAnonDecl(
553555
pt: Zcu.PerThread,
554556
decl_val: InternPool.Index,
555557
explicit_alignment: InternPool.Alignment,
556-
src_loc: Module.LazySrcLoc,
558+
src_loc: Zcu.LazySrcLoc,
557559
) !codegen.Result {
558560
return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc);
559561
}
@@ -1161,7 +1163,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
11611163

11621164
for (positionals.items) |obj| {
11631165
self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1164-
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
1166+
error.MalformedObject,
1167+
error.MalformedArchive,
1168+
error.MismatchedEflags,
1169+
error.InvalidCpuArch,
1170+
=> continue, // already reported
11651171
else => |e| try self.reportParseError(
11661172
obj.path,
11671173
"unexpected error: parsing input file failed with error {s}",
@@ -1270,7 +1276,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
12701276

12711277
for (positionals.items) |obj| {
12721278
self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1273-
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
1279+
error.MalformedObject,
1280+
error.MalformedArchive,
1281+
error.MismatchedEflags,
1282+
error.InvalidCpuArch,
1283+
=> continue, // already reported
12741284
else => |e| try self.reportParseError(
12751285
obj.path,
12761286
"unexpected error: parsing input file failed with error {s}",
@@ -1700,6 +1710,7 @@ pub const ParseError = error{
17001710
MalformedObject,
17011711
MalformedArchive,
17021712
InvalidCpuArch,
1713+
MismatchedEflags,
17031714
OutOfMemory,
17041715
Overflow,
17051716
InputOutput,
@@ -1879,6 +1890,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
18791890
}
18801891
}
18811892

1893+
pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void {
1894+
const target = self.base.comp.root_mod.resolved_target.result;
1895+
1896+
if (self.first_eflags == null) {
1897+
self.first_eflags = e_flags;
1898+
return; // there isn't anything to conflict with yet
1899+
}
1900+
const self_eflags: *elf.Elf64_Word = &self.first_eflags.?;
1901+
1902+
switch (target.cpu.arch) {
1903+
.riscv64 => {
1904+
if (e_flags != self_eflags.*) {
1905+
const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
1906+
const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
1907+
1908+
self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
1909+
self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
1910+
1911+
var is_error: bool = false;
1912+
if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
1913+
is_error = true;
1914+
_ = try self.reportParseError2(
1915+
file_index,
1916+
"cannot link object files with different float-point ABIs",
1917+
.{},
1918+
);
1919+
}
1920+
if (self_riscv_eflags.rve != riscv_eflags.rve) {
1921+
is_error = true;
1922+
_ = try self.reportParseError2(
1923+
file_index,
1924+
"cannot link object files with different RVEs",
1925+
.{},
1926+
);
1927+
}
1928+
if (is_error) return error.MismatchedEflags;
1929+
}
1930+
},
1931+
else => {},
1932+
}
1933+
}
1934+
18821935
fn accessLibPath(
18831936
self: *Elf,
18841937
arena: Allocator,
@@ -3025,7 +3078,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index:
30253078
pub fn updateExports(
30263079
self: *Elf,
30273080
pt: Zcu.PerThread,
3028-
exported: Module.Exported,
3081+
exported: Zcu.Exported,
30293082
export_indices: []const u32,
30303083
) link.File.UpdateExportsError!void {
30313084
if (build_options.skip_non_native and builtin.object_format != .elf) {
@@ -6432,8 +6485,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
64326485
const MergeSection = merge_section.MergeSection;
64336486
const MergeSubsection = merge_section.MergeSubsection;
64346487
const Zcu = @import("../Zcu.zig");
6435-
/// Deprecated.
6436-
const Module = Zcu;
64376488
const Object = @import("Elf/Object.zig");
64386489
const InternPool = @import("../InternPool.zig");
64396490
const PltSection = synthetic_sections.PltSection;
@@ -6446,3 +6497,4 @@ const Value = @import("../Value.zig");
64466497
const VerneedSection = synthetic_sections.VerneedSection;
64476498
const ZigGotSection = synthetic_sections.ZigGotSection;
64486499
const ZigObject = @import("Elf/ZigObject.zig");
6500+
const riscv = @import("riscv.zig");

src/link/Elf/Object.zig

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
9393
);
9494
return error.InvalidCpuArch;
9595
}
96+
try elf_file.validateEFlags(self.index, self.header.?.e_flags);
9697

9798
if (self.header.?.e_shnum == 0) return;
9899

src/link/Elf/relocatable.zig

+10-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
1919

2020
for (positionals.items) |obj| {
2121
parsePositional(elf_file, obj.path) catch |err| switch (err) {
22-
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
22+
error.MalformedObject,
23+
error.MalformedArchive,
24+
error.InvalidCpuArch,
25+
error.MismatchedEflags,
26+
=> continue, // already reported
2327
error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
2428
else => |e| try elf_file.reportParseError(
2529
obj.path,
@@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
168172

169173
for (positionals.items) |obj| {
170174
elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
171-
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
175+
error.MalformedObject,
176+
error.MalformedArchive,
177+
error.InvalidCpuArch,
178+
error.MismatchedEflags,
179+
=> continue, // already reported
172180
else => |e| try elf_file.reportParseError(
173181
obj.path,
174182
"unexpected error: parsing input file failed with error {s}",

src/link/riscv.zig

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ fn bitSlice(
9595
return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
9696
}
9797

98+
pub const RiscvEflags = packed struct(u32) {
99+
rvc: bool,
100+
fabi: enum(u2) {
101+
soft = 0b00,
102+
single = 0b01,
103+
double = 0b10,
104+
quad = 0b11,
105+
},
106+
rve: bool,
107+
tso: bool,
108+
_reserved: u19,
109+
_unused: u8,
110+
};
111+
98112
const encoder = @import("../arch/riscv64/encoder.zig");
99113
const Encoding = @import("../arch/riscv64/Encoding.zig");
100114
const mem = std.mem;

0 commit comments

Comments
 (0)