[llvm] ca6d86f - [JITLink][PowerPC] Support R_PPC64_PCREL34

Kai Luo via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 1 19:00:45 PDT 2023


Author: Kai Luo
Date: 2023-08-02T02:00:38Z
New Revision: ca6d86f6bf12c8694724bd4d51704b28bd0eb743

URL: https://github.com/llvm/llvm-project/commit/ca6d86f6bf12c8694724bd4d51704b28bd0eb743
DIFF: https://github.com/llvm/llvm-project/commit/ca6d86f6bf12c8694724bd4d51704b28bd0eb743.diff

LOG: [JITLink][PowerPC] Support R_PPC64_PCREL34

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

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
    llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
    llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
    llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s
    llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
index a94acce5674b70..dafe49c9232d0f 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
@@ -24,6 +24,7 @@ enum EdgeKind_ppc64 : Edge::Kind {
   Pointer64 = Edge::FirstRelocation,
   Pointer32,
   Delta64,
+  Delta34,
   Delta32,
   NegDelta32,
   Delta16,
@@ -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,
@@ -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))) {

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
index a42d86ea609378..02fdf4a62afd66 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
@@ -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);

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
index 8ec460fa545688..1f5a07fb013eb8 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
@@ -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:

diff  --git a/llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s b/llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s
index 0890525622d310..6df20014ba65ac 100644
--- a/llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/ELF_ppc64le_relocations.s
@@ -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, at function
+test_pcrel34:
+  paddi 3, 0, .L.str at PCREL, 1
+  blr
+  .size test_pcrel34, .-test_pcrel34
+
+  .type	.L.str, at object
+	.section	.rodata.str1.1,"aMS", at progbits,1
+.L.str:
+	.asciz	"Hey!"
+	.size	.L.str, 5
+
  .section .toc,"aw", at progbits
 .LC0:
   .tc external_data[TC],external_data

diff  --git a/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s b/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s
index 903e2331bc0d73..23e11764b93c0b 100644
--- a/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/ppc64le-relocs.s
@@ -183,6 +183,17 @@ bar:
 .Lfunc_end7:
 	.size	bar, .Lfunc_end7-.Lfunc_begin7
 
+  .global foobar
+  .p2align
+  .type foobar, at function
+foobar:
+.Lfunc_begin8:
+  .localentry foobar, 1
+  paddi 3, 0, .L.str at PCREL, 1
+  blr
+.Lfunc_end8:
+  .size foobar, .Lfunc_end8-.Lfunc_end8
+
 	.type	local_var, at object
 	.section	.bss,"aw", at nobits
 	.globl	local_var


        


More information about the llvm-commits mailing list