LLVM 22.0.0git
systemz.h
Go to the documentation of this file.
1//=== systemz.h - Generic JITLink systemz edge kinds, utilities -*- 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// Generic utilities for graphs representing systemz objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
14#define LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
15
16#include "TableManager.h"
18
19using namespace llvm::support::endian;
20
21namespace llvm {
22namespace jitlink {
23namespace systemz {
24
25/// Represents systemz fixups and other systemz-specific edge kinds.
26enum EdgeKind_systemz : Edge::Kind {
27
28 /// A plain 64-bit pointer value relocation.
29 ///
30 /// Fixup expression:
31 /// Fixup <- Target + Addend : uint64
32 ///
33 Pointer64 = Edge::FirstRelocation,
34
35 /// A plain 32-bit pointer value relocation.
36 ///
37 /// Fixup expression:
38 /// Fixup <- Target + Addend : uint32
39 ///
40 /// Errors:
41 /// - The target must reside in the low 32-bits of the address space,
42 /// otherwise an out-of-range error will be returned.
43 ///
45
46 /// A plain 20-bit pointer value relocation.
47 ///
48 /// Fixup expression:
49 /// Fixup <- Target + Addend : uint20
50 ///
51 /// Errors:
52 /// - The target must reside in the low 20-bits of the address space,
53 /// otherwise an out-of-range error will be returned.
54 ///
56
57 /// A plain 16-bit pointer value relocation.
58 ///
59 /// Fixup expression:
60 /// Fixup <- Target + Addend : uint16
61 ///
62 /// Errors:
63 /// - The target must reside in the low 16-bits of the address space,
64 /// otherwise an out-of-range error will be returned.
65 ///
67
68 /// A plain 12-bit pointer value relocation.
69 ///
70 /// Fixup expression:
71 /// Fixup <- Target + Addend : uint12
72 ///
73 /// Errors:
74 /// - The target must reside in the low 12-bits of the address space,
75 /// otherwise an out-of-range error will be returned.
76 ///
78
79 /// A plain 8-bit pointer value relocation.
80 ///
81 /// Fixup expression:
82 /// Fixup <- Target + Addend : uint8
83 ///
84 /// Errors:
85 /// - The target must reside in the low 8-bits of the address space,
86 /// otherwise an out-of-range error will be returned.
87 ///
89
90 /// A 64-bit delta.
91 ///
92 /// Delta from the fixup to the target.
93 ///
94 /// Fixup expression:
95 /// Fixup <- Target - Fixup + Addend : int64
96 ///
98
99 /// A 32-bit delta.
100 ///
101 /// Delta from the fixup to the target.
102 ///
103 /// Fixup expression:
104 /// Fixup <- Target - Fixup + Addend : int32
105 ///
106 /// Errors:
107 /// - The result of the fixup expression must fit into an int32, otherwise
108 /// an out-of-range error will be returned.
109 ///
111
112 /// A 16-bit delta.
113 ///
114 /// Delta from the fixup to the target.
115 ///
116 /// Fixup expression:
117 /// Fixup <- Target - Fixup + Addend : int16
118 ///
119 /// Errors:
120 /// - The result of the fixup expression must fit into an int16, otherwise
121 /// an out-of-range error will be returned.
122 ///
124
125 /// A 32-bit delta shifted by 1.
126 ///
127 /// Delta from the fixup to the target.
128 ///
129 /// Fixup expression:
130 /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
131 ///
132 /// Errors:
133 /// - The result of the fixup expression before shifting right by 1 must
134 /// fit into an int33, otherwise an out-of-range error will be returned.
135 /// - The result of the fixup expression before shifting right by 1 must
136 /// be multiple of 2, otherwise an alignment error will be returned.
137 ///
139
140 /// A 24-bit delta shifted by 1.
141 ///
142 /// Delta from the fixup to the target.
143 ///
144 /// Fixup expression:
145 /// Fixup <- (Target - Fixup + Addend) >> 1 : int24
146 ///
147 /// Errors:
148 /// - The result of the fixup expression before shifting right by 1 must
149 /// fit into an int25, otherwise an out-of-range error will be returned.
150 /// - The result of the fixup expression before shifting right by 1 must
151 /// be multiple of 2, otherwise an alignment error will be returned.
152 ///
154
155 /// A 16-bit delta shifted by 1.
156 ///
157 /// Delta from the fixup to the target.
158 ///
159 /// Fixup expression:
160 /// Fixup <- (Target - Fixup + Addend) >> 1 : int16
161 ///
162 /// Errors:
163 /// - The result of the fixup expression before shifting right by 1 must
164 /// fit into an int17, otherwise an out-of-range error will be returned.
165 /// - The result of the fixup expression before shifting right by 1 must
166 /// be multiple of 2, otherwise an alignment error will be returned.
167 ///
169
170 /// A 12-bit delta shifted by 1.
171 ///
172 /// Delta from the fixup to the target.
173 ///
174 /// Fixup expression:
175 /// Fixup <- (Target - Fixup + Addend) >> 1 : int12
176 ///
177 /// Errors:
178 /// - The result of the fixup expression before shifting right by 1 must
179 /// fit into an int13, otherwise an out-of-range error will be returned.
180 /// - The result of the fixup expression before shifting right by 1 must
181 /// be multiple of 2, otherwise an alignment error will be returned.
182 ///
184
185 /// A 64-bit negative delta.
186 ///
187 /// Delta from target back to the fixup.
188 ///
189 /// Fixup expression:
190 /// Fixup <- Fixup - Target + Addend : int64
191 ///
193
194 /// A 32-bit negative delta.
195 ///
196 /// Delta from the target back to the fixup.
197 ///
198 /// Fixup expression:
199 /// Fixup <- Fixup - Target + Addend : int32
200 ///
201 /// Errors:
202 /// - The result of the fixup expression must fit into an int32, otherwise
203 /// an out-of-range error will be returned.
205
206 /// A 32-bit Delta shifted by 1.
207 ///
208 /// Delta from the fixup to the PLT slot for the target. This will lead to
209 /// creation of a PLT stub.
210 ///
211 /// Fixup expression:
212 /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
213 ///
214 /// Errors:
215 /// - The result of the fixup expression before shifting right by 1 must
216 /// fit into an int33, otherwise an out-of-range error will be returned.
217 /// - The result of the fixup expression before shifting right by 1 must
218 /// be multiple of 2, otherwise an alignment error will be returned.
219 ///
221
222 /// A 24-bit Delta shifted by 1.
223 ///
224 /// Delta from the fixup to the PLT slot for the target. This will lead to
225 /// creation of a PLT stub.
226 ///
227 /// Fixup expression:
228 /// Fixup <- (Target - Fixup + Addend) >> 1 : int24
229 ///
230 /// Errors:
231 /// - The result of the fixup expression before shifting right by 1 must
232 /// fit into an int25, otherwise an out-of-range error will be returned.
233 /// - The result of the fixup expression before shifting right by 1 must
234 /// be multiple of 2, otherwise an alignment error will be returned.
235 ///
237
238 /// A 16-bit Delta shifted by 1.
239 ///
240 /// Delta from the fixup to the PLT slot for the target. This will lead to
241 /// creation of a PLT stub.
242 ///
243 /// Fixup expression:
244 /// Fixup <- (Target - Fixup + Addend) >> 1 : int16
245 ///
246 /// Errors:
247 /// - The result of the fixup expression before shifting right by 1 must
248 /// fit into an int17, otherwise an out-of-range error will be returned.
249 /// - The result of the fixup expression before shifting right by 1 must
250 /// be multiple of 2, otherwise an alignment error will be returned.
251 ///
253
254 /// A 12-bit Delta shifted by 1.
255 ///
256 /// Delta from the fixup to the PLT slot for the target. This will lead to
257 /// creation of a PLT stub.
258 ///
259 /// Fixup expression:
260 /// Fixup <- (Target - Fixup + Addend) >> 1 : int12
261 ///
262 /// Errors:
263 /// - The result of the fixup expression before shifting right by 1 must
264 /// fit into an int13, otherwise an out-of-range error will be returned.
265 /// - The result of the fixup expression before shifting right by 1 must
266 /// be multiple of 2, otherwise an alignment error will be returned.
267 ///
269
270 /// A 64-bit Delta.
271 ///
272 /// Delta from the fixup to the PLT slot for the target. This will lead to
273 /// creation of a PLT stub.
274 ///
275 /// Fixup expression:
276 /// Fixup <- Target - Fixup + Addend : int64
277 ///
279
280 /// A 32-bit Delta.
281 ///
282 /// Delta from the fixup to the PLT slot for the target. This will lead to
283 /// creation of a PLT stub.
284 ///
285 /// Fixup expression:
286 /// Fixup <- Target - Fixup + Addend : int32
287 ///
288 /// Errors:
289 /// - The result of the fixup expression must fit into an int32, otherwise
290 /// an out-of-range error will be returned.
291 ///
293
294 /// A 64-bit offset from GOT to PLT.
295 ///
296 /// Fixup expression:
297 /// Fixup <- Target - GOTBase + Addend : int64
298 ///
299 /// Errors:
300 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
301 /// symbol was not been defined.
302 ///
304
305 /// A 32-bit offset from GOT to PLT.
306 ///
307 /// Fixup expression:
308 /// Fixup <- Target - GOTBase + Addend : int32
309 ///
310 /// Errors:
311 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
312 /// symbol was not been defined.
313 /// - The result of the fixup expression must fit into an int32, otherwise
314 /// an out-of-range error will be returned.
315 ///
317
318 /// A 16-bit offset from GOT to PLT.
319 ///
320 /// Fixup expression:
321 /// Fixup <- Target - GOTBase + Addend : int16
322 ///
323 /// Errors:
324 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
325 /// symbol was not been defined.
326 /// - The result of the fixup expression must fit into an int16, otherwise
327 /// an out-of-range error will be returned.
328 ///
330
331 /// A 64-bit offset from GOT.
332 ///
333 /// Fixup expression:
334 /// Fixup <- Target - GOTBase + Addend : int64
335 ///
336 /// Errors:
337 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
338 /// symbol was not been defined.
339 ///
341
342 /// A 32-bit offset from GOT.
343 ///
344 /// Fixup expression:
345 /// Fixup <- Target - GOTBase + Addend : int32
346 ///
347 /// Errors:
348 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
349 /// symbol was not been defined.
350 /// - The result of the fixup expression must fit into an int32, otherwise
351 /// an out-of-range error will be returned.
352 ///
354
355 /// A 16-bit offset from GOT.
356 ///
357 /// Fixup expression:
358 /// Fixup <- Target - GOTBase + Addend : int16
359 ///
360 /// Errors:
361 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
362 /// symbol was not been defined.
363 /// - The result of the fixup expression must fit into an int16, otherwise
364 /// an out-of-range error will be returned.
365 ///
367
368 /// A 20-bit offset from GOT.
369 ///
370 /// Fixup expression:
371 /// Fixup <- Target - GOTBase + Addend : int20
372 ///
373 /// Errors:
374 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
375 /// symbol was not been defined.
376 /// - The result of the fixup expression must fit into an int16, otherwise
377 /// an out-of-range error will be returned.
378 ///
380
381 /// A 12-bit offset from GOT.
382 ///
383 /// Fixup expression:
384 /// Fixup <- Target - GOTBase + Addend : int12
385 ///
386 /// Errors:
387 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
388 /// symbol was not been defined.
389 /// - The result of the fixup expression must fit into an int16, otherwise
390 /// an out-of-range error will be returned.
391 ///
393
394 /// A GOT entry getter/constructor, transformed to Delta64FromGOT pointing
395 /// at the GOT entry for the original target.
396 ///
397 /// Indicates that this edge should be transformed into a Delta64FromGOT
398 /// targeting the GOT entry for the edge's current target, maintaining the
399 /// same addend. A GOT entry for the target should be created if one does
400 /// not already exist.
401 ///
402 /// Edges of this kind are usually handled by a GOT builder pass inserted by
403 /// default.
404 ///
405 /// Fixup expression:
406 /// NONE
407 ///
408 /// Errors:
409 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
410 ///
412
413 /// A GOT entry getter/constructor, transformed to Delta32FromGOT pointing
414 /// at the GOT entry for the original target.
415 ///
416 /// Indicates that this edge should be transformed into a Delta32FromGOT
417 /// targeting the GOT entry for the edge's current target, maintaining the
418 /// same addend. A GOT entry for the target should be created if one does
419 /// not already exist.
420 ///
421 /// Edges of this kind are usually handled by a GOT builder pass inserted by
422 /// default.
423 ///
424 /// Fixup expression:
425 /// NONE
426 ///
427 /// Errors:
428 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
429 ///
431
432 /// A GOT entry getter/constructor, transformed to Delta20FromGOT pointing
433 /// at the GOT entry for the original target.
434 ///
435 /// Indicates that this edge should be transformed into a Delta20FromGOT
436 /// targeting the GOT entry for the edge's current target, maintaining the
437 /// same addend. A GOT entry for the target should be created if one does
438 /// not already exist.
439 ///
440 /// Edges of this kind are usually handled by a GOT builder pass inserted by
441 /// default.
442 ///
443 /// Fixup expression:
444 /// NONE
445 ///
446 /// Errors:
447 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
448 ///
450
451 /// A GOT entry getter/constructor, transformed to Delta16FromGOT pointing
452 /// at the GOT entry for the original target.
453 ///
454 /// Indicates that this edge should be transformed into a Delta16FromGOT
455 /// targeting the GOT entry for the edge's current target, maintaining the
456 /// same addend. A GOT entry for the target should be created if one does
457 /// not already exist.
458 ///
459 /// Edges of this kind are usually handled by a GOT builder pass inserted by
460 /// default.
461 ///
462 /// Fixup expression:
463 /// NONE
464 ///
465 /// Errors:
466 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
467 ///
469
470 /// A GOT entry getter/constructor, transformed to Delta12FromGOT pointing
471 /// at the GOT entry for the original target.
472 ///
473 /// Indicates that this edge should be transformed into a Delta12FromGOT
474 /// targeting the GOT entry for the edge's current target, maintaining the
475 /// same addend. A GOT entry for the target should be created if one does
476 /// not already exist.
477 ///
478 /// Edges of this kind are usually handled by a GOT builder pass inserted by
479 /// default.
480 ///
481 /// Fixup expression:
482 /// NONE
483 ///
484 /// Errors:
485 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
486 /// phase will result in an assert/unreachable during the fixup phase.
487 ///
489
490 /// A GOT entry getter/constructor, transformed to Delta32dbl pointing at
491 /// the GOT entry for the original target.
492 ///
493 /// Indicates that this edge should be transformed into a Delta32dbl targeting
494 /// the GOT entry for the edge's current target, maintaining the same addend.
495 /// A GOT entry for the target should be created if one does not already
496 /// exist.
497 ///
498 /// Edges of this kind are usually handled by a GOT builder pass inserted by
499 /// default.
500 ///
501 /// Fixup expression:
502 /// NONE
503 ///
504 /// Errors:
505 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
506 /// phase will result in an assert/unreachable during the fixup phase.
507 ///
509
510 /// A TLSInfo entry getter/constructor, transformed to Delta64FromGOT.
511 ///
512 /// Indicates that this edge should be transformed into a Delta64FromGOT
513 /// targeting the TLSInfo entry for the edge's current target. A TLSInfo
514 /// entry for the target should be created if one does not already exist.
515 ///
516 /// Fixup expression:
517 /// NONE
518 ///
519 /// Errors:
520 /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
521 /// phase will result in an assert/unreachable during the fixup phase.
522 ///
524
525 /// A 32-bit Delta to GOT base.
526 ///
527 /// Fixup expression:
528 /// Fixup <- GOTBase - Fixup + Addend : int32
529 ///
530 /// Errors:
531 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
532 /// symbol was not been defined.
533 /// - The result of the fixup expression must fit into an int32, otherwise
534 /// an out-of-range error will be returned.
535 ///
537
538 /// A 32-bit Delta to GOT base shifted by 1.
539 ///
540 /// Fixup expression:
541 /// Fixup <- (GOTBase - Fixup + Addend) >> 1 : int32
542 ///
543 /// Errors:
544 /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
545 /// symbol was not been defined.
546 /// - The result of the fixup expression before shifting right by 1 must
547 /// fit into an int33, otherwise an out-of-range error will be returned.
548 /// - The result of the fixup expression before shifting right by 1 must
549 /// be multiple of 2, otherwise an alignment error will be returned.
550 ///
552
553};
554
555/// Returns a string name for the given systemz edge. For debugging purposes
556/// only
557const char *getEdgeKindName(Edge::Kind K);
558
559/// Apply fixup expression for edge to block content.
560inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
561 const Symbol *GOTSymbol) {
562 using namespace support;
563
564 char *BlockWorkingMem = B.getAlreadyMutableContent().data();
565 char *FixupPtr = BlockWorkingMem + E.getOffset();
566 orc::ExecutorAddr FixupAddress = B.getAddress() + E.getOffset();
567 int64_t S = E.getTarget().getAddress().getValue();
568 int64_t A = E.getAddend();
569 int64_t P = FixupAddress.getValue();
570 int64_t GOTBase = GOTSymbol ? GOTSymbol->getAddress().getValue() : 0;
571 Edge::Kind K = E.getKind();
572
573 DEBUG_WITH_TYPE("jitlink", {
574 dbgs() << " Applying fixup on " << G.getEdgeKindName(K)
575 << " edge, (S, A, P, .GOT.) = (" << formatv("{0:x}", S) << ", "
576 << formatv("{0:x}", A) << ", " << formatv("{0:x}", P) << ", "
577 << formatv("{0:x}", GOTBase) << ")\n";
578 });
579
580 const auto isAlignmentCorrect = [](uint64_t Value, int N) {
581 return (Value & (N - 1)) ? false : true;
582 };
583
584 switch (K) {
585 case Pointer64: {
586 uint64_t Value = S + A;
587 write64be(FixupPtr, Value);
588 break;
589 }
590 case Pointer32: {
591 uint64_t Value = S + A;
593 return makeTargetOutOfRangeError(G, B, E);
594 write32be(FixupPtr, Value);
595 break;
596 }
597 case Pointer20: {
598 uint64_t Value = S + A;
600 return makeTargetOutOfRangeError(G, B, E);
601 write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
602 ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
603 break;
604 }
605 case Pointer16: {
606 uint64_t Value = S + A;
608 return makeTargetOutOfRangeError(G, B, E);
609 write16be(FixupPtr, Value);
610 break;
611 }
612 case Pointer12: {
613 uint64_t Value = S + A;
615 return makeTargetOutOfRangeError(G, B, E);
616 write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
617 break;
618 }
619 case Pointer8: {
620 uint64_t Value = S + A;
622 return makeTargetOutOfRangeError(G, B, E);
623 *(uint8_t *)FixupPtr = Value;
624 break;
625 }
626 case Delta64:
627 case DeltaPLT64: {
628 int64_t Value = S + A - P;
629 write64be(FixupPtr, Value);
630 break;
631 }
632 case Delta32:
633 case DeltaPLT32: {
634 int64_t Value = S + A - P;
636 return makeTargetOutOfRangeError(G, B, E);
637 write32be(FixupPtr, Value);
638 break;
639 }
640 case Delta16: {
641 int64_t Value = S + A - P;
643 return makeTargetOutOfRangeError(G, B, E);
644 write16be(FixupPtr, Value);
645 break;
646 }
647 case NegDelta32: {
648 int64_t Value = P + A - S;
650 return makeTargetOutOfRangeError(G, B, E);
651 write32be(FixupPtr, Value);
652 break;
653 }
654 case Delta32dbl:
655 case DeltaPLT32dbl: {
656 int64_t Value = S + A - P;
658 return makeTargetOutOfRangeError(G, B, E);
660 return makeAlignmentError(FixupAddress, Value, 2, E);
661 write32be(FixupPtr, Value >> 1);
662 break;
663 }
664 case Delta24dbl:
665 case DeltaPLT24dbl: {
666 int64_t Value = S + A - P;
668 return makeTargetOutOfRangeError(G, B, E);
670 return makeAlignmentError(FixupAddress, Value, 2, E);
671 FixupPtr[0] = Value >> 17;
672 FixupPtr[1] = Value >> 9;
673 FixupPtr[2] = Value >> 1;
674 break;
675 }
676 case Delta16dbl:
677 case DeltaPLT16dbl: {
678 int64_t Value = S + A - P;
680 return makeTargetOutOfRangeError(G, B, E);
682 return makeAlignmentError(FixupAddress, Value, 2, E);
683 write16be(FixupPtr, Value >> 1);
684 break;
685 }
686 case Delta12dbl:
687 case DeltaPLT12dbl: {
688 int64_t Value = S + A - P;
690 return makeTargetOutOfRangeError(G, B, E);
692 return makeAlignmentError(FixupAddress, Value, 2, E);
693 write16be(FixupPtr,
694 (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
695 break;
696 }
697 case Delta32GOTBase: {
698 assert(GOTSymbol && "No GOT section symbol");
699 int64_t Value = GOTBase + A - P;
701 return makeTargetOutOfRangeError(G, B, E);
702 write32be(FixupPtr, Value);
703 break;
704 }
705 case Delta32dblGOTBase: {
706 assert(GOTSymbol && "No GOT section symbol");
707 int64_t Value = GOTBase + A - P;
709 return makeTargetOutOfRangeError(G, B, E);
711 return makeAlignmentError(FixupAddress, Value, 2, E);
712 write32be(FixupPtr, Value >> 1);
713 break;
714 }
716 case Delta64FromGOT: {
717 assert(GOTSymbol && "No GOT section symbol");
718 int64_t Value = S + A - GOTBase;
719 write64be(FixupPtr, Value);
720 break;
721 }
723 case Delta32FromGOT: {
724 assert(GOTSymbol && "No GOT section symbol");
725 int64_t Value = S + A - GOTBase;
727 return makeTargetOutOfRangeError(G, B, E);
728 write32be(FixupPtr, Value);
729 break;
730 }
732 case Delta16FromGOT: {
733 assert(GOTSymbol && "No GOT section symbol");
734 int64_t Value = S + A - GOTBase;
736 return makeTargetOutOfRangeError(G, B, E);
737 write16be(FixupPtr, Value);
738 break;
739 }
740 case Delta20FromGOT: {
741 assert(GOTSymbol && "No GOT section symbol");
742 uint64_t Value = S - GOTBase + A;
744 return makeTargetOutOfRangeError(G, B, E);
745 write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
746 ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
747 break;
748 }
749 case Delta12FromGOT: {
750 assert(GOTSymbol && "No GOT section symbol");
751 uint64_t Value = S - GOTBase + A;
753 return makeTargetOutOfRangeError(G, B, E);
754 write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
755 break;
756 }
757 default:
759 "In graph " + G.getName() + ", section " + B.getSection().getName() +
760 " unsupported edge kind " + getEdgeKindName(E.getKind()));
761 }
762
763 return Error::success();
764}
765
766/// SystemZ null pointer content.
767extern const char NullPointerContent[8];
769 return {reinterpret_cast<const char *>(NullPointerContent),
770 G.getPointerSize()};
771}
772
773/// SystemZ pointer jump stub content.
774///
775/// Contains the instruction sequence for an indirect jump via an in-memory
776/// pointer:
777/// lgrl %r1, ptr
778/// j %r1
779constexpr size_t StubEntrySize = 8;
780extern const char Pointer64JumpStubContent[StubEntrySize];
782 auto StubContent = Pointer64JumpStubContent;
783 return {reinterpret_cast<const char *>(StubContent), StubEntrySize};
784}
785
786/// Creates a new pointer block in the given section and returns an
787/// Anonymous symbol pointing to it.
788///
789/// If InitialTarget is given then an Pointer64 relocation will be added to the
790/// block pointing at InitialTarget.
792 Symbol *InitialTarget = nullptr,
793 uint64_t InitialAddend = 0) {
794 auto &B = G.createContentBlock(PointerSection, getGOTEntryBlockContent(G),
795 orc::ExecutorAddr(), G.getPointerSize(), 0);
796 if (InitialTarget)
797 B.addEdge(Pointer64, 0, *InitialTarget, InitialAddend);
798 return G.addAnonymousSymbol(B, 0, G.getPointerSize(), false, false);
799}
800
801/// Create a jump stub block that jumps via the pointer at the given symbol.
802///
803/// The stub block will have the following default values:
804/// alignment: 16-bit
805/// alignment-offset: 0
807 Symbol &PointerSymbol) {
808 auto &B = G.createContentBlock(StubSection, getStubBlockContent(G),
809 orc::ExecutorAddr(), 16, 0);
810 B.addEdge(Delta32dbl, 2, PointerSymbol, 2);
811 return B;
812}
813
814/// Create a jump stub that jumps via the pointer at the given symbol and
815/// an anonymous symbol pointing to it. Return the anonymous symbol.
816///
817/// The stub block will be created by createPointerJumpStubBlock.
819 Section &StubSection,
820 Symbol &PointerSymbol) {
821 return G.addAnonymousSymbol(
822 createPointerJumpStubBlock(G, StubSection, PointerSymbol), 0,
823 StubEntrySize, true, false);
824}
825
826/// Global Offset Table Builder.
827class GOTTableManager : public TableManager<GOTTableManager> {
828public:
829 static StringRef getSectionName() { return "$__GOT"; }
830
832 Edge::Kind KindToSet = Edge::Invalid;
833 switch (E.getKind()) {
835 KindToSet = systemz::Delta12FromGOT;
836 break;
838 KindToSet = systemz::Delta16FromGOT;
839 break;
841 KindToSet = systemz::Delta20FromGOT;
842 break;
844 KindToSet = systemz::Delta32FromGOT;
845 break;
847 KindToSet = systemz::Delta64FromGOT;
848 break;
850 KindToSet = systemz::DeltaPLT32dbl;
851 break;
852 default:
853 return false;
854 }
855 assert(KindToSet != Edge::Invalid &&
856 "Fell through switch, but no new kind to set");
857 DEBUG_WITH_TYPE("jitlink", {
858 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
859 << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
860 << formatv("{0:x}", E.getOffset()) << ")\n";
861 });
862 E.setKind(KindToSet);
863 E.setTarget(getEntryForTarget(G, E.getTarget()));
864 return true;
865 }
866
868 return createAnonymousPointer(G, getGOTSection(G), &Target);
869 }
870
871private:
872 Section &getGOTSection(LinkGraph &G) {
873 if (!GOTSection)
874 GOTSection = &G.createSection(getSectionName(),
876 return *GOTSection;
877 }
878
879 Section *GOTSection = nullptr;
880};
881
882/// Procedure Linkage Table Builder.
883class PLTTableManager : public TableManager<PLTTableManager> {
884public:
886
887 static StringRef getSectionName() { return "$__STUBS"; }
888
890 if (E.getTarget().isDefined())
891 return false;
892
893 switch (E.getKind()) {
903 break;
904 default:
905 return false;
906 }
907 DEBUG_WITH_TYPE("jitlink", {
908 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
909 << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
910 << formatv("{0:x}", E.getOffset()) << ")\n";
911 });
912 E.setTarget(getEntryForTarget(G, E.getTarget()));
913 return true;
914 }
915
918 GOT.getEntryForTarget(G, Target));
919 }
920
921public:
928
931};
932
933} // namespace systemz
934} // namespace jitlink
935} // namespace llvm
936
937#endif // LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
#define G(x, y, z)
Definition MD5.cpp:55
#define P(N)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition Value.h:75
Represents an address in the executor process.
uint64_t getValue() const
void write16be(void *P, uint16_t V)
Definition Endian.h:481
void write32be(void *P, uint32_t V)
Definition Endian.h:484
uint32_t read32be(const void *P)
Definition Endian.h:441
void write64be(void *P, uint64_t V)
Definition Endian.h:487
uint16_t read16be(const void *P)
Definition Endian.h:438
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
#define N