From 9b9c1d8fe138bad6ecec5a32a180225b0c0c4826 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 22:15:46 +0800 Subject: [PATCH] loongarch: specify relocation type on reloc creation Previously relocation types are determined based on the opcode of target instructions. However, more than one relocation types can be applied on one opcode, when it comes to, for example, TLS. Therefore, the type of relocations should be determined when a relocation is added to the list. --- src/codegen/loongarch/Mir.zig | 110 ++++++------------------------- src/codegen/loongarch/Select.zig | 34 +++++----- 2 files changed, 40 insertions(+), 104 deletions(-) diff --git a/src/codegen/loongarch/Mir.zig b/src/codegen/loongarch/Mir.zig index 44f6cfd3165cdeb04d2f0e063d214b5da34be361..f81843ff4e24ce3c395cd250844e1bed9bb368cb 100644 --- a/src/codegen/loongarch/Mir.zig +++ b/src/codegen/loongarch/Mir.zig @@ -13,7 +13,8 @@ internal_relocs: []const Reloc.Internal, pub const Reloc = struct { label: u32, - addend: i64 align(@alignOf(u32)) = 0, + type: std.elf.R_LARCH, + addend: i64 = 0, pub const Nav = struct { nav: InternPool.Nav.Index, @@ -35,14 +36,10 @@ pub const Reloc = struct { reloc: Reloc, }; - pub const Literal = struct { - label: u32, - }; - pub const Internal = struct { // Target MIR index target: usize = 0, - label: u32, + reloc: Reloc, }; }; @@ -91,7 +88,7 @@ pub fn emit( pt, nav_reloc.nav, ), - mir.body[nav_reloc.reloc.label], + nav_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label), nav_reloc.reloc.addend, ) catch |err| @@ -105,7 +102,7 @@ pub fn emit( uav_reloc.uav.val, ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu), ), - mir.body[uav_reloc.reloc.label], + uav_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + uav_reloc.reloc.label), uav_reloc.reloc.addend, ) catch |err| @@ -122,7 +119,7 @@ pub fn emit( return zcu.codegenFail(func.owner_nav, "emit lazy symbol: {t}", .{err}) else return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), - mir.body[lazy_reloc.reloc.label], + lazy_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + lazy_reloc.reloc.label), lazy_reloc.reloc.addend, ) catch |err| @@ -139,7 +136,7 @@ pub fn emit( .type = .FUNC, }) catch |err| return zcu.codegenFail(func.owner_nav, "emit global symbol failed: {t}", .{err}) else return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), - mir.body[global_reloc.reloc.label], + global_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + global_reloc.reloc.label), global_reloc.reloc.addend, ) catch |err| @@ -155,8 +152,8 @@ pub fn emit( zcu, atom_index, func_nav, - mir.body[internal_reloc.label], - body_end - @sizeOf(Instruction) * (1 + internal_reloc.label), + internal_reloc.reloc.type, + body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label), @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))), ) catch |err| return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err}); @@ -182,86 +179,21 @@ fn emitReloc( zcu: *Zcu, atom_index: link.File.AtomId, sym_index: link.File.SymbolId, - instruction: Instruction, + reloc_type: std.elf.R_LARCH, offset: u32, addend: i64, ) !void { - const mnemonic = Disassemble.decodeMnemonic(instruction) orelse { - mir_log.debug("cannot decode instruction 0x{x}", .{instruction.word}); - unreachable; - }; - switch (mnemonic) { - else => { - mir_log.debug("unimplemented reloc on {t}", .{mnemonic}); - unreachable; - }, - .pcaddu18i => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .CALL36 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.CALL36), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .b, .bl => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B26 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B26), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .beq, .bne, .ble, .bgt, .bleu, .bgtu => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B16 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B16), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .beqz, .bnez, .bceqz, .bcnez => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B21 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B21), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .pcalau12i => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_HI20 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_HI20), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .@"addi.d" => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_LO12 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_LO12), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - } + if (lf.cast(.elf2)) |ef| { + try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = reloc_type }); + } else if (lf.cast(.elf)) |ef| { + const zo = ef.zigObjectPtr().?; + const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; + try atom.addReloc(zcu.gpa, .{ + .r_offset = offset, + .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(reloc_type), + .r_addend = @bitCast(addend), + }, zo); + } else unreachable; } const Air = @import("../../Air.zig"); diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index 1b1dd5a4b858d781c19461ffae00da265c6e77a0..ba97c62105485c98a9044dd6c9a75c332c4e933e 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -101,8 +101,8 @@ pub const Block = struct { fn branch(target_block: *Block, isel: *Select) !void { if (isel.instructions.items.len > target_block.target_label) { try isel.internal_relocs.append(isel.pt.zcu.gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = target_block.target_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.b(0, 0)); } @@ -1449,6 +1449,7 @@ pub const Value = struct { .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(total_root_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0)); @@ -1460,6 +1461,7 @@ pub const Value = struct { .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(total_root_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(ptr_reg, 0)); @@ -3164,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const next_repeat_label = instruction.*; instruction.* = .b(0, 0); try isel.internal_relocs.append(gpa, .{ - .label = repeat_label, .target = isel.instructions.items.len, + .reloc = .{ .label = repeat_label, .type = .B26 }, }); repeat_label = @bitCast(next_repeat_label); } @@ -3197,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, .extension = .zero_ext, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = else_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(cond_mat.reg(), 0, 0)); try cond_mat.finish(isel); @@ -3241,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = next_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.b(0, 0)); @@ -3268,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, defer isel.freeReg(item_reg); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = case_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 }, }); try isel.emit(.beq(cond_mat.reg(), item_reg, 0)); try isel.moveIntImm(item_reg, @bitCast(item_int)); @@ -3323,13 +3325,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, else => unreachable, inline .@"extern", .func => |func| .{ .nav = func.owner_nav, - .reloc = .{ .label = @intCast(isel.instructions.items.len) }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 }, }, .ptr => |ptr| .{ .nav = ptr.base_addr.nav, .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .CALL36, }, }, }); @@ -3920,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, .extension = .zero_ext, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cmp_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0)); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cmp_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(res_reg, 0, 0)); @@ -4274,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, ); const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cont_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0)); try error_set_part_mat.finish(isel); @@ -4312,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, defer isel.freeReg(tmp_reg); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cont_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.beqz(tmp_reg, 0, 0)); @@ -6467,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(rd, rd, 0)); @@ -6475,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(rd, 0)); @@ -6489,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(rd, rd, 0)); @@ -6497,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(rd, 0)); @@ -6752,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini // load constant pointer try isel.uav_relocs.append(zcu.gpa, .{ .uav = uav, - .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 }, }); try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0)); try isel.uav_relocs.append(zcu.gpa, .{ .uav = uav, - .reloc = .{ - .label = @intCast(isel.instructions.items.len), - .addend = 0, - }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_HI20 }, }); try isel.emit(.pcalau12i(tmp_reg, 0)); -- 2.54.0