authorgravatar for xtex@astrafall.orgxtex <xtex@astrafall.org> 2026-08-30 22:15:46+08:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-30 22:54:04+02:00
log9b9c1d8fe138bad6ecec5a32a180225b0c0c4826
tree7da6ddc46ab4103930598cad379163278658c7e7
parentcca7c50b54bbf5d763da839582edff69bd9d051d

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.

2 files changed, 40 insertions(+), 104 deletions(-)

src/codegen/loongarch/Mir.zig+21-89
......@@ -13,7 +13,8 @@ internal_relocs: []const Reloc.Internal,
1313
1414pub const Reloc = struct {
1515 label: u32,
16 addend: i64 align(@alignOf(u32)) = 0,
16 type: std.elf.R_LARCH,
17 addend: i64 = 0,
1718
1819 pub const Nav = struct {
1920 nav: InternPool.Nav.Index,
......@@ -35,14 +36,10 @@ pub const Reloc = struct {
3536 reloc: Reloc,
3637 };
3738
38 pub const Literal = struct {
39 label: u32,
40 };
41
4239 pub const Internal = struct {
4340 // Target MIR index
4441 target: usize = 0,
45 label: u32,
42 reloc: Reloc,
4643 };
4744};
4845
......@@ -91,7 +88,7 @@ pub fn emit(
9188 pt,
9289 nav_reloc.nav,
9390 ),
94 mir.body[nav_reloc.reloc.label],
91 nav_reloc.reloc.type,
9592 body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label),
9693 nav_reloc.reloc.addend,
9794 ) catch |err|
......@@ -105,7 +102,7 @@ pub fn emit(
105102 uav_reloc.uav.val,
106103 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
107104 ),
108 mir.body[uav_reloc.reloc.label],
105 uav_reloc.reloc.type,
109106 body_end - @sizeOf(Instruction) * (1 + uav_reloc.reloc.label),
110107 uav_reloc.reloc.addend,
111108 ) catch |err|
......@@ -122,7 +119,7 @@ pub fn emit(
122119 return zcu.codegenFail(func.owner_nav, "emit lazy symbol: {t}", .{err})
123120 else
124121 return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
125 mir.body[lazy_reloc.reloc.label],
122 lazy_reloc.reloc.type,
126123 body_end - @sizeOf(Instruction) * (1 + lazy_reloc.reloc.label),
127124 lazy_reloc.reloc.addend,
128125 ) catch |err|
......@@ -139,7 +136,7 @@ pub fn emit(
139136 .type = .FUNC,
140137 }) catch |err|
141138 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)}),
142 mir.body[global_reloc.reloc.label],
139 global_reloc.reloc.type,
143140 body_end - @sizeOf(Instruction) * (1 + global_reloc.reloc.label),
144141 global_reloc.reloc.addend,
145142 ) catch |err|
......@@ -155,8 +152,8 @@ pub fn emit(
155152 zcu,
156153 atom_index,
157154 func_nav,
158 mir.body[internal_reloc.label],
159 body_end - @sizeOf(Instruction) * (1 + internal_reloc.label),
155 internal_reloc.reloc.type,
156 body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label),
160157 @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))),
161158 ) catch |err|
162159 return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err});
......@@ -182,86 +179,21 @@ fn emitReloc(
182179 zcu: *Zcu,
183180 atom_index: link.File.AtomId,
184181 sym_index: link.File.SymbolId,
185 instruction: Instruction,
182 reloc_type: std.elf.R_LARCH,
186183 offset: u32,
187184 addend: i64,
188185) !void {
189 const mnemonic = Disassemble.decodeMnemonic(instruction) orelse {
190 mir_log.debug("cannot decode instruction 0x{x}", .{instruction.word});
191 unreachable;
192 };
193 switch (mnemonic) {
194 else => {
195 mir_log.debug("unimplemented reloc on {t}", .{mnemonic});
196 unreachable;
197 },
198 .pcaddu18i => if (lf.cast(.elf2)) |ef| {
199 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .CALL36 });
200 } else if (lf.cast(.elf)) |ef| {
201 const zo = ef.zigObjectPtr().?;
202 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
203 try atom.addReloc(zcu.gpa, .{
204 .r_offset = offset,
205 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.CALL36),
206 .r_addend = @bitCast(addend),
207 }, zo);
208 } else unreachable,
209 .b, .bl => if (lf.cast(.elf2)) |ef| {
210 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B26 });
211 } else if (lf.cast(.elf)) |ef| {
212 const zo = ef.zigObjectPtr().?;
213 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
214 try atom.addReloc(zcu.gpa, .{
215 .r_offset = offset,
216 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B26),
217 .r_addend = @bitCast(addend),
218 }, zo);
219 } else unreachable,
220 .beq, .bne, .ble, .bgt, .bleu, .bgtu => if (lf.cast(.elf2)) |ef| {
221 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B16 });
222 } else if (lf.cast(.elf)) |ef| {
223 const zo = ef.zigObjectPtr().?;
224 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
225 try atom.addReloc(zcu.gpa, .{
226 .r_offset = offset,
227 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B16),
228 .r_addend = @bitCast(addend),
229 }, zo);
230 } else unreachable,
231 .beqz, .bnez, .bceqz, .bcnez => if (lf.cast(.elf2)) |ef| {
232 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B21 });
233 } else if (lf.cast(.elf)) |ef| {
234 const zo = ef.zigObjectPtr().?;
235 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
236 try atom.addReloc(zcu.gpa, .{
237 .r_offset = offset,
238 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B21),
239 .r_addend = @bitCast(addend),
240 }, zo);
241 } else unreachable,
242 .pcalau12i => if (lf.cast(.elf2)) |ef| {
243 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_HI20 });
244 } else if (lf.cast(.elf)) |ef| {
245 const zo = ef.zigObjectPtr().?;
246 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
247 try atom.addReloc(zcu.gpa, .{
248 .r_offset = offset,
249 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_HI20),
250 .r_addend = @bitCast(addend),
251 }, zo);
252 } else unreachable,
253 .@"addi.d" => if (lf.cast(.elf2)) |ef| {
254 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_LO12 });
255 } else if (lf.cast(.elf)) |ef| {
256 const zo = ef.zigObjectPtr().?;
257 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
258 try atom.addReloc(zcu.gpa, .{
259 .r_offset = offset,
260 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_LO12),
261 .r_addend = @bitCast(addend),
262 }, zo);
263 } else unreachable,
264 }
186 if (lf.cast(.elf2)) |ef| {
187 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = reloc_type });
188 } else if (lf.cast(.elf)) |ef| {
189 const zo = ef.zigObjectPtr().?;
190 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
191 try atom.addReloc(zcu.gpa, .{
192 .r_offset = offset,
193 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(reloc_type),
194 .r_addend = @bitCast(addend),
195 }, zo);
196 } else unreachable;
265197}
266198
267199const Air = @import("../../Air.zig");
src/codegen/loongarch/Select.zig+19-15
......@@ -101,8 +101,8 @@ pub const Block = struct {
101101 fn branch(target_block: *Block, isel: *Select) !void {
102102 if (isel.instructions.items.len > target_block.target_label) {
103103 try isel.internal_relocs.append(isel.pt.zcu.gpa, .{
104 .label = @intCast(isel.instructions.items.len),
105104 .target = target_block.target_label,
105 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
106106 });
107107 try isel.emit(.b(0, 0));
108108 }
......@@ -1449,6 +1449,7 @@ pub const Value = struct {
14491449 .reloc = .{
14501450 .label = @intCast(isel.instructions.items.len),
14511451 .addend = @intCast(total_root_offset),
1452 .type = .PCALA_LO12,
14521453 },
14531454 });
14541455 try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0));
......@@ -1460,6 +1461,7 @@ pub const Value = struct {
14601461 .reloc = .{
14611462 .label = @intCast(isel.instructions.items.len),
14621463 .addend = @intCast(total_root_offset),
1464 .type = .PCALA_HI20,
14631465 },
14641466 });
14651467 try isel.emit(.pcalau12i(ptr_reg, 0));
......@@ -3164,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
31643166 const next_repeat_label = instruction.*;
31653167 instruction.* = .b(0, 0);
31663168 try isel.internal_relocs.append(gpa, .{
3167 .label = repeat_label,
31683169 .target = isel.instructions.items.len,
3170 .reloc = .{ .label = repeat_label, .type = .B26 },
31693171 });
31703172 repeat_label = @bitCast(next_repeat_label);
31713173 }
......@@ -3197,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
31973199 .extension = .zero_ext,
31983200 });
31993201 try isel.internal_relocs.append(gpa, .{
3200 .label = @intCast(isel.instructions.items.len),
32013202 .target = else_label,
3203 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
32023204 });
32033205 try isel.emit(.beqz(cond_mat.reg(), 0, 0));
32043206 try cond_mat.finish(isel);
......@@ -3241,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
32413243 });
32423244
32433245 try isel.internal_relocs.append(gpa, .{
3244 .label = @intCast(isel.instructions.items.len),
32453246 .target = next_label,
3247 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
32463248 });
32473249 try isel.emit(.b(0, 0));
32483250
......@@ -3268,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
32683270 defer isel.freeReg(item_reg);
32693271
32703272 try isel.internal_relocs.append(gpa, .{
3271 .label = @intCast(isel.instructions.items.len),
32723273 .target = case_label,
3274 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 },
32733275 });
32743276 try isel.emit(.beq(cond_mat.reg(), item_reg, 0));
32753277 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,
33233325 else => unreachable,
33243326 inline .@"extern", .func => |func| .{
33253327 .nav = func.owner_nav,
3326 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3328 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 },
33273329 },
33283330 .ptr => |ptr| .{
33293331 .nav = ptr.base_addr.nav,
33303332 .reloc = .{
33313333 .label = @intCast(isel.instructions.items.len),
33323334 .addend = @intCast(ptr.byte_offset),
3335 .type = .CALL36,
33333336 },
33343337 },
33353338 });
......@@ -3920,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
39203923 .extension = .zero_ext,
39213924 });
39223925 try isel.internal_relocs.append(gpa, .{
3923 .label = @intCast(isel.instructions.items.len),
39243926 .target = cmp_label,
3927 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
39253928 });
39263929 try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0));
39273930 try isel.internal_relocs.append(gpa, .{
3928 .label = @intCast(isel.instructions.items.len),
39293931 .target = cmp_label,
3932 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
39303933 });
39313934 try isel.emit(.beqz(res_reg, 0, 0));
39323935
......@@ -4274,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
42744277 );
42754278 const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel);
42764279 try isel.internal_relocs.append(gpa, .{
4277 .label = @intCast(isel.instructions.items.len),
42784280 .target = cont_label,
4281 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
42794282 });
42804283 try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0));
42814284 try error_set_part_mat.finish(isel);
......@@ -4312,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
43124315 defer isel.freeReg(tmp_reg);
43134316
43144317 try isel.internal_relocs.append(gpa, .{
4315 .label = @intCast(isel.instructions.items.len),
43164318 .target = cont_label,
4319 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
43174320 });
43184321 try isel.emit(.beqz(tmp_reg, 0, 0));
43194322
......@@ -6467,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64676470 .reloc = .{
64686471 .label = @intCast(isel.instructions.items.len),
64696472 .addend = @intCast(ptr.byte_offset),
6473 .type = .PCALA_LO12,
64706474 },
64716475 });
64726476 try isel.emit(.@"addi.d"(rd, rd, 0));
......@@ -6475,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64756479 .reloc = .{
64766480 .label = @intCast(isel.instructions.items.len),
64776481 .addend = @intCast(ptr.byte_offset),
6482 .type = .PCALA_HI20,
64786483 },
64796484 });
64806485 try isel.emit(.pcalau12i(rd, 0));
......@@ -6489,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64896494 .reloc = .{
64906495 .label = @intCast(isel.instructions.items.len),
64916496 .addend = @intCast(ptr.byte_offset),
6497 .type = .PCALA_LO12,
64926498 },
64936499 });
64946500 try isel.emit(.@"addi.d"(rd, rd, 0));
......@@ -6497,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64976503 .reloc = .{
64986504 .label = @intCast(isel.instructions.items.len),
64996505 .addend = @intCast(ptr.byte_offset),
6506 .type = .PCALA_HI20,
65006507 },
65016508 });
65026509 try isel.emit(.pcalau12i(rd, 0));
......@@ -6752,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
67526759 // load constant pointer
67536760 try isel.uav_relocs.append(zcu.gpa, .{
67546761 .uav = uav,
6755 .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 },
6762 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 },
67566763 });
67576764 try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0));
67586765 try isel.uav_relocs.append(zcu.gpa, .{
67596766 .uav = uav,
6760 .reloc = .{
6761 .label = @intCast(isel.instructions.items.len),
6762 .addend = 0,
6763 },
6767 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_HI20 },
67646768 });
67656769 try isel.emit(.pcalau12i(tmp_reg, 0));
67666770