From fcff82feb2565b427349927624da85089f5e3601 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Fri, 19 Jul 2024 23:37:17 -0700 Subject: [PATCH 1/2] dev: add riscv64-linux support --- src/dev.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/dev.zig b/src/dev.zig index fc518e93b6..9746b307af 100644 --- a/src/dev.zig +++ b/src/dev.zig @@ -26,6 +26,10 @@ pub const Env = enum { /// - `zig build-* -fno-llvm -fno-lld -target x86_64-linux` @"x86_64-linux", + /// - sema + /// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux` + @"riscv64-linux", + pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool { return switch (dev_env) { .full => true, @@ -131,6 +135,12 @@ pub const Env = enum { => true, else => Env.sema.supports(feature), }, + .@"riscv64-linux" => switch (feature) { + .riscv64_backend, + .elf_linker, + => true, + else => Env.sema.supports(feature), + }, }; } From 782a9d16c7e5a2023b3cd7bc763c0cb210b86412 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Mon, 22 Jul 2024 18:01:26 -0700 Subject: [PATCH 2/2] elf: add riscv eflag collisions --- src/link/Elf.zig | 64 ++++++++++++++++++++++++++++++++---- src/link/Elf/Object.zig | 1 + src/link/Elf/relocatable.zig | 12 +++++-- src/link/riscv.zig | 14 ++++++++ 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 7b44403c8a..573c6e6704 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{} /// such as `resolver` and `comdat_groups_table`. strings: StringTable = .{}, +first_eflags: ?elf.Elf64_Word = null, + /// When allocating, the ideal_capacity is calculated by /// actual_capacity + (actual_capacity / ideal_factor) const ideal_factor = 3; @@ -553,7 +555,7 @@ pub fn lowerAnonDecl( pt: Zcu.PerThread, decl_val: InternPool.Index, explicit_alignment: InternPool.Alignment, - src_loc: Module.LazySrcLoc, + src_loc: Zcu.LazySrcLoc, ) !codegen.Result { return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc); } @@ -1158,7 +1160,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod for (positionals.items) |obj| { self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, + error.MalformedArchive, + error.MismatchedEflags, + error.InvalidCpuArch, + => continue, // already reported else => |e| try self.reportParseError( obj.path, "unexpected error: parsing input file failed with error {s}", @@ -1267,7 +1273,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod for (positionals.items) |obj| { self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, + error.MalformedArchive, + error.MismatchedEflags, + error.InvalidCpuArch, + => continue, // already reported else => |e| try self.reportParseError( obj.path, "unexpected error: parsing input file failed with error {s}", @@ -1693,6 +1703,7 @@ pub const ParseError = error{ MalformedObject, MalformedArchive, InvalidCpuArch, + MismatchedEflags, OutOfMemory, Overflow, InputOutput, @@ -1872,6 +1883,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { } } +pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void { + const target = self.base.comp.root_mod.resolved_target.result; + + if (self.first_eflags == null) { + self.first_eflags = e_flags; + return; // there isn't anything to conflict with yet + } + const self_eflags: *elf.Elf64_Word = &self.first_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 is_error: bool = false; + if (self_riscv_eflags.fabi != riscv_eflags.fabi) { + is_error = true; + _ = try self.reportParseError2( + file_index, + "cannot link object files with different float-point ABIs", + .{}, + ); + } + if (self_riscv_eflags.rve != riscv_eflags.rve) { + is_error = true; + _ = try self.reportParseError2( + file_index, + "cannot link object files with different RVEs", + .{}, + ); + } + if (is_error) return error.MismatchedEflags; + } + }, + else => {}, + } +} + fn accessLibPath( self: *Elf, arena: Allocator, @@ -3013,7 +3066,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index: pub fn updateExports( self: *Elf, pt: Zcu.PerThread, - exported: Module.Exported, + exported: Zcu.Exported, export_indices: []const u32, ) link.File.UpdateExportsError!void { if (build_options.skip_non_native and builtin.object_format != .elf) { @@ -6471,8 +6524,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object; const MergeSection = merge_section.MergeSection; const MergeSubsection = merge_section.MergeSubsection; const Zcu = @import("../Zcu.zig"); -/// Deprecated. -const Module = Zcu; const Object = @import("Elf/Object.zig"); const InternPool = @import("../InternPool.zig"); const PltSection = synthetic_sections.PltSection; @@ -6485,3 +6536,4 @@ const Value = @import("../Value.zig"); const VerneedSection = synthetic_sections.VerneedSection; const ZigGotSection = synthetic_sections.ZigGotSection; const ZigObject = @import("Elf/ZigObject.zig"); +const riscv = @import("riscv.zig"); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index c0e6266bb7..768d11f709 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil ); return error.InvalidCpuArch; } + try elf_file.validateEFlags(self.index, self.header.?.e_flags); if (self.header.?.e_shnum == 0) return; diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index c70faba020..a881a606e9 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co for (positionals.items) |obj| { parsePositional(elf_file, obj.path) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, + error.MalformedArchive, + error.InvalidCpuArch, + error.MismatchedEflags, + => continue, // already reported error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}), else => |e| try elf_file.reportParseError( obj.path, @@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const for (positionals.items) |obj| { elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, + error.MalformedArchive, + error.InvalidCpuArch, + error.MismatchedEflags, + => continue, // already reported else => |e| try elf_file.reportParseError( obj.path, "unexpected error: parsing input file failed with error {s}", diff --git a/src/link/riscv.zig b/src/link/riscv.zig index e78cb84cdf..5107992b48 100644 --- a/src/link/riscv.zig +++ b/src/link/riscv.zig @@ -95,6 +95,20 @@ fn bitSlice( return @truncate((value >> low) & (1 << (high - low + 1)) - 1); } +pub const RiscvEflags = packed struct(u32) { + rvc: bool, + fabi: enum(u2) { + soft = 0b00, + single = 0b01, + double = 0b10, + quad = 0b11, + }, + rve: bool, + tso: bool, + _reserved: u19, + _unused: u8, +}; + const encoder = @import("../arch/riscv64/encoder.zig"); const Encoding = @import("../arch/riscv64/Encoding.zig"); const mem = std.mem;