[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / ExecutionEngine / JITLink / MachO_x86_64.cpp
blobd83787ffd598692e08bb0e5bd62f9e21a3321e2a
1 //===---- MachO_x86_64.cpp -JIT linker implementation for MachO/x86-64 ----===//
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 // MachO/x86-64 jit-link implementation.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
15 #include "BasicGOTAndStubsBuilder.h"
16 #include "MachOLinkGraphBuilder.h"
18 #define DEBUG_TYPE "jitlink"
20 using namespace llvm;
21 using namespace llvm::jitlink;
22 using namespace llvm::jitlink::MachO_x86_64_Edges;
24 namespace {
26 class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
27 public:
28 MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
29 : MachOLinkGraphBuilder(Obj) {
30 addCustomSectionParser(
31 "__eh_frame", [this](NormalizedSection &EHFrameSection) {
32 if (!EHFrameSection.Data)
33 return make_error<JITLinkError>(
34 "__eh_frame section is marked zero-fill");
35 return MachOEHFrameBinaryParser(
36 *this, EHFrameSection.Address,
37 StringRef(EHFrameSection.Data, EHFrameSection.Size),
38 *EHFrameSection.GraphSection, 8, 4, NegDelta32, Delta64)
39 .addToGraph();
40 });
43 private:
44 static Expected<MachOX86RelocationKind>
45 getRelocationKind(const MachO::relocation_info &RI) {
46 switch (RI.r_type) {
47 case MachO::X86_64_RELOC_UNSIGNED:
48 if (!RI.r_pcrel) {
49 if (RI.r_length == 3)
50 return RI.r_extern ? Pointer64 : Pointer64Anon;
51 else if (RI.r_extern && RI.r_length == 2)
52 return Pointer32;
54 break;
55 case MachO::X86_64_RELOC_SIGNED:
56 if (RI.r_pcrel && RI.r_length == 2)
57 return RI.r_extern ? PCRel32 : PCRel32Anon;
58 break;
59 case MachO::X86_64_RELOC_BRANCH:
60 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
61 return Branch32;
62 break;
63 case MachO::X86_64_RELOC_GOT_LOAD:
64 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
65 return PCRel32GOTLoad;
66 break;
67 case MachO::X86_64_RELOC_GOT:
68 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
69 return PCRel32GOT;
70 break;
71 case MachO::X86_64_RELOC_SUBTRACTOR:
72 // SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3.
73 // Initially represent SUBTRACTOR relocations with 'Delta<W>'. They may
74 // be turned into NegDelta<W> by parsePairRelocation.
75 if (!RI.r_pcrel && RI.r_extern) {
76 if (RI.r_length == 2)
77 return Delta32;
78 else if (RI.r_length == 3)
79 return Delta64;
81 break;
82 case MachO::X86_64_RELOC_SIGNED_1:
83 if (RI.r_pcrel && RI.r_length == 2)
84 return RI.r_extern ? PCRel32Minus1 : PCRel32Minus1Anon;
85 break;
86 case MachO::X86_64_RELOC_SIGNED_2:
87 if (RI.r_pcrel && RI.r_length == 2)
88 return RI.r_extern ? PCRel32Minus2 : PCRel32Minus2Anon;
89 break;
90 case MachO::X86_64_RELOC_SIGNED_4:
91 if (RI.r_pcrel && RI.r_length == 2)
92 return RI.r_extern ? PCRel32Minus4 : PCRel32Minus4Anon;
93 break;
94 case MachO::X86_64_RELOC_TLV:
95 if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
96 return PCRel32TLV;
97 break;
100 return make_error<JITLinkError>(
101 "Unsupported x86-64 relocation: address=" +
102 formatv("{0:x8}", RI.r_address) +
103 ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
104 ", kind=" + formatv("{0:x1}", RI.r_type) +
105 ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
106 ", extern=" + (RI.r_extern ? "true" : "false") +
107 ", length=" + formatv("{0:d}", RI.r_length));
110 MachO::relocation_info
111 getRelocationInfo(const object::relocation_iterator RelItr) {
112 MachO::any_relocation_info ARI =
113 getObject().getRelocation(RelItr->getRawDataRefImpl());
114 MachO::relocation_info RI;
115 memcpy(&RI, &ARI, sizeof(MachO::relocation_info));
116 return RI;
119 using PairRelocInfo = std::tuple<MachOX86RelocationKind, Symbol *, uint64_t>;
121 // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
122 // returns the edge kind and addend to be used.
123 Expected<PairRelocInfo>
124 parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind,
125 const MachO::relocation_info &SubRI,
126 JITTargetAddress FixupAddress, const char *FixupContent,
127 object::relocation_iterator &UnsignedRelItr,
128 object::relocation_iterator &RelEnd) {
129 using namespace support;
131 assert(((SubtractorKind == Delta32 && SubRI.r_length == 2) ||
132 (SubtractorKind == Delta64 && SubRI.r_length == 3)) &&
133 "Subtractor kind should match length");
134 assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");
135 assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");
137 if (UnsignedRelItr == RelEnd)
138 return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "
139 "UNSIGNED relocation");
141 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
143 if (SubRI.r_address != UnsignedRI.r_address)
144 return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "
145 "point to different addresses");
147 if (SubRI.r_length != UnsignedRI.r_length)
148 return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "
149 "UNSIGNED reloc must match");
151 Symbol *FromSymbol;
152 if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
153 FromSymbol = FromSymbolOrErr->GraphSymbol;
154 else
155 return FromSymbolOrErr.takeError();
157 // Read the current fixup value.
158 uint64_t FixupValue = 0;
159 if (SubRI.r_length == 3)
160 FixupValue = *(const little64_t *)FixupContent;
161 else
162 FixupValue = *(const little32_t *)FixupContent;
164 // Find 'ToSymbol' using symbol number or address, depending on whether the
165 // paired UNSIGNED relocation is extern.
166 Symbol *ToSymbol = nullptr;
167 if (UnsignedRI.r_extern) {
168 // Find target symbol by symbol index.
169 if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
170 ToSymbol = ToSymbolOrErr->GraphSymbol;
171 else
172 return ToSymbolOrErr.takeError();
173 } else {
174 if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue))
175 ToSymbol = &*ToSymbolOrErr;
176 else
177 return ToSymbolOrErr.takeError();
178 FixupValue -= ToSymbol->getAddress();
181 MachOX86RelocationKind DeltaKind;
182 Symbol *TargetSymbol;
183 uint64_t Addend;
184 if (&BlockToFix == &FromSymbol->getAddressable()) {
185 TargetSymbol = ToSymbol;
186 DeltaKind = (SubRI.r_length == 3) ? Delta64 : Delta32;
187 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
188 // FIXME: handle extern 'from'.
189 } else if (&BlockToFix == &ToSymbol->getAddressable()) {
190 TargetSymbol = FromSymbol;
191 DeltaKind = (SubRI.r_length == 3) ? NegDelta64 : NegDelta32;
192 Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
193 } else {
194 // BlockToFix was neither FromSymbol nor ToSymbol.
195 return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
196 "either 'A' or 'B' (or a symbol in one "
197 "of their alt-entry chains)");
200 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
203 Error addRelocations() override {
204 using namespace support;
205 auto &Obj = getObject();
207 for (auto &S : Obj.sections()) {
209 JITTargetAddress SectionAddress = S.getAddress();
211 if (S.isVirtual()) {
212 if (S.relocation_begin() != S.relocation_end())
213 return make_error<JITLinkError>("Virtual section contains "
214 "relocations");
215 continue;
218 for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
219 RelItr != RelEnd; ++RelItr) {
221 MachO::relocation_info RI = getRelocationInfo(RelItr);
223 // Sanity check the relocation kind.
224 auto Kind = getRelocationKind(RI);
225 if (!Kind)
226 return Kind.takeError();
228 // Find the address of the value to fix up.
229 JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
231 LLVM_DEBUG({
232 dbgs() << "Processing relocation at "
233 << format("0x%016" PRIx64, FixupAddress) << "\n";
236 // Find the block that the fixup points to.
237 Block *BlockToFix = nullptr;
239 auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
240 if (!SymbolToFixOrErr)
241 return SymbolToFixOrErr.takeError();
242 BlockToFix = &SymbolToFixOrErr->getBlock();
245 if (FixupAddress + static_cast<JITTargetAddress>(1ULL << RI.r_length) >
246 BlockToFix->getAddress() + BlockToFix->getContent().size())
247 return make_error<JITLinkError>(
248 "Relocation extends past end of fixup block");
250 // Get a pointer to the fixup content.
251 const char *FixupContent = BlockToFix->getContent().data() +
252 (FixupAddress - BlockToFix->getAddress());
254 // The target symbol and addend will be populated by the switch below.
255 Symbol *TargetSymbol = nullptr;
256 uint64_t Addend = 0;
258 switch (*Kind) {
259 case Branch32:
260 case PCRel32:
261 case PCRel32GOTLoad:
262 case PCRel32GOT:
263 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
264 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
265 else
266 return TargetSymbolOrErr.takeError();
267 Addend = *(const ulittle32_t *)FixupContent;
268 break;
269 case Pointer32:
270 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
271 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
272 else
273 return TargetSymbolOrErr.takeError();
274 Addend = *(const ulittle32_t *)FixupContent;
275 break;
276 case Pointer64:
277 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
278 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
279 else
280 return TargetSymbolOrErr.takeError();
281 Addend = *(const ulittle64_t *)FixupContent;
282 break;
283 case Pointer64Anon: {
284 JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
285 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
286 TargetSymbol = &*TargetSymbolOrErr;
287 else
288 return TargetSymbolOrErr.takeError();
289 Addend = TargetAddress - TargetSymbol->getAddress();
290 break;
292 case PCRel32Minus1:
293 case PCRel32Minus2:
294 case PCRel32Minus4:
295 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
296 TargetSymbol = TargetSymbolOrErr->GraphSymbol;
297 else
298 return TargetSymbolOrErr.takeError();
299 Addend = *(const ulittle32_t *)FixupContent +
300 (1 << (*Kind - PCRel32Minus1));
301 break;
302 case PCRel32Anon: {
303 JITTargetAddress TargetAddress =
304 FixupAddress + 4 + *(const ulittle32_t *)FixupContent;
305 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
306 TargetSymbol = &*TargetSymbolOrErr;
307 else
308 return TargetSymbolOrErr.takeError();
309 Addend = TargetAddress - TargetSymbol->getAddress();
310 break;
312 case PCRel32Minus1Anon:
313 case PCRel32Minus2Anon:
314 case PCRel32Minus4Anon: {
315 JITTargetAddress Delta =
316 static_cast<JITTargetAddress>(1ULL << (*Kind - PCRel32Minus1Anon));
317 JITTargetAddress TargetAddress =
318 FixupAddress + 4 + Delta + *(const ulittle32_t *)FixupContent;
319 if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
320 TargetSymbol = &*TargetSymbolOrErr;
321 else
322 return TargetSymbolOrErr.takeError();
323 Addend = TargetAddress - TargetSymbol->getAddress();
324 break;
326 case Delta32:
327 case Delta64: {
328 // We use Delta32/Delta64 to represent SUBTRACTOR relocations.
329 // parsePairRelocation handles the paired reloc, and returns the
330 // edge kind to be used (either Delta32/Delta64, or
331 // NegDelta32/NegDelta64, depending on the direction of the
332 // subtraction) along with the addend.
333 auto PairInfo =
334 parsePairRelocation(*BlockToFix, *Kind, RI, FixupAddress,
335 FixupContent, ++RelItr, RelEnd);
336 if (!PairInfo)
337 return PairInfo.takeError();
338 std::tie(*Kind, TargetSymbol, Addend) = *PairInfo;
339 assert(TargetSymbol && "No target symbol from parsePairRelocation?");
340 break;
342 default:
343 llvm_unreachable("Special relocation kind should not appear in "
344 "mach-o file");
347 LLVM_DEBUG({
348 Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
349 Addend);
350 printEdge(dbgs(), *BlockToFix, GE,
351 getMachOX86RelocationKindName(*Kind));
352 dbgs() << "\n";
354 BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
355 *TargetSymbol, Addend);
358 return Error::success();
362 class MachO_x86_64_GOTAndStubsBuilder
363 : public BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder> {
364 public:
365 MachO_x86_64_GOTAndStubsBuilder(LinkGraph &G)
366 : BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder>(G) {}
368 bool isGOTEdge(Edge &E) const {
369 return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
372 Symbol &createGOTEntry(Symbol &Target) {
373 auto &GOTEntryBlock = G.createContentBlock(
374 getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
375 GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
376 return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
379 void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
380 assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
381 "Not a GOT edge?");
382 E.setKind(PCRel32);
383 E.setTarget(GOTEntry);
384 // Leave the edge addend as-is.
387 bool isExternalBranchEdge(Edge &E) {
388 return E.getKind() == Branch32 && !E.getTarget().isDefined();
391 Symbol &createStub(Symbol &Target) {
392 auto &StubContentBlock =
393 G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
394 // Re-use GOT entries for stub targets.
395 auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
396 StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, 0);
397 return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
400 void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
401 assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
402 assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
403 E.setTarget(Stub);
406 private:
407 Section &getGOTSection() {
408 if (!GOTSection)
409 GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
410 return *GOTSection;
413 Section &getStubsSection() {
414 if (!StubsSection) {
415 auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
416 sys::Memory::MF_READ | sys::Memory::MF_EXEC);
417 StubsSection = &G.createSection("$__STUBS", StubsProt);
419 return *StubsSection;
422 StringRef getGOTEntryBlockContent() {
423 return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
424 sizeof(NullGOTEntryContent));
427 StringRef getStubBlockContent() {
428 return StringRef(reinterpret_cast<const char *>(StubContent),
429 sizeof(StubContent));
432 static const uint8_t NullGOTEntryContent[8];
433 static const uint8_t StubContent[6];
434 Section *GOTSection = nullptr;
435 Section *StubsSection = nullptr;
438 const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
440 const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
441 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
442 } // namespace
444 namespace llvm {
445 namespace jitlink {
447 class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
448 friend class JITLinker<MachOJITLinker_x86_64>;
450 public:
451 MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
452 PassConfiguration PassConfig)
453 : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
455 private:
456 StringRef getEdgeKindName(Edge::Kind R) const override {
457 return getMachOX86RelocationKindName(R);
460 Expected<std::unique_ptr<LinkGraph>>
461 buildGraph(MemoryBufferRef ObjBuffer) override {
462 auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
463 if (!MachOObj)
464 return MachOObj.takeError();
465 return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
468 static Error targetOutOfRangeError(const Block &B, const Edge &E) {
469 std::string ErrMsg;
471 raw_string_ostream ErrStream(ErrMsg);
472 ErrStream << "Relocation target out of range: ";
473 printEdge(ErrStream, B, E, getMachOX86RelocationKindName(E.getKind()));
474 ErrStream << "\n";
476 return make_error<JITLinkError>(std::move(ErrMsg));
479 Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
481 using namespace support;
483 char *FixupPtr = BlockWorkingMem + E.getOffset();
484 JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
486 switch (E.getKind()) {
487 case Branch32:
488 case PCRel32:
489 case PCRel32Anon: {
490 int64_t Value =
491 E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
492 if (Value < std::numeric_limits<int32_t>::min() ||
493 Value > std::numeric_limits<int32_t>::max())
494 return targetOutOfRangeError(B, E);
495 *(little32_t *)FixupPtr = Value;
496 break;
498 case Pointer64:
499 case Pointer64Anon: {
500 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
501 *(ulittle64_t *)FixupPtr = Value;
502 break;
504 case PCRel32Minus1:
505 case PCRel32Minus2:
506 case PCRel32Minus4: {
507 int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1));
508 int64_t Value =
509 E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
510 if (Value < std::numeric_limits<int32_t>::min() ||
511 Value > std::numeric_limits<int32_t>::max())
512 return targetOutOfRangeError(B, E);
513 *(little32_t *)FixupPtr = Value;
514 break;
516 case PCRel32Minus1Anon:
517 case PCRel32Minus2Anon:
518 case PCRel32Minus4Anon: {
519 int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1Anon));
520 int64_t Value =
521 E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
522 if (Value < std::numeric_limits<int32_t>::min() ||
523 Value > std::numeric_limits<int32_t>::max())
524 return targetOutOfRangeError(B, E);
525 *(little32_t *)FixupPtr = Value;
526 break;
528 case Delta32:
529 case Delta64:
530 case NegDelta32:
531 case NegDelta64: {
532 int64_t Value;
533 if (E.getKind() == Delta32 || E.getKind() == Delta64)
534 Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
535 else
536 Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
538 if (E.getKind() == Delta32 || E.getKind() == NegDelta32) {
539 if (Value < std::numeric_limits<int32_t>::min() ||
540 Value > std::numeric_limits<int32_t>::max())
541 return targetOutOfRangeError(B, E);
542 *(little32_t *)FixupPtr = Value;
543 } else
544 *(little64_t *)FixupPtr = Value;
545 break;
547 case Pointer32: {
548 uint64_t Value = E.getTarget().getAddress() + E.getAddend();
549 if (Value > std::numeric_limits<uint32_t>::max())
550 return targetOutOfRangeError(B, E);
551 *(ulittle32_t *)FixupPtr = Value;
552 break;
554 default:
555 llvm_unreachable("Unrecognized edge kind");
558 return Error::success();
561 uint64_t NullValue = 0;
564 void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
565 PassConfiguration Config;
566 Triple TT("x86_64-apple-macosx");
568 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
569 // Add a mark-live pass.
570 if (auto MarkLive = Ctx->getMarkLivePass(TT))
571 Config.PrePrunePasses.push_back(std::move(MarkLive));
572 else
573 Config.PrePrunePasses.push_back(markAllSymbolsLive);
575 // Add an in-place GOT/Stubs pass.
576 Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
577 MachO_x86_64_GOTAndStubsBuilder(G).run();
578 return Error::success();
582 if (auto Err = Ctx->modifyPassConfig(TT, Config))
583 return Ctx->notifyFailed(std::move(Err));
585 // Construct a JITLinker and run the link function.
586 MachOJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
589 StringRef getMachOX86RelocationKindName(Edge::Kind R) {
590 switch (R) {
591 case Branch32:
592 return "Branch32";
593 case Pointer32:
594 return "Pointer32";
595 case Pointer64:
596 return "Pointer64";
597 case Pointer64Anon:
598 return "Pointer64Anon";
599 case PCRel32:
600 return "PCRel32";
601 case PCRel32Minus1:
602 return "PCRel32Minus1";
603 case PCRel32Minus2:
604 return "PCRel32Minus2";
605 case PCRel32Minus4:
606 return "PCRel32Minus4";
607 case PCRel32Anon:
608 return "PCRel32Anon";
609 case PCRel32Minus1Anon:
610 return "PCRel32Minus1Anon";
611 case PCRel32Minus2Anon:
612 return "PCRel32Minus2Anon";
613 case PCRel32Minus4Anon:
614 return "PCRel32Minus4Anon";
615 case PCRel32GOTLoad:
616 return "PCRel32GOTLoad";
617 case PCRel32GOT:
618 return "PCRel32GOT";
619 case PCRel32TLV:
620 return "PCRel32TLV";
621 case Delta32:
622 return "Delta32";
623 case Delta64:
624 return "Delta64";
625 case NegDelta32:
626 return "NegDelta32";
627 case NegDelta64:
628 return "NegDelta64";
629 default:
630 return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
634 } // end namespace jitlink
635 } // end namespace llvm