authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-23 22:29:57+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-23 22:29:57+02:00
log7aaebd17746dc97111585563c64e166e27b334af
treea2816ee7130714aa104fa179e1c38db1b50e220a
parent2e8acdf6fa0336809a2ddcd197f99a3548205768
parent782a9d16c7e5a2023b3cd7bc763c0cb210b86412
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20751 from Rexicon226/riscv-eflags

elf: add riscv eflag collisions

5 files changed, 93 insertions(+), 8 deletions(-)

src/dev.zig+10
...@@ -26,6 +26,10 @@ pub const Env = enum {...@@ -26,6 +26,10 @@ pub const Env = enum {
26 /// - `zig build-* -fno-llvm -fno-lld -target x86_64-linux`26 /// - `zig build-* -fno-llvm -fno-lld -target x86_64-linux`
27 @"x86_64-linux",27 @"x86_64-linux",
2828
29 /// - sema
30 /// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux`
31 @"riscv64-linux",
32
29 pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {33 pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
30 return switch (dev_env) {34 return switch (dev_env) {
31 .full => true,35 .full => true,
...@@ -131,6 +135,12 @@ pub const Env = enum {...@@ -131,6 +135,12 @@ pub const Env = enum {
131 => true,135 => true,
132 else => Env.sema.supports(feature),136 else => Env.sema.supports(feature),
133 },137 },
138 .@"riscv64-linux" => switch (feature) {
139 .riscv64_backend,
140 .elf_linker,
141 => true,
142 else => Env.sema.supports(feature),
143 },
134 };144 };
135 }145 }
136146
src/link/Elf.zig+58-6
...@@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}...@@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}
229/// such as `resolver` and `comdat_groups_table`.229/// such as `resolver` and `comdat_groups_table`.
230strings: StringTable = .{},230strings: StringTable = .{},
231231
232first_eflags: ?elf.Elf64_Word = null,
233
232/// When allocating, the ideal_capacity is calculated by234/// When allocating, the ideal_capacity is calculated by
233/// actual_capacity + (actual_capacity / ideal_factor)235/// actual_capacity + (actual_capacity / ideal_factor)
234const ideal_factor = 3;236const ideal_factor = 3;
...@@ -553,7 +555,7 @@ pub fn lowerAnonDecl(...@@ -553,7 +555,7 @@ pub fn lowerAnonDecl(
553 pt: Zcu.PerThread,555 pt: Zcu.PerThread,
554 decl_val: InternPool.Index,556 decl_val: InternPool.Index,
555 explicit_alignment: InternPool.Alignment,557 explicit_alignment: InternPool.Alignment,
556 src_loc: Module.LazySrcLoc,558 src_loc: Zcu.LazySrcLoc,
557) !codegen.Result {559) !codegen.Result {
558 return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc);560 return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc);
559}561}
...@@ -1161,7 +1163,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1161,7 +1163,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
11611163
1162 for (positionals.items) |obj| {1164 for (positionals.items) |obj| {
1163 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {1165 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1164 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported1166 error.MalformedObject,
1167 error.MalformedArchive,
1168 error.MismatchedEflags,
1169 error.InvalidCpuArch,
1170 => continue, // already reported
1165 else => |e| try self.reportParseError(1171 else => |e| try self.reportParseError(
1166 obj.path,1172 obj.path,
1167 "unexpected error: parsing input file failed with error {s}",1173 "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...@@ -1270,7 +1276,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
12701276
1271 for (positionals.items) |obj| {1277 for (positionals.items) |obj| {
1272 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {1278 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1273 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported1279 error.MalformedObject,
1280 error.MalformedArchive,
1281 error.MismatchedEflags,
1282 error.InvalidCpuArch,
1283 => continue, // already reported
1274 else => |e| try self.reportParseError(1284 else => |e| try self.reportParseError(
1275 obj.path,1285 obj.path,
1276 "unexpected error: parsing input file failed with error {s}",1286 "unexpected error: parsing input file failed with error {s}",
...@@ -1700,6 +1710,7 @@ pub const ParseError = error{...@@ -1700,6 +1710,7 @@ pub const ParseError = error{
1700 MalformedObject,1710 MalformedObject,
1701 MalformedArchive,1711 MalformedArchive,
1702 InvalidCpuArch,1712 InvalidCpuArch,
1713 MismatchedEflags,
1703 OutOfMemory,1714 OutOfMemory,
1704 Overflow,1715 Overflow,
1705 InputOutput,1716 InputOutput,
...@@ -1879,6 +1890,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {...@@ -1879,6 +1890,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
1879 }1890 }
1880}1891}
18811892
1893pub 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
1882fn accessLibPath(1935fn accessLibPath(
1883 self: *Elf,1936 self: *Elf,
1884 arena: Allocator,1937 arena: Allocator,
...@@ -3025,7 +3078,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index:...@@ -3025,7 +3078,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index:
3025pub fn updateExports(3078pub fn updateExports(
3026 self: *Elf,3079 self: *Elf,
3027 pt: Zcu.PerThread,3080 pt: Zcu.PerThread,
3028 exported: Module.Exported,3081 exported: Zcu.Exported,
3029 export_indices: []const u32,3082 export_indices: []const u32,
3030) link.File.UpdateExportsError!void {3083) link.File.UpdateExportsError!void {
3031 if (build_options.skip_non_native and builtin.object_format != .elf) {3084 if (build_options.skip_non_native and builtin.object_format != .elf) {
...@@ -6432,8 +6485,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;...@@ -6432,8 +6485,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
6432const MergeSection = merge_section.MergeSection;6485const MergeSection = merge_section.MergeSection;
6433const MergeSubsection = merge_section.MergeSubsection;6486const MergeSubsection = merge_section.MergeSubsection;
6434const Zcu = @import("../Zcu.zig");6487const Zcu = @import("../Zcu.zig");
6435/// Deprecated.
6436const Module = Zcu;
6437const Object = @import("Elf/Object.zig");6488const Object = @import("Elf/Object.zig");
6438const InternPool = @import("../InternPool.zig");6489const InternPool = @import("../InternPool.zig");
6439const PltSection = synthetic_sections.PltSection;6490const PltSection = synthetic_sections.PltSection;
...@@ -6446,3 +6497,4 @@ const Value = @import("../Value.zig");...@@ -6446,3 +6497,4 @@ const Value = @import("../Value.zig");
6446const VerneedSection = synthetic_sections.VerneedSection;6497const VerneedSection = synthetic_sections.VerneedSection;
6447const ZigGotSection = synthetic_sections.ZigGotSection;6498const ZigGotSection = synthetic_sections.ZigGotSection;
6448const ZigObject = @import("Elf/ZigObject.zig");6499const ZigObject = @import("Elf/ZigObject.zig");
6500const riscv = @import("riscv.zig");
src/link/Elf/Object.zig+1
...@@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil...@@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
93 );93 );
94 return error.InvalidCpuArch;94 return error.InvalidCpuArch;
95 }95 }
96 try elf_file.validateEFlags(self.index, self.header.?.e_flags);
9697
97 if (self.header.?.e_shnum == 0) return;98 if (self.header.?.e_shnum == 0) return;
9899
src/link/Elf/relocatable.zig+10-2
...@@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co...@@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
1919
20 for (positionals.items) |obj| {20 for (positionals.items) |obj| {
21 parsePositional(elf_file, obj.path) catch |err| switch (err) {21 parsePositional(elf_file, obj.path) catch |err| switch (err) {
22 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported22 error.MalformedObject,
23 error.MalformedArchive,
24 error.InvalidCpuArch,
25 error.MismatchedEflags,
26 => continue, // already reported
23 error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}),27 error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
24 else => |e| try elf_file.reportParseError(28 else => |e| try elf_file.reportParseError(
25 obj.path,29 obj.path,
...@@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const...@@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
168172
169 for (positionals.items) |obj| {173 for (positionals.items) |obj| {
170 elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {174 elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
171 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported175 error.MalformedObject,
176 error.MalformedArchive,
177 error.InvalidCpuArch,
178 error.MismatchedEflags,
179 => continue, // already reported
172 else => |e| try elf_file.reportParseError(180 else => |e| try elf_file.reportParseError(
173 obj.path,181 obj.path,
174 "unexpected error: parsing input file failed with error {s}",182 "unexpected error: parsing input file failed with error {s}",
src/link/riscv.zig+14
...@@ -95,6 +95,20 @@ fn bitSlice(...@@ -95,6 +95,20 @@ fn bitSlice(
95 return @truncate((value >> low) & (1 << (high - low + 1)) - 1);95 return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
96}96}
9797
98pub 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
98const encoder = @import("../arch/riscv64/encoder.zig");112const encoder = @import("../arch/riscv64/encoder.zig");
99const Encoding = @import("../arch/riscv64/Encoding.zig");113const Encoding = @import("../arch/riscv64/Encoding.zig");
100const mem = std.mem;114const mem = std.mem;