22#define DEBUG_TYPE "jitlink"
50 return SignExtend64<22>(Imm11H << 12 | Imm11L << 1);
64 return HalfWords{S | Imm10, J1 | J2 | Imm11};
78 return SignExtend64<25>(S << 14 | I1 | I2 | Imm10 << 12 | Imm11 << 1);
91 return HalfWords{Imm1 << 10 | Imm4, Imm3 << 12 | Imm8};
104 uint32_t Imm16 = Imm4 << 12 | Imm1 << 11 | Imm3 << 8 | Imm8;
105 assert(Imm16 <= 0xffff &&
"Decoded value out-of-range");
133 :
Hi{*reinterpret_cast<support::ulittle16_t *>(FixupPtr)},
134 Lo{*reinterpret_cast<support::ulittle16_t *>(FixupPtr + 2)} {}
143 :
Hi{*reinterpret_cast<
const support::ulittle16_t *>(FixupPtr)},
144 Lo{*reinterpret_cast<
const support::ulittle16_t *>(FixupPtr + 2)} {}
148 :
Hi{Writable.
Hi},
Lo(Writable.
Lo) {}
156 return make_error<JITLinkError>(
157 formatv(
"Invalid opcode [ 0x{0:x4}, 0x{1:x4} ] for relocation: {2}",
159 G.getEdgeKindName(Kind)));
168template <EdgeKind_aarch32 Kind>
175template <EdgeKind_aarch32 Kind>
179 "Value bits exceed bit range of given mask");
180 R.Hi = (R.Hi & ~Mask.Hi) |
Reg.Hi;
181 R.Lo = (R.Lo & ~Mask.Lo) |
Reg.Lo;
184template <EdgeKind_aarch32 Kind>
187 assert((Mask.Hi & Imm.Hi) == Imm.Hi && (Mask.Hi & Imm.Hi) == Imm.Hi &&
188 "Value bits exceed bit range of given mask");
189 R.Hi = (R.Hi & ~Mask.Hi) | Imm.Hi;
190 R.Lo = (R.Lo & ~Mask.Lo) | Imm.Lo;
198 const char *BlockWorkingMem =
B.getContent().data();
199 const char *FixupPtr = BlockWorkingMem +
E.getOffset();
206 return make_error<JITLinkError>(
207 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
208 " can not read implicit addend for aarch32 edge kind " +
209 G.getEdgeKindName(
E.getKind()));
218 return make_error<JITLinkError>(
219 "Addend extraction for relocation type not yet implemented: " +
222 return make_error<JITLinkError>(
223 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
224 " can not read implicit addend for aarch32 edge kind " +
225 G.getEdgeKindName(
E.getKind()));
236 if (!checkOpcode<Thumb_Call>(R))
243 if (!checkOpcode<Thumb_Jump24>(R))
246 return make_error<JITLinkError>(
"Relocation expects an unconditional "
247 "B.W branch instruction: " +
254 if (!checkOpcode<Thumb_MovwAbsNC>(R))
260 if (!checkOpcode<Thumb_MovtAbs>(R))
266 return make_error<JITLinkError>(
267 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
268 " can not read implicit addend for aarch32 edge kind " +
269 G.getEdgeKindName(
E.getKind()));
274 using namespace support;
276 char *BlockWorkingMem =
B.getAlreadyMutableContent().data();
277 char *FixupPtr = BlockWorkingMem +
E.getOffset();
279 auto Write32 = [FixupPtr,
Endian =
G.getEndianness()](int64_t
Value) {
280 assert(
Endian != native &&
"Must be explicit: little or big");
281 assert(isInt<32>(
Value) &&
"Must be in signed 32-bit range");
284 endian::write32<little>(FixupPtr, Imm);
286 endian::write32<big>(FixupPtr, Imm);
290 uint64_t FixupAddress = (
B.getAddress() +
E.getOffset()).getValue();
291 int64_t Addend =
E.getAddend();
292 Symbol &TargetSymbol =
E.getTarget();
301 int64_t
Value = TargetAddress - FixupAddress + Addend;
302 if (!isInt<32>(
Value))
308 int64_t
Value = TargetAddress + Addend;
309 if (!isInt<32>(
Value))
315 return make_error<JITLinkError>(
316 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
317 " encountered unfixable aarch32 edge kind " +
318 G.getEdgeKindName(
E.getKind()));
327 return make_error<JITLinkError>(
328 "Fix-up for relocation type not yet implemented: " +
331 return make_error<JITLinkError>(
332 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
333 " encountered unfixable aarch32 edge kind " +
334 G.getEdgeKindName(
E.getKind()));
344 uint64_t FixupAddress = (
B.getAddress() +
E.getOffset()).getValue();
345 int64_t Addend =
E.getAddend();
346 Symbol &TargetSymbol =
E.getTarget();
349 TargetAddress |= 0x01;
353 if (!checkOpcode<Thumb_Jump24>(R))
356 return make_error<JITLinkError>(
"Relocation expects an unconditional "
357 "B.W branch instruction: " +
360 return make_error<JITLinkError>(
"Branch relocation needs interworking "
361 "stub when bridging to ARM: " +
364 int64_t
Value = TargetAddress - FixupAddress + Addend;
366 if (!isInt<25>(
Value))
370 if (!isInt<22>(
Value))
379 if (!checkOpcode<Thumb_Call>(R))
382 int64_t
Value = TargetAddress - FixupAddress + Addend;
388 if (TargetIsArm != InstrIsBlx) {
404 if (!isInt<25>(
Value))
408 if (!isInt<22>(
Value))
415 "Opcode BLX implies H bit is clear (avoid UB in BLX T2)");
420 if (!checkOpcode<Thumb_MovwAbsNC>(R))
428 if (!checkOpcode<Thumb_MovtAbs>(R))
436 return make_error<JITLinkError>(
437 "In graph " +
G.getName() +
", section " +
B.getSection().getName() +
438 " encountered unfixable aarch32 edge kind " +
439 G.getEdgeKindName(
E.getKind()));
444 0x40, 0xf2, 0x00, 0x0c,
445 0xc0, 0xf2, 0x00, 0x0c,
454 const char *StubPtr =
B.getContent().data();
456 assert(checkRegister<Thumb_MovwAbsNC>(StubPtr, Reg12) &&
457 checkRegister<Thumb_MovtAbs>(StubPtr + 4, Reg12) &&
458 "Linker generated stubs may only corrupt register r12 (IP)");
462 Symbol &Stub =
G.addAnonymousSymbol(
B, 0,
B.getSize(),
true,
false);
468#define KIND_NAME_CASE(K) \
486#define CPUARCH_NAME_CASE(K) \
490 using namespace ARMBuildAttrs;
514#undef CPUARCH_NAME_CASE
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_LIKELY(EXPR)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define CPUARCH_NAME_CASE(K)
#define KIND_NAME_CASE(K)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
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.
bool hasTargetFlags(TargetFlagsType Flags) const
Check wehther the given target flags are set for this Symbol.
void setTargetFlags(TargetFlagsType Flags)
Set the target flags for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
Symbol & createEntry(LinkGraph &G, Symbol &Target)
Create a branch range extension stub for the class's flavor.
uint64_t getValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Expected< int64_t > readAddendThumb(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg)
Helper function to read the initial addend for Thumb-class relocations.
@ Data_Pointer32
Absolute 32-bit value relocation.
@ Arm_Call
TODO: Arm_Call is here only as a placeholder for now.
@ Thumb_Jump24
Write immediate value for (unconditional) PC-relative branch without link.
@ Thumb_MovwAbsNC
Write immediate value to the lower halfword of the destination register.
@ Data_Delta32
Relative 32-bit value relocation.
@ Thumb_Call
Write immediate value for PC-relative branch with link (can bridge between Arm and Thumb).
@ Thumb_MovtAbs
Write immediate value to the top halfword of the destination register.
Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg)
Helper function to apply the fixup for Thumb-class relocations.
int64_t decodeImmBT4BlT1BlxT2(uint32_t Hi, uint32_t Lo)
Decode 22-bit immediate value for branch instructions without J1J2 range extension (formats B T4,...
HalfWords encodeRegMovtT1MovwT3(int64_t Value)
Encode register ID for instruction formats MOVT T1 and MOVW T3.
bool checkOpcode(const ThumbRelocation &R)
Error applyFixupData(LinkGraph &G, Block &B, const Edge &E)
Helper function to apply the fixup for Data-class relocations.
HalfWords encodeImmBT4BlT1BlxT2(int64_t Value)
Encode 22-bit immediate value for branch instructions without J1J2 range extension (formats B T4,...
int64_t decodeRegMovtT1MovwT3(uint32_t Hi, uint32_t Lo)
Decode register ID from instruction formats MOVT T1 and MOVW T3.
const char * getCPUArchName(ARMBuildAttrs::CPUArch K)
Human-readable name for a given CPU architecture kind.
uint16_t decodeImmMovtT1MovwT3(uint32_t Hi, uint32_t Lo)
Decode 16-bit immediate value from move instruction formats MOVT T1 and MOVW T3.
Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E)
Helper function to apply the fixup for Arm-class relocations.
HalfWords encodeImmMovtT1MovwT3(uint16_t Value)
Encode 16-bit immediate value for move instruction formats MOVT T1 and MOVW T3.
const char * getEdgeKindName(Edge::Kind K)
Get a human-readable name for the given AArch32 edge kind.
Error makeUnexpectedOpcodeError(const LinkGraph &G, const ThumbRelocation &R, Edge::Kind Kind)
const uint8_t Thumbv7ABS[]
HalfWords encodeImmBT4BlT1BlxT2_J1J2(int64_t Value)
Encode 25-bit immediate value for branch instructions with J1J2 range extension (formats B T4,...
Expected< int64_t > readAddendArm(LinkGraph &G, Block &B, const Edge &E)
Helper function to read the initial addend for Arm-class relocations.
bool checkRegister(const ThumbRelocation &R, HalfWords Reg)
Expected< int64_t > readAddendData(LinkGraph &G, Block &B, const Edge &E)
Helper function to read the initial addend for Data-class relocations.
int64_t decodeImmBT4BlT1BlxT2_J1J2(uint32_t Hi, uint32_t Lo)
Decode 25-bit immediate value for branch instructions with J1J2 range extension (formats B T4,...
void writeImmediate(WritableThumbRelocation &R, HalfWords Imm)
bool writeRegister(WritableThumbRelocation &R, HalfWords Reg)
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.
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
uint32_t read32(const void *P, endianness E)
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
JITLink sub-arch configuration for Arm CPU models.
Collection of named constants per fixup kind.
Immutable pair of halfwords, Hi and Lo, with overflow check.
ThumbRelocation(WritableThumbRelocation &Writable)
Create a read-only Thumb32 fixup from a writeable one.
ThumbRelocation(const char *FixupPtr)
Create a read-only reference to a Thumb32 fixup.
const support::ulittle16_t & Lo
const support::ulittle16_t & Hi
32-bit Thumb instructions are stored as two little-endian halfwords.
WritableThumbRelocation(char *FixupPtr)
Create a writable reference to a Thumb32 fixup.
support::ulittle16_t & Hi
support::ulittle16_t & Lo