Skip to content

Commit

Permalink
[JITLink][PowerPC] Support R_PPC64_PCREL34
Browse files Browse the repository at this point in the history
PC-relative instructions are added in ISA-3.1 implemented by pwr10. This patch adds basic pc-relative relocation.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D155771
  • Loading branch information
bzEq committed Aug 2, 2023
1 parent ed83797 commit ca6d86f
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 0 deletions.
33 changes: 33 additions & 0 deletions llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum EdgeKind_ppc64 : Edge::Kind {
Pointer64 = Edge::FirstRelocation,
Pointer32,
Delta64,
Delta34,
Delta32,
NegDelta32,
Delta16,
Expand Down Expand Up @@ -229,6 +230,26 @@ inline static uint16_t ha16(uint64_t x) { return (x + 0x8000) >> 16; }

inline static uint16_t lo16(uint64_t x) { return x & 0xffff; }

// Prefixed instruction introduced in ISAv3.1 consists of two 32-bit words,
// prefix word and suffix word, i.e., prefixed_instruction = concat(prefix_word,
// suffix_word). That's to say, for a prefixed instruction encoded in uint64_t,
// the most significant 32 bits belong to the prefix word. The prefix word is at
// low address for both big/little endian. Byte order in each word still follows
// its endian.
template <support::endianness Endianness>
inline static uint64_t readPrefixedInstruction(const char *Loc) {
constexpr bool isLE = Endianness == support::endianness::little;
uint64_t Inst = support::endian::read64<Endianness>(Loc);
return isLE ? (Inst << 32) | (Inst >> 32) : Inst;
}

template <support::endianness Endianness>
inline static void writePrefixedInstruction(char *Loc, uint64_t Inst) {
constexpr bool isLE = Endianness == support::endianness::little;
Inst = isLE ? (Inst << 32) | (Inst >> 32) : Inst;
support::endian::write64<Endianness>(Loc, Inst);
}

/// Apply fixup expression for edge to block content.
template <support::endianness Endianness>
inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
Expand Down Expand Up @@ -315,6 +336,18 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
support::endian::write64<Endianness>(FixupPtr, Value);
break;
}
case Delta34: {
int64_t Value = S + A - P;
if (!LLVM_UNLIKELY(isInt<34>(Value)))
return makeTargetOutOfRangeError(G, B, E);
static const uint64_t SI0Mask = 0x00000003ffff0000;
static const uint64_t SI1Mask = 0x000000000000ffff;
static const uint64_t FullMask = 0x0003ffff0000ffff;
uint64_t Inst = readPrefixedInstruction<Endianness>(FixupPtr) & ~FullMask;
writePrefixedInstruction<Endianness>(
FixupPtr, Inst | ((Value & SI0Mask) << 16) | (Value & SI1Mask));
break;
}
case Delta32: {
int64_t Value = S + A - P;
if (LLVM_UNLIKELY(!isInt<32>(Value))) {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ class ELFLinkGraphBuilder_ppc64
case ELF::R_PPC64_REL64:
Kind = ppc64::Delta64;
break;
case ELF::R_PPC64_PCREL34:
Kind = ppc64::Delta34;
break;
}

Edge GE(Kind, Offset, *GraphSymbol, Addend);
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ const char *getEdgeKindName(Edge::Kind K) {
return "Pointer32";
case Delta64:
return "Delta64";
case Delta34:
return "Delta34";
case Delta32:
return "Delta32";
case NegDelta32:
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ test_external_call_notoc:
blr
.size test_external_call_notoc, .-test_external_call_notoc

# Check R_PPC64_PCREL34
# jitlink-check: (section_addr(elf_reloc.o, .rodata.str1.1) - test_pcrel34)[33:0] = \
# jitlink-check: ((((*{4}(test_pcrel34)) & 0x3ffff) << 16) | ((*{4}(test_pcrel34 + 4)) & 0xffff))[33:0]
.global test_pcrel34
.p2align 4
.type test_pcrel34,@function
test_pcrel34:
paddi 3, 0, .L.str@PCREL, 1
blr
.size test_pcrel34, .-test_pcrel34

.type .L.str,@object
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "Hey!"
.size .L.str, 5

.section .toc,"aw",@progbits
.LC0:
.tc external_data[TC],external_data
11 changes: 11 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ bar:
.Lfunc_end7:
.size bar, .Lfunc_end7-.Lfunc_begin7

.global foobar
.p2align
.type foobar,@function
foobar:
.Lfunc_begin8:
.localentry foobar, 1
paddi 3, 0, .L.str@PCREL, 1
blr
.Lfunc_end8:
.size foobar, .Lfunc_end8-.Lfunc_end8

.type local_var,@object
.section .bss,"aw",@nobits
.globl local_var
Expand Down

0 comments on commit ca6d86f

Please sign in to comment.