diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 8 | ||||
| -rw-r--r-- | src/arch/riscv64/Emit.zig | 3 | ||||
| -rw-r--r-- | src/link/Elf.zig | 31 | ||||
| -rw-r--r-- | src/link/Elf/Atom.zig | 20 | ||||
| -rw-r--r-- | src/link/Elf/relocation.zig | 4 |
5 files changed, 60 insertions, 6 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 46140b4727..040afd3160 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1510,6 +1510,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { .mul, .mul_wrap, .div_trunc, + .div_exact, .rem, .shl, .shl_exact, @@ -1533,7 +1534,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { .mod, .div_float, .div_floor, - .div_exact, => return func.fail("TODO: {s}", .{@tagName(tag)}), .sqrt, @@ -2563,10 +2563,12 @@ fn genBinOp( .mul_wrap, .rem, .div_trunc, + .div_exact, => { switch (tag) { .rem, .div_trunc, + .div_exact, => { if (!math.isPowerOfTwo(bit_size)) { try func.truncateRegister(lhs_ty, lhs_reg); @@ -2576,7 +2578,7 @@ fn genBinOp( else => { if (!math.isPowerOfTwo(bit_size)) return func.fail( - "TODO: genBinOp verify {s} non-pow 2, found {}", + "TODO: genBinOp verify if needs to truncate {s} non-pow 2, found {}", .{ @tagName(tag), bit_size }, ); }, @@ -2604,7 +2606,7 @@ fn genBinOp( 8, 16, 32 => if (is_unsigned) .remuw else .remw, else => if (is_unsigned) .remu else .rem, }, - .div_trunc => switch (bit_size) { + .div_trunc, .div_exact => switch (bit_size) { 8, 16, 32 => if (is_unsigned) .divuw else .divw, else => if (is_unsigned) .divu else .div, }, diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig index 6c04988e78..beb232b776 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -63,6 +63,9 @@ pub fn emitMir(emit: *Emit) Error!void { hi_r_type = Elf.R_ZIG_GOT_HI20; lo_r_type = Elf.R_ZIG_GOT_LO12; + } else if (sym.flags.needs_got) { + hi_r_type = Elf.R_GOT_HI20_STATIC; // TODO: rework this #20887 + lo_r_type = Elf.R_GOT_LO12_I_STATIC; // TODO: rework this #20887 } try atom_ptr.addReloc(elf_file, .{ diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 982015f61f..469e8da345 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -6059,11 +6059,40 @@ const RelaSection = struct { }; const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); -// TODO: add comptime check we don't clobber any reloc for any ISA pub const R_ZIG_GOT32: u32 = 0xff00; pub const R_ZIG_GOTPCREL: u32 = 0xff01; pub const R_ZIG_GOT_HI20: u32 = 0xff02; pub const R_ZIG_GOT_LO12: u32 = 0xff03; +pub const R_GOT_HI20_STATIC: u32 = 0xff04; +pub const R_GOT_LO12_I_STATIC: u32 = 0xff05; + +// Comptime asserts that no Zig relocs overlap with another ISA's reloc number +comptime { + const zig_relocs = .{ + R_ZIG_GOT32, + R_ZIG_GOT_HI20, + R_ZIG_GOT_LO12, + R_ZIG_GOTPCREL, + R_GOT_HI20_STATIC, + R_GOT_LO12_I_STATIC, + }; + + const other_relocs = .{ + elf.R_X86_64, + elf.R_AARCH64, + elf.R_RISCV, + elf.R_PPC64, + }; + + @setEvalBranchQuota(@min(other_relocs.len * zig_relocs.len * 256, 6200)); + for (other_relocs) |relocs| { + for (@typeInfo(relocs).Enum.fields) |reloc| { + for (zig_relocs) |zig_reloc| { + assert(reloc.value != zig_reloc); + } + } + } +} fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { return switch (cpu_arch) { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 30285f204a..b91b546103 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -2016,6 +2016,10 @@ const riscv = struct { assert(symbol.flags.has_zig_got); }, + Elf.R_GOT_HI20_STATIC, + Elf.R_GOT_LO12_I_STATIC, + => symbol.flags.needs_got = true, + else => try atom.reportUnhandledRelocError(rel, elf_file), }, } @@ -2161,16 +2165,28 @@ const riscv = struct { // Zig custom relocations Elf.R_ZIG_GOT_HI20 => { assert(target.flags.has_zig_got); - const disp: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow); + const disp: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); riscv_util.writeInstU(code[r_offset..][0..4], disp); }, Elf.R_ZIG_GOT_LO12 => { assert(target.flags.has_zig_got); - const value: u32 = @bitCast(math.cast(i32, G + ZIG_GOT + A) orelse return error.Overflow); + const value: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); riscv_util.writeInstI(code[r_offset..][0..4], value); }, + Elf.R_GOT_HI20_STATIC => { + assert(target.flags.has_got); + const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow); + riscv_util.writeInstU(code[r_offset..][0..4], disp); + }, + + Elf.R_GOT_LO12_I_STATIC => { + assert(target.flags.has_got); + const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow); + riscv_util.writeInstI(code[r_offset..][0..4], disp); + }, + else => try atom.reportUnhandledRelocError(rel, elf_file), }, } diff --git a/src/link/Elf/relocation.zig b/src/link/Elf/relocation.zig index 3c8afa3c12..5f6810d6f9 100644 --- a/src/link/Elf/relocation.zig +++ b/src/link/Elf/relocation.zig @@ -115,6 +115,10 @@ fn formatRelocType( switch (r_type) { Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"), Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"), + Elf.R_ZIG_GOT_HI20 => try writer.writeAll("R_ZIG_GOT_HI20"), + Elf.R_ZIG_GOT_LO12 => try writer.writeAll("R_ZIG_GOT_LO12"), + Elf.R_GOT_HI20_STATIC => try writer.writeAll("R_GOT_HI20_STATIC"), + Elf.R_GOT_LO12_I_STATIC => try writer.writeAll("R_GOT_LO12_I_STATIC"), else => 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)))}), |
