LLVM 24.0.0git
RuntimeDyldCOFFAArch64.h
Go to the documentation of this file.
1//===-- RuntimeDyldCOFFAArch64.h --- COFF/AArch64 specific code ---*- C++*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// COFF AArch64 support for MC-JIT runtime dynamic linker.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFAARCH64_H
14#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFAARCH64_H
15
16#include "../RuntimeDyldCOFF.h"
19#include "llvm/Object/COFF.h"
20#include "llvm/Support/Endian.h"
21
22#define DEBUG_TYPE "dyld"
23
24namespace llvm {
25
26// This relocation type is used for handling long branch instruction
27// through the Stub.
31
32static void add16(uint8_t *p, int16_t v) {
33 using namespace llvm::support::endian;
34 write16le(p, read16le(p) + v);
35}
36
37static void or32le(void *P, int32_t V) {
38 using namespace llvm::support::endian;
39
40 write32le(P, read32le(P) | V);
41}
42
43static void write32AArch64Imm(uint8_t *T, uint64_t imm, uint32_t rangeLimit) {
44 using namespace llvm::support::endian;
45
46 uint32_t orig = read32le(T);
47 orig &= ~(0xFFF << 10);
48 write32le(T, orig | ((imm & (0xFFF >> rangeLimit)) << 10));
49}
50
51/// Byte addend held in an LDR/STR (unsigned immediate) instruction. Its imm12
52/// field counts access-size units, so reading it back has to undo that scaling
53/// the way write32AArch64Ldr applies it.
54static uint64_t read32AArch64LdrAddend(uint32_t Inst) {
55 uint32_t Size = Inst >> 30;
56 // 0x04000000 indicates SIMD/FP registers, 0x00800000 indicates 128 bit.
57 if ((Inst & 0x04800000) == 0x04800000)
58 Size += 4;
59 return static_cast<uint64_t>((Inst >> 10) & 0xFFF) << Size;
60}
61
62static void write32AArch64Ldr(uint8_t *T, uint64_t imm) {
63 using namespace llvm::support::endian;
64
65 uint32_t orig = read32le(T);
66 uint32_t size = orig >> 30;
67 // 0x04000000 indicates SIMD/FP registers
68 // 0x00800000 indicates 128 bit
69 if ((orig & 0x04800000) == 0x04800000)
70 size += 4;
71 if ((imm & ((1 << size) - 1)) != 0)
72 assert(0 && "misaligned ldr/str offset");
73 write32AArch64Imm(T, imm >> size, size);
74}
75
76static void write32AArch64Addr(void *T, uint64_t s, uint64_t p, int shift) {
77 using namespace llvm::support::endian;
78
79 uint64_t Imm = (s >> shift) - (p >> shift);
80 // ADRP's page offset is 21 bits signed (+/-4 GiB); fail loudly rather than
81 // truncate into a wild pointer.
82 if (!isInt<21>(static_cast<int64_t>(Imm))) {
83 report_fatal_error(Twine("ADRP target out of range: target=") + Twine(s) +
84 " pc=" + Twine(p) +
85 " delta=" + Twine(s > p ? s - p : p - s) +
86 (s > p ? " (target above pc)" : " (target below pc)") +
87 " -- needs a 21-bit signed page offset (+/-4 GiB)");
88 }
89 uint32_t ImmLo = (Imm & 0x3) << 29;
90 uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;
91 uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);
92 write32le(T, (read32le(T) & ~Mask) | ImmLo | ImmHi);
93}
94
96
97private:
98 // When a module is loaded we save the SectionID of the unwind
99 // sections in a table until we receive a request to register all
100 // unregisteredEH frame sections with the memory manager.
101 SmallVector<SID, 2> UnregisteredEHFrameSections;
102 SmallVector<SID, 2> RegisteredEHFrameSections;
103 uint64_t ImageBase;
104
105 // Fake an __ImageBase pointer by returning the section with the lowest adress
106 uint64_t getImageBase() {
107 if (!ImageBase) {
108 ImageBase = std::numeric_limits<uint64_t>::max();
109 for (const SectionEntry &Section : Sections)
110 // The Sections list may contain sections that weren't loaded for
111 // whatever reason: they may be debug sections, and ProcessAllSections
112 // is false, or they may be sections that contain 0 bytes. If the
113 // section isn't loaded, the load address will be 0, and it should not
114 // be included in the ImageBase calculation.
115 if (Section.getLoadAddress() != 0)
116 ImageBase = std::min(ImageBase, Section.getLoadAddress());
117 }
118 return ImageBase;
119 }
120
121public:
124 : RuntimeDyldCOFF(MM, Resolver, 8, COFF::IMAGE_REL_ARM64_ADDR64),
125 ImageBase(0) {}
126
127 Align getStubAlignment() override { return Align(8); }
128
129 unsigned getMaxStubSize() const override { return 20; }
130
131 /// GOT slot in this section's stub area holding the address of \p Name, so
132 /// an ADRP can reach external symbols (e.g. DLL exports) beyond +/-4 GiB.
133 /// computeSectionStubBufSize reserves getMaxStubSize() per relocation, which
134 /// covers the 8 bytes.
135 uint64_t getGOTEntryOffset(unsigned SectionID, StubMap &Stubs, StringRef Name,
136 bool CreateIfMissing) {
137 // Key on the symbol alone; ~0 cannot collide with a branch stub's offset.
139 Key.SectionID = SectionID;
140 Key.Offset = ~uint64_t(0);
141 Key.SymbolName = Name.data();
142
143 // RelocationValueRef compares symbol-name pointers rather than their
144 // contents, but paired COFF relocations need not carry the same pointer.
145 for (const auto &[StubKey, StubOffset] : Stubs)
146 if (StubKey.SectionID == SectionID && StubKey.Offset == ~uint64_t(0) &&
147 StubKey.SymbolName && StringRef(StubKey.SymbolName) == Name)
148 return StubOffset;
149 if (!CreateIfMissing)
150 return ~uint64_t(0);
151
152 SectionEntry &Sec = Sections[SectionID];
153 uint64_t EntryOffset = alignTo(Sec.getStubOffset(), 8);
154 Sec.advanceStubOffset(EntryOffset + 8 - Sec.getStubOffset());
155 Stubs[Key] = EntryOffset;
156
157 // Have the resolver write the symbol's absolute address into the slot.
158 RelocationEntry RE(SectionID, EntryOffset, COFF::IMAGE_REL_ARM64_ADDR64, 0,
159 /*IsPCRel=*/false, Log2_64(8));
160 addRelocationForSymbol(RE, Name);
161
162 LLVM_DEBUG(dbgs() << " Created GOT entry for " << Name << " at offset "
163 << EntryOffset << "\n");
164 return EntryOffset;
165 }
166
167 /// ADD (immediate, no shift): the second half of the ADRP+ADD idiom.
168 static bool isAddImmediate(uint32_t Inst) {
169 // sf 0 0 100010 sh imm12 Rn Rd with sh == 0; excludes ADDS (bit 29).
170 return (Inst & 0x7FC00000) == 0x11000000;
171 }
172
173 std::tuple<uint64_t, uint64_t, uint64_t>
174 generateRelocationStub(unsigned SectionID, StringRef TargetName,
175 uint64_t Offset, uint64_t RelType, uint64_t Addend,
176 StubMap &Stubs) {
177 uintptr_t StubOffset;
178 SectionEntry &Section = Sections[SectionID];
179
180 RelocationValueRef OriginalRelValueRef;
181 OriginalRelValueRef.SectionID = SectionID;
182 OriginalRelValueRef.Offset = Offset;
183 OriginalRelValueRef.Addend = Addend;
184 OriginalRelValueRef.SymbolName = TargetName.data();
185
186 auto [Stub, Inserted] = Stubs.try_emplace(OriginalRelValueRef);
187 if (Inserted) {
188 LLVM_DEBUG(dbgs() << " Create a new stub function for "
189 << TargetName.data() << "\n");
190
191 StubOffset = Section.getStubOffset();
192 Stub->second = StubOffset;
193 createStubFunction(Section.getAddressWithOffset(StubOffset));
194 Section.advanceStubOffset(getMaxStubSize());
195 } else {
196 LLVM_DEBUG(dbgs() << " Stub function found for " << TargetName.data()
197 << "\n");
198 StubOffset = Stub->second;
199 }
200
201 // Resolve original relocation to stub function.
202 const RelocationEntry RE(SectionID, Offset, RelType, Addend);
203 resolveRelocation(RE, Section.getLoadAddressWithOffset(StubOffset));
204
205 // adjust relocation info so resolution writes to the stub function
206 // Here an internal relocation type is used for resolving long branch via
207 // stub instruction.
208 Addend = 0;
209 Offset = StubOffset;
211
212 return std::make_tuple(Offset, RelType, Addend);
213 }
214
217 const object::ObjectFile &Obj,
218 ObjSectionToIDMap &ObjSectionToID,
219 StubMap &Stubs) override {
220 using namespace llvm::support::endian;
221
222 auto Symbol = RelI->getSymbol();
223 if (Symbol == Obj.symbol_end())
224 report_fatal_error("Unknown symbol in relocation");
225
226 Expected<StringRef> TargetNameOrErr = Symbol->getName();
227 if (!TargetNameOrErr)
228 return TargetNameOrErr.takeError();
229 StringRef TargetName = *TargetNameOrErr;
230
231 auto SectionOrErr = Symbol->getSection();
232 if (!SectionOrErr)
233 return SectionOrErr.takeError();
234 auto Section = *SectionOrErr;
235
236 uint64_t RelType = RelI->getType();
237 uint64_t Offset = RelI->getOffset();
238
239 // If there is no section, this must be an external reference.
240 bool IsExtern = Section == Obj.section_end();
241
242 // Determine the Addend used to adjust the relocation value.
243 uint64_t Addend = 0;
244 SectionEntry &AddendSection = Sections[SectionID];
245 uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
246 uint8_t *Displacement = (uint8_t *)ObjTarget;
247
248 unsigned TargetSectionID = -1;
249 uint64_t TargetOffset = -1;
250
251 if (TargetName.starts_with(getImportSymbolPrefix())) {
252 TargetSectionID = SectionID;
253 TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName);
254 TargetName = StringRef();
255 IsExtern = false;
256 } else if (!IsExtern) {
257 if (auto TargetSectionIDOrErr = findOrEmitSection(
258 Obj, *Section, Section->isText(), ObjSectionToID))
259 TargetSectionID = *TargetSectionIDOrErr;
260 else
261 return TargetSectionIDOrErr.takeError();
262
263 TargetOffset = getSymbolOffset(*Symbol);
264 }
265
266 switch (RelType) {
271 Addend = read32le(Displacement);
272 break;
274 uint32_t orig = read32le(Displacement);
275 Addend = (orig & 0x03FFFFFF) << 2;
276
277 if (IsExtern)
278 std::tie(Offset, RelType, Addend) = generateRelocationStub(
279 SectionID, TargetName, Offset, RelType, Addend, Stubs);
280 break;
281 }
283 uint32_t orig = read32le(Displacement);
284 Addend = (orig & 0x00FFFFE0) >> 3;
285 break;
286 }
288 uint32_t orig = read32le(Displacement);
289 Addend = (orig & 0x000FFFE0) >> 3;
290 break;
291 }
294 uint32_t orig = read32le(Displacement);
295 Addend = ((orig >> 29) & 0x3) | ((orig >> 3) & 0x1FFFFC);
296
297 // External symbols are routinely beyond ADRP's +/-4 GiB on Windows and
298 // there is no veneer, so route ADRP+ADD through a GOT slot. Only that
299 // idiom qualifies: ADRP+LDR reads the symbol's contents, and a non-zero
300 // addend cannot be expressed by a slot holding plain `sym`. LLVM codegen
301 // emits direct addresses as a MOVaddr pseudo and expands it after
302 // scheduling into this adjacent ADRP+ADD pair.
303 if (IsExtern && Addend == 0 &&
305 uint32_t NextInst = read32le(Displacement + 4);
306 if (isAddImmediate(NextInst) && ((NextInst >> 10) & 0xFFF) == 0) {
307 TargetOffset = getGOTEntryOffset(SectionID, Stubs, TargetName,
308 /*CreateIfMissing=*/true);
309 TargetSectionID = SectionID;
310 TargetName = StringRef();
311 IsExtern = false;
312 Addend = 0;
313 }
314 }
315 break;
316 }
318 Addend = read32AArch64LdrAddend(read32le(Displacement));
319 break;
320 }
322 uint32_t orig = read32le(Displacement);
323 Addend = ((orig >> 10) & 0xFFF);
324
325 // Partner of the ADRP above; no slot means that ADRP was left alone.
326 if (IsExtern && Addend == 0 &&
328 uint64_t GOTOffset = getGOTEntryOffset(SectionID, Stubs, TargetName,
329 /*CreateIfMissing=*/false);
330 if (GOTOffset != ~uint64_t(0) && isAddImmediate(orig)) {
331 // ADD Xd, Xn, #imm -> LDR Xd, [Xn, #imm]: load the slot instead.
332 uint32_t Rd = orig & 0x1F;
333 uint32_t Rn = (orig >> 5) & 0x1F;
335 0xF9400000u | (Rn << 5) | Rd);
336
337 // 12L so the resolver scales the immediate for a 64-bit load.
339 TargetOffset = GOTOffset;
340 TargetSectionID = SectionID;
341 TargetName = StringRef();
342 IsExtern = false;
343 Addend = 0;
344 }
345 }
346 break;
347 }
348
350 Addend = read64le(Displacement);
351 break;
352 }
353 default:
354 break;
355 }
356
357#if !defined(NDEBUG)
358 SmallString<32> RelTypeName;
359 RelI->getTypeName(RelTypeName);
360
361 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
362 << " RelType: " << RelTypeName << " TargetName: "
363 << TargetName << " Addend " << Addend << "\n");
364#endif
365
366 if (IsExtern) {
367 RelocationEntry RE(SectionID, Offset, RelType, Addend);
368 addRelocationForSymbol(RE, TargetName);
369 } else {
370 RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
371 addRelocationForSection(RE, TargetSectionID);
372 }
373 return ++RelI;
374 }
375
376 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
377 using namespace llvm::support::endian;
378
379 const auto Section = Sections[RE.SectionID];
380 uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
381 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
382
383 switch (RE.RelType) {
384 default:
385 llvm_unreachable("unsupported relocation type");
387 // This relocation is ignored.
388 break;
389 }
391 // The page base of the target, for ADRP instruction.
392 Value += RE.Addend;
393 write32AArch64Addr(Target, Value, FinalAddress, 12);
394 break;
395 }
397 // The 12-bit relative displacement to the target, for instruction ADR
398 Value += RE.Addend;
399 write32AArch64Addr(Target, Value, FinalAddress, 0);
400 break;
401 }
403 // The 12-bit page offset of the target,
404 // for instructions ADD/ADDS (immediate) with zero shift.
405 Value += RE.Addend;
406 write32AArch64Imm(Target, Value & 0xFFF, 0);
407 break;
408 }
410 // The 12-bit page offset of the target,
411 // for instruction LDR (indexed, unsigned immediate).
412 Value += RE.Addend;
414 break;
415 }
417 // The 32-bit VA of the target.
418 uint32_t VA = Value + RE.Addend;
419 write32le(Target, VA);
420 break;
421 }
423 // The target's 32-bit RVA.
424 uint64_t RVA = Value + RE.Addend - getImageBase();
425 write32le(Target, RVA);
426 break;
427 }
429 // Encode the immadiate value for generated Stub instruction (MOVZ)
430 or32le(Target + 12, ((Value + RE.Addend) & 0xFFFF) << 5);
431 or32le(Target + 8, ((Value + RE.Addend) & 0xFFFF0000) >> 11);
432 or32le(Target + 4, ((Value + RE.Addend) & 0xFFFF00000000) >> 27);
433 or32le(Target + 0, ((Value + RE.Addend) & 0xFFFF000000000000) >> 43);
434 break;
435 }
437 // The 26-bit relative displacement to the target, for B and BL
438 // instructions.
439 uint64_t PCRelVal = Value + RE.Addend - FinalAddress;
440 assert(isInt<28>(PCRelVal) && "Branch target is out of range.");
441 write32le(Target, (read32le(Target) & ~(0x03FFFFFF)) |
442 (PCRelVal & 0x0FFFFFFC) >> 2);
443 break;
444 }
446 // The 19-bit offset to the relocation target,
447 // for conditional B instruction.
448 uint64_t PCRelVal = Value + RE.Addend - FinalAddress;
449 assert(isInt<21>(PCRelVal) && "Branch target is out of range.");
450 write32le(Target, (read32le(Target) & ~(0x00FFFFE0)) |
451 (PCRelVal & 0x001FFFFC) << 3);
452 break;
453 }
455 // The 14-bit offset to the relocation target,
456 // for instructions TBZ and TBNZ.
457 uint64_t PCRelVal = Value + RE.Addend - FinalAddress;
458 assert(isInt<16>(PCRelVal) && "Branch target is out of range.");
459 write32le(Target, (read32le(Target) & ~(0x000FFFE0)) |
460 (PCRelVal & 0x0000FFFC) << 3);
461 break;
462 }
464 // The 64-bit VA of the relocation target.
466 break;
467 }
469 // 16-bit section index of the section that contains the target.
470 assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
471 "relocation overflow");
473 break;
474 }
476 // 32-bit offset of the target from the beginning of its section.
477 assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
478 "Relocation overflow");
479 assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
480 "Relocation underflow");
482 break;
483 }
485 // The 32-bit relative address from the byte following the relocation.
486 uint64_t Result = Value - FinalAddress - 4;
487 write32le(Target, Result + RE.Addend);
488 break;
489 }
490 }
491 }
492
493 void registerEHFrames() override {}
494};
495
496} // End namespace llvm
497
498#undef DEBUG_TYPE
499
500#endif // LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFAARCH64_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
uint64_t Imm
#define T
#define P(N)
This file defines the SmallString class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
void write32le(void *P, uint32_t V)
Definition Endian.h:455
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
Symbol resolution interface.
Definition JITSymbol.h:373
RelocationEntry - used to represent relocations internally in the dynamic linker.
uint32_t RelType
RelType - relocation type.
uint64_t Offset
Offset - offset into the section.
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
unsigned SectionID
SectionID - the section this relocation points to.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition Record.h:2295
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
unsigned getMaxStubSize() const override
RuntimeDyldCOFFAArch64(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
std::tuple< uint64_t, uint64_t, uint64_t > generateRelocationStub(unsigned SectionID, StringRef TargetName, uint64_t Offset, uint64_t RelType, uint64_t Addend, StubMap &Stubs)
Expected< object::relocation_iterator > processRelocationRef(unsigned SectionID, object::relocation_iterator RelI, const object::ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) override
Parses one or more object file relocations (some object files use relocation pairs) and stores it to ...
uint64_t getGOTEntryOffset(unsigned SectionID, StubMap &Stubs, StringRef Name, bool CreateIfMissing)
GOT slot in this section's stub area holding the address of Name, so an ADRP can reach external symbo...
static bool isAddImmediate(uint32_t Inst)
ADD (immediate, no shift): the second half of the ADRP+ADD idiom.
uint64_t getSymbolOffset(const SymbolRef &Sym)
static constexpr StringRef getImportSymbolPrefix()
RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, unsigned PointerSize, uint32_t PointerReloc)
uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, StringRef Name, bool SetSectionIDMinus1=false)
std::map< SectionRef, unsigned > ObjSectionToIDMap
std::map< RelocationValueRef, uintptr_t > StubMap
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
Expected< unsigned > findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections)
Find Section in LocalSections.
uint8_t * createStubFunction(uint8_t *Addr, unsigned AbiVariant=0)
Emits long jump instruction to Addr.
SectionEntry - represents a section emitted into memory by the dynamic linker.
uint8_t * getAddressWithOffset(unsigned OffsetBytes) const
Return the address of this section with an offset.
void advanceStubOffset(unsigned StubSize)
uintptr_t getStubOffset() const
uintptr_t getObjAddress() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
This class is the base class for all object file types.
Definition ObjectFile.h:231
uint64_t getType() const
Definition ObjectFile.h:633
uint64_t getOffset() const
Definition ObjectFile.h:625
symbol_iterator getSymbol() const
Definition ObjectFile.h:629
void getTypeName(SmallVectorImpl< char > &Result) const
Get a string that represents the type of this relocation.
Definition ObjectFile.h:637
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_REL_ARM64_SECREL
Definition COFF.h:409
@ IMAGE_REL_ARM64_BRANCH19
Definition COFF.h:416
@ IMAGE_REL_ARM64_REL32
Definition COFF.h:418
@ IMAGE_REL_ARM64_ADDR32
Definition COFF.h:402
@ IMAGE_REL_ARM64_SECTION
Definition COFF.h:414
@ IMAGE_REL_ARM64_ABSOLUTE
Definition COFF.h:401
@ IMAGE_REL_ARM64_PAGEOFFSET_12A
Definition COFF.h:407
@ IMAGE_REL_ARM64_BRANCH14
Definition COFF.h:417
@ IMAGE_REL_ARM64_BRANCH26
Definition COFF.h:404
@ IMAGE_REL_ARM64_PAGEOFFSET_12L
Definition COFF.h:408
@ IMAGE_REL_ARM64_ADDR32NB
Definition COFF.h:403
@ IMAGE_REL_ARM64_PAGEBASE_REL21
Definition COFF.h:405
@ IMAGE_REL_ARM64_REL21
Definition COFF.h:406
@ IMAGE_REL_ARM64_ADDR64
Definition COFF.h:415
content_iterator< RelocationRef > relocation_iterator
Definition ObjectFile.h:79
uint64_t read64le(const void *P)
Definition Endian.h:415
uint16_t read16le(const void *P)
Definition Endian.h:409
void write64le(void *P, uint64_t V)
Definition Endian.h:458
void write16le(void *P, uint16_t V)
Definition Endian.h:452
uint32_t read32le(const void *P)
Definition Endian.h:412
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ INTERNAL_REL_ARM64_LONG_BRANCH26
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
static uint64_t read32AArch64LdrAddend(uint32_t Inst)
Byte addend held in an LDR/STR (unsigned immediate) instruction.
static void write32AArch64Ldr(uint8_t *T, uint64_t imm)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
static void or32le(void *P, int32_t V)
static void add16(uint8_t *p, int16_t v)
static void write32AArch64Imm(uint8_t *T, uint64_t imm, uint32_t rangeLimit)
static void write32AArch64Addr(void *T, uint64_t s, uint64_t p, int shift)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39