diff options
| author | Alex Rønne Petersen <alex@alexrp.com> | 2025-08-24 21:23:45 +0200 |
|---|---|---|
| committer | Alex Rønne Petersen <alex@alexrp.com> | 2025-08-25 16:15:17 +0200 |
| commit | 5d019abe4ec70373db7a75c2a8a3e2d76939817c (patch) | |
| tree | 4ca5e04afceab7cc8e363d7adfe0436f54a3e82a /src | |
| parent | 12686d9b7df8fe4c2663cd8e2136991dc3cf661c (diff) | |
| download | zig-5d019abe4ec70373db7a75c2a8a3e2d76939817c.tar.gz zig-5d019abe4ec70373db7a75c2a8a3e2d76939817c.zip | |
start adding big endian RISC-V support
The big endian RISC-V effort is mostly driven by MIPS (the company) which is
pivoting to RISC-V, and presumably needs a big endian variant to fill the niche
that big endian MIPS (the ISA) did.
GCC already supports these targets, but LLVM support will only appear in 22;
this commit just adds the necessary target knowledge and checks on our end.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 2 | ||||
| -rw-r--r-- | src/Zcu.zig | 2 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 18 | ||||
| -rw-r--r-- | src/link/Elf.zig | 16 | ||||
| -rw-r--r-- | src/link/Elf/Atom.zig | 12 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 6 | ||||
| -rw-r--r-- | src/link/Elf/Thunk.zig | 8 | ||||
| -rw-r--r-- | src/link/Elf/eh_frame.zig | 4 | ||||
| -rw-r--r-- | src/link/Elf/relocation.zig | 20 | ||||
| -rw-r--r-- | src/link/Lld.zig | 2 | ||||
| -rw-r--r-- | src/target.zig | 10 |
11 files changed, 60 insertions, 40 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index db15eee954..933774afc7 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -7051,7 +7051,7 @@ pub fn addCCArgs( // compiler frontend does. Therefore we must hard-code the -m flags for // all CPU features here. switch (target.cpu.arch) { - .riscv32, .riscv64 => { + .riscv32, .riscv32be, .riscv64, .riscv64be => { const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature }; const letters = [_]RvArchFeat{ .{ .char = 'm', .feat = .m }, diff --git a/src/Zcu.zig b/src/Zcu.zig index 53da90a9c2..97d1b821f1 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3850,6 +3850,7 @@ pub fn atomicPtrAlignment( .powerpc, .powerpcle, .riscv32, + .riscv32be, .sparc, .thumb, .thumbeb, @@ -3874,6 +3875,7 @@ pub fn atomicPtrAlignment( .powerpc64, .powerpc64le, .riscv64, + .riscv64be, .sparc64, .s390x, .wasm64, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 9d58dbd869..270149ffb9 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -82,7 +82,9 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 .powerpc64le => "powerpc64le", .amdgcn => "amdgcn", .riscv32 => "riscv32", + .riscv32be => "riscv32be", .riscv64 => "riscv64", + .riscv64be => "riscv64be", .sparc => "sparc", .sparc64 => "sparc64", .s390x => "s390x", @@ -397,10 +399,18 @@ pub fn dataLayout(target: *const std.Target) []const u8 { "e-m:e-p:32:32-i64:64-n32-S32" else "e-m:e-p:32:32-i64:64-n32-S128", + .riscv32be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:32:32-i64:64-n32-S32" + else + "E-m:e-p:32:32-i64:64-n32-S128", .riscv64 => if (target.cpu.has(.riscv, .e)) "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64" else "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", + .riscv64be => if (target.cpu.has(.riscv, .e)) + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S64" + else + "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128", .sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64", .sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128", .s390x => if (target.os.tag == .zos) @@ -12224,8 +12234,8 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), .double_integer => { const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) { - .riscv64 => .i64, - .riscv32 => .i32, + .riscv64, .riscv64be => .i64, + .riscv32, .riscv32be => .i32, else => unreachable, }; return o.builder.structType(.normal, &.{ integer, integer }); @@ -12685,7 +12695,7 @@ fn ccAbiPromoteInt( else => null, }, else => switch (target.cpu.arch) { - .loongarch64, .riscv64 => switch (int_info.bits) { + .loongarch64, .riscv64, .riscv64be => switch (int_info.bits) { 0...16 => int_info.signedness, 32 => .signed, // LLVM always signextends 32 bit ints, unsure if bug. 17...31, 33...63 => int_info.signedness, @@ -13079,7 +13089,7 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { llvm.LLVMInitializePowerPCAsmPrinter(); llvm.LLVMInitializePowerPCAsmParser(); }, - .riscv32, .riscv64 => { + .riscv32, .riscv32be, .riscv64, .riscv64be => { llvm.LLVMInitializeRISCVTarget(); llvm.LLVMInitializeRISCVTargetInfo(); llvm.LLVMInitializeRISCVTargetMC(); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 99d0ad71b0..0ebbb9f27e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3722,8 +3722,8 @@ pub fn tpAddress(self: *Elf) i64 { const phdr = self.phdrs.items[index]; const addr = switch (self.getTarget().cpu.arch) { .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), - .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), - .riscv64 => phdr.p_vaddr, + .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), + .riscv64, .riscv64be => phdr.p_vaddr, else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}), }; return @intCast(addr); @@ -4099,8 +4099,8 @@ pub fn getTarget(self: *const Elf) *const std.Target { fn requiresThunks(self: Elf) bool { return switch (self.getTarget().cpu.arch) { - .aarch64 => true, - .x86_64, .riscv64 => false, + .aarch64, .aarch64_be => true, + .x86_64, .riscv64, .riscv64be => false, else => @panic("TODO unimplemented architecture"), }; } @@ -4345,8 +4345,8 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { // A branch will need an extender if its target is larger than // `2^(jump_bits - 1) - margin` where margin is some arbitrary number. const max_distance = switch (cpu_arch) { - .aarch64 => 0x500_000, - .x86_64, .riscv64 => unreachable, + .aarch64, .aarch64_be => 0x500_000, + .x86_64, .riscv64, .riscv64be => unreachable, else => @panic("unhandled arch"), }; @@ -4392,7 +4392,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { log.debug("atom({f}) {s}", .{ ref, atom_ptr.name(elf_file) }); for (atom_ptr.relocs(elf_file)) |rel| { const is_reachable = switch (cpu_arch) { - .aarch64 => r: { + .aarch64, .aarch64_be => r: { const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); if (r_type != .CALL26 and r_type != .JUMP26) break :r true; const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file); @@ -4406,7 +4406,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { _ = math.cast(i28, taddr + rel.r_addend - saddr) orelse break :r false; break :r true; }, - .x86_64, .riscv64 => unreachable, + .x86_64, .riscv64, .riscv64be => unreachable, else => @panic("unsupported arch"), }; if (is_reachable) continue; diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index e3d17c0563..28899838b1 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -346,11 +346,11 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .aarch64 => aarch64.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) { + .aarch64, .aarch64_be => aarch64.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .riscv64 => riscv.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) { + .riscv64, .riscv64be => riscv.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, @@ -674,7 +674,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi => has_reloc_errors = true, else => |e| return e, }, - .aarch64 => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { error.RelocFailure, error.RelaxFailure, error.UnexpectedRemainder, @@ -682,7 +682,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi => has_reloc_errors = true, else => |e| return e, }, - .riscv64 => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { error.RelocFailure, error.RelaxFailure, => has_reloc_errors = true, @@ -870,11 +870,11 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .aarch64 => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .riscv64 => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index a330a184be..921b5eb733 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -189,7 +189,7 @@ pub fn validateEFlags( e_flags: elf.Word, ) !void { switch (target.cpu.arch) { - .riscv64 => { + .riscv64, .riscv64be => { const flags: riscv.Eflags = @bitCast(e_flags); var any_errors: bool = false; @@ -366,7 +366,7 @@ fn initAtoms( const rel_count: u32 = @intCast(relocs.len); self.setAtomFields(atom_ptr, .{ .rel_index = rel_index, .rel_count = rel_count }); try self.relocs.appendUnalignedSlice(gpa, relocs); - if (target.cpu.arch == .riscv64) { + if (target.cpu.arch.isRiscv64()) { sortRelocs(self.relocs.items[rel_index..][0..rel_count]); } } @@ -445,7 +445,7 @@ fn parseEhFrame( // We expect relocations to be sorted by r_offset as per this comment in mold linker: // https://github.com/rui314/mold/blob/8e4f7b53832d8af4f48a633a8385cbc932d1944e/src/input-files.cc#L653 // Except for RISCV and Loongarch which do not seem to be uphold this convention. - if (target.cpu.arch == .riscv64) { + if (target.cpu.arch.isRiscv64()) { sortRelocs(self.relocs.items[rel_start..][0..relocs.len]); } const fdes_start = self.fdes.items.len; diff --git a/src/link/Elf/Thunk.zig b/src/link/Elf/Thunk.zig index 59b867be78..db174c157f 100644 --- a/src/link/Elf/Thunk.zig +++ b/src/link/Elf/Thunk.zig @@ -24,8 +24,8 @@ pub fn targetAddress(thunk: Thunk, ref: Elf.Ref, elf_file: *Elf) i64 { pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { switch (elf_file.getTarget().cpu.arch) { - .aarch64 => try aarch64.write(thunk, elf_file, writer), - .x86_64, .riscv64 => unreachable, + .aarch64, .aarch64_be => try aarch64.write(thunk, elf_file, writer), + .x86_64, .riscv64, .riscv64be => unreachable, else => @panic("unhandled arch"), } } @@ -59,8 +59,8 @@ pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void { fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize { return switch (cpu_arch) { - .aarch64 => aarch64.trampoline_size, - .x86_64, .riscv64 => unreachable, + .aarch64, .aarch64_be => aarch64.trampoline_size, + .x86_64, .riscv64, .riscv64be => unreachable, else => @panic("unhandled arch"), }; } diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index ee1e0c5f5d..9baa2702ca 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -286,8 +286,8 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: switch (cpu_arch) { .x86_64 => try x86_64.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]), - .aarch64 => try aarch64.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]), - .riscv64 => try riscv.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]), + .aarch64, .aarch64_be => try aarch64.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]), + .riscv64, .riscv64be => try riscv.resolveReloc(rec, elf_file, rel, P, S + A, contents[offset..]), else => return error.UnsupportedCpuArch, } } diff --git a/src/link/Elf/relocation.zig b/src/link/Elf/relocation.zig index 366d19d9b3..9271d07ae1 100644 --- a/src/link/Elf/relocation.zig +++ b/src/link/Elf/relocation.zig @@ -76,8 +76,8 @@ const riscv64_relocs = Table(11, elf.R_RISCV, .{ pub fn decode(r_type: u32, cpu_arch: std.Target.Cpu.Arch) ?Kind { return switch (cpu_arch) { .x86_64 => x86_64_relocs.decode(r_type), - .aarch64 => aarch64_relocs.decode(r_type), - .riscv64 => riscv64_relocs.decode(r_type), + .aarch64, .aarch64_be => aarch64_relocs.decode(r_type), + .riscv64, .riscv64be => riscv64_relocs.decode(r_type), else => @panic("TODO unhandled cpu arch"), }; } @@ -85,8 +85,8 @@ pub fn decode(r_type: u32, cpu_arch: std.Target.Cpu.Arch) ?Kind { pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 { return switch (cpu_arch) { .x86_64 => x86_64_relocs.encode(kind), - .aarch64 => aarch64_relocs.encode(kind), - .riscv64 => riscv64_relocs.encode(kind), + .aarch64, .aarch64_be => aarch64_relocs.encode(kind), + .riscv64, .riscv64be => riscv64_relocs.encode(kind), else => @panic("TODO unhandled cpu arch"), }; } @@ -98,11 +98,11 @@ pub const dwarf = struct { .@"32" => .@"32", .@"64" => .@"64", })), - .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (format) { + .aarch64, .aarch64_be => @intFromEnum(@as(elf.R_AARCH64, switch (format) { .@"32" => .ABS32, .@"64" => .ABS64, })), - .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (format) { + .riscv64, .riscv64be => @intFromEnum(@as(elf.R_RISCV, switch (format) { .@"32" => .@"32", .@"64" => .@"64", })), @@ -125,7 +125,7 @@ pub const dwarf = struct { }, .debug_frame => .PC32, })), - .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (source_section) { + .aarch64, .aarch64_be => @intFromEnum(@as(elf.R_AARCH64, switch (source_section) { else => switch (address_size) { .@"32" => .ABS32, .@"64" => .ABS64, @@ -133,7 +133,7 @@ pub const dwarf = struct { }, .debug_frame => .PREL32, })), - .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (source_section) { + .riscv64, .riscv64be => @intFromEnum(@as(elf.R_RISCV, switch (source_section) { else => switch (address_size) { .@"32" => .@"32", .@"64" => .@"64", @@ -164,8 +164,8 @@ fn formatRelocType(ctx: FormatRelocTypeCtx, writer: *std.io.Writer) std.io.Write const r_type = ctx.r_type; switch (ctx.cpu_arch) { .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}), - .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}), - .riscv64 => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}), + .aarch64, .aarch64_be => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}), + .riscv64, .riscv64be => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}), else => unreachable, } } diff --git a/src/link/Lld.zig b/src/link/Lld.zig index 48872f7077..e271c973a3 100644 --- a/src/link/Lld.zig +++ b/src/link/Lld.zig @@ -1342,7 +1342,9 @@ fn getLDMOption(target: *const std.Target) ?[]const u8 { .powerpc64 => "elf64ppc", .powerpc64le => "elf64lppc", .riscv32 => "elf32lriscv", + .riscv32be => "elf32briscv", .riscv64 => "elf64lriscv", + .riscv64be => "elf64briscv", .s390x => "elf64_s390", .sparc64 => "elf64_sparc", .x86 => switch (target.os.tag) { diff --git a/src/target.zig b/src/target.zig index ee9d39fbf3..e999d2ae22 100644 --- a/src/target.zig +++ b/src/target.zig @@ -189,7 +189,9 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat) .powerpc64le, .amdgcn, .riscv32, + .riscv32be, .riscv64, + .riscv64be, .sparc, .sparc64, .spirv32, @@ -486,7 +488,9 @@ pub fn clangSupportsNoImplicitFloatArg(target: *const std.Target) bool { .thumb, .thumbeb, .riscv32, + .riscv32be, .riscv64, + .riscv64be, .x86, .x86_64, => true, @@ -655,7 +659,7 @@ pub fn llvmMachineAbi(target: *const std.Target) ?[:0]const u8 { else => if (target.abi.isMusl()) "elfv2" else "elfv1", }, .powerpc64le => "elfv2", - .riscv64 => if (target.cpu.has(.riscv, .e)) + .riscv64, .riscv64be => if (target.cpu.has(.riscv, .e)) "lp64e" else if (target.cpu.has(.riscv, .d)) "lp64d" @@ -663,7 +667,7 @@ pub fn llvmMachineAbi(target: *const std.Target) ?[:0]const u8 { "lp64f" else "lp64", - .riscv32 => if (target.cpu.has(.riscv, .e)) + .riscv32, .riscv32be => if (target.cpu.has(.riscv, .e)) "ilp32e" else if (target.cpu.has(.riscv, .d)) "ilp32d" @@ -707,7 +711,9 @@ pub fn defaultFunctionAlignment(target: *const std.Target) Alignment { pub fn minFunctionAlignment(target: *const std.Target) Alignment { return switch (target.cpu.arch) { .riscv32, + .riscv32be, .riscv64, + .riscv64be, => if (target.cpu.hasAny(.riscv, &.{ .c, .zca })) .@"2" else .@"4", .thumb, .thumbeb, |
