| author | |
| committer | |
| log | 9b9c1d8fe138bad6ecec5a32a180225b0c0c4826 |
| tree | 7da6ddc46ab4103930598cad379163278658c7e7 |
| parent | cca7c50b54bbf5d763da839582edff69bd9d051d |
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, |
| 13 | 13 | |
| 14 | 14 | pub const Reloc = struct { |
| 15 | 15 | label: u32, |
| 16 | addend: i64 align(@alignOf(u32)) = 0, | |
| 16 | type: std.elf.R_LARCH, | |
| 17 | addend: i64 = 0, | |
| 17 | 18 | |
| 18 | 19 | pub const Nav = struct { |
| 19 | 20 | nav: InternPool.Nav.Index, |
| ... | ... | @@ -35,14 +36,10 @@ pub const Reloc = struct { |
| 35 | 36 | reloc: Reloc, |
| 36 | 37 | }; |
| 37 | 38 | |
| 38 | pub const Literal = struct { | |
| 39 | label: u32, | |
| 40 | }; | |
| 41 | ||
| 42 | 39 | pub const Internal = struct { |
| 43 | 40 | // Target MIR index |
| 44 | 41 | target: usize = 0, |
| 45 | label: u32, | |
| 42 | reloc: Reloc, | |
| 46 | 43 | }; |
| 47 | 44 | }; |
| 48 | 45 | |
| ... | ... | @@ -91,7 +88,7 @@ pub fn emit( |
| 91 | 88 | pt, |
| 92 | 89 | nav_reloc.nav, |
| 93 | 90 | ), |
| 94 | mir.body[nav_reloc.reloc.label], | |
| 91 | nav_reloc.reloc.type, | |
| 95 | 92 | body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label), |
| 96 | 93 | nav_reloc.reloc.addend, |
| 97 | 94 | ) catch |err| |
| ... | ... | @@ -105,7 +102,7 @@ pub fn emit( |
| 105 | 102 | uav_reloc.uav.val, |
| 106 | 103 | ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu), |
| 107 | 104 | ), |
| 108 | mir.body[uav_reloc.reloc.label], | |
| 105 | uav_reloc.reloc.type, | |
| 109 | 106 | body_end - @sizeOf(Instruction) * (1 + uav_reloc.reloc.label), |
| 110 | 107 | uav_reloc.reloc.addend, |
| 111 | 108 | ) catch |err| |
| ... | ... | @@ -122,7 +119,7 @@ pub fn emit( |
| 122 | 119 | return zcu.codegenFail(func.owner_nav, "emit lazy symbol: {t}", .{err}) |
| 123 | 120 | else |
| 124 | 121 | 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, | |
| 126 | 123 | body_end - @sizeOf(Instruction) * (1 + lazy_reloc.reloc.label), |
| 127 | 124 | lazy_reloc.reloc.addend, |
| 128 | 125 | ) catch |err| |
| ... | ... | @@ -139,7 +136,7 @@ pub fn emit( |
| 139 | 136 | .type = .FUNC, |
| 140 | 137 | }) catch |err| |
| 141 | 138 | 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, | |
| 143 | 140 | body_end - @sizeOf(Instruction) * (1 + global_reloc.reloc.label), |
| 144 | 141 | global_reloc.reloc.addend, |
| 145 | 142 | ) catch |err| |
| ... | ... | @@ -155,8 +152,8 @@ pub fn emit( |
| 155 | 152 | zcu, |
| 156 | 153 | atom_index, |
| 157 | 154 | 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), | |
| 160 | 157 | @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))), |
| 161 | 158 | ) catch |err| |
| 162 | 159 | return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err}); |
| ... | ... | @@ -182,86 +179,21 @@ fn emitReloc( |
| 182 | 179 | zcu: *Zcu, |
| 183 | 180 | atom_index: link.File.AtomId, |
| 184 | 181 | sym_index: link.File.SymbolId, |
| 185 | instruction: Instruction, | |
| 182 | reloc_type: std.elf.R_LARCH, | |
| 186 | 183 | offset: u32, |
| 187 | 184 | addend: i64, |
| 188 | 185 | ) !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; | |
| 265 | 197 | } |
| 266 | 198 | |
| 267 | 199 | const Air = @import("../../Air.zig"); |
src/codegen/loongarch/Select.zig+19-15| ... | ... | @@ -101,8 +101,8 @@ pub const Block = struct { |
| 101 | 101 | fn branch(target_block: *Block, isel: *Select) !void { |
| 102 | 102 | if (isel.instructions.items.len > target_block.target_label) { |
| 103 | 103 | try isel.internal_relocs.append(isel.pt.zcu.gpa, .{ |
| 104 | .label = @intCast(isel.instructions.items.len), | |
| 105 | 104 | .target = target_block.target_label, |
| 105 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, | |
| 106 | 106 | }); |
| 107 | 107 | try isel.emit(.b(0, 0)); |
| 108 | 108 | } |
| ... | ... | @@ -1449,6 +1449,7 @@ pub const Value = struct { |
| 1449 | 1449 | .reloc = .{ |
| 1450 | 1450 | .label = @intCast(isel.instructions.items.len), |
| 1451 | 1451 | .addend = @intCast(total_root_offset), |
| 1452 | .type = .PCALA_LO12, | |
| 1452 | 1453 | }, |
| 1453 | 1454 | }); |
| 1454 | 1455 | try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0)); |
| ... | ... | @@ -1460,6 +1461,7 @@ pub const Value = struct { |
| 1460 | 1461 | .reloc = .{ |
| 1461 | 1462 | .label = @intCast(isel.instructions.items.len), |
| 1462 | 1463 | .addend = @intCast(total_root_offset), |
| 1464 | .type = .PCALA_HI20, | |
| 1463 | 1465 | }, |
| 1464 | 1466 | }); |
| 1465 | 1467 | try isel.emit(.pcalau12i(ptr_reg, 0)); |
| ... | ... | @@ -3164,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3164 | 3166 | const next_repeat_label = instruction.*; |
| 3165 | 3167 | instruction.* = .b(0, 0); |
| 3166 | 3168 | try isel.internal_relocs.append(gpa, .{ |
| 3167 | .label = repeat_label, | |
| 3168 | 3169 | .target = isel.instructions.items.len, |
| 3170 | .reloc = .{ .label = repeat_label, .type = .B26 }, | |
| 3169 | 3171 | }); |
| 3170 | 3172 | repeat_label = @bitCast(next_repeat_label); |
| 3171 | 3173 | } |
| ... | ... | @@ -3197,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3197 | 3199 | .extension = .zero_ext, |
| 3198 | 3200 | }); |
| 3199 | 3201 | try isel.internal_relocs.append(gpa, .{ |
| 3200 | .label = @intCast(isel.instructions.items.len), | |
| 3201 | 3202 | .target = else_label, |
| 3203 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, | |
| 3202 | 3204 | }); |
| 3203 | 3205 | try isel.emit(.beqz(cond_mat.reg(), 0, 0)); |
| 3204 | 3206 | try cond_mat.finish(isel); |
| ... | ... | @@ -3241,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3241 | 3243 | }); |
| 3242 | 3244 | |
| 3243 | 3245 | try isel.internal_relocs.append(gpa, .{ |
| 3244 | .label = @intCast(isel.instructions.items.len), | |
| 3245 | 3246 | .target = next_label, |
| 3247 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, | |
| 3246 | 3248 | }); |
| 3247 | 3249 | try isel.emit(.b(0, 0)); |
| 3248 | 3250 | |
| ... | ... | @@ -3268,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3268 | 3270 | defer isel.freeReg(item_reg); |
| 3269 | 3271 | |
| 3270 | 3272 | try isel.internal_relocs.append(gpa, .{ |
| 3271 | .label = @intCast(isel.instructions.items.len), | |
| 3272 | 3273 | .target = case_label, |
| 3274 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 }, | |
| 3273 | 3275 | }); |
| 3274 | 3276 | try isel.emit(.beq(cond_mat.reg(), item_reg, 0)); |
| 3275 | 3277 | 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, |
| 3323 | 3325 | else => unreachable, |
| 3324 | 3326 | inline .@"extern", .func => |func| .{ |
| 3325 | 3327 | .nav = func.owner_nav, |
| 3326 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | |
| 3328 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 }, | |
| 3327 | 3329 | }, |
| 3328 | 3330 | .ptr => |ptr| .{ |
| 3329 | 3331 | .nav = ptr.base_addr.nav, |
| 3330 | 3332 | .reloc = .{ |
| 3331 | 3333 | .label = @intCast(isel.instructions.items.len), |
| 3332 | 3334 | .addend = @intCast(ptr.byte_offset), |
| 3335 | .type = .CALL36, | |
| 3333 | 3336 | }, |
| 3334 | 3337 | }, |
| 3335 | 3338 | }); |
| ... | ... | @@ -3920,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3920 | 3923 | .extension = .zero_ext, |
| 3921 | 3924 | }); |
| 3922 | 3925 | try isel.internal_relocs.append(gpa, .{ |
| 3923 | .label = @intCast(isel.instructions.items.len), | |
| 3924 | 3926 | .target = cmp_label, |
| 3927 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, | |
| 3925 | 3928 | }); |
| 3926 | 3929 | try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0)); |
| 3927 | 3930 | try isel.internal_relocs.append(gpa, .{ |
| 3928 | .label = @intCast(isel.instructions.items.len), | |
| 3929 | 3931 | .target = cmp_label, |
| 3932 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, | |
| 3930 | 3933 | }); |
| 3931 | 3934 | try isel.emit(.beqz(res_reg, 0, 0)); |
| 3932 | 3935 | |
| ... | ... | @@ -4274,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4274 | 4277 | ); |
| 4275 | 4278 | const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel); |
| 4276 | 4279 | try isel.internal_relocs.append(gpa, .{ |
| 4277 | .label = @intCast(isel.instructions.items.len), | |
| 4278 | 4280 | .target = cont_label, |
| 4281 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, | |
| 4279 | 4282 | }); |
| 4280 | 4283 | try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0)); |
| 4281 | 4284 | try error_set_part_mat.finish(isel); |
| ... | ... | @@ -4312,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4312 | 4315 | defer isel.freeReg(tmp_reg); |
| 4313 | 4316 | |
| 4314 | 4317 | try isel.internal_relocs.append(gpa, .{ |
| 4315 | .label = @intCast(isel.instructions.items.len), | |
| 4316 | 4318 | .target = cont_label, |
| 4319 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, | |
| 4317 | 4320 | }); |
| 4318 | 4321 | try isel.emit(.beqz(tmp_reg, 0, 0)); |
| 4319 | 4322 | |
| ... | ... | @@ -6467,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6467 | 6470 | .reloc = .{ |
| 6468 | 6471 | .label = @intCast(isel.instructions.items.len), |
| 6469 | 6472 | .addend = @intCast(ptr.byte_offset), |
| 6473 | .type = .PCALA_LO12, | |
| 6470 | 6474 | }, |
| 6471 | 6475 | }); |
| 6472 | 6476 | try isel.emit(.@"addi.d"(rd, rd, 0)); |
| ... | ... | @@ -6475,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6475 | 6479 | .reloc = .{ |
| 6476 | 6480 | .label = @intCast(isel.instructions.items.len), |
| 6477 | 6481 | .addend = @intCast(ptr.byte_offset), |
| 6482 | .type = .PCALA_HI20, | |
| 6478 | 6483 | }, |
| 6479 | 6484 | }); |
| 6480 | 6485 | try isel.emit(.pcalau12i(rd, 0)); |
| ... | ... | @@ -6489,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6489 | 6494 | .reloc = .{ |
| 6490 | 6495 | .label = @intCast(isel.instructions.items.len), |
| 6491 | 6496 | .addend = @intCast(ptr.byte_offset), |
| 6497 | .type = .PCALA_LO12, | |
| 6492 | 6498 | }, |
| 6493 | 6499 | }); |
| 6494 | 6500 | try isel.emit(.@"addi.d"(rd, rd, 0)); |
| ... | ... | @@ -6497,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6497 | 6503 | .reloc = .{ |
| 6498 | 6504 | .label = @intCast(isel.instructions.items.len), |
| 6499 | 6505 | .addend = @intCast(ptr.byte_offset), |
| 6506 | .type = .PCALA_HI20, | |
| 6500 | 6507 | }, |
| 6501 | 6508 | }); |
| 6502 | 6509 | try isel.emit(.pcalau12i(rd, 0)); |
| ... | ... | @@ -6752,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6752 | 6759 | // load constant pointer |
| 6753 | 6760 | try isel.uav_relocs.append(zcu.gpa, .{ |
| 6754 | 6761 | .uav = uav, |
| 6755 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 }, | |
| 6762 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 }, | |
| 6756 | 6763 | }); |
| 6757 | 6764 | try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0)); |
| 6758 | 6765 | try isel.uav_relocs.append(zcu.gpa, .{ |
| 6759 | 6766 | .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 }, | |
| 6764 | 6768 | }); |
| 6765 | 6769 | try isel.emit(.pcalau12i(tmp_reg, 0)); |
| 6766 | 6770 |