13#ifndef LLVM_EXECUTIONENGINE_JITLINK_PPC64_H
14#define LLVM_EXECUTIONENGINE_JITLINK_PPC64_H
93template <llvm::endianness Endianness>
102 size_t Offset = isLE ? 0 : 2;
111 size_t Offset = isLE ? 4 : 6;
120 size_t Offset = isLE ? 16 : 18;
132 Symbol *InitialTarget =
nullptr,
135 "LinkGraph's pointer size should be consistent with size of "
136 "NullPointerContent");
140 B.addEdge(
Pointer64, 0, *InitialTarget, InitialAddend);
141 return G.addAnonymousSymbol(
B, 0,
G.getPointerSize(),
false,
false);
144template <llvm::endianness Endianness>
152 for (
auto const &Reloc : StubInfo.
Relocs)
153 B.addEdge(Reloc.K, Reloc.Offset, PointerSymbol, Reloc.A);
154 return G.addAnonymousSymbol(
B, 0, StubInfo.
Content.
size(),
true,
false);
157template <llvm::endianness Endianness>
173 getOrCreateTOCSection(
G);
199template <llvm::endianness Endianness>
211 bool isExternal =
E.getTarget().isExternal();
241 return createAnonymousPointerJumpStub<Endianness>(
242 G, getOrCreateStubsSection(
G), TOC.getEntryForTarget(
G,
Target),
255 TOCTableManager<Endianness> &TOC;
269 return ((x + 0x8000) >> 16) & 0xffff;
273 return ((x + 0x8000) >> 32) & 0xffff;
284template <llvm::endianness Endianness>
287 uint64_t Inst = support::endian::read64<Endianness>(Loc);
288 return isLE ? (Inst << 32) | (Inst >> 32) : Inst;
291template <llvm::endianness Endianness>
294 Inst = isLE ? (Inst << 32) | (Inst >> 32) : Inst;
295 support::endian::write64<Endianness>(Loc, Inst);
298template <llvm::endianness Endianness>
304 support::endian::write16<Endianness>(FixupPtr,
Value);
308 support::endian::write16<Endianness>(FixupPtr,
Value & ~3);
313 support::endian::write16<Endianness>(FixupPtr,
ha(
Value));
318 support::endian::write16<Endianness>(FixupPtr,
hi(
Value));
321 support::endian::write16<Endianness>(FixupPtr,
high(
Value));
324 support::endian::write16<Endianness>(FixupPtr,
higha(
Value));
327 support::endian::write16<Endianness>(FixupPtr,
higher(
Value));
330 support::endian::write16<Endianness>(FixupPtr,
highera(
Value));
333 support::endian::write16<Endianness>(FixupPtr,
highest(
Value));
336 support::endian::write16<Endianness>(FixupPtr,
highesta(
Value));
341 support::endian::write16<Endianness>(FixupPtr,
lo(
Value));
345 support::endian::write16<Endianness>(FixupPtr,
lo(
Value) & ~3);
348 return make_error<JITLinkError>(
350 " relocation does not write at half16 field");
356template <llvm::endianness Endianness>
358 const Symbol *TOCSymbol) {
359 char *BlockWorkingMem =
B.getAlreadyMutableContent().data();
360 char *FixupPtr = BlockWorkingMem +
E.getOffset();
362 int64_t S =
E.getTarget().getAddress().getValue();
363 int64_t
A =
E.getAddend();
369 dbgs() <<
" Applying fixup on " <<
G.getEdgeKindName(K)
370 <<
" edge, (S, A, P, .TOC.) = (" <<
formatv(
"{0:x}", S) <<
", "
372 <<
formatv(
"{0:x}", TOCBase) <<
")\n";
378 support::endian::write64<Endianness>(FixupPtr,
Value);
389 return relocateHalf16<Endianness>(FixupPtr,
Value, K);
392 support::endian::write64<Endianness>(FixupPtr, TOCBase);
410 return relocateHalf16<Endianness>(FixupPtr,
Value, K);
413 static const uint32_t Low14Mask = 0xfffc;
415 assert((
Value & 3) == 0 &&
"Pointer14 requires 4-byte alignment");
419 uint32_t Inst = support::endian::read32<Endianness>(FixupPtr);
420 support::endian::write32<Endianness>(FixupPtr, (Inst & ~Low14Mask) |
421 (
Value & Low14Mask));
430 int64_t
Value = S +
A - TOCBase;
434 return relocateHalf16<Endianness>(FixupPtr,
Value, K);
442 uint32_t Inst = support::endian::read32<Endianness>(FixupPtr);
443 support::endian::write32<Endianness>(FixupPtr, (Inst & 0xfc000003) |
444 (
Value & 0x03fffffc));
446 uint32_t NopInst = support::endian::read32<Endianness>(FixupPtr + 4);
447 assert(NopInst == 0x60000000 &&
448 "NOP should be placed here for restoring r2");
451 support::endian::write32<Endianness>(FixupPtr + 4, 0xe8410018);
457 support::endian::write64<Endianness>(FixupPtr,
Value);
464 static const uint64_t SI0Mask = 0x00000003ffff0000;
465 static const uint64_t SI1Mask = 0x000000000000ffff;
466 static const uint64_t FullMask = 0x0003ffff0000ffff;
467 uint64_t Inst = readPrefixedInstruction<Endianness>(FixupPtr) & ~FullMask;
468 writePrefixedInstruction<Endianness>(
469 FixupPtr, Inst | ((
Value & SI0Mask) << 16) | (
Value & SI1Mask));
477 support::endian::write32<Endianness>(FixupPtr,
Value);
485 support::endian::write32<Endianness>(FixupPtr,
Value);
489 return make_error<JITLinkError>(
490 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
LLVM Value Representation.
An Addressable with content and edges.
Represents fixups and constraints in the LinkGraph.
Represents an object file section.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
A CRTP base for tables that are built on demand, e.g.
Symbol & getEntryForTarget(LinkGraph &G, Symbol &Target)
Return the constructed entry.
static StringRef getSectionName()
bool visitEdge(LinkGraph &G, Block *B, Edge &E)
Symbol & createEntry(LinkGraph &G, Symbol &Target)
PLTTableManager(TOCTableManager< Endianness > &TOC)
static StringRef getSectionName()
bool visitEdge(LinkGraph &G, Block *B, Edge &E)
Symbol & createEntry(LinkGraph &G, Symbol &Target)
Represents an address in the executor process.
uint64_t getValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static uint64_t lo(uint64_t x)
static uint64_t high(uint64_t x)
Error relocateHalf16(char *FixupPtr, int64_t Value, Edge::Kind K)
const char PointerJumpStubNoTOCContent_big[32]
static uint64_t higha(uint64_t x)
PLTCallStubInfo pickStub(PLTCallStubKind StubKind)
Symbol & createAnonymousPointer(LinkGraph &G, Section &PointerSection, Symbol *InitialTarget=nullptr, uint64_t InitialAddend=0)
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *TOCSymbol)
Apply fixup expression for edge to block content.
static uint16_t highesta(uint64_t x)
EdgeKind_ppc64
Represents ppc64 fixups and other ppc64-specific edge kinds.
@ RequestTLSDescInGOTAndTransformToTOCDelta16HA
@ CallBranchDeltaRestoreTOC
@ RequestGOTAndTransformToDelta34
@ RequestTLSDescInGOTAndTransformToTOCDelta16LO
@ RequestTLSDescInGOTAndTransformToDelta34
const char PointerJumpStubContent_little[20]
const char PointerJumpStubContent_big[20]
static uint64_t higher(uint64_t x)
const char NullPointerContent[8]
const char PointerJumpStubNoTOCContent_little[32]
static uint64_t readPrefixedInstruction(const char *Loc)
static void writePrefixedInstruction(char *Loc, uint64_t Inst)
Symbol & createAnonymousPointerJumpStub(LinkGraph &G, Section &StubSection, Symbol &PointerSymbol, PLTCallStubKind StubKind)
static uint16_t highest(uint64_t x)
static uint64_t highera(uint64_t x)
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given ppc64 edge.
static uint16_t hi(uint64_t x)
static uint16_t ha(uint64_t x)
Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, const Edge &E)
Create an out of range error for the given edge in the given block.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SmallVector< PLTCallStubReloc, 2 > Relocs